Merge branch 'fix/misc' into for-linus
authorTakashi Iwai <tiwai@suse.de>
Sun, 8 Nov 2009 08:16:06 +0000 (09:16 +0100)
committerTakashi Iwai <tiwai@suse.de>
Sun, 8 Nov 2009 08:16:06 +0000 (09:16 +0100)
1758 files changed:
Documentation/ABI/testing/sysfs-class-uwb_rc-wusbhc [moved from Documentation/ABI/testing/sysfs-class-usb_host with 88% similarity]
Documentation/ABI/testing/sysfs-devices-cache_disable [deleted file]
Documentation/ABI/testing/sysfs-devices-system-cpu [new file with mode: 0644]
Documentation/cgroups/cgroups.txt
Documentation/cputopology.txt
Documentation/debugging-via-ohci1394.txt
Documentation/feature-removal-schedule.txt
Documentation/filesystems/ext3.txt
Documentation/filesystems/ext4.txt
Documentation/flexible-arrays.txt
Documentation/hwmon/sysfs-interface
Documentation/infiniband/user_mad.txt
Documentation/infiniband/user_verbs.txt
Documentation/isdn/INTERFACE.CAPI
Documentation/kernel-parameters.txt
Documentation/lguest/lguest.c
Documentation/networking/pktgen.txt
Documentation/scsi/hptiop.txt
Documentation/trace/ftrace.txt
Documentation/vm/hwpoison.txt [new file with mode: 0644]
Documentation/vm/ksm.txt
Documentation/vm/page-types.c
Documentation/vm/pagemap.txt
MAINTAINERS
Makefile
arch/arm/configs/n8x0_defconfig
arch/arm/configs/omap3_beagle_defconfig
arch/arm/configs/u300_defconfig
arch/arm/include/asm/bitops.h
arch/arm/include/asm/cacheflush.h
arch/arm/include/asm/elf.h
arch/arm/include/asm/tlbflush.h
arch/arm/kernel/entry-armv.S
arch/arm/kernel/entry-header.S
arch/arm/kernel/process.c
arch/arm/kernel/signal.c
arch/arm/kernel/signal.h
arch/arm/kernel/time.c
arch/arm/kernel/traps.c
arch/arm/kernel/unwind.c
arch/arm/mach-at91/at91sam9g45_devices.c
arch/arm/mach-at91/include/mach/cpu.h
arch/arm/mach-bcmring/core.c
arch/arm/mach-bcmring/include/mach/system.h
arch/arm/mach-ep93xx/Kconfig
arch/arm/mach-ep93xx/Makefile.boot
arch/arm/mach-ep93xx/clock.c
arch/arm/mach-ep93xx/core.c
arch/arm/mach-ep93xx/edb93xx.c
arch/arm/mach-ep93xx/include/mach/ep93xx-regs.h
arch/arm/mach-ep93xx/include/mach/gpio.h
arch/arm/mach-ep93xx/include/mach/memory.h
arch/arm/mach-ep93xx/include/mach/platform.h
arch/arm/mach-ep93xx/micro9.c
arch/arm/mach-integrator/include/mach/memory.h
arch/arm/mach-integrator/pci_v3.c
arch/arm/mach-mx2/clock_imx27.c
arch/arm/mach-mx2/pcm038.c
arch/arm/mach-mx2/pcm970-baseboard.c
arch/arm/mach-mx25/devices.c
arch/arm/mach-mx25/mx25pdk.c
arch/arm/mach-mx3/clock-imx35.c
arch/arm/mach-mx3/clock.c
arch/arm/mach-mx3/devices.c
arch/arm/mach-mx3/devices.h
arch/arm/mach-mx3/mm.c
arch/arm/mach-omap1/board-ams-delta.c
arch/arm/mach-omap1/board-generic.c
arch/arm/mach-omap1/board-innovator.c
arch/arm/mach-omap1/board-palmte.c
arch/arm/mach-omap1/board-palmtt.c
arch/arm/mach-omap1/board-palmz71.c
arch/arm/mach-omap1/board-sx1.c
arch/arm/mach-omap1/board-voiceblue.c
arch/arm/mach-omap1/serial.c
arch/arm/mach-omap2/Kconfig
arch/arm/mach-omap2/board-3430sdp.c
arch/arm/mach-omap2/board-4430sdp.c
arch/arm/mach-omap2/board-ldp.c
arch/arm/mach-omap2/board-omap3evm.c
arch/arm/mach-omap2/board-omap3pandora.c
arch/arm/mach-omap2/board-rx51-peripherals.c
arch/arm/mach-omap2/board-rx51.c
arch/arm/mach-omap2/board-zoom2.c
arch/arm/mach-omap2/clock24xx.c
arch/arm/mach-omap2/clock34xx.c
arch/arm/mach-omap2/clockdomain.c
arch/arm/mach-omap2/io.c
arch/arm/mach-omap2/pm-debug.c
arch/arm/mach-omap2/pm34xx.c
arch/arm/mach-omap2/powerdomain.c
arch/arm/mach-omap2/serial.c
arch/arm/mach-pxa/cm-x300.c
arch/arm/mach-pxa/cpufreq-pxa2xx.c
arch/arm/mach-pxa/csb726.c
arch/arm/mach-pxa/spitz.c
arch/arm/mach-realview/core.h
arch/arm/mach-realview/include/mach/board-pb1176.h
arch/arm/mach-realview/include/mach/board-pb11mp.h
arch/arm/mach-realview/include/mach/platform.h
arch/arm/mach-realview/include/mach/system.h
arch/arm/mach-realview/realview_pb1176.c
arch/arm/mach-realview/realview_pb11mp.c
arch/arm/mach-s3c2410/gpio.c
arch/arm/mach-s3c2410/include/mach/dma.h
arch/arm/mach-s3c2440/Kconfig
arch/arm/mach-s3c2440/mach-mini2440.c
arch/arm/mach-s3c6400/include/mach/dma.h
arch/arm/mach-sa1100/Makefile
arch/arm/mm/Kconfig
arch/arm/mm/cache-v6.S
arch/arm/mm/cache-v7.S
arch/arm/mm/context.c
arch/arm/mm/dma-mapping.c
arch/arm/mm/fault-armv.c
arch/arm/mm/fault.c
arch/arm/mm/flush.c
arch/arm/mm/highmem.c
arch/arm/mm/init.c
arch/arm/mm/mmu.c
arch/arm/mm/proc-v6.S
arch/arm/mm/proc-v7.S
arch/arm/oprofile/op_model_v6.c
arch/arm/plat-omap/dma.c
arch/arm/plat-omap/include/mach/cpu.h
arch/arm/plat-omap/include/mach/keypad.h
arch/arm/plat-omap/include/mach/powerdomain.h
arch/arm/plat-omap/iommu.c
arch/arm/plat-omap/iovmm.c
arch/arm/plat-omap/mcbsp.c
arch/arm/plat-omap/sram.c
arch/arm/plat-s3c24xx/adc.c
arch/arm/plat-s3c24xx/cpu.c
arch/arm/plat-s3c24xx/dma.c
arch/arm/plat-s3c24xx/gpio.c
arch/arm/plat-s3c24xx/include/plat/cpu-freq-core.h
arch/arm/plat-s3c24xx/include/plat/s3c2410.h
arch/arm/plat-s3c64xx/include/plat/regs-clock.h
arch/arm/plat-s3c64xx/s3c6400-clock.c
arch/avr32/mach-at32ap/include/mach/cpu.h
arch/blackfin/ADI_BSD.txt [new file with mode: 0644]
arch/blackfin/Kconfig
arch/blackfin/include/asm/atomic.h
arch/blackfin/include/asm/bfin-global.h
arch/blackfin/include/asm/bfin5xx_spi.h
arch/blackfin/include/asm/bfin_rotary.h
arch/blackfin/include/asm/bfin_simple_timer.h
arch/blackfin/include/asm/bitops.h
arch/blackfin/include/asm/blackfin.h
arch/blackfin/include/asm/bug.h
arch/blackfin/include/asm/byteorder.h
arch/blackfin/include/asm/cache.h
arch/blackfin/include/asm/cacheflush.h
arch/blackfin/include/asm/cdef_LPBlackfin.h
arch/blackfin/include/asm/checksum.h
arch/blackfin/include/asm/clocks.h
arch/blackfin/include/asm/context.S
arch/blackfin/include/asm/cplb.h
arch/blackfin/include/asm/cplbinit.h
arch/blackfin/include/asm/cpu.h
arch/blackfin/include/asm/def_LPBlackfin.h
arch/blackfin/include/asm/dma-mapping.h
arch/blackfin/include/asm/dpmc.h
arch/blackfin/include/asm/early_printk.h
arch/blackfin/include/asm/elf.h
arch/blackfin/include/asm/entry.h
arch/blackfin/include/asm/fcntl.h
arch/blackfin/include/asm/fixed_code.h
arch/blackfin/include/asm/flat.h
arch/blackfin/include/asm/gpio.h
arch/blackfin/include/asm/hardirq.h
arch/blackfin/include/asm/io.h
arch/blackfin/include/asm/irq.h
arch/blackfin/include/asm/irq_handler.h
arch/blackfin/include/asm/l1layout.h
arch/blackfin/include/asm/linkage.h
arch/blackfin/include/asm/mmu.h
arch/blackfin/include/asm/mmu_context.h
arch/blackfin/include/asm/module.h
arch/blackfin/include/asm/mutex.h
arch/blackfin/include/asm/nand.h
arch/blackfin/include/asm/page.h
arch/blackfin/include/asm/page_offset.h
arch/blackfin/include/asm/pda.h
arch/blackfin/include/asm/pgtable.h
arch/blackfin/include/asm/poll.h
arch/blackfin/include/asm/portmux.h
arch/blackfin/include/asm/posix_types.h
arch/blackfin/include/asm/processor.h
arch/blackfin/include/asm/ptrace.h
arch/blackfin/include/asm/sections.h
arch/blackfin/include/asm/segment.h
arch/blackfin/include/asm/sigcontext.h
arch/blackfin/include/asm/siginfo.h
arch/blackfin/include/asm/smp.h
arch/blackfin/include/asm/spinlock.h
arch/blackfin/include/asm/spinlock_types.h
arch/blackfin/include/asm/stat.h
arch/blackfin/include/asm/string.h
arch/blackfin/include/asm/swab.h
arch/blackfin/include/asm/system.h
arch/blackfin/include/asm/thread_info.h
arch/blackfin/include/asm/tlb.h
arch/blackfin/include/asm/trace.h
arch/blackfin/include/asm/traps.h
arch/blackfin/include/asm/uaccess.h
arch/blackfin/include/asm/unistd.h
arch/blackfin/kernel/asm-offsets.c
arch/blackfin/kernel/bfin_dma_5xx.c
arch/blackfin/kernel/bfin_gpio.c
arch/blackfin/kernel/cplb-mpu/cplbinit.c
arch/blackfin/kernel/cplb-mpu/cplbmgr.c
arch/blackfin/kernel/cplb-nompu/cplbinit.c
arch/blackfin/kernel/cplb-nompu/cplbmgr.c
arch/blackfin/kernel/cplbinfo.c
arch/blackfin/kernel/dma-mapping.c
arch/blackfin/kernel/early_printk.c
arch/blackfin/kernel/entry.S
arch/blackfin/kernel/fixed_code.S
arch/blackfin/kernel/flat.c
arch/blackfin/kernel/init_task.c
arch/blackfin/kernel/irqchip.c
arch/blackfin/kernel/module.c
arch/blackfin/kernel/process.c
arch/blackfin/kernel/ptrace.c
arch/blackfin/kernel/setup.c
arch/blackfin/kernel/shadow_console.c
arch/blackfin/kernel/signal.c
arch/blackfin/kernel/sys_bfin.c
arch/blackfin/kernel/time-ts.c
arch/blackfin/kernel/time.c
arch/blackfin/kernel/traps.c
arch/blackfin/kernel/vmlinux.lds.S
arch/blackfin/lib/ashldi3.c
arch/blackfin/lib/ashrdi3.c
arch/blackfin/lib/checksum.c
arch/blackfin/lib/divsi3.S
arch/blackfin/lib/gcclib.h
arch/blackfin/lib/lshrdi3.c
arch/blackfin/lib/memchr.S
arch/blackfin/lib/memcmp.S
arch/blackfin/lib/memcpy.S
arch/blackfin/lib/memmove.S
arch/blackfin/lib/memset.S
arch/blackfin/lib/modsi3.S
arch/blackfin/lib/muldi3.S
arch/blackfin/lib/outs.S
arch/blackfin/lib/smulsi3_highpart.S
arch/blackfin/lib/udivsi3.S
arch/blackfin/lib/umodsi3.S
arch/blackfin/lib/umulsi3_highpart.S
arch/blackfin/mach-bf518/boards/ezbrd.c
arch/blackfin/mach-bf518/dma.c
arch/blackfin/mach-bf518/include/mach/bf518.h
arch/blackfin/mach-bf518/include/mach/bfin_serial_5xx.h
arch/blackfin/mach-bf518/include/mach/blackfin.h
arch/blackfin/mach-bf518/include/mach/cdefBF512.h
arch/blackfin/mach-bf518/include/mach/cdefBF514.h
arch/blackfin/mach-bf518/include/mach/cdefBF516.h
arch/blackfin/mach-bf518/include/mach/cdefBF518.h
arch/blackfin/mach-bf518/include/mach/cdefBF51x_base.h
arch/blackfin/mach-bf518/include/mach/defBF512.h
arch/blackfin/mach-bf518/include/mach/defBF514.h
arch/blackfin/mach-bf518/include/mach/defBF516.h
arch/blackfin/mach-bf518/include/mach/defBF518.h
arch/blackfin/mach-bf518/include/mach/defBF51x_base.h
arch/blackfin/mach-bf518/include/mach/gpio.h
arch/blackfin/mach-bf518/include/mach/irq.h
arch/blackfin/mach-bf518/include/mach/portmux.h
arch/blackfin/mach-bf518/ints-priority.c
arch/blackfin/mach-bf527/boards/cm_bf527.c
arch/blackfin/mach-bf527/boards/ezbrd.c
arch/blackfin/mach-bf527/boards/ezkit.c
arch/blackfin/mach-bf527/dma.c
arch/blackfin/mach-bf527/include/mach/bf527.h
arch/blackfin/mach-bf527/include/mach/bfin_serial_5xx.h
arch/blackfin/mach-bf527/include/mach/blackfin.h
arch/blackfin/mach-bf527/include/mach/cdefBF522.h
arch/blackfin/mach-bf527/include/mach/cdefBF525.h
arch/blackfin/mach-bf527/include/mach/cdefBF527.h
arch/blackfin/mach-bf527/include/mach/cdefBF52x_base.h
arch/blackfin/mach-bf527/include/mach/defBF522.h
arch/blackfin/mach-bf527/include/mach/defBF525.h
arch/blackfin/mach-bf527/include/mach/defBF527.h
arch/blackfin/mach-bf527/include/mach/defBF52x_base.h
arch/blackfin/mach-bf527/include/mach/gpio.h
arch/blackfin/mach-bf527/include/mach/irq.h
arch/blackfin/mach-bf527/include/mach/portmux.h
arch/blackfin/mach-bf527/ints-priority.c
arch/blackfin/mach-bf533/boards/H8606.c
arch/blackfin/mach-bf533/boards/blackstamp.c
arch/blackfin/mach-bf533/boards/cm_bf533.c
arch/blackfin/mach-bf533/boards/ezkit.c
arch/blackfin/mach-bf533/boards/ip0x.c
arch/blackfin/mach-bf533/boards/stamp.c
arch/blackfin/mach-bf533/dma.c
arch/blackfin/mach-bf533/include/mach/bf533.h
arch/blackfin/mach-bf533/include/mach/bfin_serial_5xx.h
arch/blackfin/mach-bf533/include/mach/blackfin.h
arch/blackfin/mach-bf533/include/mach/cdefBF532.h
arch/blackfin/mach-bf533/include/mach/defBF532.h
arch/blackfin/mach-bf533/include/mach/gpio.h
arch/blackfin/mach-bf533/include/mach/irq.h
arch/blackfin/mach-bf533/include/mach/portmux.h
arch/blackfin/mach-bf533/ints-priority.c
arch/blackfin/mach-bf537/boards/cm_bf537e.c
arch/blackfin/mach-bf537/boards/cm_bf537u.c
arch/blackfin/mach-bf537/boards/minotaur.c
arch/blackfin/mach-bf537/boards/pnav10.c
arch/blackfin/mach-bf537/boards/stamp.c
arch/blackfin/mach-bf537/boards/tcm_bf537.c
arch/blackfin/mach-bf537/dma.c
arch/blackfin/mach-bf537/include/mach/bf537.h
arch/blackfin/mach-bf537/include/mach/bfin_serial_5xx.h
arch/blackfin/mach-bf537/include/mach/blackfin.h
arch/blackfin/mach-bf537/include/mach/cdefBF534.h
arch/blackfin/mach-bf537/include/mach/cdefBF537.h
arch/blackfin/mach-bf537/include/mach/defBF534.h
arch/blackfin/mach-bf537/include/mach/defBF537.h
arch/blackfin/mach-bf537/include/mach/gpio.h
arch/blackfin/mach-bf537/include/mach/irq.h
arch/blackfin/mach-bf537/include/mach/portmux.h
arch/blackfin/mach-bf537/ints-priority.c
arch/blackfin/mach-bf538/boards/ezkit.c
arch/blackfin/mach-bf538/dma.c
arch/blackfin/mach-bf538/include/mach/bf538.h
arch/blackfin/mach-bf538/include/mach/bfin_serial_5xx.h
arch/blackfin/mach-bf538/include/mach/blackfin.h
arch/blackfin/mach-bf538/include/mach/cdefBF538.h
arch/blackfin/mach-bf538/include/mach/defBF539.h
arch/blackfin/mach-bf538/include/mach/gpio.h
arch/blackfin/mach-bf538/include/mach/irq.h
arch/blackfin/mach-bf538/include/mach/portmux.h
arch/blackfin/mach-bf538/ints-priority.c
arch/blackfin/mach-bf548/boards/cm_bf548.c
arch/blackfin/mach-bf548/boards/ezkit.c
arch/blackfin/mach-bf548/dma.c
arch/blackfin/mach-bf548/include/mach/bf548.h
arch/blackfin/mach-bf548/include/mach/bf54x-lq043.h
arch/blackfin/mach-bf548/include/mach/bf54x_keys.h
arch/blackfin/mach-bf548/include/mach/bfin_serial_5xx.h
arch/blackfin/mach-bf548/include/mach/blackfin.h
arch/blackfin/mach-bf548/include/mach/cdefBF542.h
arch/blackfin/mach-bf548/include/mach/cdefBF544.h
arch/blackfin/mach-bf548/include/mach/cdefBF547.h
arch/blackfin/mach-bf548/include/mach/cdefBF548.h
arch/blackfin/mach-bf548/include/mach/cdefBF549.h
arch/blackfin/mach-bf548/include/mach/cdefBF54x_base.h
arch/blackfin/mach-bf548/include/mach/defBF542.h
arch/blackfin/mach-bf548/include/mach/defBF544.h
arch/blackfin/mach-bf548/include/mach/defBF547.h
arch/blackfin/mach-bf548/include/mach/defBF548.h
arch/blackfin/mach-bf548/include/mach/defBF549.h
arch/blackfin/mach-bf548/include/mach/defBF54x_base.h
arch/blackfin/mach-bf548/include/mach/gpio.h
arch/blackfin/mach-bf548/include/mach/irq.h
arch/blackfin/mach-bf548/include/mach/portmux.h
arch/blackfin/mach-bf548/ints-priority.c
arch/blackfin/mach-bf561/atomic.S
arch/blackfin/mach-bf561/boards/cm_bf561.c
arch/blackfin/mach-bf561/boards/ezkit.c
arch/blackfin/mach-bf561/boards/tepla.c
arch/blackfin/mach-bf561/dma.c
arch/blackfin/mach-bf561/include/mach/bf561.h
arch/blackfin/mach-bf561/include/mach/bfin_serial_5xx.h
arch/blackfin/mach-bf561/include/mach/blackfin.h
arch/blackfin/mach-bf561/include/mach/cdefBF561.h
arch/blackfin/mach-bf561/include/mach/defBF561.h
arch/blackfin/mach-bf561/include/mach/gpio.h
arch/blackfin/mach-bf561/include/mach/irq.h
arch/blackfin/mach-bf561/include/mach/portmux.h
arch/blackfin/mach-bf561/include/mach/smp.h
arch/blackfin/mach-bf561/ints-priority.c
arch/blackfin/mach-bf561/secondary.S
arch/blackfin/mach-bf561/smp.c
arch/blackfin/mach-common/arch_checks.c
arch/blackfin/mach-common/cache-c.c
arch/blackfin/mach-common/cache.S
arch/blackfin/mach-common/cpufreq.c
arch/blackfin/mach-common/entry.S
arch/blackfin/mach-common/head.S
arch/blackfin/mach-common/interrupt.S
arch/blackfin/mach-common/ints-priority.c
arch/blackfin/mach-common/irqpanic.c
arch/blackfin/mach-common/pm.c
arch/blackfin/mach-common/smp.c
arch/blackfin/mm/blackfin_sram.h
arch/blackfin/mm/init.c
arch/blackfin/mm/isram-driver.c
arch/blackfin/mm/sram-alloc.c
arch/frv/kernel/signal.c
arch/ia64/include/asm/spinlock.h
arch/ia64/include/asm/spinlock_types.h
arch/ia64/kernel/mca.c
arch/ia64/kernel/unaligned.c
arch/ia64/mm/tlb.c
arch/ia64/pci/pci.c
arch/ia64/sn/kernel/io_common.c
arch/ia64/sn/kernel/sn2/sn_hwperf.c
arch/m32r/kernel/smp.c
arch/m68k/Kconfig
arch/m68knommu/kernel/asm-offsets.c
arch/m68knommu/kernel/entry.S
arch/m68knommu/mm/init.c
arch/m68knommu/platform/5206e/config.c
arch/m68knommu/platform/68328/entry.S
arch/m68knommu/platform/68360/entry.S
arch/m68knommu/platform/coldfire/entry.S
arch/microblaze/kernel/entry.S
arch/microblaze/kernel/hw_exception_handler.S
arch/microblaze/kernel/process.c
arch/mips/Kconfig
arch/mips/alchemy/common/irq.c
arch/mips/alchemy/mtx-1/board_setup.c
arch/mips/ar7/platform.c
arch/mips/bcm63xx/Makefile
arch/mips/bcm63xx/boards/board_bcm963xx.c
arch/mips/bcm63xx/cpu.c
arch/mips/bcm63xx/dev-uart.c
arch/mips/bcm63xx/dev-wdt.c [new file with mode: 0644]
arch/mips/bcm63xx/setup.c
arch/mips/cavium-octeon/octeon-irq.c
arch/mips/cavium-octeon/smp.c
arch/mips/include/asm/fixmap.h
arch/mips/include/asm/gcmpregs.h
arch/mips/include/asm/gic.h
arch/mips/include/asm/mach-ar7/ar7.h
arch/mips/include/asm/mach-au1x00/gpio-au1000.h
arch/mips/include/asm/mach-bcm63xx/bcm63xx_dev_uart.h [deleted file]
arch/mips/include/asm/mach-ip27/topology.h
arch/mips/include/asm/mach-loongson/cpu-feature-overrides.h
arch/mips/include/asm/mmu_context.h
arch/mips/include/asm/setup.h
arch/mips/include/asm/smtc_ipi.h
arch/mips/include/asm/spram.h [new file with mode: 0644]
arch/mips/include/asm/thread_info.h
arch/mips/jazz/irq.c
arch/mips/kernel/cevt-bcm1480.c
arch/mips/kernel/cevt-ds1287.c
arch/mips/kernel/cevt-gt641xx.c
arch/mips/kernel/cevt-r4k.c
arch/mips/kernel/cevt-sb1250.c
arch/mips/kernel/cevt-txx9.c
arch/mips/kernel/cpu-probe.c
arch/mips/kernel/head.S
arch/mips/kernel/i8253.c
arch/mips/kernel/irq-gic.c
arch/mips/kernel/linux32.c
arch/mips/kernel/scall64-o32.S
arch/mips/kernel/smtc.c
arch/mips/kernel/spram.c
arch/mips/kernel/vpe.c
arch/mips/loongson/common/irq.c
arch/mips/math-emu/dp_simple.c
arch/mips/math-emu/sp_simple.c
arch/mips/mm/init.c
arch/mips/mti-malta/malta-amon.c
arch/mips/mti-malta/malta-int.c
arch/mips/mti-malta/malta-pci.c
arch/mips/nxp/pnx8550/common/int.c
arch/mips/nxp/pnx8550/common/time.c
arch/mips/oprofile/op_model_loongson2.c
arch/mips/sgi-ip27/ip27-timer.c
arch/mips/sni/time.c
arch/mips/txx9/generic/setup.c
arch/parisc/Kconfig
arch/parisc/include/asm/fixmap.h
arch/parisc/include/asm/hardirq.h
arch/parisc/include/asm/ptrace.h
arch/parisc/include/asm/syscall.h [new file with mode: 0644]
arch/parisc/include/asm/thread_info.h
arch/parisc/kernel/asm-offsets.c
arch/parisc/kernel/entry.S
arch/parisc/kernel/irq.c
arch/parisc/kernel/module.c
arch/parisc/kernel/ptrace.c
arch/parisc/kernel/signal.c
arch/parisc/kernel/syscall.S
arch/parisc/kernel/vmlinux.lds.S
arch/parisc/mm/init.c
arch/powerpc/boot/dts/cm5200.dts
arch/powerpc/boot/dts/digsy_mtc.dts
arch/powerpc/boot/dts/lite5200.dts
arch/powerpc/boot/dts/lite5200b.dts
arch/powerpc/boot/dts/media5200.dts
arch/powerpc/boot/dts/motionpro.dts
arch/powerpc/boot/dts/mpc5121ads.dts
arch/powerpc/boot/dts/mucmc52.dts [new file with mode: 0644]
arch/powerpc/boot/dts/pcm030.dts
arch/powerpc/boot/dts/pcm032.dts
arch/powerpc/boot/dts/tqm5200.dts
arch/powerpc/boot/dts/uc101.dts [new file with mode: 0644]
arch/powerpc/configs/52xx/cm5200_defconfig
arch/powerpc/configs/52xx/lite5200b_defconfig
arch/powerpc/configs/52xx/motionpro_defconfig
arch/powerpc/configs/52xx/pcm030_defconfig
arch/powerpc/configs/52xx/tqm5200_defconfig
arch/powerpc/configs/mpc5200_defconfig
arch/powerpc/configs/ppc64e_defconfig [new file with mode: 0644]
arch/powerpc/include/asm/firmware.h
arch/powerpc/kernel/cputable.c
arch/powerpc/kernel/entry_64.S
arch/powerpc/kernel/kgdb.c
arch/powerpc/kernel/pci-common.c
arch/powerpc/kernel/pci_64.c
arch/powerpc/kernel/perf_event.c
arch/powerpc/kernel/process.c
arch/powerpc/kernel/setup_64.c
arch/powerpc/kernel/vdso.c
arch/powerpc/kernel/vdso32/vdso32.lds.S
arch/powerpc/kernel/vmlinux.lds.S
arch/powerpc/mm/slb_low.S
arch/powerpc/platforms/52xx/mpc5200_simple.c
arch/powerpc/platforms/cell/axon_msi.c
arch/powerpc/platforms/iseries/Makefile
arch/powerpc/platforms/iseries/dt.c
arch/powerpc/platforms/powermac/low_i2c.c
arch/powerpc/platforms/pseries/firmware.c
arch/powerpc/xmon/xmon.c
arch/s390/hypfs/hypfs_diag.c
arch/s390/include/asm/cputime.h
arch/s390/include/asm/delay.h
arch/s390/include/asm/elf.h
arch/s390/include/asm/ptrace.h
arch/s390/include/asm/ucontext.h
arch/s390/kernel/compat_signal.c
arch/s390/kernel/compat_wrapper.S
arch/s390/kernel/ftrace.c
arch/s390/kernel/ipl.c
arch/s390/kernel/module.c
arch/s390/kernel/processor.c
arch/s390/kernel/ptrace.c
arch/s390/kernel/setup.c
arch/s390/kernel/smp.c
arch/s390/kernel/swsusp_asm64.S
arch/s390/kernel/vdso.c
arch/s390/kernel/vmlinux.lds.S
arch/s390/kvm/kvm-s390.h
arch/s390/lib/delay.c
arch/s390/lib/uaccess_mvcos.c
arch/s390/lib/uaccess_std.c
arch/s390/mm/pgtable.c
arch/sh/Kconfig
arch/sh/Makefile
arch/sh/boards/board-magicpanelr2.c
arch/sh/boards/mach-dreamcast/setup.c
arch/sh/boards/mach-ecovec24/setup.c
arch/sh/boards/mach-landisk/gio.c
arch/sh/boards/mach-rsk/devices-rsk7203.c
arch/sh/boards/mach-rsk/setup.c
arch/sh/boot/Makefile
arch/sh/kernel/cpu/sh3/entry.S
arch/sh/kernel/dwarf.c
arch/sh/kernel/entry-common.S
arch/sh/kernel/ftrace.c
arch/sh/kernel/io_generic.c
arch/sh/kernel/irq.c
arch/sh/kernel/machvec.c
arch/sh/kernel/setup.c
arch/sh/kernel/sh_ksyms_32.c
arch/sh/kernel/signal_32.c
arch/sh/kernel/smp.c
arch/sh/kernel/traps_32.c
arch/sh/mm/Kconfig
arch/sh/mm/cache-sh4.c
arch/sh/mm/cache-sh7705.c
arch/sh/mm/cache.c
arch/sh/mm/ioremap_32.c
arch/sh/mm/pmb.c
arch/sparc/Kconfig
arch/sparc/include/asm/hardirq_32.h
arch/sparc/include/asm/irq_32.h
arch/sparc/include/asm/pgtable_64.h
arch/sparc/kernel/ktlb.S
arch/sparc/kernel/ldc.c
arch/sparc/kernel/perf_event.c
arch/sparc/mm/init_64.c
arch/sparc/oprofile/init.c
arch/um/drivers/line.c
arch/um/drivers/port_kern.c
arch/um/kernel/irq.c
arch/x86/Kconfig
arch/x86/Kconfig.cpu
arch/x86/Makefile
arch/x86/boot/setup.ld
arch/x86/crypto/aesni-intel_glue.c
arch/x86/ia32/ia32entry.S
arch/x86/include/asm/kvm_host.h
arch/x86/include/asm/mce.h
arch/x86/include/asm/paravirt.h
arch/x86/include/asm/paravirt_types.h
arch/x86/include/asm/topology.h
arch/x86/include/asm/uv/uv_hub.h
arch/x86/kernel/acpi/realmode/wakeup.lds.S
arch/x86/kernel/apic/x2apic_uv_x.c
arch/x86/kernel/cpu/mcheck/mce.c
arch/x86/kernel/cpu/mcheck/mce_intel.c
arch/x86/kernel/cpu/mtrr/if.c
arch/x86/kernel/crash_dump_32.c
arch/x86/kernel/e820.c
arch/x86/kernel/early_printk.c
arch/x86/kernel/efi.c
arch/x86/kernel/i386_ksyms_32.c
arch/x86/kernel/irq.c
arch/x86/kernel/pci-dma.c
arch/x86/kernel/pci-gart_64.c
arch/x86/kernel/reboot.c
arch/x86/kernel/time.c
arch/x86/kernel/tlb_uv.c
arch/x86/kernel/trampoline.c
arch/x86/kernel/trampoline_64.S
arch/x86/kernel/vmi_32.c
arch/x86/kernel/vmlinux.lds.S
arch/x86/kvm/i8254.c
arch/x86/kvm/lapic.c
arch/x86/kvm/mmu.c
arch/x86/kvm/paging_tmpl.h
arch/x86/kvm/svm.c
arch/x86/kvm/vmx.c
arch/x86/kvm/x86.c
arch/x86/lib/Makefile
arch/x86/xen/enlighten.c
arch/xtensa/kernel/time.c
block/blk-core.c
block/blk-merge.c
block/blk-settings.c
block/blk-tag.c
block/cfq-iosched.c
block/elevator.c
block/genhd.c
crypto/aead.c
crypto/async_tx/async_pq.c
crypto/async_tx/async_raid6_recov.c
crypto/async_tx/async_xor.c
drivers/acpi/Kconfig
drivers/acpi/ac.c
drivers/acpi/button.c
drivers/acpi/pci_root.c
drivers/acpi/video.c
drivers/acpi/video_detect.c
drivers/ata/ahci.c
drivers/ata/libata-acpi.c
drivers/ata/libata-core.c
drivers/ata/libata-eh.c
drivers/ata/libata.h
drivers/ata/pata_ali.c
drivers/ata/pata_atiixp.c
drivers/ata/pata_atp867x.c
drivers/ata/pata_sc1200.c
drivers/ata/pata_via.c
drivers/ata/sata_mv.c
drivers/ata/sata_nv.c
drivers/base/bus.c
drivers/base/driver.c
drivers/base/platform.c
drivers/base/power/main.c
drivers/base/power/runtime.c
drivers/block/cciss.c
drivers/block/loop.c
drivers/block/virtio_blk.c
drivers/char/Kconfig
drivers/char/agp/parisc-agp.c
drivers/char/applicom.c
drivers/char/epca.c
drivers/char/generic_serial.c
drivers/char/genrtc.c
drivers/char/hw_random/virtio-rng.c
drivers/char/istallion.c
drivers/char/nozomi.c
drivers/char/pty.c
drivers/char/rio/riocmd.c
drivers/char/rio/rioctrl.c
drivers/char/rio/riotty.c
drivers/char/rtc.c
drivers/char/ser_a2232.c
drivers/char/sonypi.c
drivers/char/stallion.c
drivers/char/tlclk.c
drivers/char/tpm/tpm.c
drivers/char/tty_buffer.c
drivers/char/virtio_console.c
drivers/char/vt_ioctl.c
drivers/connector/cn_proc.c
drivers/cpuidle/cpuidle.c
drivers/crypto/padlock-sha.c
drivers/edac/Kconfig
drivers/edac/Makefile
drivers/edac/amd64_edac.c
drivers/edac/amd64_edac.h
drivers/edac/amd64_edac_inj.c
drivers/edac/edac_mce_amd.c
drivers/edac/i5000_edac.c
drivers/edac/i5400_edac.c
drivers/edac/mpc85xx_edac.c
drivers/firewire/sbp2.c
drivers/firmware/iscsi_ibft.c
drivers/firmware/iscsi_ibft_find.c
drivers/gpio/twl4030-gpio.c
drivers/gpu/drm/drm_crtc.c
drivers/gpu/drm/drm_edid.c
drivers/gpu/drm/drm_fb_helper.c
drivers/gpu/drm/i915/i915_dma.c
drivers/gpu/drm/i915/i915_drv.c
drivers/gpu/drm/i915/i915_drv.h
drivers/gpu/drm/i915/i915_gem.c
drivers/gpu/drm/i915/i915_irq.c
drivers/gpu/drm/i915/i915_trace.h
drivers/gpu/drm/i915/intel_display.c
drivers/gpu/drm/i915/intel_drv.h
drivers/gpu/drm/i915/intel_fb.c
drivers/gpu/drm/i915/intel_hdmi.c
drivers/gpu/drm/i915/intel_lvds.c
drivers/gpu/drm/i915/intel_tv.c
drivers/gpu/drm/radeon/atombios_crtc.c
drivers/gpu/drm/radeon/r100.c
drivers/gpu/drm/radeon/r100d.h
drivers/gpu/drm/radeon/r200.c
drivers/gpu/drm/radeon/r300.c
drivers/gpu/drm/radeon/r300d.h
drivers/gpu/drm/radeon/r420.c
drivers/gpu/drm/radeon/r420d.h
drivers/gpu/drm/radeon/r520.c
drivers/gpu/drm/radeon/r600.c
drivers/gpu/drm/radeon/r600_blit.c
drivers/gpu/drm/radeon/r600_blit_kms.c
drivers/gpu/drm/radeon/r600_cs.c
drivers/gpu/drm/radeon/r600d.h
drivers/gpu/drm/radeon/radeon.h
drivers/gpu/drm/radeon/radeon_asic.h
drivers/gpu/drm/radeon/radeon_bios.c
drivers/gpu/drm/radeon/radeon_clocks.c
drivers/gpu/drm/radeon/radeon_device.c
drivers/gpu/drm/radeon/radeon_display.c
drivers/gpu/drm/radeon/radeon_encoders.c
drivers/gpu/drm/radeon/radeon_fb.c
drivers/gpu/drm/radeon/radeon_irq_kms.c
drivers/gpu/drm/radeon/radeon_legacy_crtc.c
drivers/gpu/drm/radeon/radeon_legacy_encoders.c
drivers/gpu/drm/radeon/radeon_mode.h
drivers/gpu/drm/radeon/radeon_object.c
drivers/gpu/drm/radeon/rs100d.h [new file with mode: 0644]
drivers/gpu/drm/radeon/rs400.c
drivers/gpu/drm/radeon/rs400d.h [new file with mode: 0644]
drivers/gpu/drm/radeon/rs600.c
drivers/gpu/drm/radeon/rs600d.h [new file with mode: 0644]
drivers/gpu/drm/radeon/rs690.c
drivers/gpu/drm/radeon/rs690d.h [new file with mode: 0644]
drivers/gpu/drm/radeon/rs690r.h [deleted file]
drivers/gpu/drm/radeon/rv200d.h [new file with mode: 0644]
drivers/gpu/drm/radeon/rv250d.h [new file with mode: 0644]
drivers/gpu/drm/radeon/rv350d.h [new file with mode: 0644]
drivers/gpu/drm/radeon/rv515.c
drivers/gpu/drm/radeon/rv770.c
drivers/gpu/drm/ttm/ttm_global.c
drivers/hid/hid-core.c
drivers/hid/hid-twinhan.c
drivers/hid/hidraw.c
drivers/hwmon/Kconfig
drivers/hwmon/asus_atk0110.c
drivers/hwmon/dme1737.c
drivers/hwmon/fschmd.c
drivers/hwmon/hp_accel.c
drivers/hwmon/it87.c
drivers/hwmon/lis3lv02d_spi.c
drivers/hwmon/sht15.c
drivers/i2c/busses/i2c-imx.c
drivers/i2c/busses/i2c-mpc.c
drivers/ide/atiixp.c
drivers/ide/cmd64x.c
drivers/ide/ide-proc.c
drivers/ide/sis5513.c
drivers/ieee1394/raw1394.c
drivers/ieee1394/video1394.c
drivers/infiniband/core/addr.c
drivers/infiniband/core/iwcm.c
drivers/infiniband/core/ucma.c
drivers/infiniband/hw/cxgb3/iwch_provider.c
drivers/infiniband/hw/cxgb3/iwch_qp.c
drivers/infiniband/hw/ipath/ipath_driver.c
drivers/infiniband/hw/ipath/ipath_iba7220.c
drivers/infiniband/hw/ipath/ipath_intr.c
drivers/infiniband/hw/ipath/ipath_qp.c
drivers/infiniband/hw/ipath/ipath_ruc.c
drivers/infiniband/hw/ipath/ipath_ud.c
drivers/infiniband/hw/ipath/ipath_user_pages.c
drivers/infiniband/hw/ipath/ipath_user_sdma.c
drivers/infiniband/hw/ipath/ipath_verbs_mcast.c
drivers/infiniband/ulp/iser/iscsi_iser.c
drivers/input/input.c
drivers/input/joystick/xpad.c
drivers/input/keyboard/atkbd.c
drivers/input/keyboard/gpio_keys.c
drivers/input/keyboard/hilkbd.c
drivers/input/keyboard/sunkbd.c
drivers/input/misc/Kconfig
drivers/input/misc/hp_sdc_rtc.c
drivers/input/misc/rotary_encoder.c
drivers/input/misc/sparcspkr.c
drivers/input/misc/wistron_btns.c
drivers/input/mouse/logips2pp.c
drivers/input/mouse/synaptics.c
drivers/input/serio/Kconfig
drivers/input/serio/i8042-x86ia64io.h
drivers/input/serio/i8042.c
drivers/input/serio/libps2.c
drivers/input/serio/serio_raw.c
drivers/input/serio/serport.c
drivers/input/touchscreen/ad7879.c
drivers/isdn/capi/capi.c
drivers/isdn/capi/capidrv.c
drivers/isdn/capi/kcapi.c
drivers/isdn/gigaset/asyncdata.c
drivers/isdn/gigaset/bas-gigaset.c
drivers/isdn/gigaset/common.c
drivers/isdn/gigaset/ev-layer.c
drivers/isdn/gigaset/i4l.c
drivers/isdn/gigaset/interface.c
drivers/isdn/gigaset/isocdata.c
drivers/isdn/hisax/arcofi.c
drivers/isdn/hisax/hfc_2bds0.c
drivers/isdn/hisax/hfc_pci.c
drivers/isdn/hysdn/hysdn_procconf.c
drivers/isdn/hysdn/hysdn_proclog.c
drivers/isdn/i4l/isdn_net.h
drivers/isdn/pcbit/drv.c
drivers/isdn/pcbit/layer2.c
drivers/isdn/sc/init.c
drivers/lguest/interrupts_and_traps.c
drivers/macintosh/via-pmu.c
drivers/md/Makefile
drivers/md/bitmap.c
drivers/md/dm-exception-store.c
drivers/md/dm-exception-store.h
drivers/md/dm-log-userspace-base.c
drivers/md/dm-snap-persistent.c
drivers/md/dm-snap.c
drivers/md/dm.c
drivers/md/md.c
drivers/md/raid1.c
drivers/md/raid10.c
drivers/md/raid5.c
drivers/md/raid5.h
drivers/md/raid6altivec.uc
drivers/md/raid6int.uc
drivers/md/raid6test/Makefile
drivers/md/unroll.awk [new file with mode: 0644]
drivers/md/unroll.pl [deleted file]
drivers/media/dvb/dvb-core/dvb_net.c
drivers/media/video/meye.c
drivers/media/video/videobuf-core.c
drivers/media/video/videobuf-dma-sg.c
drivers/message/fusion/mptlan.c
drivers/mfd/twl4030-core.c
drivers/mfd/ucb1x00-core.c
drivers/mfd/wm831x-irq.c
drivers/misc/hpilo.c
drivers/misc/ibmasm/command.c
drivers/misc/ibmasm/event.c
drivers/misc/ibmasm/r_heartbeat.c
drivers/misc/phantom.c
drivers/mmc/core/sdio_cis.c
drivers/mmc/host/at91_mci.c
drivers/mmc/host/omap_hsmmc.c
drivers/mmc/host/pxamci.c
drivers/mtd/devices/m25p80.c
drivers/mtd/devices/sst25l.c
drivers/mtd/ubi/build.c
drivers/mtd/ubi/scan.c
drivers/mtd/ubi/scan.h
drivers/net/Kconfig
drivers/net/Makefile
drivers/net/acenic.c
drivers/net/au1000_eth.c
drivers/net/benet/be_cmds.c
drivers/net/benet/be_cmds.h
drivers/net/benet/be_ethtool.c
drivers/net/benet/be_main.c
drivers/net/bnx2.h
drivers/net/bonding/bond_main.c
drivers/net/bonding/bond_sysfs.c
drivers/net/can/sja1000/sja1000_of_platform.c
drivers/net/cnic.c
drivers/net/davinci_emac.c
drivers/net/depca.c
drivers/net/dm9000.h
drivers/net/e100.c
drivers/net/e1000e/82571.c
drivers/net/e1000e/defines.h
drivers/net/e1000e/e1000.h
drivers/net/e1000e/hw.h
drivers/net/e1000e/ich8lan.c
drivers/net/e1000e/phy.c
drivers/net/eql.c
drivers/net/ethoc.c
drivers/net/ewrk3.c
drivers/net/fec.c
drivers/net/fec_mpc52xx.c
drivers/net/fec_mpc52xx_phy.c
drivers/net/forcedeth.c
drivers/net/fs_enet/fs_enet-main.c
drivers/net/fs_enet/mii-bitbang.c
drivers/net/fs_enet/mii-fec.c
drivers/net/fsl_pq_mdio.c
drivers/net/gianfar.c
drivers/net/hamachi.c
drivers/net/hamradio/baycom_epp.c
drivers/net/hamradio/baycom_ser_fdx.c
drivers/net/hamradio/baycom_ser_hdx.c
drivers/net/hamradio/hdlcdrv.c
drivers/net/hp100.c
drivers/net/ibm_newemac/core.c
drivers/net/ibm_newemac/emac.h
drivers/net/ifb.c
drivers/net/igb/igb_ethtool.c
drivers/net/igbvf/ethtool.c
drivers/net/irda/sa1100_ir.c
drivers/net/irda/toim3232-sir.c
drivers/net/ixgbe/ixgbe_82599.c
drivers/net/ixgbe/ixgbe_ethtool.c
drivers/net/ixgbe/ixgbe_main.c
drivers/net/ixgbe/ixgbe_type.h
drivers/net/ixp2000/enp2611.c
drivers/net/ixp2000/ixpdev.c
drivers/net/ks8851.c
drivers/net/ks8851.h
drivers/net/mlx4/main.c
drivers/net/myri10ge/myri10ge.c
drivers/net/netxen/netxen_nic_hdr.h
drivers/net/netxen/netxen_nic_hw.c
drivers/net/netxen/netxen_nic_init.c
drivers/net/netxen/netxen_nic_main.c
drivers/net/niu.c
drivers/net/ns83820.c
drivers/net/pasemi_mac_ethtool.c
drivers/net/pcmcia/3c574_cs.c
drivers/net/pcmcia/pcnet_cs.c
drivers/net/pcnet32.c
drivers/net/phy/mdio-gpio.c
drivers/net/pppoe.c
drivers/net/qlge/qlge.h
drivers/net/qlge/qlge_ethtool.c
drivers/net/qlge/qlge_main.c
drivers/net/qlge/qlge_mpi.c
drivers/net/r8169.c
drivers/net/sb1000.c
drivers/net/sfc/rx.c
drivers/net/sh_eth.c
drivers/net/sis900.c
drivers/net/skfp/skfddi.c
drivers/net/skge.c
drivers/net/sky2.c
drivers/net/slip.c
drivers/net/stmmac/Kconfig [new file with mode: 0644]
drivers/net/stmmac/Makefile [new file with mode: 0644]
drivers/net/stmmac/common.h [new file with mode: 0644]
drivers/net/stmmac/descs.h [new file with mode: 0644]
drivers/net/stmmac/gmac.c [new file with mode: 0644]
drivers/net/stmmac/gmac.h [new file with mode: 0644]
drivers/net/stmmac/mac100.c [new file with mode: 0644]
drivers/net/stmmac/mac100.h [new file with mode: 0644]
drivers/net/stmmac/stmmac.h [new file with mode: 0644]
drivers/net/stmmac/stmmac_ethtool.c [new file with mode: 0644]
drivers/net/stmmac/stmmac_main.c [new file with mode: 0644]
drivers/net/stmmac/stmmac_mdio.c [new file with mode: 0644]
drivers/net/stmmac/stmmac_timer.c [new file with mode: 0644]
drivers/net/stmmac/stmmac_timer.h [new file with mode: 0644]
drivers/net/sungem.c
drivers/net/tg3.c
drivers/net/tg3.h
drivers/net/tokenring/ibmtr.c
drivers/net/typhoon.c
drivers/net/usb/dm9601.c
drivers/net/usb/pegasus.c
drivers/net/usb/pegasus.h
drivers/net/usb/rndis_host.c
drivers/net/virtio_net.c
drivers/net/vmxnet3/Makefile [new file with mode: 0644]
drivers/net/vmxnet3/upt1_defs.h [new file with mode: 0644]
drivers/net/vmxnet3/vmxnet3_defs.h [new file with mode: 0644]
drivers/net/vmxnet3/vmxnet3_drv.c [new file with mode: 0644]
drivers/net/vmxnet3/vmxnet3_ethtool.c [new file with mode: 0644]
drivers/net/vmxnet3/vmxnet3_int.h [new file with mode: 0644]
drivers/net/wan/c101.c
drivers/net/wan/cosa.c
drivers/net/wan/cycx_x25.c
drivers/net/wan/dscc4.c
drivers/net/wan/farsync.c
drivers/net/wan/hdlc_cisco.c
drivers/net/wan/n2.c
drivers/net/wan/pci200syn.c
drivers/net/wireless/adm8211.h
drivers/net/wireless/airo.c
drivers/net/wireless/ath/ath9k/rc.c
drivers/net/wireless/b43/b43.h
drivers/net/wireless/b43/dma.c
drivers/net/wireless/b43/leds.c
drivers/net/wireless/b43/leds.h
drivers/net/wireless/b43/main.c
drivers/net/wireless/b43/pio.c
drivers/net/wireless/b43/rfkill.c
drivers/net/wireless/b43/xmit.c
drivers/net/wireless/b43legacy/main.c
drivers/net/wireless/b43legacy/phy.c
drivers/net/wireless/hostap/hostap_info.c
drivers/net/wireless/hostap/hostap_ioctl.c
drivers/net/wireless/ipw2x00/ipw2100.c
drivers/net/wireless/ipw2x00/ipw2200.c
drivers/net/wireless/ipw2x00/libipw.h
drivers/net/wireless/ipw2x00/libipw_module.c
drivers/net/wireless/iwlwifi/iwl-3945-rs.c
drivers/net/wireless/iwlwifi/iwl-3945.c
drivers/net/wireless/iwlwifi/iwl-4965.c
drivers/net/wireless/iwlwifi/iwl-5000.c
drivers/net/wireless/iwlwifi/iwl-agn.c
drivers/net/wireless/iwlwifi/iwl-commands.h
drivers/net/wireless/iwlwifi/iwl-core.c
drivers/net/wireless/iwlwifi/iwl-eeprom.c
drivers/net/wireless/iwlwifi/iwl-eeprom.h
drivers/net/wireless/iwlwifi/iwl-hcmd.c
drivers/net/wireless/iwlwifi/iwl-rx.c
drivers/net/wireless/iwlwifi/iwl-tx.c
drivers/net/wireless/iwlwifi/iwl3945-base.c
drivers/net/wireless/iwmc3200wifi/cfg80211.c
drivers/net/wireless/iwmc3200wifi/commands.c
drivers/net/wireless/iwmc3200wifi/main.c
drivers/net/wireless/iwmc3200wifi/rx.c
drivers/net/wireless/libertas/cmd.c
drivers/net/wireless/libertas/cmdresp.c
drivers/net/wireless/libertas/if_spi.c
drivers/net/wireless/libertas/if_usb.c
drivers/net/wireless/libertas/tx.c
drivers/net/wireless/prism54/isl_ioctl.c
drivers/net/wireless/prism54/islpci_dev.c
drivers/net/wireless/prism54/islpci_mgt.c
drivers/net/wireless/ray_cs.c
drivers/net/wireless/rt2x00/rt2800usb.c
drivers/net/wireless/rt2x00/rt2x00debug.c
drivers/net/wireless/rt2x00/rt73usb.c
drivers/net/znet.c
drivers/of/of_mdio.c
drivers/oprofile/event_buffer.c
drivers/pci/dmar.c
drivers/pci/hotplug/cpqphp.h
drivers/pci/intel-iommu.c
drivers/pci/pci.c
drivers/pci/pcie/aer/aerdrv.c
drivers/pci/pcie/portdrv_pci.c
drivers/pci/quirks.c
drivers/pci/setup-res.c
drivers/pcmcia/cistpl.c
drivers/pcmcia/cs.c
drivers/pcmcia/cs_internal.h
drivers/pcmcia/ds.c
drivers/pcmcia/i82365.c
drivers/pcmcia/m32r_cfc.c
drivers/pcmcia/m32r_pcc.c
drivers/pcmcia/m8xx_pcmcia.c
drivers/pcmcia/pcmcia_ioctl.c
drivers/pcmcia/pd6729.c
drivers/pcmcia/rsrc_nonstatic.c
drivers/pcmcia/soc_common.c
drivers/pcmcia/socket_sysfs.c
drivers/pcmcia/tcic.c
drivers/pcmcia/yenta_socket.c
drivers/platform/x86/eeepc-laptop.c
drivers/platform/x86/fujitsu-laptop.c
drivers/rtc/interface.c
drivers/rtc/rtc-dev.c
drivers/s390/block/dasd.c
drivers/s390/block/dasd_eckd.c
drivers/s390/char/raw3270.c
drivers/s390/char/sclp_async.c
drivers/s390/char/sclp_vt220.c
drivers/s390/char/tape_block.c
drivers/s390/cio/blacklist.c
drivers/s390/cio/chp.c
drivers/s390/cio/device.c
drivers/s390/cio/device.h
drivers/s390/cio/device_fsm.c
drivers/s390/crypto/zcrypt_pcixcc.c
drivers/s390/net/smsgiucv.c
drivers/s390/scsi/zfcp_aux.c
drivers/s390/scsi/zfcp_ccw.c
drivers/s390/scsi/zfcp_cfdc.c
drivers/s390/scsi/zfcp_erp.c
drivers/s390/scsi/zfcp_ext.h
drivers/s390/scsi/zfcp_fc.c
drivers/s390/scsi/zfcp_fsf.c
drivers/s390/scsi/zfcp_sysfs.c
drivers/scsi/Kconfig
drivers/scsi/Makefile
drivers/scsi/be2iscsi/Kconfig [new file with mode: 0644]
drivers/scsi/be2iscsi/Makefile [new file with mode: 0644]
drivers/scsi/be2iscsi/be.h [new file with mode: 0644]
drivers/scsi/be2iscsi/be_cmds.c [new file with mode: 0644]
drivers/scsi/be2iscsi/be_cmds.h [new file with mode: 0644]
drivers/scsi/be2iscsi/be_iscsi.c [new file with mode: 0644]
drivers/scsi/be2iscsi/be_iscsi.h [new file with mode: 0644]
drivers/scsi/be2iscsi/be_main.c [new file with mode: 0644]
drivers/scsi/be2iscsi/be_main.h [new file with mode: 0644]
drivers/scsi/be2iscsi/be_mgmt.c [new file with mode: 0644]
drivers/scsi/be2iscsi/be_mgmt.h [new file with mode: 0644]
drivers/scsi/bfa/Makefile [new file with mode: 0644]
drivers/scsi/bfa/bfa_callback_priv.h [new file with mode: 0644]
drivers/scsi/bfa/bfa_cb_ioim_macros.h [new file with mode: 0644]
drivers/scsi/bfa/bfa_cee.c [new file with mode: 0644]
drivers/scsi/bfa/bfa_core.c [new file with mode: 0644]
drivers/scsi/bfa/bfa_csdebug.c [new file with mode: 0644]
drivers/scsi/bfa/bfa_fcpim.c [new file with mode: 0644]
drivers/scsi/bfa/bfa_fcpim_priv.h [new file with mode: 0644]
drivers/scsi/bfa/bfa_fcport.c [new file with mode: 0644]
drivers/scsi/bfa/bfa_fcs.c [new file with mode: 0644]
drivers/scsi/bfa/bfa_fcs_lport.c [new file with mode: 0644]
drivers/scsi/bfa/bfa_fcs_port.c [new file with mode: 0644]
drivers/scsi/bfa/bfa_fcs_uf.c [new file with mode: 0644]
drivers/scsi/bfa/bfa_fcxp.c [new file with mode: 0644]
drivers/scsi/bfa/bfa_fcxp_priv.h [new file with mode: 0644]
drivers/scsi/bfa/bfa_fwimg_priv.h [new file with mode: 0644]
drivers/scsi/bfa/bfa_hw_cb.c [new file with mode: 0644]
drivers/scsi/bfa/bfa_hw_ct.c [new file with mode: 0644]
drivers/scsi/bfa/bfa_intr.c [new file with mode: 0644]
drivers/scsi/bfa/bfa_intr_priv.h [new file with mode: 0644]
drivers/scsi/bfa/bfa_ioc.c [new file with mode: 0644]
drivers/scsi/bfa/bfa_ioc.h [new file with mode: 0644]
drivers/scsi/bfa/bfa_iocfc.c [new file with mode: 0644]
drivers/scsi/bfa/bfa_iocfc.h [new file with mode: 0644]
drivers/scsi/bfa/bfa_iocfc_q.c [new file with mode: 0644]
drivers/scsi/bfa/bfa_ioim.c [new file with mode: 0644]
drivers/scsi/bfa/bfa_itnim.c [new file with mode: 0644]
drivers/scsi/bfa/bfa_log.c [new file with mode: 0644]
drivers/scsi/bfa/bfa_log_module.c [new file with mode: 0644]
drivers/scsi/bfa/bfa_lps.c [new file with mode: 0644]
drivers/scsi/bfa/bfa_lps_priv.h [new file with mode: 0644]
drivers/scsi/bfa/bfa_module.c [new file with mode: 0644]
drivers/scsi/bfa/bfa_modules_priv.h [new file with mode: 0644]
drivers/scsi/bfa/bfa_os_inc.h [new file with mode: 0644]
drivers/scsi/bfa/bfa_port.c [new file with mode: 0644]
drivers/scsi/bfa/bfa_port_priv.h [new file with mode: 0644]
drivers/scsi/bfa/bfa_priv.h [new file with mode: 0644]
drivers/scsi/bfa/bfa_rport.c [new file with mode: 0644]
drivers/scsi/bfa/bfa_rport_priv.h [new file with mode: 0644]
drivers/scsi/bfa/bfa_sgpg.c [new file with mode: 0644]
drivers/scsi/bfa/bfa_sgpg_priv.h [new file with mode: 0644]
drivers/scsi/bfa/bfa_sm.c [new file with mode: 0644]
drivers/scsi/bfa/bfa_timer.c [new file with mode: 0644]
drivers/scsi/bfa/bfa_trcmod_priv.h [new file with mode: 0644]
drivers/scsi/bfa/bfa_tskim.c [new file with mode: 0644]
drivers/scsi/bfa/bfa_uf.c [new file with mode: 0644]
drivers/scsi/bfa/bfa_uf_priv.h [new file with mode: 0644]
drivers/scsi/bfa/bfad.c [new file with mode: 0644]
drivers/scsi/bfa/bfad_attr.c [new file with mode: 0644]
drivers/scsi/bfa/bfad_attr.h [new file with mode: 0644]
drivers/scsi/bfa/bfad_drv.h [new file with mode: 0644]
drivers/scsi/bfa/bfad_fwimg.c [new file with mode: 0644]
drivers/scsi/bfa/bfad_im.c [new file with mode: 0644]
drivers/scsi/bfa/bfad_im.h [new file with mode: 0644]
drivers/scsi/bfa/bfad_im_compat.h [new file with mode: 0644]
drivers/scsi/bfa/bfad_intr.c [new file with mode: 0644]
drivers/scsi/bfa/bfad_ipfc.h [new file with mode: 0644]
drivers/scsi/bfa/bfad_os.c [new file with mode: 0644]
drivers/scsi/bfa/bfad_tm.h [new file with mode: 0644]
drivers/scsi/bfa/bfad_trcmod.h [new file with mode: 0644]
drivers/scsi/bfa/fab.c [new file with mode: 0644]
drivers/scsi/bfa/fabric.c [new file with mode: 0644]
drivers/scsi/bfa/fcbuild.c [new file with mode: 0644]
drivers/scsi/bfa/fcbuild.h [new file with mode: 0644]
drivers/scsi/bfa/fcpim.c [new file with mode: 0644]
drivers/scsi/bfa/fcptm.c [new file with mode: 0644]
drivers/scsi/bfa/fcs.h [new file with mode: 0644]
drivers/scsi/bfa/fcs_auth.h [new file with mode: 0644]
drivers/scsi/bfa/fcs_fabric.h [new file with mode: 0644]
drivers/scsi/bfa/fcs_fcpim.h [new file with mode: 0644]
drivers/scsi/bfa/fcs_fcptm.h [new file with mode: 0644]
drivers/scsi/bfa/fcs_fcxp.h [new file with mode: 0644]
drivers/scsi/bfa/fcs_lport.h [new file with mode: 0644]
drivers/scsi/bfa/fcs_ms.h [new file with mode: 0644]
drivers/scsi/bfa/fcs_port.h [new file with mode: 0644]
drivers/scsi/bfa/fcs_rport.h [new file with mode: 0644]
drivers/scsi/bfa/fcs_trcmod.h [new file with mode: 0644]
drivers/scsi/bfa/fcs_uf.h [new file with mode: 0644]
drivers/scsi/bfa/fcs_vport.h [new file with mode: 0644]
drivers/scsi/bfa/fdmi.c [new file with mode: 0644]
drivers/scsi/bfa/include/aen/bfa_aen.h [new file with mode: 0644]
drivers/scsi/bfa/include/aen/bfa_aen_adapter.h [new file with mode: 0644]
drivers/scsi/bfa/include/aen/bfa_aen_audit.h [new file with mode: 0644]
drivers/scsi/bfa/include/aen/bfa_aen_ethport.h [new file with mode: 0644]
drivers/scsi/bfa/include/aen/bfa_aen_ioc.h [new file with mode: 0644]
drivers/scsi/bfa/include/aen/bfa_aen_itnim.h [new file with mode: 0644]
drivers/scsi/bfa/include/aen/bfa_aen_lport.h [new file with mode: 0644]
drivers/scsi/bfa/include/aen/bfa_aen_port.h [new file with mode: 0644]
drivers/scsi/bfa/include/aen/bfa_aen_rport.h [new file with mode: 0644]
drivers/scsi/bfa/include/bfa.h [new file with mode: 0644]
drivers/scsi/bfa/include/bfa_fcpim.h [new file with mode: 0644]
drivers/scsi/bfa/include/bfa_fcptm.h [new file with mode: 0644]
drivers/scsi/bfa/include/bfa_svc.h [new file with mode: 0644]
drivers/scsi/bfa/include/bfa_timer.h [new file with mode: 0644]
drivers/scsi/bfa/include/bfi/bfi.h [new file with mode: 0644]
drivers/scsi/bfa/include/bfi/bfi_boot.h [new file with mode: 0644]
drivers/scsi/bfa/include/bfi/bfi_cbreg.h [new file with mode: 0644]
drivers/scsi/bfa/include/bfi/bfi_cee.h [new file with mode: 0644]
drivers/scsi/bfa/include/bfi/bfi_ctreg.h [new file with mode: 0644]
drivers/scsi/bfa/include/bfi/bfi_fabric.h [new file with mode: 0644]
drivers/scsi/bfa/include/bfi/bfi_fcpim.h [new file with mode: 0644]
drivers/scsi/bfa/include/bfi/bfi_fcxp.h [new file with mode: 0644]
drivers/scsi/bfa/include/bfi/bfi_ioc.h [new file with mode: 0644]
drivers/scsi/bfa/include/bfi/bfi_iocfc.h [new file with mode: 0644]
drivers/scsi/bfa/include/bfi/bfi_lport.h [new file with mode: 0644]
drivers/scsi/bfa/include/bfi/bfi_lps.h [new file with mode: 0644]
drivers/scsi/bfa/include/bfi/bfi_port.h [new file with mode: 0644]
drivers/scsi/bfa/include/bfi/bfi_pport.h [new file with mode: 0644]
drivers/scsi/bfa/include/bfi/bfi_rport.h [new file with mode: 0644]
drivers/scsi/bfa/include/bfi/bfi_uf.h [new file with mode: 0644]
drivers/scsi/bfa/include/cna/bfa_cna_trcmod.h [new file with mode: 0644]
drivers/scsi/bfa/include/cna/cee/bfa_cee.h [new file with mode: 0644]
drivers/scsi/bfa/include/cna/port/bfa_port.h [new file with mode: 0644]
drivers/scsi/bfa/include/cna/pstats/ethport_defs.h [new file with mode: 0644]
drivers/scsi/bfa/include/cna/pstats/phyport_defs.h [new file with mode: 0644]
drivers/scsi/bfa/include/cs/bfa_checksum.h [new file with mode: 0644]
drivers/scsi/bfa/include/cs/bfa_debug.h [new file with mode: 0644]
drivers/scsi/bfa/include/cs/bfa_log.h [new file with mode: 0644]
drivers/scsi/bfa/include/cs/bfa_perf.h [new file with mode: 0644]
drivers/scsi/bfa/include/cs/bfa_plog.h [new file with mode: 0644]
drivers/scsi/bfa/include/cs/bfa_q.h [new file with mode: 0644]
drivers/scsi/bfa/include/cs/bfa_sm.h [new file with mode: 0644]
drivers/scsi/bfa/include/cs/bfa_trc.h [new file with mode: 0644]
drivers/scsi/bfa/include/cs/bfa_wc.h [new file with mode: 0644]
drivers/scsi/bfa/include/defs/bfa_defs_adapter.h [new file with mode: 0644]
drivers/scsi/bfa/include/defs/bfa_defs_aen.h [new file with mode: 0644]
drivers/scsi/bfa/include/defs/bfa_defs_audit.h [new file with mode: 0644]
drivers/scsi/bfa/include/defs/bfa_defs_auth.h [new file with mode: 0644]
drivers/scsi/bfa/include/defs/bfa_defs_boot.h [new file with mode: 0644]
drivers/scsi/bfa/include/defs/bfa_defs_cee.h [new file with mode: 0644]
drivers/scsi/bfa/include/defs/bfa_defs_driver.h [new file with mode: 0644]
drivers/scsi/bfa/include/defs/bfa_defs_ethport.h [new file with mode: 0644]
drivers/scsi/bfa/include/defs/bfa_defs_fcpim.h [new file with mode: 0644]
drivers/scsi/bfa/include/defs/bfa_defs_im_common.h [new file with mode: 0644]
drivers/scsi/bfa/include/defs/bfa_defs_im_team.h [new file with mode: 0644]
drivers/scsi/bfa/include/defs/bfa_defs_ioc.h [new file with mode: 0644]
drivers/scsi/bfa/include/defs/bfa_defs_iocfc.h [new file with mode: 0644]
drivers/scsi/bfa/include/defs/bfa_defs_ipfc.h [new file with mode: 0644]
drivers/scsi/bfa/include/defs/bfa_defs_itnim.h [new file with mode: 0644]
drivers/scsi/bfa/include/defs/bfa_defs_led.h [new file with mode: 0644]
drivers/scsi/bfa/include/defs/bfa_defs_lport.h [new file with mode: 0644]
drivers/scsi/bfa/include/defs/bfa_defs_mfg.h [new file with mode: 0644]
drivers/scsi/bfa/include/defs/bfa_defs_pci.h [new file with mode: 0644]
drivers/scsi/bfa/include/defs/bfa_defs_pm.h [new file with mode: 0644]
drivers/scsi/bfa/include/defs/bfa_defs_pom.h [new file with mode: 0644]
drivers/scsi/bfa/include/defs/bfa_defs_port.h [new file with mode: 0644]
drivers/scsi/bfa/include/defs/bfa_defs_pport.h [new file with mode: 0644]
drivers/scsi/bfa/include/defs/bfa_defs_qos.h [new file with mode: 0644]
drivers/scsi/bfa/include/defs/bfa_defs_rport.h [new file with mode: 0644]
drivers/scsi/bfa/include/defs/bfa_defs_status.h [new file with mode: 0644]
drivers/scsi/bfa/include/defs/bfa_defs_tin.h [new file with mode: 0644]
drivers/scsi/bfa/include/defs/bfa_defs_tsensor.h [new file with mode: 0644]
drivers/scsi/bfa/include/defs/bfa_defs_types.h [new file with mode: 0644]
drivers/scsi/bfa/include/defs/bfa_defs_version.h [new file with mode: 0644]
drivers/scsi/bfa/include/defs/bfa_defs_vf.h [new file with mode: 0644]
drivers/scsi/bfa/include/defs/bfa_defs_vport.h [new file with mode: 0644]
drivers/scsi/bfa/include/fcb/bfa_fcb.h [new file with mode: 0644]
drivers/scsi/bfa/include/fcb/bfa_fcb_fcpim.h [new file with mode: 0644]
drivers/scsi/bfa/include/fcb/bfa_fcb_port.h [new file with mode: 0644]
drivers/scsi/bfa/include/fcb/bfa_fcb_rport.h [new file with mode: 0644]
drivers/scsi/bfa/include/fcb/bfa_fcb_vf.h [new file with mode: 0644]
drivers/scsi/bfa/include/fcb/bfa_fcb_vport.h [new file with mode: 0644]
drivers/scsi/bfa/include/fcs/bfa_fcs.h [new file with mode: 0644]
drivers/scsi/bfa/include/fcs/bfa_fcs_auth.h [new file with mode: 0644]
drivers/scsi/bfa/include/fcs/bfa_fcs_fabric.h [new file with mode: 0644]
drivers/scsi/bfa/include/fcs/bfa_fcs_fcpim.h [new file with mode: 0644]
drivers/scsi/bfa/include/fcs/bfa_fcs_fdmi.h [new file with mode: 0644]
drivers/scsi/bfa/include/fcs/bfa_fcs_lport.h [new file with mode: 0644]
drivers/scsi/bfa/include/fcs/bfa_fcs_rport.h [new file with mode: 0644]
drivers/scsi/bfa/include/fcs/bfa_fcs_vport.h [new file with mode: 0644]
drivers/scsi/bfa/include/log/bfa_log_fcs.h [new file with mode: 0644]
drivers/scsi/bfa/include/log/bfa_log_hal.h [new file with mode: 0644]
drivers/scsi/bfa/include/log/bfa_log_linux.h [new file with mode: 0644]
drivers/scsi/bfa/include/log/bfa_log_wdrv.h [new file with mode: 0644]
drivers/scsi/bfa/include/protocol/ct.h [new file with mode: 0644]
drivers/scsi/bfa/include/protocol/fc.h [new file with mode: 0644]
drivers/scsi/bfa/include/protocol/fc_sp.h [new file with mode: 0644]
drivers/scsi/bfa/include/protocol/fcp.h [new file with mode: 0644]
drivers/scsi/bfa/include/protocol/fdmi.h [new file with mode: 0644]
drivers/scsi/bfa/include/protocol/pcifw.h [new file with mode: 0644]
drivers/scsi/bfa/include/protocol/scsi.h [new file with mode: 0644]
drivers/scsi/bfa/include/protocol/types.h [new file with mode: 0644]
drivers/scsi/bfa/loop.c [new file with mode: 0644]
drivers/scsi/bfa/lport_api.c [new file with mode: 0644]
drivers/scsi/bfa/lport_priv.h [new file with mode: 0644]
drivers/scsi/bfa/ms.c [new file with mode: 0644]
drivers/scsi/bfa/n2n.c [new file with mode: 0644]
drivers/scsi/bfa/ns.c [new file with mode: 0644]
drivers/scsi/bfa/plog.c [new file with mode: 0644]
drivers/scsi/bfa/rport.c [new file with mode: 0644]
drivers/scsi/bfa/rport_api.c [new file with mode: 0644]
drivers/scsi/bfa/rport_ftrs.c [new file with mode: 0644]
drivers/scsi/bfa/scn.c [new file with mode: 0644]
drivers/scsi/bfa/vfapi.c [new file with mode: 0644]
drivers/scsi/bfa/vport.c [new file with mode: 0644]
drivers/scsi/bnx2i/bnx2i.h
drivers/scsi/bnx2i/bnx2i_hwi.c
drivers/scsi/bnx2i/bnx2i_iscsi.c
drivers/scsi/cxgb3i/cxgb3i_iscsi.c
drivers/scsi/device_handler/scsi_dh_rdac.c
drivers/scsi/dpt_i2o.c
drivers/scsi/hptiop.c
drivers/scsi/hptiop.h
drivers/scsi/iscsi_tcp.c
drivers/scsi/libiscsi.c
drivers/scsi/lpfc/lpfc_scsi.c
drivers/scsi/mpt2sas/Kconfig
drivers/scsi/mpt2sas/mpi/mpi2.h
drivers/scsi/mpt2sas/mpi/mpi2_cnfg.h
drivers/scsi/mpt2sas/mpi/mpi2_history.txt [new file with mode: 0644]
drivers/scsi/mpt2sas/mpi/mpi2_init.h
drivers/scsi/mpt2sas/mpi/mpi2_ioc.h
drivers/scsi/mpt2sas/mpi/mpi2_tool.h
drivers/scsi/mpt2sas/mpt2sas_base.c
drivers/scsi/mpt2sas/mpt2sas_base.h
drivers/scsi/mpt2sas/mpt2sas_config.c
drivers/scsi/mpt2sas/mpt2sas_ctl.c
drivers/scsi/mpt2sas/mpt2sas_ctl.h
drivers/scsi/mpt2sas/mpt2sas_debug.h
drivers/scsi/mpt2sas/mpt2sas_scsih.c
drivers/scsi/mpt2sas/mpt2sas_transport.c
drivers/scsi/mvsas/mv_defs.h
drivers/scsi/mvsas/mv_init.c
drivers/scsi/pmcraid.c
drivers/scsi/qla2xxx/qla_mid.c
drivers/scsi/scsi.c
drivers/scsi/scsi_debug.c
drivers/scsi/scsi_error.c
drivers/scsi/scsi_scan.c
drivers/scsi/scsi_sysfs.c
drivers/scsi/scsi_transport_fc.c
drivers/scsi/sd.c
drivers/scsi/sd.h
drivers/scsi/sd_dif.c
drivers/scsi/sg.c
drivers/scsi/sr.c
drivers/scsi/st.c
drivers/serial/8250_pci.c
drivers/serial/atmel_serial.c
drivers/serial/mpc52xx_uart.c
drivers/serial/serial_core.c
drivers/serial/serial_cs.c
drivers/spi/amba-pl022.c
drivers/staging/Kconfig
drivers/staging/Makefile
drivers/staging/agnx/Kconfig [deleted file]
drivers/staging/agnx/Makefile [deleted file]
drivers/staging/agnx/TODO [deleted file]
drivers/staging/agnx/agnx.h [deleted file]
drivers/staging/agnx/debug.h [deleted file]
drivers/staging/agnx/pci.c [deleted file]
drivers/staging/agnx/phy.c [deleted file]
drivers/staging/agnx/phy.h [deleted file]
drivers/staging/agnx/rf.c [deleted file]
drivers/staging/agnx/sta.c [deleted file]
drivers/staging/agnx/sta.h [deleted file]
drivers/staging/agnx/table.c [deleted file]
drivers/staging/agnx/table.h [deleted file]
drivers/staging/agnx/xmit.c [deleted file]
drivers/staging/agnx/xmit.h [deleted file]
drivers/staging/android/Kconfig
drivers/staging/b3dfg/b3dfg.c
drivers/staging/comedi/Kconfig
drivers/staging/comedi/comedi_fops.c
drivers/staging/comedi/drivers/cb_das16_cs.c
drivers/staging/comedi/drivers/cb_pcidio.c
drivers/staging/comedi/drivers/jr3_pci.c
drivers/staging/comedi/drivers/me_daq.c
drivers/staging/comedi/drivers/ni_65xx.c
drivers/staging/comedi/drivers/ni_daq_700.c
drivers/staging/comedi/drivers/ni_daq_dio24.c
drivers/staging/comedi/drivers/ni_labpc_cs.c
drivers/staging/comedi/drivers/ni_mio_common.c
drivers/staging/comedi/drivers/ni_mio_cs.c
drivers/staging/comedi/drivers/ni_pcidio.c
drivers/staging/comedi/drivers/ni_pcimio.c
drivers/staging/comedi/drivers/quatech_daqp_cs.c
drivers/staging/comedi/drivers/s526.c
drivers/staging/comedi/drivers/serial2002.c
drivers/staging/cowloop/Kconfig [deleted file]
drivers/staging/cowloop/Makefile [deleted file]
drivers/staging/cowloop/TODO [deleted file]
drivers/staging/cowloop/cowloop.c [deleted file]
drivers/staging/cowloop/cowloop.h [deleted file]
drivers/staging/et131x/et1310_address_map.h
drivers/staging/et131x/et1310_rx.c
drivers/staging/hv/ChannelMgmt.h
drivers/staging/hv/NetVsc.c
drivers/staging/hv/TODO
drivers/staging/hv/osd.c
drivers/staging/hv/osd.h
drivers/staging/hv/vmbus_drv.c
drivers/staging/iio/Kconfig
drivers/staging/iio/industrialio-core.c
drivers/staging/otus/Kconfig
drivers/staging/p9auth/p9auth.c
drivers/staging/panel/panel.c
drivers/staging/poch/poch.c
drivers/staging/rt2860/Kconfig
drivers/staging/rt2860/common/cmm_data_2860.c
drivers/staging/rt2860/common/cmm_info.c
drivers/staging/rt2860/rt_linux.c
drivers/staging/rt2870/Kconfig
drivers/staging/rt3090/Kconfig
drivers/staging/rt3090/common/cmm_info.c
drivers/staging/rt3090/rt_linux.c
drivers/staging/rtl8187se/Kconfig
drivers/staging/rtl8187se/ieee80211/ieee80211_crypt.c
drivers/staging/rtl8187se/ieee80211/ieee80211_module.c
drivers/staging/rtl8187se/ieee80211/ieee80211_softmac.c
drivers/staging/rtl8187se/ieee80211/ieee80211_wx.c
drivers/staging/rtl8192e/Kconfig
drivers/staging/rtl8192e/ieee80211/ieee80211_crypt.c
drivers/staging/rtl8192e/ieee80211/ieee80211_module.c
drivers/staging/rtl8192e/ieee80211/ieee80211_softmac.c
drivers/staging/rtl8192e/ieee80211/ieee80211_wx.c
drivers/staging/rtl8192e/r8192E_core.c
drivers/staging/rtl8192su/Kconfig
drivers/staging/rtl8192su/ieee80211/ieee80211_crypt.c
drivers/staging/rtl8192su/ieee80211/ieee80211_module.c
drivers/staging/rtl8192su/ieee80211/ieee80211_softmac.c
drivers/staging/rtl8192su/ieee80211/ieee80211_wx.c
drivers/staging/sep/sep_driver.c
drivers/staging/stlc45xx/Kconfig [deleted file]
drivers/staging/stlc45xx/Makefile [deleted file]
drivers/staging/stlc45xx/stlc45xx.c [deleted file]
drivers/staging/stlc45xx/stlc45xx.h [deleted file]
drivers/staging/stlc45xx/stlc45xx_lmac.h [deleted file]
drivers/staging/vme/bridges/vme_ca91cx42.c
drivers/staging/vme/bridges/vme_tsi148.c
drivers/staging/vt6656/main_usb.c
drivers/staging/winbond/Kconfig
drivers/staging/winbond/wbusb.c
drivers/staging/wlan-ng/Kconfig
drivers/uio/uio.c
drivers/usb/class/usbtmc.c
drivers/usb/gadget/Kconfig
drivers/usb/gadget/ether.c
drivers/usb/gadget/fsl_udc_core.c
drivers/usb/gadget/imx_udc.c
drivers/usb/gadget/r8a66597-udc.h
drivers/usb/host/ehci-sched.c
drivers/usb/host/isp1362-hcd.c
drivers/usb/host/isp1362.h
drivers/usb/host/pci-quirks.c
drivers/usb/host/r8a66597-hcd.c
drivers/usb/host/whci/asl.c
drivers/usb/host/whci/pzl.c
drivers/usb/host/xhci-hcd.c
drivers/usb/misc/usblcd.c
drivers/usb/musb/Kconfig
drivers/usb/musb/blackfin.c
drivers/usb/musb/musb_core.h
drivers/usb/musb/musb_regs.h
drivers/usb/serial/aircable.c
drivers/usb/serial/cp210x.c
drivers/usb/serial/cypress_m8.c
drivers/usb/serial/digi_acceleport.c
drivers/usb/serial/empeg.c
drivers/usb/serial/ftdi_sio.c
drivers/usb/serial/garmin_gps.c
drivers/usb/serial/generic.c
drivers/usb/serial/ipaq.c
drivers/usb/serial/keyspan_pda.c
drivers/usb/serial/kl5kusb105.c
drivers/usb/serial/mct_u232.c
drivers/usb/serial/opticon.c
drivers/usb/serial/option.c
drivers/usb/serial/oti6858.c
drivers/usb/serial/pl2303.c
drivers/usb/serial/sierra.c
drivers/usb/serial/symbolserial.c
drivers/usb/serial/usb-serial.c
drivers/usb/serial/visor.c
drivers/usb/serial/whiteheat.c
drivers/usb/storage/transport.c
drivers/usb/storage/unusual_devs.h
drivers/usb/wusbcore/security.c
drivers/uwb/whc-rc.c
drivers/video/da8xx-fb.c
drivers/video/msm/mddi.c
drivers/video/omap/blizzard.c
drivers/video/omap/omapfb_main.c
drivers/virtio/virtio_balloon.c
drivers/virtio/virtio_pci.c
drivers/virtio/virtio_ring.c
drivers/watchdog/riowd.c
firmware/Makefile
firmware/WHENCE
firmware/cis/COMpad2.cis.ihex [new file with mode: 0644]
firmware/cis/COMpad4.cis.ihex [new file with mode: 0644]
firmware/cis/DP83903.cis.ihex [new file with mode: 0644]
firmware/cis/NE2K.cis.ihex [new file with mode: 0644]
firmware/cis/PE-200.cis.ihex [new file with mode: 0644]
firmware/cis/SW_555_SER.cis.ihex [new file with mode: 0644]
firmware/cis/SW_7xx_SER.cis.ihex [new file with mode: 0644]
firmware/cis/SW_8xx_SER.cis.ihex [new file with mode: 0644]
firmware/cis/tamarack.cis.ihex [new file with mode: 0644]
fs/9p/vfs_dir.c
fs/9p/vfs_inode.c
fs/Kconfig
fs/block_dev.c
fs/btrfs/acl.c
fs/btrfs/async-thread.c
fs/btrfs/async-thread.h
fs/btrfs/btrfs_inode.h
fs/btrfs/ctree.h
fs/btrfs/disk-io.c
fs/btrfs/extent-tree.c
fs/btrfs/extent_io.c
fs/btrfs/extent_io.h
fs/btrfs/file.c
fs/btrfs/inode.c
fs/btrfs/ioctl.c
fs/btrfs/ordered-data.c
fs/btrfs/relocation.c
fs/btrfs/super.c
fs/btrfs/transaction.c
fs/btrfs/transaction.h
fs/btrfs/tree-log.c
fs/btrfs/tree-log.h
fs/btrfs/xattr.c
fs/cifs/connect.c
fs/dlm/lowcomms.c
fs/ecryptfs/Kconfig
fs/ecryptfs/main.c
fs/ext3/super.c
fs/ext4/ext4.h
fs/ext4/super.c
fs/file.c
fs/hfs/btree.c
fs/hfsplus/wrapper.c
fs/nfs/client.c
fs/nfs/dir.c
fs/nfs/direct.c
fs/nfs/nfs4namespace.c
fs/nfs/nfs4proc.c
fs/nfs/nfs4renewd.c
fs/nfs/nfs4xdr.c
fs/nfs/super.c
fs/nilfs2/btnode.c
fs/nilfs2/segment.c
fs/notify/dnotify/dnotify.c
fs/notify/inode_mark.c
fs/notify/notification.c
fs/partitions/check.c
fs/pipe.c
fs/proc/kcore.c
fs/proc/meminfo.c
fs/proc/page.c
fs/romfs/storage.c
fs/sysfs/dir.c
fs/sysfs/file.c
fs/xfs/linux-2.6/xfs_aops.c
fs/xfs/linux-2.6/xfs_file.c
fs/xfs/linux-2.6/xfs_iops.c
fs/xfs/linux-2.6/xfs_lrw.c
fs/xfs/linux-2.6/xfs_quotaops.c
fs/xfs/linux-2.6/xfs_super.c
fs/xfs/linux-2.6/xfs_sync.c
fs/xfs/quota/xfs_qm_syscalls.c
fs/xfs/xfs_dfrag.c
fs/xfs/xfs_dir2_leaf.c
fs/xfs/xfs_ialloc.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_vnodeops.c
include/asm-generic/hardirq.h
include/drm/drm_crtc_helper.h
include/drm/drm_fb_helper.h
include/drm/drm_pciids.h
include/linux/Kbuild
include/linux/ata.h
include/linux/blkdev.h
include/linux/cpufreq.h
include/linux/device.h
include/linux/elf.h
include/linux/ftrace.h
include/linux/futex.h
include/linux/genhd.h
include/linux/i2c/twl4030.h
include/linux/init.h
include/linux/interrupt.h
include/linux/kernel.h
include/linux/libata.h
include/linux/mmc/host.h
include/linux/moduleparam.h
include/linux/netdevice.h
include/linux/pci_ids.h
include/linux/perf_event.h
include/linux/prctl.h
include/linux/rcupdate.h
include/linux/rcutree.h
include/linux/skbuff.h
include/linux/socket.h
include/linux/string.h
include/linux/topology.h
include/linux/trace_seq.h
include/linux/usb/serial.h
include/linux/virtio_9p.h
include/linux/virtio_balloon.h
include/linux/virtio_blk.h
include/linux/virtio_console.h
include/linux/virtio_net.h
include/linux/virtio_rng.h
include/linux/workqueue.h
include/net/9p/client.h
include/net/inet_timewait_sock.h
include/net/ip_fib.h
include/net/mac80211.h
include/net/sock.h
include/pcmcia/ss.h
include/scsi/libiscsi.h
include/scsi/scsi.h
include/scsi/scsi_cmnd.h
include/scsi/scsi_host.h
init/Kconfig
init/main.c
kernel/cgroup.c
kernel/exit.c
kernel/fork.c
kernel/futex.c
kernel/hrtimer.c
kernel/irq/handle.c
kernel/lockdep.c
kernel/mutex-debug.c
kernel/panic.c
kernel/params.c
kernel/perf_event.c
kernel/power/hibernate.c
kernel/power/suspend_test.c
kernel/power/swap.c
kernel/rcupdate.c
kernel/rcutorture.c
kernel/rcutree.c
kernel/rcutree.h
kernel/rcutree_plugin.h
kernel/rcutree_trace.c
kernel/sched.c
kernel/sched_fair.c
kernel/sys.c
kernel/sysctl_check.c
kernel/time/tick-sched.c
kernel/time/timekeeping.c
kernel/trace/ftrace.c
kernel/trace/kmemtrace.c
kernel/trace/ring_buffer.c
kernel/trace/trace.c
kernel/trace/trace_branch.c
kernel/trace/trace_event_profile.c
kernel/trace/trace_events_filter.c
kernel/trace/trace_hw_branches.c
kernel/trace/trace_output.c
kernel/trace/trace_syscalls.c
kernel/workqueue.c
lib/Kconfig.debug
lib/debugobjects.c
lib/fault-inject.c
mm/Kconfig
mm/backing-dev.c
mm/kmemleak.c
mm/ksm.c
mm/memory-failure.c
mm/memory.c
mm/mempolicy.c
mm/nommu.c
mm/page-writeback.c
mm/page_alloc.c
mm/percpu.c
mm/swapfile.c
mm/vmalloc.c
mm/vmscan.c
net/9p/client.c
net/9p/trans_virtio.c
net/bluetooth/hci_sysfs.c
net/bluetooth/l2cap.c
net/core/datagram.c
net/core/net-sysfs.c
net/core/pktgen.c
net/ipv4/devinet.c
net/ipv4/fib_frontend.c
net/ipv4/inet_connection_sock.c
net/ipv4/ip_gre.c
net/ipv4/ip_sockglue.c
net/ipv4/raw.c
net/ipv4/route.c
net/ipv4/tcp.c
net/ipv4/tcp_minisocks.c
net/ipv4/udp.c
net/ipv6/ipv6_sockglue.c
net/ipv6/udp.c
net/irda/ircomm/ircomm_tty_attach.c
net/irda/irlan/irlan_common.c
net/irda/irlan/irlan_eth.c
net/irda/irnet/irnet_irda.c
net/irda/irnet/irnet_ppp.c
net/mac80211/agg-tx.c
net/mac80211/cfg.c
net/mac80211/ht.c
net/mac80211/ibss.c
net/mac80211/mesh_hwmp.c
net/mac80211/mlme.c
net/mac80211/rc80211_pid_debugfs.c
net/mac80211/rx.c
net/mac80211/sta_info.c
net/mac80211/tx.c
net/mac80211/util.c
net/netfilter/nf_conntrack_core.c
net/packet/af_packet.c
net/sched/act_pedit.c
net/sched/cls_api.c
net/sunrpc/svcsock.c
net/sunrpc/xprtrdma/svc_rdma_transport.c
net/unix/af_unix.c
net/wireless/core.c
net/wireless/core.h
net/wireless/mlme.c
net/wireless/nl80211.c
net/wireless/sme.c
scripts/Kbuild.include
scripts/Makefile.lib
scripts/checkkconfigsymbols.sh
scripts/checkpatch.pl
scripts/get_maintainer.pl
scripts/headers_install.pl
scripts/mkcompile_h
scripts/package/Makefile
scripts/package/mkspec
security/keys/keyctl.c
sound/pci/hda/hda_intel.c
sound/pci/hda/patch_realtek.c
sound/ppc/Kconfig
sound/soc/omap/Kconfig
sound/soc/omap/omap-pcm.c
sound/soc/s3c24xx/s3c24xx-pcm.c
sound/soc/s3c24xx/s3c64xx-i2s.c
sound/soc/soc-core.c
sound/soc/soc-dapm.c
tools/perf/Documentation/perf-timechart.txt
tools/perf/Makefile
tools/perf/builtin-record.c
tools/perf/builtin-sched.c
tools/perf/builtin-stat.c
tools/perf/builtin-timechart.c
tools/perf/builtin-top.c
tools/perf/builtin-trace.c
tools/perf/design.txt
tools/perf/util/PERF-VERSION-GEN
tools/perf/util/parse-events.c
tools/perf/util/svghelper.c
tools/perf/util/symbol.c
tools/perf/util/symbol.h
tools/perf/util/trace-event-parse.c
virt/kvm/kvm_main.c

@@ -1,4 +1,4 @@
-What:           /sys/class/usb_host/usb_hostN/wusb_chid
+What:           /sys/class/uwb_rc/uwbN/wusbhc/wusb_chid
 Date:           July 2008
 KernelVersion:  2.6.27
 Contact:        David Vrabel <david.vrabel@csr.com>
@@ -9,7 +9,7 @@ Description:
 
                 Set an all zero CHID to stop the host controller.
 
-What:           /sys/class/usb_host/usb_hostN/wusb_trust_timeout
+What:           /sys/class/uwb_rc/uwbN/wusbhc/wusb_trust_timeout
 Date:           July 2008
 KernelVersion:  2.6.27
 Contact:        David Vrabel <david.vrabel@csr.com>
diff --git a/Documentation/ABI/testing/sysfs-devices-cache_disable b/Documentation/ABI/testing/sysfs-devices-cache_disable
deleted file mode 100644 (file)
index 175bb4f..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-What:      /sys/devices/system/cpu/cpu*/cache/index*/cache_disable_X
-Date:      August 2008
-KernelVersion: 2.6.27
-Contact:       mark.langsdorf@amd.com
-Description:   These files exist in every cpu's cache index directories.
-               There are currently 2 cache_disable_# files in each
-               directory.  Reading from these files on a supported
-               processor will return that cache disable index value
-               for that processor and node.  Writing to one of these
-               files will cause the specificed cache index to be disabled.
-
-               Currently, only AMD Family 10h Processors support cache index
-               disable, and only for their L3 caches.  See the BIOS and
-               Kernel Developer's Guide at
-               http://www.amd.com/us-en/assets/content_type/white_papers_and_tech_docs/31116-Public-GH-BKDG_3.20_2-4-09.pdf
-               for formatting information and other details on the
-               cache index disable.
-Users:    joachim.deguara@amd.com
diff --git a/Documentation/ABI/testing/sysfs-devices-system-cpu b/Documentation/ABI/testing/sysfs-devices-system-cpu
new file mode 100644 (file)
index 0000000..a703b9e
--- /dev/null
@@ -0,0 +1,156 @@
+What:          /sys/devices/system/cpu/
+Date:          pre-git history
+Contact:       Linux kernel mailing list <linux-kernel@vger.kernel.org>
+Description:
+               A collection of both global and individual CPU attributes
+
+               Individual CPU attributes are contained in subdirectories
+               named by the kernel's logical CPU number, e.g.:
+
+               /sys/devices/system/cpu/cpu#/
+
+What:          /sys/devices/system/cpu/sched_mc_power_savings
+               /sys/devices/system/cpu/sched_smt_power_savings
+Date:          June 2006
+Contact:       Linux kernel mailing list <linux-kernel@vger.kernel.org>
+Description:   Discover and adjust the kernel's multi-core scheduler support.
+
+               Possible values are:
+
+               0 - No power saving load balance (default value)
+               1 - Fill one thread/core/package first for long running threads
+               2 - Also bias task wakeups to semi-idle cpu package for power
+                   savings
+
+               sched_mc_power_savings is dependent upon SCHED_MC, which is
+               itself architecture dependent.
+
+               sched_smt_power_savings is dependent upon SCHED_SMT, which
+               is itself architecture dependent.
+
+               The two files are independent of each other. It is possible
+               that one file may be present without the other.
+
+               Introduced by git commit 5c45bf27.
+
+
+What:          /sys/devices/system/cpu/kernel_max
+               /sys/devices/system/cpu/offline
+               /sys/devices/system/cpu/online
+               /sys/devices/system/cpu/possible
+               /sys/devices/system/cpu/present
+Date:          December 2008
+Contact:       Linux kernel mailing list <linux-kernel@vger.kernel.org>
+Description:   CPU topology files that describe kernel limits related to
+               hotplug. Briefly:
+
+               kernel_max: the maximum cpu index allowed by the kernel
+               configuration.
+
+               offline: cpus that are not online because they have been
+               HOTPLUGGED off or exceed the limit of cpus allowed by the
+               kernel configuration (kernel_max above).
+
+               online: cpus that are online and being scheduled.
+
+               possible: cpus that have been allocated resources and can be
+               brought online if they are present.
+
+               present: cpus that have been identified as being present in
+               the system.
+
+               See Documentation/cputopology.txt for more information.
+
+
+
+What:          /sys/devices/system/cpu/cpu#/node
+Date:          October 2009
+Contact:       Linux memory management mailing list <linux-mm@kvack.org>
+Description:   Discover NUMA node a CPU belongs to
+
+               When CONFIG_NUMA is enabled, a symbolic link that points
+               to the corresponding NUMA node directory.
+
+               For example, the following symlink is created for cpu42
+               in NUMA node 2:
+
+               /sys/devices/system/cpu/cpu42/node2 -> ../../node/node2
+
+
+What:          /sys/devices/system/cpu/cpu#/topology/core_id
+               /sys/devices/system/cpu/cpu#/topology/core_siblings
+               /sys/devices/system/cpu/cpu#/topology/core_siblings_list
+               /sys/devices/system/cpu/cpu#/topology/physical_package_id
+               /sys/devices/system/cpu/cpu#/topology/thread_siblings
+               /sys/devices/system/cpu/cpu#/topology/thread_siblings_list
+Date:          December 2008
+Contact:       Linux kernel mailing list <linux-kernel@vger.kernel.org>
+Description:   CPU topology files that describe a logical CPU's relationship
+               to other cores and threads in the same physical package.
+
+               One cpu# directory is created per logical CPU in the system,
+               e.g. /sys/devices/system/cpu/cpu42/.
+
+               Briefly, the files above are:
+
+               core_id: the CPU core ID of cpu#. Typically it is the
+               hardware platform's identifier (rather than the kernel's).
+               The actual value is architecture and platform dependent.
+
+               core_siblings: internal kernel map of cpu#'s hardware threads
+               within the same physical_package_id.
+
+               core_siblings_list: human-readable list of the logical CPU
+               numbers within the same physical_package_id as cpu#.
+
+               physical_package_id: physical package id of cpu#. Typically
+               corresponds to a physical socket number, but the actual value
+               is architecture and platform dependent.
+
+               thread_siblings: internel kernel map of cpu#'s hardware
+               threads within the same core as cpu#
+
+               thread_siblings_list: human-readable list of cpu#'s hardware
+               threads within the same core as cpu#
+
+               See Documentation/cputopology.txt for more information.
+
+
+What:          /sys/devices/system/cpu/cpuidle/current_driver
+               /sys/devices/system/cpu/cpuidle/current_governer_ro
+Date:          September 2007
+Contact:       Linux kernel mailing list <linux-kernel@vger.kernel.org>
+Description:   Discover cpuidle policy and mechanism
+
+               Various CPUs today support multiple idle levels that are
+               differentiated by varying exit latencies and power
+               consumption during idle.
+
+               Idle policy (governor) is differentiated from idle mechanism
+               (driver)
+
+               current_driver: displays current idle mechanism
+
+               current_governor_ro: displays current idle policy
+
+               See files in Documentation/cpuidle/ for more information.
+
+
+What:      /sys/devices/system/cpu/cpu*/cache/index*/cache_disable_X
+Date:      August 2008
+KernelVersion: 2.6.27
+Contact:       mark.langsdorf@amd.com
+Description:   These files exist in every cpu's cache index directories.
+               There are currently 2 cache_disable_# files in each
+               directory.  Reading from these files on a supported
+               processor will return that cache disable index value
+               for that processor and node.  Writing to one of these
+               files will cause the specificed cache index to be disabled.
+
+               Currently, only AMD Family 10h Processors support cache index
+               disable, and only for their L3 caches.  See the BIOS and
+               Kernel Developer's Guide at
+               http://www.amd.com/us-en/assets/content_type/white_papers_and_tech_docs/31116-Public-GH-BKDG_3.20_2-4-09.pdf
+               for formatting information and other details on the
+               cache index disable.
+Users:    joachim.deguara@amd.com
index 455d4e6..0b33bfe 100644 (file)
@@ -227,7 +227,14 @@ as the path relative to the root of the cgroup file system.
 Each cgroup is represented by a directory in the cgroup file system
 containing the following files describing that cgroup:
 
- - tasks: list of tasks (by pid) attached to that cgroup
+ - tasks: list of tasks (by pid) attached to that cgroup.  This list
+   is not guaranteed to be sorted.  Writing a thread id into this file
+   moves the thread into this cgroup.
+ - cgroup.procs: list of tgids in the cgroup.  This list is not
+   guaranteed to be sorted or free of duplicate tgids, and userspace
+   should sort/uniquify the list if this property is required.
+   Writing a tgid into this file moves all threads with that tgid into
+   this cgroup.
  - notify_on_release flag: run the release agent on exit?
  - release_agent: the path to use for release notifications (this file
    exists in the top cgroup only)
@@ -374,7 +381,7 @@ Now you want to do something with this cgroup.
 
 In this directory you can find several files:
 # ls
-notify_on_release tasks
+cgroup.procs notify_on_release tasks
 (plus whatever files added by the attached subsystems)
 
 Now attach your shell to this cgroup:
index b41f3e5..f1c5c4b 100644 (file)
@@ -1,15 +1,28 @@
 
-Export cpu topology info via sysfs. Items (attributes) are similar
+Export CPU topology info via sysfs. Items (attributes) are similar
 to /proc/cpuinfo.
 
 1) /sys/devices/system/cpu/cpuX/topology/physical_package_id:
-represent the physical package id of  cpu X;
+
+       physical package id of cpuX. Typically corresponds to a physical
+       socket number, but the actual value is architecture and platform
+       dependent.
+
 2) /sys/devices/system/cpu/cpuX/topology/core_id:
-represent the cpu core id to cpu X;
+
+       the CPU core ID of cpuX. Typically it is the hardware platform's
+       identifier (rather than the kernel's).  The actual value is
+       architecture and platform dependent.
+
 3) /sys/devices/system/cpu/cpuX/topology/thread_siblings:
-represent the thread siblings to cpu X in the same core;
+
+       internel kernel map of cpuX's hardware threads within the same
+       core as cpuX
+
 4) /sys/devices/system/cpu/cpuX/topology/core_siblings:
-represent the thread siblings to cpu X in the same physical package;
+
+       internal kernel map of cpuX's hardware threads within the same
+       physical_package_id.
 
 To implement it in an architecture-neutral way, a new source file,
 drivers/base/topology.c, is to export the 4 attributes.
@@ -32,32 +45,32 @@ not defined by include/asm-XXX/topology.h:
 3) thread_siblings: just the given CPU
 4) core_siblings: just the given CPU
 
-Additionally, cpu topology information is provided under
+Additionally, CPU topology information is provided under
 /sys/devices/system/cpu and includes these files.  The internal
 source for the output is in brackets ("[]").
 
-    kernel_max: the maximum cpu index allowed by the kernel configuration.
+    kernel_max: the maximum CPU index allowed by the kernel configuration.
                [NR_CPUS-1]
 
-    offline:   cpus that are not online because they have been
+    offline:   CPUs that are not online because they have been
                HOTPLUGGED off (see cpu-hotplug.txt) or exceed the limit
-               of cpus allowed by the kernel configuration (kernel_max
+               of CPUs allowed by the kernel configuration (kernel_max
                above). [~cpu_online_mask + cpus >= NR_CPUS]
 
-    online:    cpus that are online and being scheduled [cpu_online_mask]
+    online:    CPUs that are online and being scheduled [cpu_online_mask]
 
-    possible:  cpus that have been allocated resources and can be
+    possible:  CPUs that have been allocated resources and can be
                brought online if they are present. [cpu_possible_mask]
 
-    present:   cpus that have been identified as being present in the
+    present:   CPUs that have been identified as being present in the
                system. [cpu_present_mask]
 
 The format for the above output is compatible with cpulist_parse()
 [see <linux/cpumask.h>].  Some examples follow.
 
-In this example, there are 64 cpus in the system but cpus 32-63 exceed
+In this example, there are 64 CPUs in the system but cpus 32-63 exceed
 the kernel max which is limited to 0..31 by the NR_CPUS config option
-being 32.  Note also that cpus 2 and 4-31 are not online but could be
+being 32.  Note also that CPUs 2 and 4-31 are not online but could be
 brought online as they are both present and possible.
 
      kernel_max: 31
@@ -67,8 +80,8 @@ brought online as they are both present and possible.
         present: 0-31
 
 In this example, the NR_CPUS config option is 128, but the kernel was
-started with possible_cpus=144.  There are 4 cpus in the system and cpu2
-was manually taken offline (and is the only cpu that can be brought
+started with possible_cpus=144.  There are 4 CPUs in the system and cpu2
+was manually taken offline (and is the only CPU that can be brought
 online.)
 
      kernel_max: 127
@@ -78,4 +91,4 @@ online.)
         present: 0-3
 
 See cpu-hotplug.txt for the possible_cpus=NUM kernel start parameter
-as well as more information on the various cpumask's.
+as well as more information on the various cpumasks.
index 59a91e5..611f5a5 100644 (file)
@@ -64,14 +64,14 @@ be used to view the printk buffer of a remote machine, even with live update.
 
 Bernhard Kaindl enhanced firescope to support accessing 64-bit machines
 from 32-bit firescope and vice versa:
-- ftp://ftp.suse.de/private/bk/firewire/tools/firescope-0.2.2.tar.bz2
+- http://halobates.de/firewire/firescope-0.2.2.tar.bz2
 
 and he implemented fast system dump (alpha version - read README.txt):
-- ftp://ftp.suse.de/private/bk/firewire/tools/firedump-0.1.tar.bz2
+- http://halobates.de/firewire/firedump-0.1.tar.bz2
 
 There is also a gdb proxy for firewire which allows to use gdb to access
 data which can be referenced from symbols found by gdb in vmlinux:
-- ftp://ftp.suse.de/private/bk/firewire/tools/fireproxy-0.33.tar.bz2
+- http://halobates.de/firewire/fireproxy-0.33.tar.bz2
 
 The latest version of this gdb proxy (fireproxy-0.34) can communicate (not
 yet stable) with kgdb over an memory-based communication module (kgdbom).
@@ -178,7 +178,7 @@ Step-by-step instructions for using firescope with early OHCI initialization:
 
 Notes
 -----
-Documentation and specifications: ftp://ftp.suse.de/private/bk/firewire/docs
+Documentation and specifications: http://halobates.de/firewire/
 
 FireWire is a trademark of Apple Inc. - for more information please refer to:
 http://en.wikipedia.org/wiki/FireWire
index 89a47b5..bc693ff 100644 (file)
@@ -418,6 +418,14 @@ When:      2.6.33
 Why:   Should be implemented in userspace, policy daemon.
 Who:   Johannes Berg <johannes@sipsolutions.net>
 
+---------------------------
+
+What:  CONFIG_INOTIFY
+When:  2.6.33
+Why:   last user (audit) will be converted to the newer more generic
+       and more easily maintained fsnotify subsystem
+Who:   Eric Paris <eparis@redhat.com>
+
 ----------------------------
 
 What:  lock_policy_rwsem_* and unlock_policy_rwsem_* will not be
@@ -451,3 +459,33 @@ Why:       OSS sound_core grabs all legacy minors (0-255) of SOUND_MAJOR
        will also allow making ALSA OSS emulation independent of
        sound_core.  The dependency will be broken then too.
 Who:   Tejun Heo <tj@kernel.org>
+
+----------------------------
+
+What:  Support for VMware's guest paravirtuliazation technique [VMI] will be
+       dropped.
+When:  2.6.37 or earlier.
+Why:   With the recent innovations in CPU hardware acceleration technologies
+       from Intel and AMD, VMware ran a few experiments to compare these
+       techniques to guest paravirtualization technique on VMware's platform.
+       These hardware assisted virtualization techniques have outperformed the
+       performance benefits provided by VMI in most of the workloads. VMware
+       expects that these hardware features will be ubiquitous in a couple of
+       years, as a result, VMware has started a phased retirement of this
+       feature from the hypervisor. We will be removing this feature from the
+       Kernel too. Right now we are targeting 2.6.37 but can retire earlier if
+       technical reasons (read opportunity to remove major chunk of pvops)
+       arise.
+
+       Please note that VMI has always been an optimization and non-VMI kernels
+       still work fine on VMware's platform.
+       Latest versions of VMware's product which support VMI are,
+       Workstation 7.0 and VSphere 4.0 on ESX side, future maintainence
+       releases for these products will continue supporting VMI.
+
+       For more details about VMI retirement take a look at this,
+       http://blogs.vmware.com/guestosguide/2009/09/vmi-retirement.html
+
+Who:   Alok N Kataria <akataria@vmware.com>
+
+----------------------------
index 570f9bd..05d5cf1 100644 (file)
@@ -123,10 +123,18 @@ resuid=n          The user ID which may use the reserved blocks.
 
 sb=n                   Use alternate superblock at this location.
 
-quota
-noquota
-grpquota
-usrquota
+quota                  These options are ignored by the filesystem. They
+noquota                        are used only by quota tools to recognize volumes
+grpquota               where quota should be turned on. See documentation
+usrquota               in the quota-tools package for more details
+                       (http://sourceforge.net/projects/linuxquota).
+
+jqfmt=<quota type>     These options tell filesystem details about quota
+usrjquota=<file>       so that quota information can be properly updated
+grpjquota=<file>       during journal replay. They replace the above
+                       quota options. See documentation in the quota-tools
+                       package for more details
+                       (http://sourceforge.net/projects/linuxquota).
 
 bh             (*)     ext3 associates buffer heads to data pages to
 nobh                   (a) cache disk block mapping information
index bf4f4b7..6d94e06 100644 (file)
@@ -134,9 +134,15 @@ ro                         Mount filesystem read only. Note that ext4 will
                        mount options "ro,noload" can be used to prevent
                        writes to the filesystem.
 
+journal_checksum       Enable checksumming of the journal transactions.
+                       This will allow the recovery code in e2fsck and the
+                       kernel to detect corruption in the kernel.  It is a
+                       compatible change and will be ignored by older kernels.
+
 journal_async_commit   Commit block can be written to disk without waiting
                        for descriptor blocks. If enabled older kernels cannot
-                       mount the device.
+                       mount the device. This will enable 'journal_checksum'
+                       internally.
 
 journal=update         Update the ext4 file system's journal to the current
                        format.
index 84eb268..cb8a3a0 100644 (file)
@@ -1,5 +1,5 @@
 Using flexible arrays in the kernel
-Last updated for 2.6.31
+Last updated for 2.6.32
 Jonathan Corbet <corbet@lwn.net>
 
 Large contiguous memory allocations can be unreliable in the Linux kernel.
@@ -40,6 +40,13 @@ argument is passed directly to the internal memory allocation calls.  With
 the current code, using flags to ask for high memory is likely to lead to
 notably unpleasant side effects.
 
+It is also possible to define flexible arrays at compile time with:
+
+    DEFINE_FLEX_ARRAY(name, element_size, total);
+
+This macro will result in a definition of an array with the given name; the
+element size and total will be checked for validity at compile time.
+
 Storing data into a flexible array is accomplished with a call to:
 
     int flex_array_put(struct flex_array *array, unsigned int element_nr,
@@ -76,16 +83,30 @@ particular element has never been allocated.
 Note that it is possible to get back a valid pointer for an element which
 has never been stored in the array.  Memory for array elements is allocated
 one page at a time; a single allocation could provide memory for several
-adjacent elements.  The flexible array code does not know if a specific
-element has been written; it only knows if the associated memory is
-present.  So a flex_array_get() call on an element which was never stored
-in the array has the potential to return a pointer to random data.  If the
-caller does not have a separate way to know which elements were actually
-stored, it might be wise, at least, to add GFP_ZERO to the flags argument
-to ensure that all elements are zeroed.
-
-There is no way to remove a single element from the array.  It is possible,
-though, to remove all elements with a call to:
+adjacent elements.  Flexible array elements are normally initialized to the
+value FLEX_ARRAY_FREE (defined as 0x6c in <linux/poison.h>), so errors
+involving that number probably result from use of unstored array entries.
+Note that, if array elements are allocated with __GFP_ZERO, they will be
+initialized to zero and this poisoning will not happen.
+
+Individual elements in the array can be cleared with:
+
+    int flex_array_clear(struct flex_array *array, unsigned int element_nr);
+
+This function will set the given element to FLEX_ARRAY_FREE and return
+zero.  If storage for the indicated element is not allocated for the array,
+flex_array_clear() will return -EINVAL instead.  Note that clearing an
+element does not release the storage associated with it; to reduce the
+allocated size of an array, call:
+
+    int flex_array_shrink(struct flex_array *array);
+
+The return value will be the number of pages of memory actually freed.
+This function works by scanning the array for pages containing nothing but
+FLEX_ARRAY_FREE bytes, so (1) it can be expensive, and (2) it will not work
+if the array's pages are allocated with __GFP_ZERO.
+
+It is possible to remove all elements of an array with a call to:
 
     void flex_array_free_parts(struct flex_array *array);
 
index dcbd502..82def88 100644 (file)
@@ -353,10 +353,20 @@ power[1-*]_average                Average power use
                                Unit: microWatt
                                RO
 
-power[1-*]_average_interval    Power use averaging interval
+power[1-*]_average_interval    Power use averaging interval.  A poll
+                               notification is sent to this file if the
+                               hardware changes the averaging interval.
                                Unit: milliseconds
                                RW
 
+power[1-*]_average_interval_max        Maximum power use averaging interval
+                               Unit: milliseconds
+                               RO
+
+power[1-*]_average_interval_min        Minimum power use averaging interval
+                               Unit: milliseconds
+                               RO
+
 power[1-*]_average_highest     Historical average maximum power use
                                Unit: microWatt
                                RO
@@ -365,6 +375,18 @@ power[1-*]_average_lowest  Historical average minimum power use
                                Unit: microWatt
                                RO
 
+power[1-*]_average_max         A poll notification is sent to
+                               power[1-*]_average when power use
+                               rises above this value.
+                               Unit: microWatt
+                               RW
+
+power[1-*]_average_min         A poll notification is sent to
+                               power[1-*]_average when power use
+                               sinks below this value.
+                               Unit: microWatt
+                               RW
+
 power[1-*]_input               Instantaneous power use
                                Unit: microWatt
                                RO
@@ -381,6 +403,39 @@ power[1-*]_reset_history   Reset input_highest, input_lowest,
                                average_highest and average_lowest.
                                WO
 
+power[1-*]_accuracy            Accuracy of the power meter.
+                               Unit: Percent
+                               RO
+
+power[1-*]_alarm               1 if the system is drawing more power than the
+                               cap allows; 0 otherwise.  A poll notification is
+                               sent to this file when the power use exceeds the
+                               cap.  This file only appears if the cap is known
+                               to be enforced by hardware.
+                               RO
+
+power[1-*]_cap                 If power use rises above this limit, the
+                               system should take action to reduce power use.
+                               A poll notification is sent to this file if the
+                               cap is changed by the hardware.  The *_cap
+                               files only appear if the cap is known to be
+                               enforced by hardware.
+                               Unit: microWatt
+                               RW
+
+power[1-*]_cap_hyst            Margin of hysteresis built around capping and
+                               notification.
+                               Unit: microWatt
+                               RW
+
+power[1-*]_cap_max             Maximum cap that can be set.
+                               Unit: microWatt
+                               RO
+
+power[1-*]_cap_min             Minimum cap that can be set.
+                               Unit: microWatt
+                               RO
+
 **********
 * Energy *
 **********
index 744687d..8a36695 100644 (file)
@@ -128,8 +128,8 @@ Setting IsSM Capability Bit
   To create the appropriate character device files automatically with
   udev, a rule like
 
-    KERNEL="umad*", NAME="infiniband/%k"
-    KERNEL="issm*", NAME="infiniband/%k"
+    KERNEL=="umad*", NAME="infiniband/%k"
+    KERNEL=="issm*", NAME="infiniband/%k"
 
   can be used.  This will create device nodes named
 
index f847501..afe3f8d 100644 (file)
@@ -58,7 +58,7 @@ Memory pinning
   To create the appropriate character device files automatically with
   udev, a rule like
 
-    KERNEL="uverbs*", NAME="infiniband/%k"
+    KERNEL=="uverbs*", NAME="infiniband/%k"
 
   can be used.  This will create device nodes named
 
index 686e107..5fe8de5 100644 (file)
@@ -60,10 +60,9 @@ open() operation on regular files or character devices.
 
 After a successful return from register_appl(), CAPI messages from the
 application may be passed to the driver for the device via calls to the
-send_message() callback function. The CAPI message to send is stored in the
-data portion of an skb. Conversely, the driver may call Kernel CAPI's
-capi_ctr_handle_message() function to pass a received CAPI message to Kernel
-CAPI for forwarding to an application, specifying its ApplID.
+send_message() callback function. Conversely, the driver may call Kernel
+CAPI's capi_ctr_handle_message() function to pass a received CAPI message to
+Kernel CAPI for forwarding to an application, specifying its ApplID.
 
 Deregistration requests (CAPI operation CAPI_RELEASE) from applications are
 forwarded as calls to the release_appl() callback function, passing the same
@@ -142,6 +141,7 @@ u16  (*send_message)(struct capi_ctr *ctrlr, struct sk_buff *skb)
        to accepting or queueing the message. Errors occurring during the
        actual processing of the message should be signaled with an
        appropriate reply message.
+       May be called in process or interrupt context.
        Calls to this function are not serialized by Kernel CAPI, ie. it must
        be prepared to be re-entered.
 
@@ -154,7 +154,8 @@ read_proc_t *ctr_read_proc
        system entry, /proc/capi/controllers/<n>; will be called with a
        pointer to the device's capi_ctr structure as the last (data) argument
 
-Note: Callback functions are never called in interrupt context.
+Note: Callback functions except send_message() are never called in interrupt
+context.
 
 - to be filled in before calling capi_ctr_ready():
 
@@ -171,14 +172,40 @@ u8 serial[CAPI_SERIAL_LEN]
        value to return for CAPI_GET_SERIAL
 
 
-4.3 The _cmsg Structure
+4.3 SKBs
+
+CAPI messages are passed between Kernel CAPI and the driver via send_message()
+and capi_ctr_handle_message(), stored in the data portion of a socket buffer
+(skb).  Each skb contains a single CAPI message coded according to the CAPI 2.0
+standard.
+
+For the data transfer messages, DATA_B3_REQ and DATA_B3_IND, the actual
+payload data immediately follows the CAPI message itself within the same skb.
+The Data and Data64 parameters are not used for processing. The Data64
+parameter may be omitted by setting the length field of the CAPI message to 22
+instead of 30.
+
+
+4.4 The _cmsg Structure
 
 (declared in <linux/isdn/capiutil.h>)
 
 The _cmsg structure stores the contents of a CAPI 2.0 message in an easily
-accessible form. It contains members for all possible CAPI 2.0 parameters, of
-which only those appearing in the message type currently being processed are
-actually used. Unused members should be set to zero.
+accessible form. It contains members for all possible CAPI 2.0 parameters,
+including subparameters of the Additional Info and B Protocol structured
+parameters, with the following exceptions:
+
+* second Calling party number (CONNECT_IND)
+
+* Data64 (DATA_B3_REQ and DATA_B3_IND)
+
+* Sending complete (subparameter of Additional Info, CONNECT_REQ and INFO_REQ)
+
+* Global Configuration (subparameter of B Protocol, CONNECT_REQ, CONNECT_RESP
+  and SELECT_B_PROTOCOL_REQ)
+
+Only those parameters appearing in the message type currently being processed
+are actually used. Unused members should be set to zero.
 
 Members are named after the CAPI 2.0 standard names of the parameters they
 represent. See <linux/isdn/capiutil.h> for the exact spelling. Member data
@@ -190,18 +217,19 @@ u16         for CAPI parameters of type 'word'
 
 u32         for CAPI parameters of type 'dword'
 
-_cstruct    for CAPI parameters of type 'struct' not containing any
-           variably-sized (struct) subparameters (eg. 'Called Party Number')
+_cstruct    for CAPI parameters of type 'struct'
            The member is a pointer to a buffer containing the parameter in
            CAPI encoding (length + content). It may also be NULL, which will
            be taken to represent an empty (zero length) parameter.
+           Subparameters are stored in encoded form within the content part.
 
-_cmstruct   for CAPI parameters of type 'struct' containing 'struct'
-           subparameters ('Additional Info' and 'B Protocol')
+_cmstruct   alternative representation for CAPI parameters of type 'struct'
+           (used only for the 'Additional Info' and 'B Protocol' parameters)
            The representation is a single byte containing one of the values:
-           CAPI_DEFAULT: the parameter is empty
-           CAPI_COMPOSE: the values of the subparameters are stored
-           individually in the corresponding _cmsg structure members
+           CAPI_DEFAULT: The parameter is empty/absent.
+           CAPI_COMPOSE: The parameter is present.
+           Subparameter values are stored individually in the corresponding
+           _cmsg structure members.
 
 Functions capi_cmsg2message() and capi_message2cmsg() are provided to convert
 messages between their transport encoding described in the CAPI 2.0 standard
@@ -297,3 +325,26 @@ char *capi_cmd2str(u8 Command, u8 Subcommand)
        be NULL if the command/subcommand is not one of those defined in the
        CAPI 2.0 standard.
 
+
+7. Debugging
+
+The module kernelcapi has a module parameter showcapimsgs controlling some
+debugging output produced by the module. It can only be set when the module is
+loaded, via a parameter "showcapimsgs=<n>" to the modprobe command, either on
+the command line or in the configuration file.
+
+If the lowest bit of showcapimsgs is set, kernelcapi logs controller and
+application up and down events.
+
+In addition, every registered CAPI controller has an associated traceflag
+parameter controlling how CAPI messages sent from and to tha controller are
+logged. The traceflag parameter is initialized with the value of the
+showcapimsgs parameter when the controller is registered, but can later be
+changed via the MANUFACTURER_REQ command KCAPI_CMD_TRACE.
+
+If the value of traceflag is non-zero, CAPI messages are logged.
+DATA_B3 messages are only logged if the value of traceflag is > 2.
+
+If the lowest bit of traceflag is set, only the command/subcommand and message
+length are logged. Otherwise, kernelcapi logs a readable representation of
+the entire message.
index 6fa7292..9107b38 100644 (file)
@@ -671,6 +671,7 @@ and is between 256 and 4096 characters. It is defined in the file
        earlyprintk=    [X86,SH,BLACKFIN]
                        earlyprintk=vga
                        earlyprintk=serial[,ttySn[,baudrate]]
+                       earlyprintk=ttySn[,baudrate]
                        earlyprintk=dbgp[debugController#]
 
                        Append ",keep" to not disable it when the real console
index ba9373f..098de5b 100644 (file)
@@ -42,7 +42,6 @@
 #include <signal.h>
 #include "linux/lguest_launcher.h"
 #include "linux/virtio_config.h"
-#include <linux/virtio_ids.h>
 #include "linux/virtio_net.h"
 #include "linux/virtio_blk.h"
 #include "linux/virtio_console.h"
index c6cf4a3..61bb645 100644 (file)
@@ -90,6 +90,11 @@ Examples:
  pgset "dstmac 00:00:00:00:00:00"    sets MAC destination address
  pgset "srcmac 00:00:00:00:00:00"    sets MAC source address
 
+ pgset "queue_map_min 0" Sets the min value of tx queue interval
+ pgset "queue_map_max 7" Sets the max value of tx queue interval, for multiqueue devices
+                         To select queue 1 of a given device,
+                         use queue_map_min=1 and queue_map_max=1
+
  pgset "src_mac_count 1" Sets the number of MACs we'll range through.  
                          The 'minimum' MAC is what you set with srcmac.
 
@@ -101,6 +106,9 @@ Examples:
                               IPDST_RND, UDPSRC_RND,
                               UDPDST_RND, MACSRC_RND, MACDST_RND 
                               MPLS_RND, VID_RND, SVID_RND
+                              QUEUE_MAP_RND # queue map random
+                              QUEUE_MAP_CPU # queue map mirrors smp_processor_id()
+
 
  pgset "udp_src_min 9"   set UDP source port min, If < udp_src_max, then
                          cycle through the port range.
index a6eb4ad..9605179 100644 (file)
@@ -3,6 +3,25 @@ HIGHPOINT ROCKETRAID 3xxx/4xxx ADAPTER DRIVER (hptiop)
 Controller Register Map
 -------------------------
 
+For RR44xx Intel IOP based adapters, the controller IOP is accessed via PCI BAR0 and BAR2:
+
+     BAR0 offset    Register
+            0x11C5C Link Interface IRQ Set
+            0x11C60 Link Interface IRQ Clear
+
+     BAR2 offset    Register
+            0x10    Inbound Message Register 0
+            0x14    Inbound Message Register 1
+            0x18    Outbound Message Register 0
+            0x1C    Outbound Message Register 1
+            0x20    Inbound Doorbell Register
+            0x24    Inbound Interrupt Status Register
+            0x28    Inbound Interrupt Mask Register
+            0x30    Outbound Interrupt Status Register
+            0x34    Outbound Interrupt Mask Register
+            0x40    Inbound Queue Port
+            0x44    Outbound Queue Port
+
 For Intel IOP based adapters, the controller IOP is accessed via PCI BAR0:
 
      BAR0 offset    Register
@@ -93,7 +112,7 @@ The driver exposes following sysfs attributes:
 
 
 -----------------------------------------------------------------------------
-Copyright (C) 2006-2007 HighPoint Technologies, Inc. All Rights Reserved.
+Copyright (C) 2006-2009 HighPoint Technologies, Inc. All Rights Reserved.
 
   This file is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
index 957b22f..8179692 100644 (file)
@@ -1231,6 +1231,7 @@ something like this simple program:
 #include <sys/stat.h>
 #include <fcntl.h>
 #include <unistd.h>
+#include <string.h>
 
 #define _STR(x) #x
 #define STR(x) _STR(x)
@@ -1265,6 +1266,7 @@ const char *find_debugfs(void)
                return NULL;
        }
 
+       strcat(debugfs, "/tracing/");
        debugfs_found = 1;
 
        return debugfs;
diff --git a/Documentation/vm/hwpoison.txt b/Documentation/vm/hwpoison.txt
new file mode 100644 (file)
index 0000000..3ffadf8
--- /dev/null
@@ -0,0 +1,136 @@
+What is hwpoison?
+
+Upcoming Intel CPUs have support for recovering from some memory errors
+(``MCA recovery''). This requires the OS to declare a page "poisoned",
+kill the processes associated with it and avoid using it in the future.
+
+This patchkit implements the necessary infrastructure in the VM.
+
+To quote the overview comment:
+
+ * High level machine check handler. Handles pages reported by the
+ * hardware as being corrupted usually due to a 2bit ECC memory or cache
+ * failure.
+ *
+ * This focusses on pages detected as corrupted in the background.
+ * When the current CPU tries to consume corruption the currently
+ * running process can just be killed directly instead. This implies
+ * that if the error cannot be handled for some reason it's safe to
+ * just ignore it because no corruption has been consumed yet. Instead
+ * when that happens another machine check will happen.
+ *
+ * Handles page cache pages in various states. The tricky part
+ * here is that we can access any page asynchronous to other VM
+ * users, because memory failures could happen anytime and anywhere,
+ * possibly violating some of their assumptions. This is why this code
+ * has to be extremely careful. Generally it tries to use normal locking
+ * rules, as in get the standard locks, even if that means the
+ * error handling takes potentially a long time.
+ *
+ * Some of the operations here are somewhat inefficient and have non
+ * linear algorithmic complexity, because the data structures have not
+ * been optimized for this case. This is in particular the case
+ * for the mapping from a vma to a process. Since this case is expected
+ * to be rare we hope we can get away with this.
+
+The code consists of a the high level handler in mm/memory-failure.c,
+a new page poison bit and various checks in the VM to handle poisoned
+pages.
+
+The main target right now is KVM guests, but it works for all kinds
+of applications. KVM support requires a recent qemu-kvm release.
+
+For the KVM use there was need for a new signal type so that
+KVM can inject the machine check into the guest with the proper
+address. This in theory allows other applications to handle
+memory failures too. The expection is that near all applications
+won't do that, but some very specialized ones might.
+
+---
+
+There are two (actually three) modi memory failure recovery can be in:
+
+vm.memory_failure_recovery sysctl set to zero:
+       All memory failures cause a panic. Do not attempt recovery.
+       (on x86 this can be also affected by the tolerant level of the
+       MCE subsystem)
+
+early kill
+       (can be controlled globally and per process)
+       Send SIGBUS to the application as soon as the error is detected
+       This allows applications who can process memory errors in a gentle
+       way (e.g. drop affected object)
+       This is the mode used by KVM qemu.
+
+late kill
+       Send SIGBUS when the application runs into the corrupted page.
+       This is best for memory error unaware applications and default
+       Note some pages are always handled as late kill.
+
+---
+
+User control:
+
+vm.memory_failure_recovery
+       See sysctl.txt
+
+vm.memory_failure_early_kill
+       Enable early kill mode globally
+
+PR_MCE_KILL
+       Set early/late kill mode/revert to system default
+       arg1: PR_MCE_KILL_CLEAR: Revert to system default
+       arg1: PR_MCE_KILL_SET: arg2 defines thread specific mode
+               PR_MCE_KILL_EARLY: Early kill
+               PR_MCE_KILL_LATE:  Late kill
+               PR_MCE_KILL_DEFAULT: Use system global default
+PR_MCE_KILL_GET
+       return current mode
+
+
+---
+
+Testing:
+
+madvise(MADV_POISON, ....)
+       (as root)
+       Poison a page in the process for testing
+
+
+hwpoison-inject module through debugfs
+       /sys/debug/hwpoison/corrupt-pfn
+
+Inject hwpoison fault at PFN echoed into this file
+
+
+Architecture specific MCE injector
+
+x86 has mce-inject, mce-test
+
+Some portable hwpoison test programs in mce-test, see blow.
+
+---
+
+References:
+
+http://halobates.de/mce-lc09-2.pdf
+       Overview presentation from LinuxCon 09
+
+git://git.kernel.org/pub/scm/utils/cpu/mce/mce-test.git
+       Test suite (hwpoison specific portable tests in tsrc)
+
+git://git.kernel.org/pub/scm/utils/cpu/mce/mce-inject.git
+       x86 specific injector
+
+
+---
+
+Limitations:
+
+- Not all page types are supported and never will. Most kernel internal
+objects cannot be recovered, only LRU pages for now.
+- Right now hugepage support is missing.
+
+---
+Andi Kleen, Oct 2009
+
index 72a22f6..262d8e6 100644 (file)
@@ -52,15 +52,15 @@ The KSM daemon is controlled by sysfs files in /sys/kernel/mm/ksm/,
 readable by all but writable only by root:
 
 max_kernel_pages - set to maximum number of kernel pages that KSM may use
-                   e.g. "echo 2000 > /sys/kernel/mm/ksm/max_kernel_pages"
+                   e.g. "echo 100000 > /sys/kernel/mm/ksm/max_kernel_pages"
                    Value 0 imposes no limit on the kernel pages KSM may use;
                    but note that any process using MADV_MERGEABLE can cause
                    KSM to allocate these pages, unswappable until it exits.
-                   Default: 2000 (chosen for demonstration purposes)
+                   Default: quarter of memory (chosen to not pin too much)
 
 pages_to_scan    - how many present pages to scan before ksmd goes to sleep
-                   e.g. "echo 200 > /sys/kernel/mm/ksm/pages_to_scan"
-                   Default: 200 (chosen for demonstration purposes)
+                   e.g. "echo 100 > /sys/kernel/mm/ksm/pages_to_scan"
+                   Default: 100 (chosen for demonstration purposes)
 
 sleep_millisecs  - how many milliseconds ksmd should sleep before next scan
                    e.g. "echo 20 > /sys/kernel/mm/ksm/sleep_millisecs"
@@ -70,7 +70,8 @@ run              - set 0 to stop ksmd from running but keep merged pages,
                    set 1 to run ksmd e.g. "echo 1 > /sys/kernel/mm/ksm/run",
                    set 2 to stop ksmd and unmerge all pages currently merged,
                          but leave mergeable areas registered for next run
-                   Default: 1 (for immediate use by apps which register)
+                   Default: 0 (must be changed to 1 to activate KSM,
+                               except if CONFIG_SYSFS is disabled)
 
 The effectiveness of KSM and MADV_MERGEABLE is shown in /sys/kernel/mm/ksm/:
 
@@ -86,4 +87,4 @@ pages_volatile embraces several different kinds of activity, but a high
 proportion there would also indicate poor use of madvise MADV_MERGEABLE.
 
 Izik Eidus,
-Hugh Dickins, 30 July 2009
+Hugh Dickins, 24 Sept 2009
index fa1a30d..3ec4f2a 100644 (file)
@@ -2,7 +2,10 @@
  * page-types: Tool for querying page flags
  *
  * Copyright (C) 2009 Intel corporation
- * Copyright (C) 2009 Wu Fengguang <fengguang.wu@intel.com>
+ *
+ * Authors: Wu Fengguang <fengguang.wu@intel.com>
+ *
+ * Released under the General Public License (GPL).
  */
 
 #define _LARGEFILE64_SOURCE
@@ -69,7 +72,9 @@
 #define KPF_COMPOUND_TAIL      16
 #define KPF_HUGE               17
 #define KPF_UNEVICTABLE                18
+#define KPF_HWPOISON           19
 #define KPF_NOPAGE             20
+#define KPF_KSM                        21
 
 /* [32-] kernel hacking assistances */
 #define KPF_RESERVED           32
@@ -116,7 +121,9 @@ static char *page_flag_names[] = {
        [KPF_COMPOUND_TAIL]     = "T:compound_tail",
        [KPF_HUGE]              = "G:huge",
        [KPF_UNEVICTABLE]       = "u:unevictable",
+       [KPF_HWPOISON]          = "X:hwpoison",
        [KPF_NOPAGE]            = "n:nopage",
+       [KPF_KSM]               = "x:ksm",
 
        [KPF_RESERVED]          = "r:reserved",
        [KPF_MLOCKED]           = "m:mlocked",
@@ -152,9 +159,6 @@ static unsigned long        opt_size[MAX_ADDR_RANGES];
 static int             nr_vmas;
 static unsigned long   pg_start[MAX_VMAS];
 static unsigned long   pg_end[MAX_VMAS];
-static unsigned long   voffset;
-
-static int             pagemap_fd;
 
 #define MAX_BIT_FILTERS        64
 static int             nr_bit_filters;
@@ -163,9 +167,16 @@ static uint64_t            opt_bits[MAX_BIT_FILTERS];
 
 static int             page_size;
 
-#define PAGES_BATCH    (64 << 10)      /* 64k pages */
+static int             pagemap_fd;
 static int             kpageflags_fd;
 
+static int             opt_hwpoison;
+static int             opt_unpoison;
+
+static char            *hwpoison_debug_fs = "/debug/hwpoison";
+static int             hwpoison_inject_fd;
+static int             hwpoison_forget_fd;
+
 #define HASH_SHIFT     13
 #define HASH_SIZE      (1 << HASH_SHIFT)
 #define HASH_MASK      (HASH_SIZE - 1)
@@ -207,6 +218,74 @@ static void fatal(const char *x, ...)
        exit(EXIT_FAILURE);
 }
 
+int checked_open(const char *pathname, int flags)
+{
+       int fd = open(pathname, flags);
+
+       if (fd < 0) {
+               perror(pathname);
+               exit(EXIT_FAILURE);
+       }
+
+       return fd;
+}
+
+/*
+ * pagemap/kpageflags routines
+ */
+
+static unsigned long do_u64_read(int fd, char *name,
+                                uint64_t *buf,
+                                unsigned long index,
+                                unsigned long count)
+{
+       long bytes;
+
+       if (index > ULONG_MAX / 8)
+               fatal("index overflow: %lu\n", index);
+
+       if (lseek(fd, index * 8, SEEK_SET) < 0) {
+               perror(name);
+               exit(EXIT_FAILURE);
+       }
+
+       bytes = read(fd, buf, count * 8);
+       if (bytes < 0) {
+               perror(name);
+               exit(EXIT_FAILURE);
+       }
+       if (bytes % 8)
+               fatal("partial read: %lu bytes\n", bytes);
+
+       return bytes / 8;
+}
+
+static unsigned long kpageflags_read(uint64_t *buf,
+                                    unsigned long index,
+                                    unsigned long pages)
+{
+       return do_u64_read(kpageflags_fd, PROC_KPAGEFLAGS, buf, index, pages);
+}
+
+static unsigned long pagemap_read(uint64_t *buf,
+                                 unsigned long index,
+                                 unsigned long pages)
+{
+       return do_u64_read(pagemap_fd, "/proc/pid/pagemap", buf, index, pages);
+}
+
+static unsigned long pagemap_pfn(uint64_t val)
+{
+       unsigned long pfn;
+
+       if (val & PM_PRESENT)
+               pfn = PM_PFRAME(val);
+       else
+               pfn = 0;
+
+       return pfn;
+}
+
 
 /*
  * page flag names
@@ -255,7 +334,8 @@ static char *page_flag_longname(uint64_t flags)
  * page list and summary
  */
 
-static void show_page_range(unsigned long offset, uint64_t flags)
+static void show_page_range(unsigned long voffset,
+                           unsigned long offset, uint64_t flags)
 {
        static uint64_t      flags0;
        static unsigned long voff;
@@ -281,7 +361,8 @@ static void show_page_range(unsigned long offset, uint64_t flags)
        count  = 1;
 }
 
-static void show_page(unsigned long offset, uint64_t flags)
+static void show_page(unsigned long voffset,
+                     unsigned long offset, uint64_t flags)
 {
        if (opt_pid)
                printf("%lx\t", voffset);
@@ -362,6 +443,62 @@ static uint64_t well_known_flags(uint64_t flags)
        return flags;
 }
 
+static uint64_t kpageflags_flags(uint64_t flags)
+{
+       flags = expand_overloaded_flags(flags);
+
+       if (!opt_raw)
+               flags = well_known_flags(flags);
+
+       return flags;
+}
+
+/*
+ * page actions
+ */
+
+static void prepare_hwpoison_fd(void)
+{
+       char buf[100];
+
+       if (opt_hwpoison && !hwpoison_inject_fd) {
+               sprintf(buf, "%s/corrupt-pfn", hwpoison_debug_fs);
+               hwpoison_inject_fd = checked_open(buf, O_WRONLY);
+       }
+
+       if (opt_unpoison && !hwpoison_forget_fd) {
+               sprintf(buf, "%s/renew-pfn", hwpoison_debug_fs);
+               hwpoison_forget_fd = checked_open(buf, O_WRONLY);
+       }
+}
+
+static int hwpoison_page(unsigned long offset)
+{
+       char buf[100];
+       int len;
+
+       len = sprintf(buf, "0x%lx\n", offset);
+       len = write(hwpoison_inject_fd, buf, len);
+       if (len < 0) {
+               perror("hwpoison inject");
+               return len;
+       }
+       return 0;
+}
+
+static int unpoison_page(unsigned long offset)
+{
+       char buf[100];
+       int len;
+
+       len = sprintf(buf, "0x%lx\n", offset);
+       len = write(hwpoison_forget_fd, buf, len);
+       if (len < 0) {
+               perror("hwpoison forget");
+               return len;
+       }
+       return 0;
+}
 
 /*
  * page frame walker
@@ -394,104 +531,83 @@ static int hash_slot(uint64_t flags)
        exit(EXIT_FAILURE);
 }
 
-static void add_page(unsigned long offset, uint64_t flags)
+static void add_page(unsigned long voffset,
+                    unsigned long offset, uint64_t flags)
 {
-       flags = expand_overloaded_flags(flags);
-
-       if (!opt_raw)
-               flags = well_known_flags(flags);
+       flags = kpageflags_flags(flags);
 
        if (!bit_mask_ok(flags))
                return;
 
+       if (opt_hwpoison)
+               hwpoison_page(offset);
+       if (opt_unpoison)
+               unpoison_page(offset);
+
        if (opt_list == 1)
-               show_page_range(offset, flags);
+               show_page_range(voffset, offset, flags);
        else if (opt_list == 2)
-               show_page(offset, flags);
+               show_page(voffset, offset, flags);
 
        nr_pages[hash_slot(flags)]++;
        total_pages++;
 }
 
-static void walk_pfn(unsigned long index, unsigned long count)
+#define KPAGEFLAGS_BATCH       (64 << 10)      /* 64k pages */
+static void walk_pfn(unsigned long voffset,
+                    unsigned long index,
+                    unsigned long count)
 {
+       uint64_t buf[KPAGEFLAGS_BATCH];
        unsigned long batch;
-       unsigned long n;
+       unsigned long pages;
        unsigned long i;
 
-       if (index > ULONG_MAX / KPF_BYTES)
-               fatal("index overflow: %lu\n", index);
-
-       lseek(kpageflags_fd, index * KPF_BYTES, SEEK_SET);
-
        while (count) {
-               uint64_t kpageflags_buf[KPF_BYTES * PAGES_BATCH];
-
-               batch = min_t(unsigned long, count, PAGES_BATCH);
-               n = read(kpageflags_fd, kpageflags_buf, batch * KPF_BYTES);
-               if (n == 0)
+               batch = min_t(unsigned long, count, KPAGEFLAGS_BATCH);
+               pages = kpageflags_read(buf, index, batch);
+               if (pages == 0)
                        break;
-               if (n < 0) {
-                       perror(PROC_KPAGEFLAGS);
-                       exit(EXIT_FAILURE);
-               }
 
-               if (n % KPF_BYTES != 0)
-                       fatal("partial read: %lu bytes\n", n);
-               n = n / KPF_BYTES;
+               for (i = 0; i < pages; i++)
+                       add_page(voffset + i, index + i, buf[i]);
 
-               for (i = 0; i < n; i++)
-                       add_page(index + i, kpageflags_buf[i]);
-
-               index += batch;
-               count -= batch;
+               index += pages;
+               count -= pages;
        }
 }
 
-
-#define PAGEMAP_BATCH  4096
-static unsigned long task_pfn(unsigned long pgoff)
+#define PAGEMAP_BATCH  (64 << 10)
+static void walk_vma(unsigned long index, unsigned long count)
 {
-       static uint64_t buf[PAGEMAP_BATCH];
-       static unsigned long start;
-       static long count;
-       uint64_t pfn;
+       uint64_t buf[PAGEMAP_BATCH];
+       unsigned long batch;
+       unsigned long pages;
+       unsigned long pfn;
+       unsigned long i;
 
-       if (pgoff < start || pgoff >= start + count) {
-               if (lseek64(pagemap_fd,
-                           (uint64_t)pgoff * PM_ENTRY_BYTES,
-                           SEEK_SET) < 0) {
-                       perror("pagemap seek");
-                       exit(EXIT_FAILURE);
-               }
-               count = read(pagemap_fd, buf, sizeof(buf));
-               if (count == 0)
-                       return 0;
-               if (count < 0) {
-                       perror("pagemap read");
-                       exit(EXIT_FAILURE);
-               }
-               if (count % PM_ENTRY_BYTES) {
-                       fatal("pagemap read not aligned.\n");
-                       exit(EXIT_FAILURE);
-               }
-               count /= PM_ENTRY_BYTES;
-               start = pgoff;
-       }
+       while (count) {
+               batch = min_t(unsigned long, count, PAGEMAP_BATCH);
+               pages = pagemap_read(buf, index, batch);
+               if (pages == 0)
+                       break;
 
-       pfn = buf[pgoff - start];
-       if (pfn & PM_PRESENT)
-               pfn = PM_PFRAME(pfn);
-       else
-               pfn = 0;
+               for (i = 0; i < pages; i++) {
+                       pfn = pagemap_pfn(buf[i]);
+                       if (pfn)
+                               walk_pfn(index + i, pfn, 1);
+               }
 
-       return pfn;
+               index += pages;
+               count -= pages;
+       }
 }
 
 static void walk_task(unsigned long index, unsigned long count)
 {
-       int i = 0;
        const unsigned long end = index + count;
+       unsigned long start;
+       int i = 0;
 
        while (index < end) {
 
@@ -501,15 +617,11 @@ static void walk_task(unsigned long index, unsigned long count)
                if (pg_start[i] >= end)
                        return;
 
-               voffset = max_t(unsigned long, pg_start[i], index);
-               index   = min_t(unsigned long, pg_end[i], end);
+               start = max_t(unsigned long, pg_start[i], index);
+               index = min_t(unsigned long, pg_end[i], end);
 
-               assert(voffset < index);
-               for (; voffset < index; voffset++) {
-                       unsigned long pfn = task_pfn(voffset);
-                       if (pfn)
-                               walk_pfn(pfn, 1);
-               }
+               assert(start < index);
+               walk_vma(start, index - start);
        }
 }
 
@@ -527,18 +639,14 @@ static void walk_addr_ranges(void)
 {
        int i;
 
-       kpageflags_fd = open(PROC_KPAGEFLAGS, O_RDONLY);
-       if (kpageflags_fd < 0) {
-               perror(PROC_KPAGEFLAGS);
-               exit(EXIT_FAILURE);
-       }
+       kpageflags_fd = checked_open(PROC_KPAGEFLAGS, O_RDONLY);
 
        if (!nr_addr_ranges)
                add_addr_range(0, ULONG_MAX);
 
        for (i = 0; i < nr_addr_ranges; i++)
                if (!opt_pid)
-                       walk_pfn(opt_offset[i], opt_size[i]);
+                       walk_pfn(0, opt_offset[i], opt_size[i]);
                else
                        walk_task(opt_offset[i], opt_size[i]);
 
@@ -575,6 +683,8 @@ static void usage(void)
 "            -l|--list                 Show page details in ranges\n"
 "            -L|--list-each            Show page details one by one\n"
 "            -N|--no-summary           Don't show summay info\n"
+"            -X|--hwpoison             hwpoison pages\n"
+"            -x|--unpoison             unpoison pages\n"
 "            -h|--help                 Show this usage message\n"
 "addr-spec:\n"
 "            N                         one page at offset N (unit: pages)\n"
@@ -624,11 +734,7 @@ static void parse_pid(const char *str)
        opt_pid = parse_number(str);
 
        sprintf(buf, "/proc/%d/pagemap", opt_pid);
-       pagemap_fd = open(buf, O_RDONLY);
-       if (pagemap_fd < 0) {
-               perror(buf);
-               exit(EXIT_FAILURE);
-       }
+       pagemap_fd = checked_open(buf, O_RDONLY);
 
        sprintf(buf, "/proc/%d/maps", opt_pid);
        file = fopen(buf, "r");
@@ -788,6 +894,8 @@ static struct option opts[] = {
        { "list"      , 0, NULL, 'l' },
        { "list-each" , 0, NULL, 'L' },
        { "no-summary", 0, NULL, 'N' },
+       { "hwpoison"  , 0, NULL, 'X' },
+       { "unpoison"  , 0, NULL, 'x' },
        { "help"      , 0, NULL, 'h' },
        { NULL        , 0, NULL, 0 }
 };
@@ -799,7 +907,7 @@ int main(int argc, char *argv[])
        page_size = getpagesize();
 
        while ((c = getopt_long(argc, argv,
-                               "rp:f:a:b:lLNh", opts, NULL)) != -1) {
+                               "rp:f:a:b:lLNXxh", opts, NULL)) != -1) {
                switch (c) {
                case 'r':
                        opt_raw = 1;
@@ -825,6 +933,14 @@ int main(int argc, char *argv[])
                case 'N':
                        opt_no_summary = 1;
                        break;
+               case 'X':
+                       opt_hwpoison = 1;
+                       prepare_hwpoison_fd();
+                       break;
+               case 'x':
+                       opt_unpoison = 1;
+                       prepare_hwpoison_fd();
+                       break;
                case 'h':
                        usage();
                        exit(0);
@@ -844,7 +960,7 @@ int main(int argc, char *argv[])
        walk_addr_ranges();
 
        if (opt_list == 1)
-               show_page_range(0, 0);  /* drain the buffer */
+               show_page_range(0, 0, 0);  /* drain the buffer */
 
        if (opt_no_summary)
                return 0;
index 600a304..df09b96 100644 (file)
@@ -57,7 +57,9 @@ There are three components to pagemap:
     16. COMPOUND_TAIL
     16. HUGE
     18. UNEVICTABLE
+    19. HWPOISON
     20. NOPAGE
+    21. KSM
 
 Short descriptions to the page flags:
 
@@ -86,9 +88,15 @@ Short descriptions to the page flags:
 17. HUGE
     this is an integral part of a HugeTLB page
 
+19. HWPOISON
+    hardware detected memory corruption on this page: don't touch the data!
+
 20. NOPAGE
     no page frame exists at the requested address
 
+21. KSM
+    identical memory pages dynamically shared between one or more processes
+
     [IO related page flags]
  1. ERROR     IO error occurred
  3. UPTODATE  page has up-to-date data
index 09a2028..a1a2ace 100644 (file)
@@ -65,43 +65,51 @@ trivial patch so apply some common sense.
 
 8.     Happy hacking.
 
-               -----------------------------------
-
-Maintainers List (try to look for most precise areas first)
+Descriptions of section entries:
+
+       P: Person (obsolete)
+       M: Mail patches to: FullName <address@domain>
+       L: Mailing list that is relevant to this area
+       W: Web-page with status/info
+       T: SCM tree type and location.  Type is one of: git, hg, quilt, stgit.
+       S: Status, one of the following:
+          Supported:   Someone is actually paid to look after this.
+          Maintained:  Someone actually looks after it.
+          Odd Fixes:   It has a maintainer but they don't have time to do
+                       much other than throw the odd patch in. See below..
+          Orphan:      No current maintainer [but maybe you could take the
+                       role as you write your new code].
+          Obsolete:    Old code. Something tagged obsolete generally means
+                       it has been replaced by a better system and you
+                       should be using that.
+       F: Files and directories with wildcard patterns.
+          A trailing slash includes all files and subdirectory files.
+          F:   drivers/net/    all files in and below drivers/net
+          F:   drivers/net/*   all files in drivers/net, but not below
+          F:   */net/*         all files in "any top level directory"/net
+          One pattern per line.  Multiple F: lines acceptable.
+       X: Files and directories that are NOT maintained, same rules as F:
+          Files exclusions are tested before file matches.
+          Can be useful for excluding a specific subdirectory, for instance:
+          F:   net/
+          X:   net/ipv6/
+          matches all files in and below net excluding net/ipv6/
+       K: Keyword perl extended regex pattern to match content in a
+          patch or file.  For instance:
+          K: of_get_profile
+             matches patches or files that contain "of_get_profile"
+          K: \b(printk|pr_(info|err))\b
+             matches patches or files that contain one or more of the words
+             printk, pr_info or pr_err
+          One regex pattern per line.  Multiple K: lines acceptable.
 
 Note: For the hard of thinking, this list is meant to remain in alphabetical
 order. If you could add yourselves to it in alphabetical order that would be
 so much easier [Ed]
 
-P: Person (obsolete)
-M: Mail patches to: FullName <address@domain>
-L: Mailing list that is relevant to this area
-W: Web-page with status/info
-T: SCM tree type and location.  Type is one of: git, hg, quilt, stgit.
-S: Status, one of the following:
-
-       Supported:      Someone is actually paid to look after this.
-       Maintained:     Someone actually looks after it.
-       Odd Fixes:      It has a maintainer but they don't have time to do
-                       much other than throw the odd patch in. See below..
-       Orphan:         No current maintainer [but maybe you could take the
-                       role as you write your new code].
-       Obsolete:       Old code. Something tagged obsolete generally means
-                       it has been replaced by a better system and you
-                       should be using that.
+Maintainers List (try to look for most precise areas first)
 
-F: Files and directories with wildcard patterns.
-   A trailing slash includes all files and subdirectory files.
-       F:      drivers/net/    all files in and below drivers/net
-       F:      drivers/net/*   all files in drivers/net, but not below
-       F:      */net/*         all files in "any top level directory"/net
-   One pattern per line.  Multiple F: lines acceptable.
-X: Files and directories that are NOT maintained, same rules as F:
-   Files exclusions are tested before file matches.
-   Can be useful for excluding a specific subdirectory, for instance:
-       F:      net/
-       X:      net/ipv6/
-   matches all files in and below net excluding net/ipv6/
+               -----------------------------------
 
 3C505 NETWORK DRIVER
 M:     Philip Blundell <philb@gnu.org>
@@ -577,6 +585,11 @@ M: Mike Rapoport <mike@compulab.co.il>
 L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
 S:     Maintained
 
+ARM/CONTEC MICRO9 MACHINE SUPPORT
+M:     Hubert Feurstein <hubert.feurstein@contec.at>
+S:     Maintained
+F:     arch/arm/mach-ep93xx/micro9.c
+
 ARM/CORGI MACHINE SUPPORT
 M:     Richard Purdie <rpurdie@rpsys.net>
 S:     Maintained
@@ -987,7 +1000,7 @@ F: drivers/net/atlx/
 
 ATM
 M:     Chas Williams <chas@cmf.nrl.navy.mil>
-L:     linux-atm-general@lists.sourceforge.net (subscribers-only)
+L:     linux-atm-general@lists.sourceforge.net (moderated for non-subscribers)
 L:     netdev@vger.kernel.org
 W:     http://linux-atm.sourceforge.net
 S:     Maintained
@@ -1231,6 +1244,13 @@ L:       netdev@vger.kernel.org
 S:     Supported
 F:     drivers/net/tg3.*
 
+BROCADE BFA FC SCSI DRIVER
+P:      Jing Huang
+M:      huangj@brocade.com
+L:      linux-scsi@vger.kernel.org
+S:      Supported
+F:      drivers/scsi/bfa/
+
 BSG (block layer generic sg v4 driver)
 M:     FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>
 L:     linux-scsi@vger.kernel.org
@@ -1468,6 +1488,7 @@ F:        mm/*cgroup*
 
 CORETEMP HARDWARE MONITORING DRIVER
 M:     Rudolf Marek <r.marek@assembler.cz>
+M:     Huaxu Wan <huaxu.wan@intel.com>
 L:     lm-sensors@lm-sensors.org
 S:     Maintained
 F:     Documentation/hwmon/coretemp
@@ -2058,7 +2079,7 @@ S:        Maintained
 F:     fs/*
 
 FINTEK F75375S HARDWARE MONITOR AND FAN CONTROLLER DRIVER
-M:     Riku Voipio <riku.vipio@iki.fi>
+M:     Riku Voipio <riku.voipio@iki.fi>
 L:     lm-sensors@lm-sensors.org
 S:     Maintained
 F:     drivers/hwmon/f75375s.c
@@ -2139,7 +2160,7 @@ S:        Supported
 F:     arch/powerpc/sysdev/qe_lib/
 F:     arch/powerpc/include/asm/*qe.h
 
-FREESCALE USB PERIPHERIAL DRIVERS
+FREESCALE USB PERIPHERAL DRIVERS
 M:     Li Yang <leoli@freescale.com>
 L:     linux-usb@vger.kernel.org
 L:     linuxppc-dev@ozlabs.org
@@ -2190,18 +2211,6 @@ F:       Documentation/filesystems/caching/
 F:     fs/fscache/
 F:     include/linux/fscache*.h
 
-TRACING
-M:     Steven Rostedt <rostedt@goodmis.org>
-M:     Frederic Weisbecker <fweisbec@gmail.com>
-M:     Ingo Molnar <mingo@redhat.com>
-T:     git git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip.git tracing/core
-S:     Maintained
-F:     Documentation/trace/ftrace.txt
-F:     arch/*/*/*/ftrace.h
-F:     arch/*/kernel/ftrace.c
-F:     include/*/ftrace.h include/trace/ include/linux/trace*.h
-F:     kernel/trace/
-
 FUJITSU FR-V (FRV) PORT
 M:     David Howells <dhowells@redhat.com>
 S:     Maintained
@@ -2260,9 +2269,8 @@ S:        Maintained
 F:     include/asm-generic
 
 GENERIC UIO DRIVER FOR PCI DEVICES
-M:     Michael S. Tsirkin <mst@redhat.com>
+M:     "Michael S. Tsirkin" <mst@redhat.com>
 L:     kvm@vger.kernel.org
-L:     linux-kernel@vger.kernel.org
 S:     Supported
 F:     drivers/uio/uio_pci_generic.c
 
@@ -2603,6 +2611,7 @@ L:        linux1394-devel@lists.sourceforge.net
 W:     http://www.linux1394.org/
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/ieee1394/linux1394-2.6.git
 S:     Maintained
+F:     Documentation/debugging-via-ohci1394.txt
 F:     drivers/ieee1394/
 
 IEEE 1394 RAW I/O DRIVER
@@ -2991,8 +3000,8 @@ F:        scripts/Makefile.*
 
 KERNEL JANITORS
 L:     kernel-janitors@vger.kernel.org
-W:     http://www.kerneljanitors.org/
-S:     Maintained
+W:     http://janitor.kernelnewbies.org/
+S:     Odd Fixes
 
 KERNEL NFSD, SUNRPC, AND LOCKD SERVERS
 M:     "J. Bruce Fields" <bfields@fieldses.org>
@@ -3643,10 +3652,18 @@ F:      Documentation/blockdev/nbd.txt
 F:     drivers/block/nbd.c
 F:     include/linux/nbd.h
 
+NETWORK DROP MONITOR
+M:     Neil Horman <nhorman@tuxdriver.com>
+L:     netdev@vger.kernel.org
+S:     Maintained
+W:     https://fedorahosted.org/dropwatch/
+F:     net/core/drop_monitor.c
+
 NETWORKING [GENERAL]
 M:     "David S. Miller" <davem@davemloft.net>
 L:     netdev@vger.kernel.org
 W:     http://www.linuxfoundation.org/en/Net
+W:     http://patchwork.ozlabs.org/project/netdev/list/
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-2.6.git
 S:     Maintained
 F:     net/
@@ -3764,7 +3781,7 @@ F:        drivers/video/riva/
 F:     drivers/video/nvidia/
 
 OMAP SUPPORT
-M:     "Tony Lindgren <tony@atomide.com>" <tony@atomide.com>
+M:     Tony Lindgren <tony@atomide.com>
 L:     linux-omap@vger.kernel.org
 W:     http://www.muru.com/linux/omap/
 W:     http://linux.omap.com/
@@ -3869,6 +3886,15 @@ S:       Maintained
 F:     Documentation/i2c/busses/i2c-ocores
 F:     drivers/i2c/busses/i2c-ocores.c
 
+OPEN FIRMWARE AND FLATTENED DEVICE TREE
+M:     Grant Likely <grant.likely@secretlab.ca>
+L:     devicetree-discuss@lists.ozlabs.org
+W:     http://fdt.secretlab.ca
+S:     Maintained
+F:     drivers/of
+F:     include/linux/of*.h
+K:     of_get_property
+
 OPROFILE
 M:     Robert Richter <robert.richter@amd.com>
 L:     oprofile-list@lists.sf.net
@@ -3973,6 +3999,7 @@ F:        drivers/block/paride/
 PARISC ARCHITECTURE
 M:     Kyle McMartin <kyle@mcmartin.ca>
 M:     Helge Deller <deller@gmx.de>
+M:     "James E.J. Bottomley" <jejb@parisc-linux.org>
 L:     linux-parisc@vger.kernel.org
 W:     http://www.parisc-linux.org/
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/kyle/parisc-2.6.git
@@ -4056,6 +4083,13 @@ M:       Peter Zijlstra <a.p.zijlstra@chello.nl>
 M:     Paul Mackerras <paulus@samba.org>
 M:     Ingo Molnar <mingo@elte.hu>
 S:     Supported
+F:     kernel/perf_event.c
+F:     include/linux/perf_event.h
+F:     arch/*/*/kernel/perf_event.c
+F:     arch/*/include/asm/perf_event.h
+F:     arch/*/lib/perf_event.c
+F:     arch/*/kernel/perf_callchain.c
+F:     tools/perf/
 
 PERSONALITY HANDLING
 M:     Christoph Hellwig <hch@infradead.org>
@@ -4296,7 +4330,7 @@ F:        drivers/video/aty/aty128fb.c
 RALINK RT2X00 WIRELESS LAN DRIVER
 P:     rt2x00 project
 L:     linux-wireless@vger.kernel.org
-L:     users@rt2x00.serialmonkey.com
+L:     users@rt2x00.serialmonkey.com (moderated for non-subscribers)
 W:     http://rt2x00.serialmonkey.com/
 S:     Maintained
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/ivd/rt2x00.git
@@ -4505,12 +4539,11 @@ F:      kernel/sched*
 F:     include/linux/sched.h
 
 SCORE ARCHITECTURE
-P:     Chen Liqin
-M:     liqin.chen@sunplusct.com
-P:     Lennox Wu
-M:     lennox.wu@gmail.com
+M:     Chen Liqin <liqin.chen@sunplusct.com>
+M:     Lennox Wu <lennox.wu@gmail.com>
 W:     http://www.sunplusct.com
 S:     Supported
+F:     arch/score/
 
 SCSI CDROM DRIVER
 M:     Jens Axboe <axboe@kernel.dk>
@@ -4583,20 +4616,20 @@ S:      Maintained
 F:     drivers/mmc/host/sdricoh_cs.c
 
 SECURE DIGITAL HOST CONTROLLER INTERFACE (SDHCI) DRIVER
-S:     Orphan
-L:     linux-mmc@vger.kernel.org
-F:     drivers/mmc/host/sdhci.*
+S:     Orphan
+L:     linux-mmc@vger.kernel.org
+F:     drivers/mmc/host/sdhci.*
 
 SECURE DIGITAL HOST CONTROLLER INTERFACE, OPEN FIRMWARE BINDINGS (SDHCI-OF)
 M:     Anton Vorontsov <avorontsov@ru.mvista.com>
 L:     linuxppc-dev@ozlabs.org
-L:     linux-mmc@vger.kernel.org
+L:     linux-mmc@vger.kernel.org
 S:     Maintained
-F:     drivers/mmc/host/sdhci-of.*
+F:     drivers/mmc/host/sdhci-of.*
 
 SECURE DIGITAL HOST CONTROLLER INTERFACE (SDHCI) SAMSUNG DRIVER
 M:     Ben Dooks <ben-linux@fluff.org>
-L:     linux-mmc@vger.kernel.org
+L:     linux-mmc@vger.kernel.org
 S:     Maintained
 F:     drivers/mmc/host/sdhci-s3c.c
 
@@ -4638,6 +4671,14 @@ F:       drivers/ata/
 F:     include/linux/ata.h
 F:     include/linux/libata.h
 
+SERVER ENGINES 10Gbps iSCSI - BladeEngine 2 DRIVER
+P:     Jayamohan Kallickal
+M:     jayamohank@serverengines.com
+L:     linux-scsi@vger.kernel.org
+W:     http://www.serverengines.com
+S:     Supported
+F:     drivers/scsi/be2iscsi/
+
 SERVER ENGINES 10Gbps NIC - BladeEngine 2 DRIVER
 M:     Sathya Perla <sathyap@serverengines.com>
 M:     Subbu Seetharaman <subbus@serverengines.com>
@@ -4691,8 +4732,7 @@ F:        drivers/usb/gadget/lh7a40*
 F:     drivers/usb/host/ohci-lh7a40*
 
 SIMPLE FIRMWARE INTERFACE (SFI)
-P:     Len Brown
-M:     lenb@kernel.org
+M:     Len Brown <lenb@kernel.org>
 L:     sfi-devel@simplefirmware.org
 W:     http://simplefirmware.org/
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/lenb/linux-sfi-2.6.git
@@ -5140,6 +5180,20 @@ L:       tpmdd-devel@lists.sourceforge.net (moderated for non-subscribers)
 S:     Maintained
 F:     drivers/char/tpm/
 
+TRACING
+M:     Steven Rostedt <rostedt@goodmis.org>
+M:     Frederic Weisbecker <fweisbec@gmail.com>
+M:     Ingo Molnar <mingo@redhat.com>
+T:     git git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip.git tracing/core
+S:     Maintained
+F:     Documentation/trace/ftrace.txt
+F:     arch/*/*/*/ftrace.h
+F:     arch/*/kernel/ftrace.c
+F:     include/*/ftrace.h
+F:     include/linux/trace*.h
+F:     include/trace/
+F:     kernel/trace/
+
 TRIVIAL PATCHES
 M:     Jiri Kosina <trivial@kernel.org>
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/jikos/trivial.git
@@ -5628,6 +5682,13 @@ S:       Maintained
 F:     drivers/vlynq/vlynq.c
 F:     include/linux/vlynq.h
 
+VMWARE VMXNET3 ETHERNET DRIVER
+M:     Shreyas Bhatewara <sbhatewara@vmware.com>
+M:     VMware, Inc. <pv-drivers@vmware.com>
+L:     netdev@vger.kernel.org
+S:     Maintained
+F:     drivers/net/vmxnet3/
+
 VOLTAGE AND CURRENT REGULATOR FRAMEWORK
 M:     Liam Girdwood <lrg@slimlogic.co.uk>
 M:     Mark Brown <broonie@opensource.wolfsonmicro.com>
@@ -5699,8 +5760,7 @@ S:        Maintained
 F:     drivers/scsi/wd7000.c
 
 WINBOND CIR DRIVER
-P:     David Härdeman
-M:     david@hardeman.nu
+M:     David Härdeman <david@hardeman.nu>
 S:     Maintained
 F:     drivers/input/misc/winbond-cir.c
 
@@ -5757,9 +5817,7 @@ F:        drivers/input/touchscreen/*wm97*
 F:     include/linux/wm97xx.h
 
 WOLFSON MICROELECTRONICS PMIC DRIVERS
-P:     Mark Brown
-M:     broonie@opensource.wolfsonmicro.com
-L:     linux-kernel@vger.kernel.org
+M:     Mark Brown <broonie@opensource.wolfsonmicro.com>
 T:     git git://opensource.wolfsonmicro.com/linux-2.6-audioplus
 W:     http://opensource.wolfsonmicro.com/node/8
 S:     Supported
index e50569a..b4c04f7 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
 VERSION = 2
 PATCHLEVEL = 6
 SUBLEVEL = 32
-EXTRAVERSION = -rc3
+EXTRAVERSION = -rc6
 NAME = Man-Eating Seals of Antiquity
 
 # *DOCUMENTATION*
@@ -179,46 +179,9 @@ SUBARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ \
 # Alternatively CROSS_COMPILE can be set in the environment.
 # Default value for CROSS_COMPILE is not to prefix executables
 # Note: Some architectures assign CROSS_COMPILE in their arch/*/Makefile
-#
-# To force ARCH and CROSS_COMPILE settings include kernel.* files
-# in the kernel tree - do not patch this file.
 export KBUILD_BUILDHOST := $(SUBARCH)
-
-# Kbuild save the ARCH and CROSS_COMPILE setting in kernel.* files.
-# Restore these settings and check that user did not specify
-# conflicting values.
-
-saved_arch  := $(shell cat include/generated/kernel.arch  2> /dev/null)
-saved_cross := $(shell cat include/generated/kernel.cross 2> /dev/null)
-
-ifneq ($(CROSS_COMPILE),)
-        ifneq ($(saved_cross),)
-                ifneq ($(CROSS_COMPILE),$(saved_cross))
-                        $(error CROSS_COMPILE changed from \
-                                "$(saved_cross)" to \
-                                 to "$(CROSS_COMPILE)". \
-                                 Use "make mrproper" to fix it up)
-                endif
-        endif
-else
-    CROSS_COMPILE := $(saved_cross)
-endif
-
-ifneq ($(ARCH),)
-        ifneq ($(saved_arch),)
-                ifneq ($(saved_arch),$(ARCH))
-                        $(error ARCH changed from \
-                                "$(saved_arch)" to "$(ARCH)". \
-                                 Use "make mrproper" to fix it up)
-                endif
-        endif
-else
-        ifneq ($(saved_arch),)
-                ARCH := $(saved_arch)
-        else
-                ARCH := $(SUBARCH)
-        endif
-endif
+ARCH           ?= $(SUBARCH)
+CROSS_COMPILE  ?=
 
 # Architecture as present in compile.h
 UTS_MACHINE    := $(ARCH)
@@ -483,11 +446,6 @@ ifeq ($(config-targets),1)
 include $(srctree)/arch/$(SRCARCH)/Makefile
 export KBUILD_DEFCONFIG KBUILD_KCONFIG
 
-# save ARCH & CROSS_COMPILE settings
-$(shell mkdir -p include/generated &&                            \
-        echo $(ARCH)          > include/generated/kernel.arch && \
-        echo $(CROSS_COMPILE) > include/generated/kernel.cross)
-
 config: scripts_basic outputmakefile FORCE
        $(Q)mkdir -p include/linux include/config
        $(Q)$(MAKE) $(build)=scripts/kconfig $@
index 8da75de..264f52b 100644 (file)
@@ -304,7 +304,7 @@ CONFIG_ALIGNMENT_TRAP=y
 CONFIG_ZBOOT_ROM_TEXT=0x10C08000
 CONFIG_ZBOOT_ROM_BSS=0x10200000
 # CONFIG_ZBOOT_ROM is not set
-CONFIG_CMDLINE="root=1f03 rootfstype=jffs2 console=ttyS0,115200n8"
+CONFIG_CMDLINE="root=1f03 rootfstype=jffs2 console=ttyS2,115200n8"
 # CONFIG_XIP_KERNEL is not set
 # CONFIG_KEXEC is not set
 
index 357d402..b3c8cce 100644 (file)
@@ -969,7 +969,6 @@ CONFIG_USB_ETH_RNDIS=y
 #
 CONFIG_USB_OTG_UTILS=y
 # CONFIG_USB_GPIO_VBUS is not set
-# CONFIG_ISP1301_OMAP is not set
 CONFIG_TWL4030_USB=y
 # CONFIG_NOP_USB_XCEIV is not set
 CONFIG_MMC=y
index 7d61ae6..953ba02 100644 (file)
@@ -1,14 +1,14 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.31-rc3
-# Thu Jul 16 23:36:10 2009
+# Linux kernel version: 2.6.32-rc5
+# Sat Oct 17 23:32:24 2009
 #
 CONFIG_ARM=y
 CONFIG_SYS_SUPPORTS_APM_EMULATION=y
 CONFIG_GENERIC_GPIO=y
 CONFIG_GENERIC_TIME=y
 CONFIG_GENERIC_CLOCKEVENTS=y
-CONFIG_MMU=y
+CONFIG_HAVE_TCM=y
 CONFIG_GENERIC_HARDIRQS=y
 CONFIG_STACKTRACE_SUPPORT=y
 CONFIG_HAVE_LATENCYTOP_SUPPORT=y
@@ -44,11 +44,12 @@ CONFIG_SYSVIPC_SYSCTL=y
 #
 # RCU Subsystem
 #
-CONFIG_CLASSIC_RCU=y
-# CONFIG_TREE_RCU is not set
-# CONFIG_PREEMPT_RCU is not set
+CONFIG_TREE_RCU=y
+# CONFIG_TREE_PREEMPT_RCU is not set
+# CONFIG_RCU_TRACE is not set
+CONFIG_RCU_FANOUT=32
+# CONFIG_RCU_FANOUT_EXACT is not set
 # CONFIG_TREE_RCU_TRACE is not set
-# CONFIG_PREEMPT_RCU_TRACE is not set
 # CONFIG_IKCONFIG is not set
 CONFIG_LOG_BUF_SHIFT=14
 # CONFIG_GROUP_SCHED is not set
@@ -80,17 +81,15 @@ CONFIG_SHMEM=y
 # CONFIG_AIO is not set
 
 #
-# Performance Counters
+# Kernel Performance Events And Counters
 #
 # CONFIG_VM_EVENT_COUNTERS is not set
 CONFIG_SLUB_DEBUG=y
-# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_COMPAT_BRK=y
 # CONFIG_SLAB is not set
 CONFIG_SLUB=y
 # CONFIG_SLOB is not set
 # CONFIG_PROFILING is not set
-# CONFIG_MARKERS is not set
 CONFIG_HAVE_OPROFILE=y
 # CONFIG_KPROBES is not set
 CONFIG_HAVE_KPROBES=y
@@ -133,6 +132,7 @@ CONFIG_DEFAULT_IOSCHED="deadline"
 #
 # System Type
 #
+CONFIG_MMU=y
 # CONFIG_ARCH_AAEC2000 is not set
 # CONFIG_ARCH_INTEGRATOR is not set
 # CONFIG_ARCH_REALVIEW is not set
@@ -147,6 +147,7 @@ CONFIG_DEFAULT_IOSCHED="deadline"
 # CONFIG_ARCH_STMP3XXX is not set
 # CONFIG_ARCH_NETX is not set
 # CONFIG_ARCH_H720X is not set
+# CONFIG_ARCH_NOMADIK is not set
 # CONFIG_ARCH_IOP13XX is not set
 # CONFIG_ARCH_IOP32X is not set
 # CONFIG_ARCH_IOP33X is not set
@@ -169,11 +170,13 @@ CONFIG_DEFAULT_IOSCHED="deadline"
 # CONFIG_ARCH_SA1100 is not set
 # CONFIG_ARCH_S3C2410 is not set
 # CONFIG_ARCH_S3C64XX is not set
+# CONFIG_ARCH_S5PC1XX is not set
 # CONFIG_ARCH_SHARK is not set
 # CONFIG_ARCH_LH7A40X is not set
 CONFIG_ARCH_U300=y
 # CONFIG_ARCH_DAVINCI is not set
 # CONFIG_ARCH_OMAP is not set
+# CONFIG_ARCH_BCMRING is not set
 
 #
 # ST-Ericsson AB U300/U330/U335/U365 Platform
@@ -195,6 +198,7 @@ CONFIG_MACH_U300_BS335=y
 CONFIG_MACH_U300_DUAL_RAM=y
 CONFIG_U300_DEBUG=y
 # CONFIG_MACH_U300_SEMI_IS_SHARED is not set
+CONFIG_MACH_U300_SPIDUMMY=y
 
 #
 # All the settings below must match the bootloader's settings
@@ -207,7 +211,7 @@ CONFIG_CPU_32=y
 CONFIG_CPU_ARM926T=y
 CONFIG_CPU_32v5=y
 CONFIG_CPU_ABRT_EV5TJ=y
-CONFIG_CPU_PABRT_NOIFAR=y
+CONFIG_CPU_PABRT_LEGACY=y
 CONFIG_CPU_CACHE_VIVT=y
 CONFIG_CPU_COPY_V4WB=y
 CONFIG_CPU_TLB_V4WBI=y
@@ -222,6 +226,7 @@ CONFIG_ARM_THUMB=y
 # CONFIG_CPU_DCACHE_DISABLE is not set
 # CONFIG_CPU_DCACHE_WRITETHROUGH is not set
 # CONFIG_CPU_CACHE_ROUND_ROBIN is not set
+CONFIG_ARM_L1_CACHE_SHIFT=5
 CONFIG_ARM_VIC=y
 CONFIG_ARM_VIC_NR=2
 CONFIG_COMMON_CLKDEV=y
@@ -245,6 +250,8 @@ CONFIG_VMSPLIT_3G=y
 # CONFIG_VMSPLIT_2G is not set
 # CONFIG_VMSPLIT_1G is not set
 CONFIG_PAGE_OFFSET=0xC0000000
+# CONFIG_PREEMPT_NONE is not set
+# CONFIG_PREEMPT_VOLUNTARY is not set
 CONFIG_PREEMPT=y
 CONFIG_HZ=100
 CONFIG_AEABI=y
@@ -265,6 +272,7 @@ CONFIG_ZONE_DMA_FLAG=0
 CONFIG_VIRT_TO_BUS=y
 CONFIG_HAVE_MLOCK=y
 CONFIG_HAVE_MLOCKED_PAGE_BIT=y
+# CONFIG_KSM is not set
 CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
 CONFIG_ALIGNMENT_TRAP=y
 # CONFIG_UACCESS_WITH_MEMCPY is not set
@@ -313,6 +321,7 @@ CONFIG_PM=y
 # CONFIG_PM_DEBUG is not set
 # CONFIG_SUSPEND is not set
 # CONFIG_APM_EMULATION is not set
+# CONFIG_PM_RUNTIME is not set
 CONFIG_ARCH_SUSPEND_POSSIBLE=y
 CONFIG_NET=y
 
@@ -351,6 +360,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
 # CONFIG_NETFILTER is not set
 # CONFIG_IP_DCCP is not set
 # CONFIG_IP_SCTP is not set
+# CONFIG_RDS is not set
 # CONFIG_TIPC is not set
 # CONFIG_ATM is not set
 # CONFIG_BRIDGE is not set
@@ -391,6 +401,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
 # Generic Driver Options
 #
 CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+# CONFIG_DEVTMPFS is not set
 CONFIG_STANDALONE=y
 # CONFIG_PREVENT_FIRMWARE_BUILD is not set
 CONFIG_FW_LOADER=y
@@ -402,9 +413,9 @@ CONFIG_EXTRA_FIRMWARE=""
 # CONFIG_CONNECTOR is not set
 CONFIG_MTD=y
 # CONFIG_MTD_DEBUG is not set
+# CONFIG_MTD_TESTS is not set
 # CONFIG_MTD_CONCAT is not set
 CONFIG_MTD_PARTITIONS=y
-# CONFIG_MTD_TESTS is not set
 # CONFIG_MTD_REDBOOT_PARTS is not set
 CONFIG_MTD_CMDLINE_PARTS=y
 # CONFIG_MTD_AFS_PARTS is not set
@@ -453,6 +464,7 @@ CONFIG_MTD_CFI_I2=y
 #
 # CONFIG_MTD_DATAFLASH is not set
 # CONFIG_MTD_M25P80 is not set
+# CONFIG_MTD_SST25L is not set
 # CONFIG_MTD_SLRAM is not set
 # CONFIG_MTD_PHRAM is not set
 # CONFIG_MTD_MTDRAM is not set
@@ -520,6 +532,7 @@ CONFIG_HAVE_IDE=y
 # CONFIG_MD is not set
 # CONFIG_NETDEVICES is not set
 # CONFIG_ISDN is not set
+# CONFIG_PHONE is not set
 
 #
 # Input device support
@@ -540,12 +553,16 @@ CONFIG_INPUT_EVDEV=y
 # Input Device Drivers
 #
 CONFIG_INPUT_KEYBOARD=y
+# CONFIG_KEYBOARD_ADP5588 is not set
 # CONFIG_KEYBOARD_ATKBD is not set
+# CONFIG_QT2160 is not set
 # CONFIG_KEYBOARD_LKKBD is not set
 # CONFIG_KEYBOARD_GPIO is not set
 # CONFIG_KEYBOARD_MATRIX is not set
 # CONFIG_KEYBOARD_LM8323 is not set
+# CONFIG_KEYBOARD_MAX7359 is not set
 # CONFIG_KEYBOARD_NEWTON is not set
+# CONFIG_KEYBOARD_OPENCORES is not set
 # CONFIG_KEYBOARD_STOWAWAY is not set
 # CONFIG_KEYBOARD_SUNKBD is not set
 # CONFIG_KEYBOARD_XTKBD is not set
@@ -597,6 +614,7 @@ CONFIG_LEGACY_PTY_COUNT=16
 # CONFIG_TCG_TPM is not set
 CONFIG_I2C=y
 CONFIG_I2C_BOARDINFO=y
+CONFIG_I2C_COMPAT=y
 # CONFIG_I2C_CHARDEV is not set
 CONFIG_I2C_HELPER_AUTO=y
 
@@ -629,9 +647,6 @@ CONFIG_I2C_STU300=y
 # Miscellaneous I2C Chip support
 #
 # CONFIG_DS1682 is not set
-# CONFIG_SENSORS_PCF8574 is not set
-# CONFIG_PCF8575 is not set
-# CONFIG_SENSORS_PCA9539 is not set
 # CONFIG_SENSORS_TSL2550 is not set
 # CONFIG_I2C_DEBUG_CORE is not set
 # CONFIG_I2C_DEBUG_ALGO is not set
@@ -653,16 +668,21 @@ CONFIG_SPI_PL022=y
 #
 # CONFIG_SPI_SPIDEV is not set
 # CONFIG_SPI_TLE62X0 is not set
+
+#
+# PPS support
+#
+# CONFIG_PPS is not set
 # CONFIG_W1 is not set
 CONFIG_POWER_SUPPLY=y
 # CONFIG_POWER_SUPPLY_DEBUG is not set
 # CONFIG_PDA_POWER is not set
 # CONFIG_BATTERY_DS2760 is not set
+# CONFIG_BATTERY_DS2782 is not set
 # CONFIG_BATTERY_BQ27x00 is not set
 # CONFIG_BATTERY_MAX17040 is not set
 # CONFIG_HWMON is not set
 # CONFIG_THERMAL is not set
-# CONFIG_THERMAL_HWMON is not set
 CONFIG_WATCHDOG=y
 # CONFIG_WATCHDOG_NOWAYOUT is not set
 
@@ -690,10 +710,24 @@ CONFIG_SSB_POSSIBLE=y
 # CONFIG_MFD_TC6387XB is not set
 # CONFIG_PMIC_DA903X is not set
 # CONFIG_MFD_WM8400 is not set
+# CONFIG_MFD_WM831X is not set
 # CONFIG_MFD_WM8350_I2C is not set
 # CONFIG_MFD_PCF50633 is not set
+# CONFIG_MFD_MC13783 is not set
 CONFIG_AB3100_CORE=y
+CONFIG_AB3100_OTP=y
 # CONFIG_EZX_PCAP is not set
+CONFIG_REGULATOR=y
+# CONFIG_REGULATOR_DEBUG is not set
+# CONFIG_REGULATOR_FIXED_VOLTAGE is not set
+# CONFIG_REGULATOR_VIRTUAL_CONSUMER is not set
+# CONFIG_REGULATOR_USERSPACE_CONSUMER is not set
+# CONFIG_REGULATOR_BQ24022 is not set
+# CONFIG_REGULATOR_MAX1586 is not set
+# CONFIG_REGULATOR_LP3971 is not set
+CONFIG_REGULATOR_AB3100=y
+# CONFIG_REGULATOR_TPS65023 is not set
+# CONFIG_REGULATOR_TPS6507X is not set
 # CONFIG_MEDIA_SUPPORT is not set
 
 #
@@ -792,9 +826,10 @@ CONFIG_MMC_BLOCK_BOUNCE=y
 #
 CONFIG_MMC_ARMMMCI=y
 # CONFIG_MMC_SDHCI is not set
+# CONFIG_MMC_AT91 is not set
+# CONFIG_MMC_ATMELMCI is not set
 # CONFIG_MMC_SPI is not set
 # CONFIG_MEMSTICK is not set
-# CONFIG_ACCESSIBILITY is not set
 CONFIG_NEW_LEDS=y
 CONFIG_LEDS_CLASS=y
 
@@ -820,10 +855,10 @@ CONFIG_LEDS_TRIGGER_BACKLIGHT=y
 #
 # iptables trigger is under Netfilter config (LED target)
 #
+# CONFIG_ACCESSIBILITY is not set
 CONFIG_RTC_LIB=y
 CONFIG_RTC_CLASS=y
-CONFIG_RTC_HCTOSYS=y
-CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
+# CONFIG_RTC_HCTOSYS is not set
 # CONFIG_RTC_DEBUG is not set
 
 #
@@ -863,6 +898,7 @@ CONFIG_RTC_INTF_DEV=y
 # CONFIG_RTC_DRV_R9701 is not set
 # CONFIG_RTC_DRV_RS5C348 is not set
 # CONFIG_RTC_DRV_DS3234 is not set
+# CONFIG_RTC_DRV_PCF2123 is not set
 
 #
 # Platform RTC drivers
@@ -878,27 +914,25 @@ CONFIG_RTC_INTF_DEV=y
 # CONFIG_RTC_DRV_M48T59 is not set
 # CONFIG_RTC_DRV_BQ4802 is not set
 # CONFIG_RTC_DRV_V3020 is not set
+CONFIG_RTC_DRV_AB3100=y
 
 #
 # on-CPU RTC drivers
 #
 # CONFIG_RTC_DRV_PL030 is not set
 # CONFIG_RTC_DRV_PL031 is not set
+CONFIG_RTC_DRV_COH901331=y
 CONFIG_DMADEVICES=y
 
 #
 # DMA Devices
 #
 # CONFIG_AUXDISPLAY is not set
-CONFIG_REGULATOR=y
-# CONFIG_REGULATOR_DEBUG is not set
-# CONFIG_REGULATOR_FIXED_VOLTAGE is not set
-# CONFIG_REGULATOR_VIRTUAL_CONSUMER is not set
-# CONFIG_REGULATOR_USERSPACE_CONSUMER is not set
-# CONFIG_REGULATOR_BQ24022 is not set
-# CONFIG_REGULATOR_MAX1586 is not set
-# CONFIG_REGULATOR_LP3971 is not set
 # CONFIG_UIO is not set
+
+#
+# TI VLYNQ
+#
 # CONFIG_STAGING is not set
 
 #
@@ -913,6 +947,7 @@ CONFIG_REGULATOR=y
 # CONFIG_XFS_FS is not set
 # CONFIG_OCFS2_FS is not set
 # CONFIG_BTRFS_FS is not set
+# CONFIG_NILFS2_FS is not set
 CONFIG_FILE_LOCKING=y
 CONFIG_FSNOTIFY=y
 # CONFIG_DNOTIFY is not set
@@ -975,7 +1010,6 @@ CONFIG_MISC_FILESYSTEMS=y
 # CONFIG_ROMFS_FS is not set
 # CONFIG_SYSV_FS is not set
 # CONFIG_UFS_FS is not set
-# CONFIG_NILFS2_FS is not set
 # CONFIG_NETWORK_FILESYSTEMS is not set
 
 #
@@ -1033,6 +1067,7 @@ CONFIG_ENABLE_WARN_DEPRECATED=y
 CONFIG_ENABLE_MUST_CHECK=y
 CONFIG_FRAME_WARN=1024
 # CONFIG_MAGIC_SYSRQ is not set
+# CONFIG_STRIP_ASM_SYMS is not set
 # CONFIG_UNUSED_SYMBOLS is not set
 # CONFIG_DEBUG_FS is not set
 # CONFIG_HEADERS_CHECK is not set
@@ -1066,11 +1101,13 @@ CONFIG_DEBUG_INFO=y
 # CONFIG_DEBUG_LIST is not set
 # CONFIG_DEBUG_SG is not set
 # CONFIG_DEBUG_NOTIFIERS is not set
+# CONFIG_DEBUG_CREDENTIALS is not set
 # CONFIG_BOOT_PRINTK_DELAY is not set
 # CONFIG_RCU_TORTURE_TEST is not set
 # CONFIG_RCU_CPU_STALL_DETECTOR is not set
 # CONFIG_BACKTRACE_SELF_TEST is not set
 # CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
+# CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set
 # CONFIG_FAULT_INJECTION is not set
 # CONFIG_LATENCYTOP is not set
 # CONFIG_SYSCTL_SYSCALL_CHECK is not set
@@ -1121,6 +1158,7 @@ CONFIG_GENERIC_FIND_LAST_BIT=y
 # CONFIG_CRC32 is not set
 # CONFIG_CRC7 is not set
 # CONFIG_LIBCRC32C is not set
+CONFIG_GENERIC_ALLOCATOR=y
 CONFIG_HAS_IOMEM=y
 CONFIG_HAS_IOPORT=y
 CONFIG_HAS_DMA=y
index 63a481f..338ff19 100644 (file)
@@ -84,7 +84,7 @@ ____atomic_test_and_set_bit(unsigned int bit, volatile unsigned long *p)
        *p = res | mask;
        raw_local_irq_restore(flags);
 
-       return res & mask;
+       return (res & mask) != 0;
 }
 
 static inline int
@@ -101,7 +101,7 @@ ____atomic_test_and_clear_bit(unsigned int bit, volatile unsigned long *p)
        *p = res & ~mask;
        raw_local_irq_restore(flags);
 
-       return res & mask;
+       return (res & mask) != 0;
 }
 
 static inline int
@@ -118,7 +118,7 @@ ____atomic_test_and_change_bit(unsigned int bit, volatile unsigned long *p)
        *p = res ^ mask;
        raw_local_irq_restore(flags);
 
-       return res & mask;
+       return (res & mask) != 0;
 }
 
 #include <asm-generic/bitops/non-atomic.h>
index fd03fb6..3d0cdd2 100644 (file)
@@ -414,9 +414,14 @@ extern void __flush_dcache_page(struct address_space *mapping, struct page *page
 
 static inline void __flush_icache_all(void)
 {
+#ifdef CONFIG_ARM_ERRATA_411920
+       extern void v6_icache_inval_all(void);
+       v6_icache_inval_all();
+#else
        asm("mcr        p15, 0, %0, c7, c5, 0   @ invalidate I-cache\n"
            :
            : "r" (0));
+#endif
 }
 
 #define ARCH_HAS_FLUSH_ANON_PAGE
index c3b911e..6aac3f5 100644 (file)
@@ -98,6 +98,9 @@ extern int elf_check_arch(const struct elf32_hdr *);
 extern int arm_elf_read_implies_exec(const struct elf32_hdr *, int);
 #define elf_read_implies_exec(ex,stk) arm_elf_read_implies_exec(&(ex), stk)
 
+int dump_task_regs(struct task_struct *t, elf_gregset_t *elfregs);
+#define ELF_CORE_COPY_TASK_REGS dump_task_regs
+
 #define USE_ELF_CORE_DUMP
 #define ELF_EXEC_PAGESIZE      4096
 
index a45ab5d..c2f1605 100644 (file)
@@ -350,7 +350,7 @@ static inline void local_flush_tlb_mm(struct mm_struct *mm)
        if (tlb_flag(TLB_WB))
                dsb();
 
-       if (cpumask_test_cpu(smp_processor_id(), mm_cpumask(mm))) {
+       if (cpumask_test_cpu(get_cpu(), mm_cpumask(mm))) {
                if (tlb_flag(TLB_V3_FULL))
                        asm("mcr p15, 0, %0, c6, c0, 0" : : "r" (zero) : "cc");
                if (tlb_flag(TLB_V4_U_FULL))
@@ -360,6 +360,7 @@ static inline void local_flush_tlb_mm(struct mm_struct *mm)
                if (tlb_flag(TLB_V4_I_FULL))
                        asm("mcr p15, 0, %0, c8, c5, 0" : : "r" (zero) : "cc");
        }
+       put_cpu();
 
        if (tlb_flag(TLB_V6_U_ASID))
                asm("mcr p15, 0, %0, c8, c7, 2" : : "r" (asid) : "cc");
index 322410b..0022b4d 100644 (file)
@@ -608,33 +608,33 @@ call_fpe:
  THUMB(        add     pc, r8                  )
        nop
 
-       W(mov)  pc, lr                          @ CP#0
+       movw_pc lr                              @ CP#0
        W(b)    do_fpe                          @ CP#1 (FPE)
        W(b)    do_fpe                          @ CP#2 (FPE)
-       W(mov)  pc, lr                          @ CP#3
+       movw_pc lr                              @ CP#3
 #ifdef CONFIG_CRUNCH
        b       crunch_task_enable              @ CP#4 (MaverickCrunch)
        b       crunch_task_enable              @ CP#5 (MaverickCrunch)
        b       crunch_task_enable              @ CP#6 (MaverickCrunch)
 #else
-       W(mov)  pc, lr                          @ CP#4
-       W(mov)  pc, lr                          @ CP#5
-       W(mov)  pc, lr                          @ CP#6
+       movw_pc lr                              @ CP#4
+       movw_pc lr                              @ CP#5
+       movw_pc lr                              @ CP#6
 #endif
-       W(mov)  pc, lr                          @ CP#7
-       W(mov)  pc, lr                          @ CP#8
-       W(mov)  pc, lr                          @ CP#9
+       movw_pc lr                              @ CP#7
+       movw_pc lr                              @ CP#8
+       movw_pc lr                              @ CP#9
 #ifdef CONFIG_VFP
        W(b)    do_vfp                          @ CP#10 (VFP)
        W(b)    do_vfp                          @ CP#11 (VFP)
 #else
-       W(mov)  pc, lr                          @ CP#10 (VFP)
-       W(mov)  pc, lr                          @ CP#11 (VFP)
+       movw_pc lr                              @ CP#10 (VFP)
+       movw_pc lr                              @ CP#11 (VFP)
 #endif
-       W(mov)  pc, lr                          @ CP#12
-       W(mov)  pc, lr                          @ CP#13
-       W(mov)  pc, lr                          @ CP#14 (Debug)
-       W(mov)  pc, lr                          @ CP#15 (Control)
+       movw_pc lr                              @ CP#12
+       movw_pc lr                              @ CP#13
+       movw_pc lr                              @ CP#14 (Debug)
+       movw_pc lr                              @ CP#15 (Control)
 
 #ifdef CONFIG_NEON
        .align  6
index ac34c0d..7e9ed1e 100644 (file)
        mov     \rd, sp, lsr #13
        mov     \rd, \rd, lsl #13
        .endm
+
+       @
+       @ 32-bit wide "mov pc, reg"
+       @
+       .macro  movw_pc, reg
+       mov     pc, \reg
+       .endm
 #else  /* CONFIG_THUMB2_KERNEL */
        .macro  svc_exit, rpsr
        clrex                                   @ clear the exclusive monitor
        lsr     \rd, \rd, #13
        mov     \rd, \rd, lsl #13
        .endm
+
+       @
+       @ 32-bit wide "mov pc, reg"
+       @
+       .macro  movw_pc, reg
+       mov     pc, \reg
+       nop
+       .endm
 #endif /* !CONFIG_THUMB2_KERNEL */
 
 /*
index 790fbee..0d96d01 100644 (file)
@@ -328,6 +328,15 @@ copy_thread(unsigned long clone_flags, unsigned long stack_start,
 }
 
 /*
+ * Fill in the task's elfregs structure for a core dump.
+ */
+int dump_task_regs(struct task_struct *t, elf_gregset_t *elfregs)
+{
+       elf_core_copy_regs(elfregs, task_pt_regs(t));
+       return 1;
+}
+
+/*
  * fill in the fpe structure for a core dump...
  */
 int dump_fpu (struct pt_regs *regs, struct user_fp *fp)
index 1423a34..2a573d4 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  linux/arch/arm/kernel/signal.c
  *
- *  Copyright (C) 1995-2002 Russell King
+ *  Copyright (C) 1995-2009 Russell King
  *
  * 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
@@ -29,6 +29,7 @@
  */
 #define SWI_SYS_SIGRETURN      (0xef000000|(__NR_sigreturn)|(__NR_OABI_SYSCALL_BASE))
 #define SWI_SYS_RT_SIGRETURN   (0xef000000|(__NR_rt_sigreturn)|(__NR_OABI_SYSCALL_BASE))
+#define SWI_SYS_RESTART                (0xef000000|__NR_restart_syscall|__NR_OABI_SYSCALL_BASE)
 
 /*
  * With EABI, the syscall number has to be loaded into r7.
@@ -49,6 +50,18 @@ const unsigned long sigreturn_codes[7] = {
 };
 
 /*
+ * Either we support OABI only, or we have EABI with the OABI
+ * compat layer enabled.  In the later case we don't know if
+ * user space is EABI or not, and if not we must not clobber r7.
+ * Always using the OABI syscall solves that issue and works for
+ * all those cases.
+ */
+const unsigned long syscall_restart_code[2] = {
+       SWI_SYS_RESTART,        /* swi  __NR_restart_syscall */
+       0xe49df004,             /* ldr  pc, [sp], #4 */
+};
+
+/*
  * atomically swap in the new signal mask, and wait for a signal.
  */
 asmlinkage int sys_sigsuspend(int restart, unsigned long oldmask, old_sigset_t mask)
@@ -645,32 +658,12 @@ static void do_signal(struct pt_regs *regs, int syscall)
                                regs->ARM_pc -= 4;
 #else
                                u32 __user *usp;
-                               u32 swival = __NR_restart_syscall;
 
-                               regs->ARM_sp -= 12;
+                               regs->ARM_sp -= 4;
                                usp = (u32 __user *)regs->ARM_sp;
 
-                               /*
-                                * Either we supports OABI only, or we have
-                                * EABI with the OABI compat layer enabled.
-                                * In the later case we don't know if user
-                                * space is EABI or not, and if not we must
-                                * not clobber r7.  Always using the OABI
-                                * syscall solves that issue and works for
-                                * all those cases.
-                                */
-                               swival = swival - __NR_SYSCALL_BASE + __NR_OABI_SYSCALL_BASE;
-
-                               put_user(regs->ARM_pc, &usp[0]);
-                               /* swi __NR_restart_syscall */
-                               put_user(0xef000000 | swival, &usp[1]);
-                               /* ldr  pc, [sp], #12 */
-                               put_user(0xe49df00c, &usp[2]);
-
-                               flush_icache_range((unsigned long)usp,
-                                                  (unsigned long)(usp + 3));
-
-                               regs->ARM_pc = regs->ARM_sp + 4;
+                               put_user(regs->ARM_pc, usp);
+                               regs->ARM_pc = KERN_RESTART_CODE;
 #endif
                        }
                }
index 27beece..6fcfe83 100644 (file)
@@ -1,12 +1,14 @@
 /*
  *  linux/arch/arm/kernel/signal.h
  *
- *  Copyright (C) 2005 Russell King.
+ *  Copyright (C) 2005-2009 Russell King.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  */
 #define KERN_SIGRETURN_CODE    (CONFIG_VECTORS_BASE + 0x00000500)
+#define KERN_RESTART_CODE      (KERN_SIGRETURN_CODE + sizeof(sigreturn_codes))
 
 extern const unsigned long sigreturn_codes[7];
+extern const unsigned long syscall_restart_code[2];
index 4cdc4a0..d38cdf2 100644 (file)
@@ -21,6 +21,7 @@
 #include <linux/interrupt.h>
 #include <linux/time.h>
 #include <linux/init.h>
+#include <linux/sched.h>
 #include <linux/smp.h>
 #include <linux/timex.h>
 #include <linux/errno.h>
index 467b69e..95718a6 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  linux/arch/arm/kernel/traps.c
  *
- *  Copyright (C) 1995-2002 Russell King
+ *  Copyright (C) 1995-2009 Russell King
  *  Fragments that appear the same as linux/arch/i386/kernel/traps.c (C) Linus Torvalds
  *
  * This program is free software; you can redistribute it and/or modify
@@ -45,21 +45,21 @@ static int __init user_debug_setup(char *str)
 __setup("user_debug=", user_debug_setup);
 #endif
 
-static void dump_mem(const char *str, unsigned long bottom, unsigned long top);
+static void dump_mem(const char *, const char *, unsigned long, unsigned long);
 
 void dump_backtrace_entry(unsigned long where, unsigned long from, unsigned long frame)
 {
 #ifdef CONFIG_KALLSYMS
-       printk("[<%08lx>] ", where);
-       print_symbol("(%s) ", where);
-       printk("from [<%08lx>] ", from);
-       print_symbol("(%s)\n", from);
+       char sym1[KSYM_SYMBOL_LEN], sym2[KSYM_SYMBOL_LEN];
+       sprint_symbol(sym1, where);
+       sprint_symbol(sym2, from);
+       printk("[<%08lx>] (%s) from [<%08lx>] (%s)\n", where, sym1, from, sym2);
 #else
        printk("Function entered at [<%08lx>] from [<%08lx>]\n", where, from);
 #endif
 
        if (in_exception_text(where))
-               dump_mem("Exception stack", frame + 4, frame + 4 + sizeof(struct pt_regs));
+               dump_mem("", "Exception stack", frame + 4, frame + 4 + sizeof(struct pt_regs));
 }
 
 #ifndef CONFIG_ARM_UNWIND
@@ -81,9 +81,10 @@ static int verify_stack(unsigned long sp)
 /*
  * Dump out the contents of some memory nicely...
  */
-static void dump_mem(const char *str, unsigned long bottom, unsigned long top)
+static void dump_mem(const char *lvl, const char *str, unsigned long bottom,
+                    unsigned long top)
 {
-       unsigned long p = bottom & ~31;
+       unsigned long first;
        mm_segment_t fs;
        int i;
 
@@ -95,33 +96,37 @@ static void dump_mem(const char *str, unsigned long bottom, unsigned long top)
        fs = get_fs();
        set_fs(KERNEL_DS);
 
-       printk("%s(0x%08lx to 0x%08lx)\n", str, bottom, top);
+       printk("%s%s(0x%08lx to 0x%08lx)\n", lvl, str, bottom, top);
 
-       for (p = bottom & ~31; p < top;) {
-               printk("%04lx: ", p & 0xffff);
+       for (first = bottom & ~31; first < top; first += 32) {
+               unsigned long p;
+               char str[sizeof(" 12345678") * 8 + 1];
 
-               for (i = 0; i < 8; i++, p += 4) {
-                       unsigned int val;
+               memset(str, ' ', sizeof(str));
+               str[sizeof(str) - 1] = '\0';
 
-                       if (p < bottom || p >= top)
-                               printk("         ");
-                       else {
-                               __get_user(val, (unsigned long *)p);
-                               printk("%08x ", val);
+               for (p = first, i = 0; i < 8 && p < top; i++, p += 4) {
+                       if (p >= bottom && p < top) {
+                               unsigned long val;
+                               if (__get_user(val, (unsigned long *)p) == 0)
+                                       sprintf(str + i * 9, " %08lx", val);
+                               else
+                                       sprintf(str + i * 9, " ????????");
                        }
                }
-               printk ("\n");
+               printk("%s%04lx:%s\n", lvl, first & 0xffff, str);
        }
 
        set_fs(fs);
 }
 
-static void dump_instr(struct pt_regs *regs)
+static void dump_instr(const char *lvl, struct pt_regs *regs)
 {
        unsigned long addr = instruction_pointer(regs);
        const int thumb = thumb_mode(regs);
        const int width = thumb ? 4 : 8;
        mm_segment_t fs;
+       char str[sizeof("00000000 ") * 5 + 2 + 1], *p = str;
        int i;
 
        /*
@@ -132,7 +137,6 @@ static void dump_instr(struct pt_regs *regs)
        fs = get_fs();
        set_fs(KERNEL_DS);
 
-       printk("Code: ");
        for (i = -4; i < 1; i++) {
                unsigned int val, bad;
 
@@ -142,13 +146,14 @@ static void dump_instr(struct pt_regs *regs)
                        bad = __get_user(val, &((u32 *)addr)[i]);
 
                if (!bad)
-                       printk(i == 0 ? "(%0*x) " : "%0*x ", width, val);
+                       p += sprintf(p, i == 0 ? "(%0*x) " : "%0*x ",
+                                       width, val);
                else {
-                       printk("bad PC value.");
+                       p += sprintf(p, "bad PC value");
                        break;
                }
        }
-       printk("\n");
+       printk("%sCode: %s\n", lvl, str);
 
        set_fs(fs);
 }
@@ -224,18 +229,19 @@ static void __die(const char *str, int err, struct thread_info *thread, struct p
        struct task_struct *tsk = thread->task;
        static int die_counter;
 
-       printk("Internal error: %s: %x [#%d]" S_PREEMPT S_SMP "\n",
+       printk(KERN_EMERG "Internal error: %s: %x [#%d]" S_PREEMPT S_SMP "\n",
               str, err, ++die_counter);
+       sysfs_printk_last_file();
        print_modules();
        __show_regs(regs);
-       printk("Process %s (pid: %d, stack limit = 0x%p)\n",
-               tsk->comm, task_pid_nr(tsk), thread + 1);
+       printk(KERN_EMERG "Process %.*s (pid: %d, stack limit = 0x%p)\n",
+               TASK_COMM_LEN, tsk->comm, task_pid_nr(tsk), thread + 1);
 
        if (!user_mode(regs) || in_interrupt()) {
-               dump_mem("Stack: ", regs->ARM_sp,
+               dump_mem(KERN_EMERG, "Stack: ", regs->ARM_sp,
                         THREAD_SIZE + (unsigned long)task_stack_page(tsk));
                dump_backtrace(regs, tsk);
-               dump_instr(regs);
+               dump_instr(KERN_EMERG, regs);
        }
 }
 
@@ -250,13 +256,14 @@ NORET_TYPE void die(const char *str, struct pt_regs *regs, int err)
 
        oops_enter();
 
-       console_verbose();
        spin_lock_irq(&die_lock);
+       console_verbose();
        bust_spinlocks(1);
        __die(str, err, thread, regs);
        bust_spinlocks(0);
        add_taint(TAINT_DIE);
        spin_unlock_irq(&die_lock);
+       oops_exit();
 
        if (in_interrupt())
                panic("Fatal exception in interrupt");
@@ -264,7 +271,6 @@ NORET_TYPE void die(const char *str, struct pt_regs *regs, int err)
        if (panic_on_oops)
                panic("Fatal exception");
 
-       oops_exit();
        do_exit(SIGSEGV);
 }
 
@@ -349,7 +355,7 @@ asmlinkage void __exception do_undefinstr(struct pt_regs *regs)
        if (user_debug & UDBG_UNDEFINED) {
                printk(KERN_INFO "%s (%d): undefined instruction: pc=%p\n",
                        current->comm, task_pid_nr(current), pc);
-               dump_instr(regs);
+               dump_instr(KERN_INFO, regs);
        }
 #endif
 
@@ -400,7 +406,7 @@ static int bad_syscall(int n, struct pt_regs *regs)
        if (user_debug & UDBG_SYSCALL) {
                printk(KERN_ERR "[%d] %s: obsolete system call %08x.\n",
                        task_pid_nr(current), current->comm, n);
-               dump_instr(regs);
+               dump_instr(KERN_ERR, regs);
        }
 #endif
 
@@ -579,7 +585,7 @@ asmlinkage int arm_syscall(int no, struct pt_regs *regs)
        if (user_debug & UDBG_SYSCALL) {
                printk("[%d] %s: arm syscall %d\n",
                       task_pid_nr(current), current->comm, no);
-               dump_instr(regs);
+               dump_instr("", regs);
                if (user_mode(regs)) {
                        __show_regs(regs);
                        c_backtrace(regs->ARM_fp, processor_mode(regs));
@@ -656,7 +662,7 @@ baddataabort(int code, unsigned long instr, struct pt_regs *regs)
        if (user_debug & UDBG_BADABORT) {
                printk(KERN_ERR "[%d] %s: bad data abort: code %d instr 0x%08lx\n",
                        task_pid_nr(current), current->comm, code, instr);
-               dump_instr(regs);
+               dump_instr(KERN_ERR, regs);
                show_pte(current->mm, addr);
        }
 #endif
@@ -745,6 +751,8 @@ void __init early_trap_init(void)
         */
        memcpy((void *)KERN_SIGRETURN_CODE, sigreturn_codes,
               sizeof(sigreturn_codes));
+       memcpy((void *)KERN_RESTART_CODE, syscall_restart_code,
+              sizeof(syscall_restart_code));
 
        flush_icache_range(vectors, vectors + PAGE_SIZE);
        modify_domain(DOMAIN_USER, DOMAIN_CLIENT);
index 39baf11..786ac2b 100644 (file)
  * http://infocenter.arm.com/help/topic/com.arm.doc.subset.swdev.abi/index.html
  */
 
+#if !defined (__ARM_EABI__)
+#warning Your compiler does not have EABI support.
+#warning    ARM unwind is known to compile only with EABI compilers.
+#warning    Change compiler or disable ARM_UNWIND option.
+#elif (__GNUC__ == 4 && __GNUC_MINOR__ <= 2)
+#warning Your compiler is too buggy; it is known to not compile ARM unwind support.
+#warning    Change compiler or disable ARM_UNWIND option.
+#endif
+
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/module.h>
index d581cff..332b784 100644 (file)
@@ -838,7 +838,7 @@ static void __init at91_add_device_rtt(void)
  *  Watchdog
  * -------------------------------------------------------------------- */
 
-#if defined(CONFIG_AT91SAM9_WATCHDOG) || defined(CONFIG_AT91SAM9_WATCHDOG_MODULE)
+#if defined(CONFIG_AT91SAM9X_WATCHDOG) || defined(CONFIG_AT91SAM9X_WATCHDOG_MODULE)
 static struct platform_device at91sam9g45_wdt_device = {
        .name           = "at91_wdt",
        .id             = -1,
index 34a9502..c22df30 100644 (file)
@@ -25,6 +25,8 @@
 #define ARCH_ID_AT91SAM9G20    0x019905a0
 #define ARCH_ID_AT91SAM9RL64   0x019b03a0
 #define ARCH_ID_AT91SAM9G45    0x819b05a0
+#define ARCH_ID_AT91SAM9G45MRL 0x819b05a2      /* aka 9G45-ES2 & non ES lots */
+#define ARCH_ID_AT91SAM9G45ES  0x819b05a1      /* 9G45-ES (Engineering Sample) */
 #define ARCH_ID_AT91CAP9       0x039A03A0
 
 #define ARCH_ID_AT91SAM9XE128  0x329973a0
@@ -41,6 +43,11 @@ static inline unsigned long at91_cpu_identify(void)
        return (at91_sys_read(AT91_DBGU_CIDR) & ~AT91_CIDR_VERSION);
 }
 
+static inline unsigned long at91_cpu_fully_identify(void)
+{
+       return at91_sys_read(AT91_DBGU_CIDR);
+}
+
 #define ARCH_EXID_AT91SAM9M11  0x00000001
 #define ARCH_EXID_AT91SAM9M10  0x00000002
 #define ARCH_EXID_AT91SAM9G45  0x00000004
@@ -118,8 +125,10 @@ static inline unsigned long at91cap9_rev_identify(void)
 
 #ifdef CONFIG_ARCH_AT91SAM9G45
 #define cpu_is_at91sam9g45()   (at91_cpu_identify() == ARCH_ID_AT91SAM9G45)
+#define cpu_is_at91sam9g45es() (at91_cpu_fully_identify() == ARCH_ID_AT91SAM9G45ES)
 #else
 #define cpu_is_at91sam9g45()   (0)
+#define cpu_is_at91sam9g45es() (0)
 #endif
 
 #ifdef CONFIG_ARCH_AT91CAP9
index 4b4f692..e590bbe 100644 (file)
@@ -271,12 +271,12 @@ static struct irqaction bcmring_timer_irq = {
        .handler = bcmring_timer_interrupt,
 };
 
-static cycle_t bcmring_get_cycles_timer1(void)
+static cycle_t bcmring_get_cycles_timer1(struct clocksource *cs)
 {
        return ~readl(TIMER1_VA_BASE + TIMER_VALUE);
 }
 
-static cycle_t bcmring_get_cycles_timer3(void)
+static cycle_t bcmring_get_cycles_timer3(struct clocksource *cs)
 {
        return ~readl(TIMER3_VA_BASE + TIMER_VALUE);
 }
index cdbf93c..38b3706 100644 (file)
@@ -29,7 +29,7 @@ static inline void arch_idle(void)
        cpu_do_idle();
 }
 
-static inline void arch_reset(char mode, char *cmd)
+static inline void arch_reset(char mode, const char *cmd)
 {
        printk("arch_reset:%c %x\n", mode, bcmring_arch_warm_reboot);
 
index d7291c6..9167c3d 100644 (file)
@@ -17,13 +17,31 @@ config EP93XX_SDCE3_SYNC_PHYS_OFFSET
        bool "0x00000000 - SDCE3/SyncBoot"
        help
          Select this option if you want support for EP93xx boards with the
-         first SDRAM bank at 0x00000000
+         first SDRAM bank at 0x00000000.
 
 config EP93XX_SDCE0_PHYS_OFFSET
        bool "0xc0000000 - SDCEO"
        help
          Select this option if you want support for EP93xx boards with the
-         first SDRAM bank at 0xc0000000
+         first SDRAM bank at 0xc0000000.
+
+config EP93XX_SDCE1_PHYS_OFFSET
+       bool "0xd0000000 - SDCE1"
+       help
+         Select this option if you want support for EP93xx boards with the
+         first SDRAM bank at 0xd0000000.
+
+config EP93XX_SDCE2_PHYS_OFFSET
+       bool "0xe0000000 - SDCE2"
+       help
+         Select this option if you want support for EP93xx boards with the
+         first SDRAM bank at 0xe0000000.
+
+config EP93XX_SDCE3_ASYNC_PHYS_OFFSET
+       bool "0xf0000000 - SDCE3/AsyncBoot"
+       help
+         Select this option if you want support for EP93xx boards with the
+         first SDRAM bank at 0xf0000000.
 
 endchoice
 
@@ -112,28 +130,36 @@ config MACH_MICRO9
        bool
 
 config MACH_MICRO9H
-       bool "Support Contec Hypercontrol Micro9-H"
+       bool "Support Contec Micro9-High"
        depends on EP93XX_SDCE3_SYNC_PHYS_OFFSET
        select MACH_MICRO9
        help
          Say 'Y' here if you want your kernel to support the
-         Contec Hypercontrol Micro9-H board.
+         Contec Micro9-High board.
 
 config MACH_MICRO9M
-       bool "Support Contec Hypercontrol Micro9-M"
-       depends on EP93XX_SDCE3_SYNC_PHYS_OFFSET
+       bool "Support Contec Micro9-Mid"
+       depends on EP93XX_SDCE3_ASYNC_PHYS_OFFSET
        select MACH_MICRO9
        help
          Say 'Y' here if you want your kernel to support the
-         Contec Hypercontrol Micro9-M board.
+         Contec Micro9-Mid board.
 
 config MACH_MICRO9L
-       bool "Support Contec Hypercontrol Micro9-L"
+       bool "Support Contec Micro9-Lite"
        depends on EP93XX_SDCE3_SYNC_PHYS_OFFSET
        select MACH_MICRO9
        help
          Say 'Y' here if you want your kernel to support the
-         Contec Hypercontrol Micro9-L board.
+         Contec Micro9-Lite board.
+
+config MACH_MICRO9S
+       bool "Support Contec Micro9-Slim"
+       depends on EP93XX_SDCE3_ASYNC_PHYS_OFFSET
+       select MACH_MICRO9
+       help
+         Say 'Y' here if you want your kernel to support the
+         Contec Micro9-Slim board.
 
 config MACH_TS72XX
        bool "Support Technologic Systems TS-72xx SBC"
index 27a085a..0ad33f1 100644 (file)
@@ -3,3 +3,12 @@ params_phys-$(CONFIG_EP93XX_SDCE3_SYNC_PHYS_OFFSET)    := 0x00000100
 
    zreladdr-$(CONFIG_EP93XX_SDCE0_PHYS_OFFSET)         := 0xc0008000
 params_phys-$(CONFIG_EP93XX_SDCE0_PHYS_OFFSET)         := 0xc0000100
+
+   zreladdr-$(CONFIG_EP93XX_SDCE1_PHYS_OFFSET)         := 0xd0008000
+params_phys-$(CONFIG_EP93XX_SDCE1_PHYS_OFFSET)         := 0xd0000100
+
+   zreladdr-$(CONFIG_EP93XX_SDCE2_PHYS_OFFSET)         := 0xe0008000
+params_phys-$(CONFIG_EP93XX_SDCE2_PHYS_OFFSET)         := 0xe0000100
+
+   zreladdr-$(CONFIG_EP93XX_SDCE3_ASYNC_PHYS_OFFSET)   := 0xf0008000
+params_phys-$(CONFIG_EP93XX_SDCE3_ASYNC_PHYS_OFFSET)   := 0xf0000100
index dda19cd..1d0f9d8 100644 (file)
 #include <linux/module.h>
 #include <linux/string.h>
 #include <linux/io.h>
+#include <linux/spinlock.h>
+
+#include <mach/hardware.h>
 
 #include <asm/clkdev.h>
 #include <asm/div64.h>
-#include <mach/hardware.h>
 
 
 struct clk {
+       struct clk      *parent;
        unsigned long   rate;
        int             users;
        int             sw_locked;
@@ -39,40 +42,60 @@ static unsigned long get_uart_rate(struct clk *clk);
 static int set_keytchclk_rate(struct clk *clk, unsigned long rate);
 static int set_div_rate(struct clk *clk, unsigned long rate);
 
+
+static struct clk clk_xtali = {
+       .rate           = EP93XX_EXT_CLK_RATE,
+};
 static struct clk clk_uart1 = {
+       .parent         = &clk_xtali,
        .sw_locked      = 1,
        .enable_reg     = EP93XX_SYSCON_DEVCFG,
        .enable_mask    = EP93XX_SYSCON_DEVCFG_U1EN,
        .get_rate       = get_uart_rate,
 };
 static struct clk clk_uart2 = {
+       .parent         = &clk_xtali,
        .sw_locked      = 1,
        .enable_reg     = EP93XX_SYSCON_DEVCFG,
        .enable_mask    = EP93XX_SYSCON_DEVCFG_U2EN,
        .get_rate       = get_uart_rate,
 };
 static struct clk clk_uart3 = {
+       .parent         = &clk_xtali,
        .sw_locked      = 1,
        .enable_reg     = EP93XX_SYSCON_DEVCFG,
        .enable_mask    = EP93XX_SYSCON_DEVCFG_U3EN,
        .get_rate       = get_uart_rate,
 };
-static struct clk clk_pll1;
-static struct clk clk_f;
-static struct clk clk_h;
-static struct clk clk_p;
-static struct clk clk_pll2;
+static struct clk clk_pll1 = {
+       .parent         = &clk_xtali,
+};
+static struct clk clk_f = {
+       .parent         = &clk_pll1,
+};
+static struct clk clk_h = {
+       .parent         = &clk_pll1,
+};
+static struct clk clk_p = {
+       .parent         = &clk_pll1,
+};
+static struct clk clk_pll2 = {
+       .parent         = &clk_xtali,
+};
 static struct clk clk_usb_host = {
+       .parent         = &clk_pll2,
        .enable_reg     = EP93XX_SYSCON_PWRCNT,
        .enable_mask    = EP93XX_SYSCON_PWRCNT_USH_EN,
 };
 static struct clk clk_keypad = {
+       .parent         = &clk_xtali,
        .sw_locked      = 1,
        .enable_reg     = EP93XX_SYSCON_KEYTCHCLKDIV,
        .enable_mask    = EP93XX_SYSCON_KEYTCHCLKDIV_KEN,
        .set_rate       = set_keytchclk_rate,
 };
 static struct clk clk_pwm = {
+       .parent         = &clk_xtali,
        .rate           = EP93XX_EXT_CLK_RATE,
 };
 
@@ -85,50 +108,62 @@ static struct clk clk_video = {
 
 /* DMA Clocks */
 static struct clk clk_m2p0 = {
+       .parent         = &clk_h,
        .enable_reg     = EP93XX_SYSCON_PWRCNT,
        .enable_mask    = EP93XX_SYSCON_PWRCNT_DMA_M2P0,
 };
 static struct clk clk_m2p1 = {
+       .parent         = &clk_h,
        .enable_reg     = EP93XX_SYSCON_PWRCNT,
        .enable_mask    = EP93XX_SYSCON_PWRCNT_DMA_M2P1,
 };
 static struct clk clk_m2p2 = {
+       .parent         = &clk_h,
        .enable_reg     = EP93XX_SYSCON_PWRCNT,
        .enable_mask    = EP93XX_SYSCON_PWRCNT_DMA_M2P2,
 };
 static struct clk clk_m2p3 = {
+       .parent         = &clk_h,
        .enable_reg     = EP93XX_SYSCON_PWRCNT,
        .enable_mask    = EP93XX_SYSCON_PWRCNT_DMA_M2P3,
 };
 static struct clk clk_m2p4 = {
+       .parent         = &clk_h,
        .enable_reg     = EP93XX_SYSCON_PWRCNT,
        .enable_mask    = EP93XX_SYSCON_PWRCNT_DMA_M2P4,
 };
 static struct clk clk_m2p5 = {
+       .parent         = &clk_h,
        .enable_reg     = EP93XX_SYSCON_PWRCNT,
        .enable_mask    = EP93XX_SYSCON_PWRCNT_DMA_M2P5,
 };
 static struct clk clk_m2p6 = {
+       .parent         = &clk_h,
        .enable_reg     = EP93XX_SYSCON_PWRCNT,
        .enable_mask    = EP93XX_SYSCON_PWRCNT_DMA_M2P6,
 };
 static struct clk clk_m2p7 = {
+       .parent         = &clk_h,
        .enable_reg     = EP93XX_SYSCON_PWRCNT,
        .enable_mask    = EP93XX_SYSCON_PWRCNT_DMA_M2P7,
 };
 static struct clk clk_m2p8 = {
+       .parent         = &clk_h,
        .enable_reg     = EP93XX_SYSCON_PWRCNT,
        .enable_mask    = EP93XX_SYSCON_PWRCNT_DMA_M2P8,
 };
 static struct clk clk_m2p9 = {
+       .parent         = &clk_h,
        .enable_reg     = EP93XX_SYSCON_PWRCNT,
        .enable_mask    = EP93XX_SYSCON_PWRCNT_DMA_M2P9,
 };
 static struct clk clk_m2m0 = {
+       .parent         = &clk_h,
        .enable_reg     = EP93XX_SYSCON_PWRCNT,
        .enable_mask    = EP93XX_SYSCON_PWRCNT_DMA_M2M0,
 };
 static struct clk clk_m2m1 = {
+       .parent         = &clk_h,
        .enable_reg     = EP93XX_SYSCON_PWRCNT,
        .enable_mask    = EP93XX_SYSCON_PWRCNT_DMA_M2M1,
 };
@@ -137,6 +172,7 @@ static struct clk clk_m2m1 = {
        { .dev_id = dev, .con_id = con, .clk = ck }
 
 static struct clk_lookup clocks[] = {
+       INIT_CK(NULL,                   "xtali",        &clk_xtali),
        INIT_CK("apb:uart1",            NULL,           &clk_uart1),
        INIT_CK("apb:uart2",            NULL,           &clk_uart2),
        INIT_CK("apb:uart3",            NULL,           &clk_uart3),
@@ -163,48 +199,84 @@ static struct clk_lookup clocks[] = {
        INIT_CK(NULL,                   "m2m1",         &clk_m2m1),
 };
 
+static DEFINE_SPINLOCK(clk_lock);
+
+static void __clk_enable(struct clk *clk)
+{
+       if (!clk->users++) {
+               if (clk->parent)
+                       __clk_enable(clk->parent);
+
+               if (clk->enable_reg) {
+                       u32 v;
+
+                       v = __raw_readl(clk->enable_reg);
+                       v |= clk->enable_mask;
+                       if (clk->sw_locked)
+                               ep93xx_syscon_swlocked_write(v, clk->enable_reg);
+                       else
+                               __raw_writel(v, clk->enable_reg);
+               }
+       }
+}
 
 int clk_enable(struct clk *clk)
 {
-       if (!clk->users++ && clk->enable_reg) {
-               u32 value;
+       unsigned long flags;
 
-               value = __raw_readl(clk->enable_reg);
-               value |= clk->enable_mask;
-               if (clk->sw_locked)
-                       ep93xx_syscon_swlocked_write(value, clk->enable_reg);
-               else
-                       __raw_writel(value, clk->enable_reg);
-       }
+       if (!clk)
+               return -EINVAL;
+
+       spin_lock_irqsave(&clk_lock, flags);
+       __clk_enable(clk);
+       spin_unlock_irqrestore(&clk_lock, flags);
 
        return 0;
 }
 EXPORT_SYMBOL(clk_enable);
 
-void clk_disable(struct clk *clk)
+static void __clk_disable(struct clk *clk)
 {
-       if (!--clk->users && clk->enable_reg) {
-               u32 value;
+       if (!--clk->users) {
+               if (clk->enable_reg) {
+                       u32 v;
+
+                       v = __raw_readl(clk->enable_reg);
+                       v &= ~clk->enable_mask;
+                       if (clk->sw_locked)
+                               ep93xx_syscon_swlocked_write(v, clk->enable_reg);
+                       else
+                               __raw_writel(v, clk->enable_reg);
+               }
 
-               value = __raw_readl(clk->enable_reg);
-               value &= ~clk->enable_mask;
-               if (clk->sw_locked)
-                       ep93xx_syscon_swlocked_write(value, clk->enable_reg);
-               else
-                       __raw_writel(value, clk->enable_reg);
+               if (clk->parent)
+                       __clk_disable(clk->parent);
        }
 }
+
+void clk_disable(struct clk *clk)
+{
+       unsigned long flags;
+
+       if (!clk)
+               return;
+
+       spin_lock_irqsave(&clk_lock, flags);
+       __clk_disable(clk);
+       spin_unlock_irqrestore(&clk_lock, flags);
+}
 EXPORT_SYMBOL(clk_disable);
 
 static unsigned long get_uart_rate(struct clk *clk)
 {
+       unsigned long rate = clk_get_rate(clk->parent);
        u32 value;
 
        value = __raw_readl(EP93XX_SYSCON_PWRCNT);
        if (value & EP93XX_SYSCON_PWRCNT_UARTBAUD)
-               return EP93XX_EXT_CLK_RATE;
+               return rate;
        else
-               return EP93XX_EXT_CLK_RATE / 2;
+               return rate / 2;
 }
 
 unsigned long clk_get_rate(struct clk *clk)
@@ -244,16 +316,16 @@ static int set_keytchclk_rate(struct clk *clk, unsigned long rate)
        return 0;
 }
 
-static unsigned long calc_clk_div(unsigned long rate, int *psel, int *esel,
-                                 int *pdiv, int *div)
+static int calc_clk_div(struct clk *clk, unsigned long rate,
+                       int *psel, int *esel, int *pdiv, int *div)
 {
-       unsigned long max_rate, best_rate = 0,
-               actual_rate = 0, mclk_rate = 0, rate_err = -1;
+       struct clk *mclk;
+       unsigned long max_rate, actual_rate, mclk_rate, rate_err = -1;
        int i, found = 0, __div = 0, __pdiv = 0;
 
        /* Don't exceed the maximum rate */
        max_rate = max(max(clk_pll1.rate / 4, clk_pll2.rate / 4),
-                      (unsigned long)EP93XX_EXT_CLK_RATE / 4);
+                      clk_xtali.rate / 4);
        rate = min(rate, max_rate);
 
        /*
@@ -267,11 +339,12 @@ static unsigned long calc_clk_div(unsigned long rate, int *psel, int *esel,
         */
        for (i = 0; i < 3; i++) {
                if (i == 0)
-                       mclk_rate = EP93XX_EXT_CLK_RATE * 2;
+                       mclk = &clk_xtali;
                else if (i == 1)
-                       mclk_rate = clk_pll1.rate * 2;
-               else if (i == 2)
-                       mclk_rate = clk_pll2.rate * 2;
+                       mclk = &clk_pll1;
+               else
+                       mclk = &clk_pll2;
+               mclk_rate = mclk->rate * 2;
 
                /* Try each predivider value */
                for (__pdiv = 4; __pdiv <= 6; __pdiv++) {
@@ -286,7 +359,8 @@ static unsigned long calc_clk_div(unsigned long rate, int *psel, int *esel,
                                *div = __div;
                                *psel = (i == 2);
                                *esel = (i != 0);
-                               best_rate = actual_rate;
+                               clk->parent = mclk;
+                               clk->rate = actual_rate;
                                rate_err = abs(actual_rate - rate);
                                found = 1;
                        }
@@ -294,21 +368,19 @@ static unsigned long calc_clk_div(unsigned long rate, int *psel, int *esel,
        }
 
        if (!found)
-               return 0;
+               return -EINVAL;
 
-       return best_rate;
+       return 0;
 }
 
 static int set_div_rate(struct clk *clk, unsigned long rate)
 {
-       unsigned long actual_rate;
-       int psel = 0, esel = 0, pdiv = 0, div = 0;
+       int err, psel = 0, esel = 0, pdiv = 0, div = 0;
        u32 val;
 
-       actual_rate = calc_clk_div(rate, &psel, &esel, &pdiv, &div);
-       if (actual_rate == 0)
-               return -EINVAL;
-       clk->rate = actual_rate;
+       err = calc_clk_div(clk, rate, &psel, &esel, &pdiv, &div);
+       if (err)
+               return err;
 
        /* Clear the esel, psel, pdiv and div bits */
        val = __raw_readl(clk->enable_reg);
@@ -344,7 +416,7 @@ static unsigned long calc_pll_rate(u32 config_word)
        unsigned long long rate;
        int i;
 
-       rate = EP93XX_EXT_CLK_RATE;
+       rate = clk_xtali.rate;
        rate *= ((config_word >> 11) & 0x1f) + 1;               /* X1FBD */
        rate *= ((config_word >> 5) & 0x3f) + 1;                /* X2FBD */
        do_div(rate, (config_word & 0x1f) + 1);                 /* X2IPD */
@@ -377,7 +449,7 @@ static int __init ep93xx_clock_init(void)
 
        value = __raw_readl(EP93XX_SYSCON_CLOCK_SET1);
        if (!(value & 0x00800000)) {                    /* PLL1 bypassed?  */
-               clk_pll1.rate = EP93XX_EXT_CLK_RATE;
+               clk_pll1.rate = clk_xtali.rate;
        } else {
                clk_pll1.rate = calc_pll_rate(value);
        }
@@ -388,7 +460,7 @@ static int __init ep93xx_clock_init(void)
 
        value = __raw_readl(EP93XX_SYSCON_CLOCK_SET2);
        if (!(value & 0x00080000)) {                    /* PLL2 bypassed?  */
-               clk_pll2.rate = EP93XX_EXT_CLK_RATE;
+               clk_pll2.rate = clk_xtali.rate;
        } else if (value & 0x00040000) {                /* PLL2 enabled?  */
                clk_pll2.rate = calc_pll_rate(value);
        } else {
index f7ebed9..b4357c3 100644 (file)
@@ -206,7 +206,6 @@ static void ep93xx_gpio_ab_irq_handler(unsigned int irq, struct irq_desc *desc)
        for (i = 0; i < 8; i++) {
                if (status & (1 << i)) {
                        int gpio_irq = gpio_to_irq(EP93XX_GPIO_LINE_B(0)) + i;
-                       desc = irq_desc + gpio_irq;
                        generic_handle_irq(gpio_irq);
                }
        }
@@ -550,13 +549,11 @@ void __init ep93xx_register_eth(struct ep93xx_eth_data *data, int copy_addr)
        platform_device_register(&ep93xx_eth_device);
 }
 
-static struct i2c_gpio_platform_data ep93xx_i2c_data = {
-       .sda_pin                = EP93XX_GPIO_LINE_EEDAT,
-       .sda_is_open_drain      = 0,
-       .scl_pin                = EP93XX_GPIO_LINE_EECLK,
-       .scl_is_open_drain      = 0,
-       .udelay                 = 2,
-};
+
+/*************************************************************************
+ * EP93xx i2c peripheral handling
+ *************************************************************************/
+static struct i2c_gpio_platform_data ep93xx_i2c_data;
 
 static struct platform_device ep93xx_i2c_device = {
        .name                   = "i2c-gpio",
@@ -564,8 +561,25 @@ static struct platform_device ep93xx_i2c_device = {
        .dev.platform_data      = &ep93xx_i2c_data,
 };
 
-void __init ep93xx_register_i2c(struct i2c_board_info *devices, int num)
+void __init ep93xx_register_i2c(struct i2c_gpio_platform_data *data,
+                               struct i2c_board_info *devices, int num)
 {
+       /*
+        * Set the EEPROM interface pin drive type control.
+        * Defines the driver type for the EECLK and EEDAT pins as either
+        * open drain, which will require an external pull-up, or a normal
+        * CMOS driver.
+        */
+       if (data->sda_is_open_drain && data->sda_pin != EP93XX_GPIO_LINE_EEDAT)
+               pr_warning("ep93xx: sda != EEDAT, open drain has no effect\n");
+       if (data->scl_is_open_drain && data->scl_pin != EP93XX_GPIO_LINE_EECLK)
+               pr_warning("ep93xx: scl != EECLK, open drain has no effect\n");
+
+       __raw_writel((data->sda_is_open_drain << 1) |
+                    (data->scl_is_open_drain << 0),
+                    EP93XX_GPIO_EEDRIVE);
+
+       ep93xx_i2c_data = *data;
        i2c_register_board_info(0, devices, num);
        platform_device_register(&ep93xx_i2c_device);
 }
index 73145ae..a4a7be3 100644 (file)
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/platform_device.h>
-#include <linux/i2c.h>
 #include <linux/mtd/physmap.h>
+#include <linux/gpio.h>
+#include <linux/i2c.h>
+#include <linux/i2c-gpio.h>
 
 #include <mach/hardware.h>
 
@@ -76,13 +78,26 @@ static struct ep93xx_eth_data edb93xx_eth_data = {
        .phy_id         = 1,
 };
 
-static struct i2c_board_info __initdata edb93xxa_i2c_data[] = {
+
+/*************************************************************************
+ * EDB93xx i2c peripheral handling
+ *************************************************************************/
+static struct i2c_gpio_platform_data edb93xx_i2c_gpio_data = {
+       .sda_pin                = EP93XX_GPIO_LINE_EEDAT,
+       .sda_is_open_drain      = 0,
+       .scl_pin                = EP93XX_GPIO_LINE_EECLK,
+       .scl_is_open_drain      = 0,
+       .udelay                 = 0,    /* default to 100 kHz */
+       .timeout                = 0,    /* default to 100 ms */
+};
+
+static struct i2c_board_info __initdata edb93xxa_i2c_board_info[] = {
        {
                I2C_BOARD_INFO("isl1208", 0x6f),
        },
 };
 
-static struct i2c_board_info __initdata edb93xx_i2c_data[] = {
+static struct i2c_board_info __initdata edb93xx_i2c_board_info[] = {
        {
                I2C_BOARD_INFO("ds1337", 0x68),
        },
@@ -92,12 +107,14 @@ static void __init edb93xx_register_i2c(void)
 {
        if (machine_is_edb9302a() || machine_is_edb9307a() ||
            machine_is_edb9315a()) {
-               ep93xx_register_i2c(edb93xxa_i2c_data,
-                               ARRAY_SIZE(edb93xxa_i2c_data));
+               ep93xx_register_i2c(&edb93xx_i2c_gpio_data,
+                                   edb93xxa_i2c_board_info,
+                                   ARRAY_SIZE(edb93xxa_i2c_board_info));
        } else if (machine_is_edb9307() || machine_is_edb9312() ||
                   machine_is_edb9315()) {
-               ep93xx_register_i2c(edb93xx_i2c_data,
-                               ARRAY_SIZE(edb93xx_i2c_data));
+               ep93xx_register_i2c(&edb93xx_i2c_gpio_data,
+                                   edb93xx_i2c_board_info,
+                                   ARRAY_SIZE(edb93xx_i2c_board_info));
        }
 }
 
index 0fbf87b..b1f937e 100644 (file)
 #define EP93XX_AHB_VIRT_BASE           0xfef00000
 #define EP93XX_AHB_SIZE                        0x00100000
 
+#define EP93XX_AHB_PHYS(x)             (EP93XX_AHB_PHYS_BASE + (x))
 #define EP93XX_AHB_IOMEM(x)            IOMEM(EP93XX_AHB_VIRT_BASE + (x))
 
 #define EP93XX_APB_PHYS_BASE           0x80800000
 #define EP93XX_APB_VIRT_BASE           0xfed00000
 #define EP93XX_APB_SIZE                        0x00200000
 
+#define EP93XX_APB_PHYS(x)             (EP93XX_APB_PHYS_BASE + (x))
 #define EP93XX_APB_IOMEM(x)            IOMEM(EP93XX_APB_VIRT_BASE + (x))
 
 
 /* AHB peripherals */
 #define EP93XX_DMA_BASE                        EP93XX_AHB_IOMEM(0x00000000)
 
-#define EP93XX_ETHERNET_PHYS_BASE      (EP93XX_AHB_PHYS_BASE + 0x00010000)
+#define EP93XX_ETHERNET_PHYS_BASE      EP93XX_AHB_PHYS(0x00010000)
 #define EP93XX_ETHERNET_BASE           EP93XX_AHB_IOMEM(0x00010000)
 
-#define EP93XX_USB_PHYS_BASE           (EP93XX_AHB_PHYS_BASE + 0x00020000)
+#define EP93XX_USB_PHYS_BASE           EP93XX_AHB_PHYS(0x00020000)
 #define EP93XX_USB_BASE                        EP93XX_AHB_IOMEM(0x00020000)
 
-#define EP93XX_RASTER_PHYS_BASE                (EP93XX_AHB_PHYS_BASE + 0x00030000)
+#define EP93XX_RASTER_PHYS_BASE                EP93XX_AHB_PHYS(0x00030000)
 #define EP93XX_RASTER_BASE             EP93XX_AHB_IOMEM(0x00030000)
 
 #define EP93XX_GRAPHICS_ACCEL_BASE     EP93XX_AHB_IOMEM(0x00040000)
 
 #define EP93XX_GPIO_BASE               EP93XX_APB_IOMEM(0x00040000)
 #define EP93XX_GPIO_REG(x)             (EP93XX_GPIO_BASE + (x))
-#define EP93XX_GPIO_F_INT_TYPE1                EP93XX_GPIO_REG(0x4c)
-#define EP93XX_GPIO_F_INT_TYPE2                EP93XX_GPIO_REG(0x50)
-#define EP93XX_GPIO_F_INT_ACK          EP93XX_GPIO_REG(0x54)
-#define EP93XX_GPIO_F_INT_ENABLE       EP93XX_GPIO_REG(0x58)
 #define EP93XX_GPIO_F_INT_STATUS       EP93XX_GPIO_REG(0x5c)
-#define EP93XX_GPIO_A_INT_TYPE1                EP93XX_GPIO_REG(0x90)
-#define EP93XX_GPIO_A_INT_TYPE2                EP93XX_GPIO_REG(0x94)
-#define EP93XX_GPIO_A_INT_ACK          EP93XX_GPIO_REG(0x98)
-#define EP93XX_GPIO_A_INT_ENABLE       EP93XX_GPIO_REG(0x9c)
 #define EP93XX_GPIO_A_INT_STATUS       EP93XX_GPIO_REG(0xa0)
-#define EP93XX_GPIO_B_INT_TYPE1                EP93XX_GPIO_REG(0xac)
-#define EP93XX_GPIO_B_INT_TYPE2                EP93XX_GPIO_REG(0xb0)
-#define EP93XX_GPIO_B_INT_ACK          EP93XX_GPIO_REG(0xb4)
-#define EP93XX_GPIO_B_INT_ENABLE       EP93XX_GPIO_REG(0xb8)
 #define EP93XX_GPIO_B_INT_STATUS       EP93XX_GPIO_REG(0xbc)
+#define EP93XX_GPIO_EEDRIVE            EP93XX_GPIO_REG(0xc8)
 
 #define EP93XX_AAC_BASE                        EP93XX_APB_IOMEM(0x00080000)
 
 
 #define EP93XX_IRDA_BASE               EP93XX_APB_IOMEM(0x000b0000)
 
-#define EP93XX_UART1_PHYS_BASE         (EP93XX_APB_PHYS_BASE + 0x000c0000)
+#define EP93XX_UART1_PHYS_BASE         EP93XX_APB_PHYS(0x000c0000)
 #define EP93XX_UART1_BASE              EP93XX_APB_IOMEM(0x000c0000)
 
-#define EP93XX_UART2_PHYS_BASE         (EP93XX_APB_PHYS_BASE + 0x000d0000)
+#define EP93XX_UART2_PHYS_BASE         EP93XX_APB_PHYS(0x000d0000)
 #define EP93XX_UART2_BASE              EP93XX_APB_IOMEM(0x000d0000)
 
-#define EP93XX_UART3_PHYS_BASE         (EP93XX_APB_PHYS_BASE + 0x000e0000)
+#define EP93XX_UART3_PHYS_BASE         EP93XX_APB_PHYS(0x000e0000)
 #define EP93XX_UART3_BASE              EP93XX_APB_IOMEM(0x000e0000)
 
 #define EP93XX_KEY_MATRIX_BASE         EP93XX_APB_IOMEM(0x000f0000)
 #define EP93XX_ADC_BASE                        EP93XX_APB_IOMEM(0x00100000)
 #define EP93XX_TOUCHSCREEN_BASE                EP93XX_APB_IOMEM(0x00100000)
 
-#define EP93XX_PWM_PHYS_BASE           (EP93XX_APB_PHYS_BASE + 0x00110000)
+#define EP93XX_PWM_PHYS_BASE           EP93XX_APB_PHYS(0x00110000)
 #define EP93XX_PWM_BASE                        EP93XX_APB_IOMEM(0x00110000)
 
-#define EP93XX_RTC_PHYS_BASE           (EP93XX_APB_PHYS_BASE + 0x00120000)
+#define EP93XX_RTC_PHYS_BASE           EP93XX_APB_PHYS(0x00120000)
 #define EP93XX_RTC_BASE                        EP93XX_APB_IOMEM(0x00120000)
 
 #define EP93XX_SYSCON_BASE             EP93XX_APB_IOMEM(0x00130000)
 #define EP93XX_SYSCON_KEYTCHCLKDIV_ADIV        (1<<16)
 #define EP93XX_SYSCON_KEYTCHCLKDIV_KEN (1<<15)
 #define EP93XX_SYSCON_KEYTCHCLKDIV_KDIV        (1<<0)
+#define EP93XX_SYSCON_SYSCFG           EP93XX_SYSCON_REG(0x9c)
+#define EP93XX_SYSCON_SYSCFG_REV_MASK  (0xf0000000)
+#define EP93XX_SYSCON_SYSCFG_REV_SHIFT (28)
+#define EP93XX_SYSCON_SYSCFG_SBOOT     (1<<8)
+#define EP93XX_SYSCON_SYSCFG_LCSN7     (1<<7)
+#define EP93XX_SYSCON_SYSCFG_LCSN6     (1<<6)
+#define EP93XX_SYSCON_SYSCFG_LASDO     (1<<5)
+#define EP93XX_SYSCON_SYSCFG_LEEDA     (1<<4)
+#define EP93XX_SYSCON_SYSCFG_LEECLK    (1<<3)
+#define EP93XX_SYSCON_SYSCFG_LCSN2     (1<<1)
+#define EP93XX_SYSCON_SYSCFG_LCSN1     (1<<0)
 #define EP93XX_SYSCON_SWLOCK           EP93XX_SYSCON_REG(0xc0)
 
 #define EP93XX_WATCHDOG_BASE           EP93XX_APB_IOMEM(0x00140000)
index 0a1498a..c991b14 100644 (file)
@@ -114,17 +114,9 @@ extern void ep93xx_gpio_int_debounce(unsigned int irq, int enable);
  *          B0..B7  (7..15) to irq 72..79, and
  *          F0..F7 (16..24) to irq 80..87.
  */
-static inline int gpio_to_irq(unsigned gpio)
-{
-       if (gpio <= EP93XX_GPIO_LINE_MAX_IRQ)
-               return 64 + gpio;
-
-       return -EINVAL;
-}
-
-static inline int irq_to_gpio(unsigned irq)
-{
-       return irq - gpio_to_irq(0);
-}
+#define gpio_to_irq(gpio)      \
+       (((gpio) <= EP93XX_GPIO_LINE_MAX_IRQ) ? (64 + (gpio)) : -EINVAL)
+
+#define irq_to_gpio(irq)       ((irq) - gpio_to_irq(0))
 
 #endif
index 925b12e..554064e 100644 (file)
@@ -9,6 +9,12 @@
 #define PHYS_OFFSET            UL(0x00000000)
 #elif defined(CONFIG_EP93XX_SDCE0_PHYS_OFFSET)
 #define PHYS_OFFSET            UL(0xc0000000)
+#elif defined(CONFIG_EP93XX_SDCE1_PHYS_OFFSET)
+#define PHYS_OFFSET            UL(0xd0000000)
+#elif defined(CONFIG_EP93XX_SDCE2_PHYS_OFFSET)
+#define PHYS_OFFSET            UL(0xe0000000)
+#elif defined(CONFIG_EP93XX_SDCE3_ASYNC_PHYS_OFFSET)
+#define PHYS_OFFSET            UL(0xf0000000)
 #else
 #error "Kconfig bug: No EP93xx PHYS_OFFSET set"
 #endif
index 01a0f08..469fd96 100644 (file)
@@ -4,6 +4,7 @@
 
 #ifndef __ASSEMBLY__
 
+struct i2c_gpio_platform_data;
 struct i2c_board_info;
 struct platform_device;
 struct ep93xxfb_mach_info;
@@ -16,7 +17,6 @@ struct ep93xx_eth_data
 
 void ep93xx_map_io(void);
 void ep93xx_init_irq(void);
-void ep93xx_init_time(unsigned long);
 
 /* EP93xx System Controller software locked register write */
 void ep93xx_syscon_swlocked_write(unsigned int val, void __iomem *reg);
@@ -33,7 +33,8 @@ static inline void ep93xx_devcfg_clear_bits(unsigned int bits)
 }
 
 void ep93xx_register_eth(struct ep93xx_eth_data *data, int copy_addr);
-void ep93xx_register_i2c(struct i2c_board_info *devices, int num);
+void ep93xx_register_i2c(struct i2c_gpio_platform_data *data,
+                        struct i2c_board_info *devices, int num);
 void ep93xx_register_fb(struct ep93xxfb_mach_info *data);
 void ep93xx_register_pwm(int pwm0, int pwm1);
 int ep93xx_pwm_acquire_gpio(struct platform_device *pdev);
index 0a313e8..d83b804 100644 (file)
@@ -2,7 +2,9 @@
  *  linux/arch/arm/mach-ep93xx/micro9.c
  *
  * Copyright (C) 2006 Contec Steuerungstechnik & Automation GmbH
- *                   Manfred Gruber <manfred.gruber@contec.at>
+ *                    Manfred Gruber <m.gruber@tirol.com>
+ * Copyright (C) 2009 Contec Steuerungstechnik & Automation GmbH
+ *                    Hubert Feurstein <hubert.feurstein@contec.at>
  *
  * 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
 #include <asm/mach/arch.h>
 
 
-static struct ep93xx_eth_data micro9_eth_data = {
-       .phy_id         = 0x1f,
-};
-
-static void __init micro9_init(void)
-{
-       ep93xx_register_eth(&micro9_eth_data, 1);
-}
-
-/*
- * Micro9-H
- */
-#ifdef CONFIG_MACH_MICRO9H
-static struct physmap_flash_data micro9h_flash_data = {
-       .width          = 4,
-};
-
-static struct resource micro9h_flash_resource = {
+/*************************************************************************
+ * Micro9 NOR Flash
+ *
+ * Micro9-High has up to 64MB of 32-bit flash on CS1
+ * Micro9-Mid has up to 64MB of either 32-bit or 16-bit flash on CS1
+ * Micro9-Lite uses a seperate MTD map driver for flash support
+ * Micro9-Slim has up to 64MB of either 32-bit or 16-bit flash on CS1
+ *************************************************************************/
+static struct physmap_flash_data micro9_flash_data;
+
+static struct resource micro9_flash_resource = {
        .start          = EP93XX_CS1_PHYS_BASE,
        .end            = EP93XX_CS1_PHYS_BASE + SZ_64M - 1,
        .flags          = IORESOURCE_MEM,
 };
 
-static struct platform_device micro9h_flash = {
+static struct platform_device micro9_flash = {
        .name           = "physmap-flash",
        .id             = 0,
        .dev            = {
-               .platform_data  = &micro9h_flash_data,
+               .platform_data  = &micro9_flash_data,
        },
        .num_resources  = 1,
-       .resource       = &micro9h_flash_resource,
+       .resource       = &micro9_flash_resource,
 };
 
-static void __init micro9h_init(void)
+static void __init __micro9_register_flash(unsigned int width)
+{
+       micro9_flash_data.width = width;
+
+       platform_device_register(&micro9_flash);
+}
+
+static unsigned int __init micro9_detect_bootwidth(void)
+{
+       u32 v;
+
+       /* Detect the bus width of the external flash memory */
+       v = __raw_readl(EP93XX_SYSCON_SYSCFG);
+       if (v & EP93XX_SYSCON_SYSCFG_LCSN7)
+               return 4; /* 32-bit */
+       else
+               return 2; /* 16-bit */
+}
+
+static void __init micro9_register_flash(void)
 {
-       platform_device_register(&micro9h_flash);
+       if (machine_is_micro9())
+               __micro9_register_flash(4);
+       else if (machine_is_micro9m() || machine_is_micro9s())
+               __micro9_register_flash(micro9_detect_bootwidth());
 }
 
-static void __init micro9h_init_machine(void)
+
+/*************************************************************************
+ * Micro9 Ethernet
+ *************************************************************************/
+static struct ep93xx_eth_data micro9_eth_data = {
+       .phy_id         = 0x1f,
+};
+
+
+static void __init micro9_init_machine(void)
 {
        ep93xx_init_devices();
-       micro9_init();
-       micro9h_init();
+       ep93xx_register_eth(&micro9_eth_data, 1);
+       micro9_register_flash();
 }
 
-MACHINE_START(MICRO9, "Contec Hypercontrol Micro9-H")
-       /* Maintainer: Manfred Gruber <manfred.gruber@contec.at> */
+
+#ifdef CONFIG_MACH_MICRO9H
+MACHINE_START(MICRO9, "Contec Micro9-High")
+       /* Maintainer: Hubert Feurstein <hubert.feurstein@contec.at> */
        .phys_io        = EP93XX_APB_PHYS_BASE,
        .io_pg_offst    = ((EP93XX_APB_VIRT_BASE) >> 18) & 0xfffc,
        .boot_params    = EP93XX_SDCE3_PHYS_BASE_SYNC + 0x100,
        .map_io         = ep93xx_map_io,
        .init_irq       = ep93xx_init_irq,
        .timer          = &ep93xx_timer,
-       .init_machine   = micro9h_init_machine,
+       .init_machine   = micro9_init_machine,
 MACHINE_END
 #endif
 
-/*
- * Micro9-M
- */
 #ifdef CONFIG_MACH_MICRO9M
-static void __init micro9m_init_machine(void)
-{
-       ep93xx_init_devices();
-       micro9_init();
-}
-
-MACHINE_START(MICRO9M, "Contec Hypercontrol Micro9-M")
-       /* Maintainer: Manfred Gruber <manfred.gruber@contec.at> */
+MACHINE_START(MICRO9M, "Contec Micro9-Mid")
+       /* Maintainer: Hubert Feurstein <hubert.feurstein@contec.at> */
        .phys_io        = EP93XX_APB_PHYS_BASE,
        .io_pg_offst    = ((EP93XX_APB_VIRT_BASE) >> 18) & 0xfffc,
-       .boot_params    = EP93XX_SDCE3_PHYS_BASE_SYNC + 0x100,
+       .boot_params    = EP93XX_SDCE3_PHYS_BASE_ASYNC + 0x100,
        .map_io         = ep93xx_map_io,
        .init_irq       = ep93xx_init_irq,
        .timer          = &ep93xx_timer,
-       .init_machine   = micro9m_init_machine,
+       .init_machine   = micro9_init_machine,
 MACHINE_END
 #endif
 
-/*
- * Micro9-L
- */
 #ifdef CONFIG_MACH_MICRO9L
-static void __init micro9l_init_machine(void)
-{
-       ep93xx_init_devices();
-       micro9_init();
-}
-
-MACHINE_START(MICRO9L, "Contec Hypercontrol Micro9-L")
-       /* Maintainer: Manfred Gruber <manfred.gruber@contec.at> */
+MACHINE_START(MICRO9L, "Contec Micro9-Lite")
+       /* Maintainer: Hubert Feurstein <hubert.feurstein@contec.at> */
        .phys_io        = EP93XX_APB_PHYS_BASE,
        .io_pg_offst    = ((EP93XX_APB_VIRT_BASE) >> 18) & 0xfffc,
        .boot_params    = EP93XX_SDCE3_PHYS_BASE_SYNC + 0x100,
        .map_io         = ep93xx_map_io,
        .init_irq       = ep93xx_init_irq,
        .timer          = &ep93xx_timer,
-       .init_machine   = micro9l_init_machine,
+       .init_machine   = micro9_init_machine,
 MACHINE_END
 #endif
 
+#ifdef CONFIG_MACH_MICRO9S
+MACHINE_START(MICRO9S, "Contec Micro9-Slim")
+       /* Maintainer: Hubert Feurstein <hubert.feurstein@contec.at> */
+       .phys_io        = EP93XX_APB_PHYS_BASE,
+       .io_pg_offst    = ((EP93XX_APB_VIRT_BASE) >> 18) & 0xfffc,
+       .boot_params    = EP93XX_SDCE3_PHYS_BASE_ASYNC + 0x100,
+       .map_io         = ep93xx_map_io,
+       .init_irq       = ep93xx_init_irq,
+       .timer          = &ep93xx_timer,
+       .init_machine   = micro9_init_machine,
+MACHINE_END
+#endif
index 2b2e7a1..4891828 100644 (file)
@@ -28,5 +28,6 @@
 #define BUS_OFFSET     UL(0x80000000)
 #define __virt_to_bus(x)       ((x) - PAGE_OFFSET + BUS_OFFSET)
 #define __bus_to_virt(x)       ((x) - BUS_OFFSET + PAGE_OFFSET)
+#define __pfn_to_bus(x)                (((x) << PAGE_SHIFT) + BUS_OFFSET)
 
 #endif
index 901cc20..148d25f 100644 (file)
@@ -31,6 +31,7 @@
 
 #include <mach/hardware.h>
 #include <asm/irq.h>
+#include <asm/signal.h>
 #include <asm/system.h>
 #include <asm/mach/pci.h>
 #include <asm/irq_regs.h>
index 4089951..ff5e332 100644 (file)
@@ -638,9 +638,9 @@ static struct clk_lookup lookups[] = {
        _REGISTER_CLOCK("mxc-mmc.0", NULL, sdhc1_clk)
        _REGISTER_CLOCK("mxc-mmc.1", NULL, sdhc2_clk)
        _REGISTER_CLOCK("mxc-mmc.2", NULL, sdhc3_clk)
-       _REGISTER_CLOCK(NULL, "cspi1", cspi1_clk)
-       _REGISTER_CLOCK(NULL, "cspi2", cspi2_clk)
-       _REGISTER_CLOCK(NULL, "cspi3", cspi3_clk)
+       _REGISTER_CLOCK("spi_imx.0", NULL, cspi1_clk)
+       _REGISTER_CLOCK("spi_imx.1", NULL, cspi2_clk)
+       _REGISTER_CLOCK("spi_imx.2", NULL, cspi3_clk)
        _REGISTER_CLOCK("imx-fb.0", NULL, lcdc_clk)
        _REGISTER_CLOCK(NULL, "csi", csi_clk)
        _REGISTER_CLOCK("fsl-usb2-udc", "usb", usb_clk)
@@ -665,7 +665,7 @@ static struct clk_lookup lookups[] = {
        _REGISTER_CLOCK(NULL, "sahara2", sahara2_clk)
        _REGISTER_CLOCK(NULL, "ata", ata_clk)
        _REGISTER_CLOCK(NULL, "mstick", mstick_clk)
-       _REGISTER_CLOCK(NULL, "wdog", wdog_clk)
+       _REGISTER_CLOCK("imx-wdt.0", NULL, wdog_clk)
        _REGISTER_CLOCK(NULL, "gpio", gpio_clk)
        _REGISTER_CLOCK("imx-i2c.0", NULL, i2c1_clk)
        _REGISTER_CLOCK("imx-i2c.1", NULL, i2c2_clk)
index ee65dda..906d59b 100644 (file)
 #include <linux/mtd/plat-ram.h>
 #include <linux/mtd/physmap.h>
 #include <linux/platform_device.h>
+#include <linux/regulator/machine.h>
+#include <linux/mfd/mc13783.h>
+#include <linux/spi/spi.h>
+#include <linux/irq.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
@@ -35,6 +39,7 @@
 #include <mach/iomux.h>
 #include <mach/imx-uart.h>
 #include <mach/mxc_nand.h>
+#include <mach/spi.h>
 
 #include "devices.h"
 
@@ -78,8 +83,6 @@ static int pcm038_pins[] = {
        PC6_PF_I2C2_SCL,
        /* SPI1 */
        PD25_PF_CSPI1_RDY,
-       PD27_PF_CSPI1_SS1,
-       PD28_PF_CSPI1_SS0,
        PD29_PF_CSPI1_SCLK,
        PD30_PF_CSPI1_MISO,
        PD31_PF_CSPI1_MOSI,
@@ -196,6 +199,86 @@ static struct i2c_board_info pcm038_i2c_devices[] = {
        }
 };
 
+static int pcm038_spi_cs[] = {GPIO_PORTD + 28};
+
+static struct spi_imx_master pcm038_spi_0_data = {
+       .chipselect = pcm038_spi_cs,
+       .num_chipselect = ARRAY_SIZE(pcm038_spi_cs),
+};
+
+static struct regulator_consumer_supply sdhc1_consumers[] = {
+       {
+               .dev    = &mxc_sdhc_device1.dev,
+               .supply = "sdhc_vcc",
+       },
+};
+
+static struct regulator_init_data sdhc1_data = {
+       .constraints = {
+               .min_uV = 3000000,
+               .max_uV = 3400000,
+               .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE |
+                       REGULATOR_CHANGE_MODE | REGULATOR_CHANGE_STATUS,
+               .valid_modes_mask = REGULATOR_MODE_NORMAL |
+                       REGULATOR_MODE_FAST,
+               .always_on = 0,
+               .boot_on = 0,
+       },
+       .num_consumer_supplies = ARRAY_SIZE(sdhc1_consumers),
+       .consumer_supplies = sdhc1_consumers,
+};
+
+static struct regulator_consumer_supply cam_consumers[] = {
+       {
+               .dev    = NULL,
+               .supply = "imx_cam_vcc",
+       },
+};
+
+static struct regulator_init_data cam_data = {
+       .constraints = {
+               .min_uV = 3000000,
+               .max_uV = 3400000,
+               .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE |
+                       REGULATOR_CHANGE_MODE | REGULATOR_CHANGE_STATUS,
+               .valid_modes_mask = REGULATOR_MODE_NORMAL |
+                       REGULATOR_MODE_FAST,
+               .always_on = 0,
+               .boot_on = 0,
+       },
+       .num_consumer_supplies = ARRAY_SIZE(cam_consumers),
+       .consumer_supplies = cam_consumers,
+};
+
+struct mc13783_regulator_init_data pcm038_regulators[] = {
+       {
+               .id = MC13783_REGU_VCAM,
+               .init_data = &cam_data,
+       }, {
+               .id = MC13783_REGU_VMMC1,
+               .init_data = &sdhc1_data,
+       },
+};
+
+static struct mc13783_platform_data pcm038_pmic = {
+       .regulators = pcm038_regulators,
+       .num_regulators = ARRAY_SIZE(pcm038_regulators),
+       .flags = MC13783_USE_ADC | MC13783_USE_REGULATOR |
+                MC13783_USE_TOUCHSCREEN,
+};
+
+static struct spi_board_info pcm038_spi_board_info[] __initdata = {
+       {
+               .modalias = "mc13783",
+               .irq = IRQ_GPIOB(23),
+               .max_speed_hz = 300000,
+               .bus_num = 0,
+               .chip_select = 0,
+               .platform_data = &pcm038_pmic,
+               .mode = SPI_CS_HIGH,
+       }
+};
+
 static void __init pcm038_init(void)
 {
        mxc_gpio_setup_multiple_pins(pcm038_pins, ARRAY_SIZE(pcm038_pins),
@@ -219,6 +302,15 @@ static void __init pcm038_init(void)
        /* PE18 for user-LED D40 */
        mxc_gpio_mode(GPIO_PORTE | 18 | GPIO_GPIO | GPIO_OUT);
 
+       mxc_gpio_mode(GPIO_PORTD | 28 | GPIO_GPIO | GPIO_OUT);
+
+       /* MC13783 IRQ */
+       mxc_gpio_mode(GPIO_PORTB | 23 | GPIO_GPIO | GPIO_IN);
+
+       mxc_register_device(&mxc_spi_device0, &pcm038_spi_0_data);
+       spi_register_board_info(pcm038_spi_board_info,
+                               ARRAY_SIZE(pcm038_spi_board_info));
+
        platform_add_devices(platform_devices, ARRAY_SIZE(platform_devices));
 
 #ifdef CONFIG_MACH_PCM970_BASEBOARD
index c261f59..3cb7f45 100644 (file)
@@ -39,7 +39,6 @@ static int pcm970_pins[] = {
        PB7_PF_SD2_D3,
        PB8_PF_SD2_CMD,
        PB9_PF_SD2_CLK,
-       GPIO_PORTC | 28 | GPIO_GPIO | GPIO_IN, /* card detect */
        /* display */
        PA5_PF_LSCLK,
        PA6_PF_LD0,
@@ -228,6 +227,7 @@ void __init pcm970_baseboard_init(void)
                        "PCM970");
 
        mxc_register_device(&mxc_fb_device, &pcm038_fb_data);
+       mxc_gpio_mode(GPIO_PORTC | 28 | GPIO_GPIO | GPIO_IN);
        mxc_register_device(&mxc_sdhc_device1, &sdhc_pdata);
        platform_device_register(&pcm970_sja1000);
 }
index eb12de1..63511de 100644 (file)
@@ -1,4 +1,23 @@
+/*
+ * Copyright 2009 Sascha Hauer, <kernel@pengutronix.de>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA  02110-1301, USA.
+ */
+
 #include <linux/platform_device.h>
+#include <linux/dma-mapping.h>
 #include <linux/gpio.h>
 #include <mach/mx25.h>
 #include <mach/irqs.h>
index 92aa4fd..d23ae57 100644 (file)
@@ -1,3 +1,21 @@
+/*
+ * Copyright 2009 Sascha Hauer, <kernel@pengutronix.de>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA  02110-1301, USA.
+ */
+
 #include <linux/types.h>
 #include <linux/init.h>
 #include <linux/clk.h>
@@ -23,19 +41,12 @@ static struct imxuart_platform_data uart_pdata = {
        .flags = IMXUART_HAVE_RTSCTS,
 };
 
-static struct mxc_nand_platform_data nand_board_info = {
-       .width = 1,
-       .hw_ecc = 1,
-};
-
 static void __init mx25pdk_init(void)
 {
        mxc_register_device(&mxc_uart_device0, &uart_pdata);
        mxc_register_device(&mxc_usbh2, NULL);
-       mxc_register_device(&mxc_nand_device, &nand_board_info);
 }
 
-
 static void __init mx25pdk_timer_init(void)
 {
        mx25_clocks_init(26000000);
index fe5c421..c595260 100644 (file)
@@ -443,7 +443,7 @@ static struct clk_lookup lookups[] = {
        _REGISTER_CLOCK("mxc-ehci.1", "usb", usbotg_clk)
        _REGISTER_CLOCK("mxc-ehci.2", "usb", usbotg_clk)
        _REGISTER_CLOCK("fsl-usb2-udc", "usb", usbotg_clk)
-       _REGISTER_CLOCK("mxc_wdt.0", NULL, wdog_clk)
+       _REGISTER_CLOCK("imx-wdt.0", NULL, wdog_clk)
        _REGISTER_CLOCK(NULL, "max", max_clk)
        _REGISTER_CLOCK(NULL, "admux", admux_clk)
        _REGISTER_CLOCK(NULL, "csi", csi_clk)
index 06bd618..b2a3bcf 100644 (file)
@@ -530,7 +530,7 @@ static struct clk_lookup lookups[] = {
        _REGISTER_CLOCK("spi_imx.2", NULL, cspi3_clk)
        _REGISTER_CLOCK(NULL, "gpt", gpt_clk)
        _REGISTER_CLOCK(NULL, "pwm", pwm_clk)
-       _REGISTER_CLOCK(NULL, "wdog", wdog_clk)
+       _REGISTER_CLOCK("imx-wdt.0", NULL, wdog_clk)
        _REGISTER_CLOCK(NULL, "rtc", rtc_clk)
        _REGISTER_CLOCK(NULL, "epit", epit1_clk)
        _REGISTER_CLOCK(NULL, "epit", epit2_clk)
index 8a577f3..e6abe18 100644 (file)
@@ -459,7 +459,7 @@ struct platform_device mxc_usbh2 = {
  * SPI master controller
  * 3 channels
  */
-static struct resource imx_spi_0_resources[] = {
+static struct resource mxc_spi_0_resources[] = {
        {
               .start = CSPI1_BASE_ADDR,
               .end = CSPI1_BASE_ADDR + SZ_4K - 1,
@@ -471,7 +471,7 @@ static struct resource imx_spi_0_resources[] = {
        },
 };
 
-static struct resource imx_spi_1_resources[] = {
+static struct resource mxc_spi_1_resources[] = {
        {
                .start = CSPI2_BASE_ADDR,
                .end = CSPI2_BASE_ADDR + SZ_4K - 1,
@@ -483,7 +483,7 @@ static struct resource imx_spi_1_resources[] = {
        },
 };
 
-static struct resource imx_spi_2_resources[] = {
+static struct resource mxc_spi_2_resources[] = {
        {
                .start = CSPI3_BASE_ADDR,
                .end = CSPI3_BASE_ADDR + SZ_4K - 1,
@@ -495,25 +495,25 @@ static struct resource imx_spi_2_resources[] = {
        },
 };
 
-struct platform_device imx_spi_device0 = {
+struct platform_device mxc_spi_device0 = {
        .name = "spi_imx",
        .id = 0,
-       .num_resources = ARRAY_SIZE(imx_spi_0_resources),
-       .resource = imx_spi_0_resources,
+       .num_resources = ARRAY_SIZE(mxc_spi_0_resources),
+       .resource = mxc_spi_0_resources,
 };
 
-struct platform_device imx_spi_device1 = {
+struct platform_device mxc_spi_device1 = {
        .name = "spi_imx",
        .id = 1,
-       .num_resources = ARRAY_SIZE(imx_spi_1_resources),
-       .resource = imx_spi_1_resources,
+       .num_resources = ARRAY_SIZE(mxc_spi_1_resources),
+       .resource = mxc_spi_1_resources,
 };
 
-struct platform_device imx_spi_device2 = {
+struct platform_device mxc_spi_device2 = {
        .name = "spi_imx",
        .id = 2,
-       .num_resources = ARRAY_SIZE(imx_spi_2_resources),
-       .resource = imx_spi_2_resources,
+       .num_resources = ARRAY_SIZE(mxc_spi_2_resources),
+       .resource = mxc_spi_2_resources,
 };
 
 #ifdef CONFIG_ARCH_MX35
index 79f2be4..ab87419 100644 (file)
@@ -20,7 +20,7 @@ extern struct platform_device mxc_otg_host;
 extern struct platform_device mxc_usbh1;
 extern struct platform_device mxc_usbh2;
 extern struct platform_device mxc_rnga_device;
-extern struct platform_device imx_spi_device0;
-extern struct platform_device imx_spi_device1;
-extern struct platform_device imx_spi_device2;
+extern struct platform_device mxc_spi_device0;
+extern struct platform_device mxc_spi_device1;
+extern struct platform_device mxc_spi_device2;
 
index ad5a112..bedf5b8 100644 (file)
@@ -81,6 +81,7 @@ void __init mx31_map_io(void)
        iotable_init(mxc_io_desc, ARRAY_SIZE(mxc_io_desc));
 }
 
+#ifdef CONFIG_ARCH_MX35
 void __init mx35_map_io(void)
 {
        mxc_set_cpu_type(MXC_CPU_MX35);
@@ -89,6 +90,7 @@ void __init mx35_map_io(void)
 
        iotable_init(mxc_io_desc, ARRAY_SIZE(mxc_io_desc));
 }
+#endif
 
 void __init mx31_init_irq(void)
 {
index 42920f9..8ad5cc3 100644 (file)
@@ -219,6 +219,10 @@ static struct platform_device *ams_delta_devices[] __initdata = {
 
 static void __init ams_delta_init(void)
 {
+       /* mux pins for uarts */
+       omap_cfg_reg(UART1_TX);
+       omap_cfg_reg(UART1_RTS);
+
        iotable_init(ams_delta_io_desc, ARRAY_SIZE(ams_delta_io_desc));
 
        omap_board_config = ams_delta_config;
@@ -231,6 +235,8 @@ static void __init ams_delta_init(void)
 
        omap_usb_init(&ams_delta_usb_config);
        platform_add_devices(ams_delta_devices, ARRAY_SIZE(ams_delta_devices));
+
+       omap_writew(omap_readw(ARM_RSTCT1) | 0x0004, ARM_RSTCT1);
 }
 
 static struct plat_serial8250_port ams_delta_modem_ports[] = {
index fb47239..6c8a41f 100644 (file)
@@ -64,6 +64,14 @@ static void __init omap_generic_init(void)
 {
 #ifdef CONFIG_ARCH_OMAP15XX
        if (cpu_is_omap15xx()) {
+               /* mux pins for uarts */
+               omap_cfg_reg(UART1_TX);
+               omap_cfg_reg(UART1_RTS);
+               omap_cfg_reg(UART2_TX);
+               omap_cfg_reg(UART2_RTS);
+               omap_cfg_reg(UART3_TX);
+               omap_cfg_reg(UART3_RX);
+
                omap_usb_init(&generic1510_usb_config);
        }
 #endif
index cc2abbb..cd6c395 100644 (file)
@@ -376,6 +376,26 @@ static void __init innovator_init(void)
 {
 #ifdef CONFIG_ARCH_OMAP15XX
        if (cpu_is_omap1510()) {
+               unsigned char reg;
+
+               /* mux pins for uarts */
+               omap_cfg_reg(UART1_TX);
+               omap_cfg_reg(UART1_RTS);
+               omap_cfg_reg(UART2_TX);
+               omap_cfg_reg(UART2_RTS);
+               omap_cfg_reg(UART3_TX);
+               omap_cfg_reg(UART3_RX);
+
+               reg = fpga_read(OMAP1510_FPGA_POWER);
+               reg |= OMAP1510_FPGA_PCR_COM1_EN;
+               fpga_write(reg, OMAP1510_FPGA_POWER);
+               udelay(10);
+
+               reg = fpga_read(OMAP1510_FPGA_POWER);
+               reg |= OMAP1510_FPGA_PCR_COM2_EN;
+               fpga_write(reg, OMAP1510_FPGA_POWER);
+               udelay(10);
+
                platform_add_devices(innovator1510_devices, ARRAY_SIZE(innovator1510_devices));
                spi_register_board_info(innovator1510_boardinfo,
                                ARRAY_SIZE(innovator1510_boardinfo));
index 90dd043..4de2584 100644 (file)
@@ -342,6 +342,14 @@ static void __init palmte_misc_gpio_setup(void)
 
 static void __init omap_palmte_init(void)
 {
+       /* mux pins for uarts */
+       omap_cfg_reg(UART1_TX);
+       omap_cfg_reg(UART1_RTS);
+       omap_cfg_reg(UART2_TX);
+       omap_cfg_reg(UART2_RTS);
+       omap_cfg_reg(UART3_TX);
+       omap_cfg_reg(UART3_RX);
+
        omap_board_config = palmte_config;
        omap_board_config_size = ARRAY_SIZE(palmte_config);
 
index 8256139..d972cf9 100644 (file)
@@ -289,6 +289,14 @@ static void __init omap_mpu_wdt_mode(int mode) {
 
 static void __init omap_palmtt_init(void)
 {
+       /* mux pins for uarts */
+       omap_cfg_reg(UART1_TX);
+       omap_cfg_reg(UART1_RTS);
+       omap_cfg_reg(UART2_TX);
+       omap_cfg_reg(UART2_RTS);
+       omap_cfg_reg(UART3_TX);
+       omap_cfg_reg(UART3_RX);
+
        omap_mpu_wdt_mode(0);
 
        omap_board_config = palmtt_config;
index 81b6bde..986bd4d 100644 (file)
@@ -307,6 +307,14 @@ palmz71_gpio_setup(int early)
 static void __init
 omap_palmz71_init(void)
 {
+       /* mux pins for uarts */
+       omap_cfg_reg(UART1_TX);
+       omap_cfg_reg(UART1_RTS);
+       omap_cfg_reg(UART2_TX);
+       omap_cfg_reg(UART2_RTS);
+       omap_cfg_reg(UART3_TX);
+       omap_cfg_reg(UART3_RX);
+
        palmz71_gpio_setup(1);
        omap_mpu_wdt_mode(0);
 
index 02c85ca..056ae64 100644 (file)
@@ -377,6 +377,14 @@ static struct omap_board_config_kernel sx1_config[] __initdata = {
 
 static void __init omap_sx1_init(void)
 {
+       /* mux pins for uarts */
+       omap_cfg_reg(UART1_TX);
+       omap_cfg_reg(UART1_RTS);
+       omap_cfg_reg(UART2_TX);
+       omap_cfg_reg(UART2_RTS);
+       omap_cfg_reg(UART3_TX);
+       omap_cfg_reg(UART3_RX);
+
        platform_add_devices(sx1_devices, ARRAY_SIZE(sx1_devices));
 
        omap_board_config = sx1_config;
index c06e7a5..07b0752 100644 (file)
@@ -152,6 +152,14 @@ static void __init voiceblue_init_irq(void)
 
 static void __init voiceblue_init(void)
 {
+       /* mux pins for uarts */
+       omap_cfg_reg(UART1_TX);
+       omap_cfg_reg(UART1_RTS);
+       omap_cfg_reg(UART2_TX);
+       omap_cfg_reg(UART2_RTS);
+       omap_cfg_reg(UART3_TX);
+       omap_cfg_reg(UART3_RX);
+
        /* Watchdog */
        gpio_request(0, "Watchdog");
        /* smc91x reset */
index d496e50..d23979b 100644 (file)
@@ -131,8 +131,6 @@ void __init omap_serial_init(void)
        }
 
        for (i = 0; i < OMAP_MAX_NR_PORTS; i++) {
-               unsigned char reg;
-
                switch (i) {
                case 0:
                        uart1_ck = clk_get(NULL, "uart1_ck");
@@ -143,16 +141,6 @@ void __init omap_serial_init(void)
                                if (cpu_is_omap15xx())
                                        clk_set_rate(uart1_ck, 12000000);
                        }
-                       if (cpu_is_omap15xx()) {
-                               omap_cfg_reg(UART1_TX);
-                               omap_cfg_reg(UART1_RTS);
-                               if (machine_is_omap_innovator()) {
-                                       reg = fpga_read(OMAP1510_FPGA_POWER);
-                                       reg |= OMAP1510_FPGA_PCR_COM1_EN;
-                                       fpga_write(reg, OMAP1510_FPGA_POWER);
-                                       udelay(10);
-                               }
-                       }
                        break;
                case 1:
                        uart2_ck = clk_get(NULL, "uart2_ck");
@@ -165,16 +153,6 @@ void __init omap_serial_init(void)
                                else
                                        clk_set_rate(uart2_ck, 48000000);
                        }
-                       if (cpu_is_omap15xx()) {
-                               omap_cfg_reg(UART2_TX);
-                               omap_cfg_reg(UART2_RTS);
-                               if (machine_is_omap_innovator()) {
-                                       reg = fpga_read(OMAP1510_FPGA_POWER);
-                                       reg |= OMAP1510_FPGA_PCR_COM2_EN;
-                                       fpga_write(reg, OMAP1510_FPGA_POWER);
-                                       udelay(10);
-                               }
-                       }
                        break;
                case 2:
                        uart3_ck = clk_get(NULL, "uart3_ck");
@@ -185,10 +163,6 @@ void __init omap_serial_init(void)
                                if (cpu_is_omap15xx())
                                        clk_set_rate(uart3_ck, 12000000);
                        }
-                       if (cpu_is_omap15xx()) {
-                               omap_cfg_reg(UART3_TX);
-                               omap_cfg_reg(UART3_RX);
-                       }
                        break;
                }
                omap_serial_reset(&serial_platform_data[i]);
index 75b1c7e..aad194f 100644 (file)
@@ -73,9 +73,21 @@ config MACH_OMAP_3430SDP
        bool "OMAP 3430 SDP board"
        depends on ARCH_OMAP3 && ARCH_OMAP34XX
 
+config MACH_NOKIA_N800
+       bool
+
+config MACH_NOKIA_N810
+       bool
+
+config MACH_NOKIA_N810_WIMAX
+       bool
+
 config MACH_NOKIA_N8X0
        bool "Nokia N800/N810"
        depends on ARCH_OMAP2420
+       select MACH_NOKIA_N800
+       select MACH_NOKIA_N810
+       select MACH_NOKIA_N810_WIMAX
 
 config MACH_NOKIA_RX51
        bool "Nokia RX-51 board"
index efaf053..0acb556 100644 (file)
@@ -17,6 +17,7 @@
 #include <linux/platform_device.h>
 #include <linux/delay.h>
 #include <linux/input.h>
+#include <linux/input/matrix_keypad.h>
 #include <linux/spi/spi.h>
 #include <linux/spi/ads7846.h>
 #include <linux/i2c/twl4030.h>
@@ -38,7 +39,6 @@
 #include <mach/gpmc.h>
 
 #include <mach/control.h>
-#include <mach/keypad.h>
 #include <mach/gpmc-smc91x.h>
 
 #include "sdram-qimonda-hyb18m512160af-6.h"
index eb37c40..609a5a4 100644 (file)
@@ -58,6 +58,8 @@ static void __init gic_init_irq(void)
 
 static void __init omap_4430sdp_init_irq(void)
 {
+       omap_board_config = sdp4430_config;
+       omap_board_config_size = ARRAY_SIZE(sdp4430_config);
        omap2_init_common_hw(NULL, NULL);
 #ifdef CONFIG_OMAP_32K_TIMER
        omap2_gp_clockevent_set_gptimer(1);
@@ -70,8 +72,6 @@ static void __init omap_4430sdp_init_irq(void)
 static void __init omap_4430sdp_init(void)
 {
        platform_add_devices(sdp4430_devices, ARRAY_SIZE(sdp4430_devices));
-       omap_board_config = sdp4430_config;
-       omap_board_config_size = ARRAY_SIZE(sdp4430_config);
        omap_serial_init();
 }
 
index d110a7f..d57ec2f 100644 (file)
@@ -16,6 +16,7 @@
 #include <linux/platform_device.h>
 #include <linux/delay.h>
 #include <linux/input.h>
+#include <linux/input/matrix_keypad.h>
 #include <linux/gpio_keys.h>
 #include <linux/workqueue.h>
 #include <linux/err.h>
@@ -41,7 +42,6 @@
 #include <asm/delay.h>
 #include <mach/control.h>
 #include <mach/usb.h>
-#include <mach/keypad.h>
 
 #include "mmc-twl4030.h"
 
index e4ec0c5..4c4d7f8 100644 (file)
@@ -20,6 +20,7 @@
 #include <linux/clk.h>
 #include <linux/gpio.h>
 #include <linux/input.h>
+#include <linux/input/matrix_keypad.h>
 #include <linux/leds.h>
 
 #include <linux/spi/spi.h>
@@ -37,7 +38,6 @@
 #include <mach/usb.h>
 #include <mach/common.h>
 #include <mach/mcspi.h>
-#include <mach/keypad.h>
 
 #include "sdram-micron-mt46h32m32lf-6.h"
 #include "mmc-twl4030.h"
index 7f6bf87..5326e0d 100644 (file)
@@ -27,6 +27,7 @@
 #include <linux/i2c/twl4030.h>
 #include <linux/leds.h>
 #include <linux/input.h>
+#include <linux/input/matrix_keypad.h>
 #include <linux/gpio_keys.h>
 
 #include <asm/mach-types.h>
@@ -39,7 +40,6 @@
 #include <mach/hardware.h>
 #include <mach/mcspi.h>
 #include <mach/usb.h>
-#include <mach/keypad.h>
 #include <mach/mux.h>
 
 #include "sdram-micron-mt46h32m32lf-6.h"
index b45ad31..e34d96a 100644 (file)
@@ -12,6 +12,7 @@
 #include <linux/init.h>
 #include <linux/platform_device.h>
 #include <linux/input.h>
+#include <linux/input/matrix_keypad.h>
 #include <linux/spi/spi.h>
 #include <linux/i2c.h>
 #include <linux/i2c/twl4030.h>
@@ -27,7 +28,6 @@
 #include <mach/common.h>
 #include <mach/dma.h>
 #include <mach/gpmc.h>
-#include <mach/keypad.h>
 #include <mach/onenand.h>
 #include <mach/gpmc-smc91x.h>
 
 
 static int board_keymap[] = {
        KEY(0, 0, KEY_Q),
-       KEY(0, 1, KEY_W),
-       KEY(0, 2, KEY_E),
-       KEY(0, 3, KEY_R),
-       KEY(0, 4, KEY_T),
-       KEY(0, 5, KEY_Y),
-       KEY(0, 6, KEY_U),
-       KEY(0, 7, KEY_I),
-       KEY(1, 0, KEY_O),
+       KEY(0, 1, KEY_O),
+       KEY(0, 2, KEY_P),
+       KEY(0, 3, KEY_COMMA),
+       KEY(0, 4, KEY_BACKSPACE),
+       KEY(0, 6, KEY_A),
+       KEY(0, 7, KEY_S),
+       KEY(1, 0, KEY_W),
        KEY(1, 1, KEY_D),
-       KEY(1, 2, KEY_DOT),
-       KEY(1, 3, KEY_V),
-       KEY(1, 4, KEY_DOWN),
-       KEY(2, 0, KEY_P),
-       KEY(2, 1, KEY_F),
+       KEY(1, 2, KEY_F),
+       KEY(1, 3, KEY_G),
+       KEY(1, 4, KEY_H),
+       KEY(1, 5, KEY_J),
+       KEY(1, 6, KEY_K),
+       KEY(1, 7, KEY_L),
+       KEY(2, 0, KEY_E),
+       KEY(2, 1, KEY_DOT),
        KEY(2, 2, KEY_UP),
-       KEY(2, 3, KEY_B),
-       KEY(2, 4, KEY_RIGHT),
-       KEY(3, 0, KEY_COMMA),
-       KEY(3, 1, KEY_G),
-       KEY(3, 2, KEY_ENTER),
+       KEY(2, 3, KEY_ENTER),
+       KEY(2, 5, KEY_Z),
+       KEY(2, 6, KEY_X),
+       KEY(2, 7, KEY_C),
+       KEY(3, 0, KEY_R),
+       KEY(3, 1, KEY_V),
+       KEY(3, 2, KEY_B),
        KEY(3, 3, KEY_N),
-       KEY(4, 0, KEY_BACKSPACE),
-       KEY(4, 1, KEY_H),
-       KEY(4, 3, KEY_M),
+       KEY(3, 4, KEY_M),
+       KEY(3, 5, KEY_SPACE),
+       KEY(3, 6, KEY_SPACE),
+       KEY(3, 7, KEY_LEFT),
+       KEY(4, 0, KEY_T),
+       KEY(4, 1, KEY_DOWN),
+       KEY(4, 2, KEY_RIGHT),
        KEY(4, 4, KEY_LEFTCTRL),
-       KEY(5, 1, KEY_J),
-       KEY(5, 2, KEY_Z),
-       KEY(5, 3, KEY_SPACE),
-       KEY(5, 4, KEY_LEFTSHIFT),
-       KEY(6, 0, KEY_A),
-       KEY(6, 1, KEY_K),
-       KEY(6, 2, KEY_X),
-       KEY(6, 3, KEY_SPACE),
-       KEY(6, 4, KEY_FN),
-       KEY(7, 0, KEY_S),
-       KEY(7, 1, KEY_L),
-       KEY(7, 2, KEY_C),
-       KEY(7, 3, KEY_LEFT),
-       KEY(0xff, 0, KEY_F6),
-       KEY(0xff, 1, KEY_F7),
-       KEY(0xff, 2, KEY_F8),
-       KEY(0xff, 4, KEY_F9),
-       KEY(0xff, 5, KEY_F10),
+       KEY(4, 5, KEY_RIGHTALT),
+       KEY(4, 6, KEY_LEFTSHIFT),
+       KEY(5, 0, KEY_Y),
+       KEY(6, 0, KEY_U),
+       KEY(7, 0, KEY_I),
+       KEY(7, 1, KEY_F7),
+       KEY(7, 2, KEY_F8),
+       KEY(0xff, 2, KEY_F9),
+       KEY(0xff, 4, KEY_F10),
+       KEY(0xff, 5, KEY_F11),
 };
 
 static struct matrix_keymap_data board_map_data = {
@@ -444,7 +444,7 @@ static int __init rx51_i2c_init(void)
                rx51_twldata.vaux3 = &rx51_vaux3_cam;
                rx51_twldata.vmmc2 = &rx51_vmmc2;
        }
-       omap_register_i2c_bus(1, 2600, rx51_peripherals_i2c_board_info_1,
+       omap_register_i2c_bus(1, 2200, rx51_peripherals_i2c_board_info_1,
                        ARRAY_SIZE(rx51_peripherals_i2c_board_info_1));
        omap_register_i2c_bus(2, 100, NULL, 0);
        omap_register_i2c_bus(3, 400, NULL, 0);
index f9196c3..78869a9 100644 (file)
@@ -26,7 +26,6 @@
 #include <mach/mux.h>
 #include <mach/board.h>
 #include <mach/common.h>
-#include <mach/keypad.h>
 #include <mach/dma.h>
 #include <mach/gpmc.h>
 #include <mach/usb.h>
index b7b3220..ea00486 100644 (file)
@@ -13,6 +13,7 @@
 #include <linux/init.h>
 #include <linux/platform_device.h>
 #include <linux/input.h>
+#include <linux/input/matrix_keypad.h>
 #include <linux/gpio.h>
 #include <linux/i2c/twl4030.h>
 #include <linux/regulator/machine.h>
@@ -22,9 +23,9 @@
 
 #include <mach/common.h>
 #include <mach/usb.h>
-#include <mach/keypad.h>
 
 #include "mmc-twl4030.h"
+#include "sdram-micron-mt46h32m32lf-6.h"
 
 /* Zoom2 has Qwerty keyboard*/
 static int board_keymap[] = {
@@ -213,7 +214,8 @@ static void __init omap_zoom2_init_irq(void)
 {
        omap_board_config = zoom2_config;
        omap_board_config_size = ARRAY_SIZE(zoom2_config);
-       omap2_init_common_hw(NULL, NULL);
+       omap2_init_common_hw(mt46h32m32lf6_sdrc_params,
+                                mt46h32m32lf6_sdrc_params);
        omap_init_irq();
        omap_gpio_init();
 }
index bc5d3ac..e2dbedd 100644 (file)
@@ -769,6 +769,7 @@ int __init omap2_clk_init(void)
                if (c->cpu & cpu_mask) {
                        clkdev_add(&c->lk);
                        clk_register(c->lk.clk);
+                       omap2_init_clk_clkdm(c->lk.clk);
                }
 
        /* Check the MPU rate set by bootloader */
index fafcd32..489556e 100644 (file)
@@ -338,6 +338,13 @@ static struct omap_clk omap34xx_clks[] = {
  */
 #define SDRC_MPURATE_LOOPS             96
 
+/*
+ * DPLL5_FREQ_FOR_USBHOST: USBHOST and USBTLL are the only clocks
+ * that are sourced by DPLL5, and both of these require this clock
+ * to be at 120 MHz for proper operation.
+ */
+#define DPLL5_FREQ_FOR_USBHOST         120000000
+
 /**
  * omap3430es2_clk_ssi_find_idlest - return CM_IDLEST info for SSI
  * @clk: struct clk * being enabled
@@ -1056,6 +1063,28 @@ void omap2_clk_prepare_for_reboot(void)
 #endif
 }
 
+static void omap3_clk_lock_dpll5(void)
+{
+       struct clk *dpll5_clk;
+       struct clk *dpll5_m2_clk;
+
+       dpll5_clk = clk_get(NULL, "dpll5_ck");
+       clk_set_rate(dpll5_clk, DPLL5_FREQ_FOR_USBHOST);
+       clk_enable(dpll5_clk);
+
+       /* Enable autoidle to allow it to enter low power bypass */
+       omap3_dpll_allow_idle(dpll5_clk);
+
+       /* Program dpll5_m2_clk divider for no division */
+       dpll5_m2_clk = clk_get(NULL, "dpll5_m2_ck");
+       clk_enable(dpll5_m2_clk);
+       clk_set_rate(dpll5_m2_clk, DPLL5_FREQ_FOR_USBHOST);
+
+       clk_disable(dpll5_m2_clk);
+       clk_disable(dpll5_clk);
+       return;
+}
+
 /* REVISIT: Move this init stuff out into clock.c */
 
 /*
@@ -1148,6 +1177,12 @@ int __init omap2_clk_init(void)
         */
        clk_enable_init_clocks();
 
+       /*
+        * Lock DPLL5 and put it in autoidle.
+        */
+       if (omap_rev() >= OMAP3430_REV_ES2_0)
+               omap3_clk_lock_dpll5();
+
        /* Avoid sleeping during omap2_clk_prepare_for_reboot() */
        /* REVISIT: not yet ready for 343x */
 #if 0
index 4ef7b4f..58aff84 100644 (file)
@@ -137,6 +137,36 @@ static void _clkdm_del_autodeps(struct clockdomain *clkdm)
        }
 }
 
+/*
+ * _omap2_clkdm_set_hwsup - set the hwsup idle transition bit
+ * @clkdm: struct clockdomain *
+ * @enable: int 0 to disable, 1 to enable
+ *
+ * Internal helper for actually switching the bit that controls hwsup
+ * idle transitions for clkdm.
+ */
+static void _omap2_clkdm_set_hwsup(struct clockdomain *clkdm, int enable)
+{
+       u32 v;
+
+       if (cpu_is_omap24xx()) {
+               if (enable)
+                       v = OMAP24XX_CLKSTCTRL_ENABLE_AUTO;
+               else
+                       v = OMAP24XX_CLKSTCTRL_DISABLE_AUTO;
+       } else if (cpu_is_omap34xx()) {
+               if (enable)
+                       v = OMAP34XX_CLKSTCTRL_ENABLE_AUTO;
+               else
+                       v = OMAP34XX_CLKSTCTRL_DISABLE_AUTO;
+       } else {
+               BUG();
+       }
+
+       cm_rmw_mod_reg_bits(clkdm->clktrctrl_mask,
+                           v << __ffs(clkdm->clktrctrl_mask),
+                           clkdm->pwrdm.ptr->prcm_offs, CM_CLKSTCTRL);
+}
 
 static struct clockdomain *_clkdm_lookup(const char *name)
 {
@@ -456,8 +486,6 @@ int omap2_clkdm_wakeup(struct clockdomain *clkdm)
  */
 void omap2_clkdm_allow_idle(struct clockdomain *clkdm)
 {
-       u32 v;
-
        if (!clkdm)
                return;
 
@@ -473,18 +501,7 @@ void omap2_clkdm_allow_idle(struct clockdomain *clkdm)
        if (atomic_read(&clkdm->usecount) > 0)
                _clkdm_add_autodeps(clkdm);
 
-       if (cpu_is_omap24xx())
-               v = OMAP24XX_CLKSTCTRL_ENABLE_AUTO;
-       else if (cpu_is_omap34xx())
-               v = OMAP34XX_CLKSTCTRL_ENABLE_AUTO;
-       else
-               BUG();
-
-
-       cm_rmw_mod_reg_bits(clkdm->clktrctrl_mask,
-                           v << __ffs(clkdm->clktrctrl_mask),
-                           clkdm->pwrdm.ptr->prcm_offs,
-                           CM_CLKSTCTRL);
+       _omap2_clkdm_set_hwsup(clkdm, 1);
 
        pwrdm_clkdm_state_switch(clkdm);
 }
@@ -500,8 +517,6 @@ void omap2_clkdm_allow_idle(struct clockdomain *clkdm)
  */
 void omap2_clkdm_deny_idle(struct clockdomain *clkdm)
 {
-       u32 v;
-
        if (!clkdm)
                return;
 
@@ -514,16 +529,7 @@ void omap2_clkdm_deny_idle(struct clockdomain *clkdm)
        pr_debug("clockdomain: disabling automatic idle transitions for %s\n",
                 clkdm->name);
 
-       if (cpu_is_omap24xx())
-               v = OMAP24XX_CLKSTCTRL_DISABLE_AUTO;
-       else if (cpu_is_omap34xx())
-               v = OMAP34XX_CLKSTCTRL_DISABLE_AUTO;
-       else
-               BUG();
-
-       cm_rmw_mod_reg_bits(clkdm->clktrctrl_mask,
-                           v << __ffs(clkdm->clktrctrl_mask),
-                           clkdm->pwrdm.ptr->prcm_offs, CM_CLKSTCTRL);
+       _omap2_clkdm_set_hwsup(clkdm, 0);
 
        if (atomic_read(&clkdm->usecount) > 0)
                _clkdm_del_autodeps(clkdm);
@@ -569,10 +575,14 @@ int omap2_clkdm_clk_enable(struct clockdomain *clkdm, struct clk *clk)
        v = omap2_clkdm_clktrctrl_read(clkdm);
 
        if ((cpu_is_omap34xx() && v == OMAP34XX_CLKSTCTRL_ENABLE_AUTO) ||
-           (cpu_is_omap24xx() && v == OMAP24XX_CLKSTCTRL_ENABLE_AUTO))
+           (cpu_is_omap24xx() && v == OMAP24XX_CLKSTCTRL_ENABLE_AUTO)) {
+               /* Disable HW transitions when we are changing deps */
+               _omap2_clkdm_set_hwsup(clkdm, 0);
                _clkdm_add_autodeps(clkdm);
-       else
+               _omap2_clkdm_set_hwsup(clkdm, 1);
+       } else {
                omap2_clkdm_wakeup(clkdm);
+       }
 
        pwrdm_wait_transition(clkdm->pwrdm.ptr);
        pwrdm_clkdm_state_switch(clkdm);
@@ -623,10 +633,14 @@ int omap2_clkdm_clk_disable(struct clockdomain *clkdm, struct clk *clk)
        v = omap2_clkdm_clktrctrl_read(clkdm);
 
        if ((cpu_is_omap34xx() && v == OMAP34XX_CLKSTCTRL_ENABLE_AUTO) ||
-           (cpu_is_omap24xx() && v == OMAP24XX_CLKSTCTRL_ENABLE_AUTO))
+           (cpu_is_omap24xx() && v == OMAP24XX_CLKSTCTRL_ENABLE_AUTO)) {
+               /* Disable HW transitions when we are changing deps */
+               _omap2_clkdm_set_hwsup(clkdm, 0);
                _clkdm_del_autodeps(clkdm);
-       else
+               _omap2_clkdm_set_hwsup(clkdm, 1);
+       } else {
                omap2_clkdm_sleep(clkdm);
+       }
 
        pwrdm_clkdm_state_switch(clkdm);
 
index e3a3bad..56be87d 100644 (file)
@@ -302,7 +302,9 @@ void __init omap2_init_common_hw(struct omap_sdrc_params *sdrc_cs0,
        pwrdm_init(powerdomains_omap);
        clkdm_init(clockdomains_omap, clkdm_pwrdm_autodeps);
        omap2_clk_init();
+#endif
        omap_serial_early_init();
+#ifndef CONFIG_ARCH_OMAP4
        omap_hwmod_late_init();
        omap_pm_if_init();
        omap2_sdrc_init(sdrc_cs0, sdrc_cs1);
index 1b4c160..2fc4d6a 100644 (file)
@@ -541,7 +541,7 @@ static int __init pm_dbg_init(void)
                printk(KERN_ERR "%s: only OMAP3 supported\n", __func__);
                return -ENODEV;
        }
-               
+
        d = debugfs_create_dir("pm_debug", NULL);
        if (IS_ERR(d))
                return PTR_ERR(d);
@@ -551,7 +551,7 @@ static int __init pm_dbg_init(void)
        (void) debugfs_create_file("time", S_IRUGO,
                d, (void *)DEBUG_FILE_TIMERS, &debug_fops);
 
-       pwrdm_for_each(pwrdms_setup, (void *)d);
+       pwrdm_for_each_nolock(pwrdms_setup, (void *)d);
 
        pm_dbg_dir = debugfs_create_dir("registers", d);
        if (IS_ERR(pm_dbg_dir))
index 0ff5a6c..8946319 100644 (file)
@@ -51,97 +51,112 @@ static void (*_omap_sram_idle)(u32 *addr, int save_state);
 
 static struct powerdomain *mpu_pwrdm;
 
-/* PRCM Interrupt Handler for wakeups */
-static irqreturn_t prcm_interrupt_handler (int irq, void *dev_id)
+/*
+ * PRCM Interrupt Handler Helper Function
+ *
+ * The purpose of this function is to clear any wake-up events latched
+ * in the PRCM PM_WKST_x registers. It is possible that a wake-up event
+ * may occur whilst attempting to clear a PM_WKST_x register and thus
+ * set another bit in this register. A while loop is used to ensure
+ * that any peripheral wake-up events occurring while attempting to
+ * clear the PM_WKST_x are detected and cleared.
+ */
+static int prcm_clear_mod_irqs(s16 module, u8 regs)
 {
-       u32 wkst, irqstatus_mpu;
-       u32 fclk, iclk;
-
-       /* WKUP */
-       wkst = prm_read_mod_reg(WKUP_MOD, PM_WKST);
+       u32 wkst, fclk, iclk, clken;
+       u16 wkst_off = (regs == 3) ? OMAP3430ES2_PM_WKST3 : PM_WKST1;
+       u16 fclk_off = (regs == 3) ? OMAP3430ES2_CM_FCLKEN3 : CM_FCLKEN1;
+       u16 iclk_off = (regs == 3) ? CM_ICLKEN3 : CM_ICLKEN1;
+       u16 grpsel_off = (regs == 3) ?
+               OMAP3430ES2_PM_MPUGRPSEL3 : OMAP3430_PM_MPUGRPSEL;
+       int c = 0;
+
+       wkst = prm_read_mod_reg(module, wkst_off);
+       wkst &= prm_read_mod_reg(module, grpsel_off);
        if (wkst) {
-               iclk = cm_read_mod_reg(WKUP_MOD, CM_ICLKEN);
-               fclk = cm_read_mod_reg(WKUP_MOD, CM_FCLKEN);
-               cm_set_mod_reg_bits(wkst, WKUP_MOD, CM_ICLKEN);
-               cm_set_mod_reg_bits(wkst, WKUP_MOD, CM_FCLKEN);
-               prm_write_mod_reg(wkst, WKUP_MOD, PM_WKST);
-               while (prm_read_mod_reg(WKUP_MOD, PM_WKST))
-                       cpu_relax();
-               cm_write_mod_reg(iclk, WKUP_MOD, CM_ICLKEN);
-               cm_write_mod_reg(fclk, WKUP_MOD, CM_FCLKEN);
+               iclk = cm_read_mod_reg(module, iclk_off);
+               fclk = cm_read_mod_reg(module, fclk_off);
+               while (wkst) {
+                       clken = wkst;
+                       cm_set_mod_reg_bits(clken, module, iclk_off);
+                       /*
+                        * For USBHOST, we don't know whether HOST1 or
+                        * HOST2 woke us up, so enable both f-clocks
+                        */
+                       if (module == OMAP3430ES2_USBHOST_MOD)
+                               clken |= 1 << OMAP3430ES2_EN_USBHOST2_SHIFT;
+                       cm_set_mod_reg_bits(clken, module, fclk_off);
+                       prm_write_mod_reg(wkst, module, wkst_off);
+                       wkst = prm_read_mod_reg(module, wkst_off);
+                       c++;
+               }
+               cm_write_mod_reg(iclk, module, iclk_off);
+               cm_write_mod_reg(fclk, module, fclk_off);
        }
 
-       /* CORE */
-       wkst = prm_read_mod_reg(CORE_MOD, PM_WKST1);
-       if (wkst) {
-               iclk = cm_read_mod_reg(CORE_MOD, CM_ICLKEN1);
-               fclk = cm_read_mod_reg(CORE_MOD, CM_FCLKEN1);
-               cm_set_mod_reg_bits(wkst, CORE_MOD, CM_ICLKEN1);
-               cm_set_mod_reg_bits(wkst, CORE_MOD, CM_FCLKEN1);
-               prm_write_mod_reg(wkst, CORE_MOD, PM_WKST1);
-               while (prm_read_mod_reg(CORE_MOD, PM_WKST1))
-                       cpu_relax();
-               cm_write_mod_reg(iclk, CORE_MOD, CM_ICLKEN1);
-               cm_write_mod_reg(fclk, CORE_MOD, CM_FCLKEN1);
-       }
-       wkst = prm_read_mod_reg(CORE_MOD, OMAP3430ES2_PM_WKST3);
-       if (wkst) {
-               iclk = cm_read_mod_reg(CORE_MOD, CM_ICLKEN3);
-               fclk = cm_read_mod_reg(CORE_MOD, OMAP3430ES2_CM_FCLKEN3);
-               cm_set_mod_reg_bits(wkst, CORE_MOD, CM_ICLKEN3);
-               cm_set_mod_reg_bits(wkst, CORE_MOD, OMAP3430ES2_CM_FCLKEN3);
-               prm_write_mod_reg(wkst, CORE_MOD, OMAP3430ES2_PM_WKST3);
-               while (prm_read_mod_reg(CORE_MOD, OMAP3430ES2_PM_WKST3))
-                       cpu_relax();
-               cm_write_mod_reg(iclk, CORE_MOD, CM_ICLKEN3);
-               cm_write_mod_reg(fclk, CORE_MOD, OMAP3430ES2_CM_FCLKEN3);
-       }
+       return c;
+}
 
-       /* PER */
-       wkst = prm_read_mod_reg(OMAP3430_PER_MOD, PM_WKST);
-       if (wkst) {
-               iclk = cm_read_mod_reg(OMAP3430_PER_MOD, CM_ICLKEN);
-               fclk = cm_read_mod_reg(OMAP3430_PER_MOD, CM_FCLKEN);
-               cm_set_mod_reg_bits(wkst, OMAP3430_PER_MOD, CM_ICLKEN);
-               cm_set_mod_reg_bits(wkst, OMAP3430_PER_MOD, CM_FCLKEN);
-               prm_write_mod_reg(wkst, OMAP3430_PER_MOD, PM_WKST);
-               while (prm_read_mod_reg(OMAP3430_PER_MOD, PM_WKST))
-                       cpu_relax();
-               cm_write_mod_reg(iclk, OMAP3430_PER_MOD, CM_ICLKEN);
-               cm_write_mod_reg(fclk, OMAP3430_PER_MOD, CM_FCLKEN);
-       }
+static int _prcm_int_handle_wakeup(void)
+{
+       int c;
 
+       c = prcm_clear_mod_irqs(WKUP_MOD, 1);
+       c += prcm_clear_mod_irqs(CORE_MOD, 1);
+       c += prcm_clear_mod_irqs(OMAP3430_PER_MOD, 1);
        if (omap_rev() > OMAP3430_REV_ES1_0) {
-               /* USBHOST */
-               wkst = prm_read_mod_reg(OMAP3430ES2_USBHOST_MOD, PM_WKST);
-               if (wkst) {
-                       iclk = cm_read_mod_reg(OMAP3430ES2_USBHOST_MOD,
-                                              CM_ICLKEN);
-                       fclk = cm_read_mod_reg(OMAP3430ES2_USBHOST_MOD,
-                                              CM_FCLKEN);
-                       cm_set_mod_reg_bits(wkst, OMAP3430ES2_USBHOST_MOD,
-                                           CM_ICLKEN);
-                       cm_set_mod_reg_bits(wkst, OMAP3430ES2_USBHOST_MOD,
-                                           CM_FCLKEN);
-                       prm_write_mod_reg(wkst, OMAP3430ES2_USBHOST_MOD,
-                                         PM_WKST);
-                       while (prm_read_mod_reg(OMAP3430ES2_USBHOST_MOD,
-                                               PM_WKST))
-                               cpu_relax();
-                       cm_write_mod_reg(iclk, OMAP3430ES2_USBHOST_MOD,
-                                        CM_ICLKEN);
-                       cm_write_mod_reg(fclk, OMAP3430ES2_USBHOST_MOD,
-                                        CM_FCLKEN);
-               }
+               c += prcm_clear_mod_irqs(CORE_MOD, 3);
+               c += prcm_clear_mod_irqs(OMAP3430ES2_USBHOST_MOD, 1);
        }
 
-       irqstatus_mpu = prm_read_mod_reg(OCP_MOD,
-                                        OMAP3_PRM_IRQSTATUS_MPU_OFFSET);
-       prm_write_mod_reg(irqstatus_mpu, OCP_MOD,
-                         OMAP3_PRM_IRQSTATUS_MPU_OFFSET);
+       return c;
+}
+
+/*
+ * PRCM Interrupt Handler
+ *
+ * The PRM_IRQSTATUS_MPU register indicates if there are any pending
+ * interrupts from the PRCM for the MPU. These bits must be cleared in
+ * order to clear the PRCM interrupt. The PRCM interrupt handler is
+ * implemented to simply clear the PRM_IRQSTATUS_MPU in order to clear
+ * the PRCM interrupt. Please note that bit 0 of the PRM_IRQSTATUS_MPU
+ * register indicates that a wake-up event is pending for the MPU and
+ * this bit can only be cleared if the all the wake-up events latched
+ * in the various PM_WKST_x registers have been cleared. The interrupt
+ * handler is implemented using a do-while loop so that if a wake-up
+ * event occurred during the processing of the prcm interrupt handler
+ * (setting a bit in the corresponding PM_WKST_x register and thus
+ * preventing us from clearing bit 0 of the PRM_IRQSTATUS_MPU register)
+ * this would be handled.
+ */
+static irqreturn_t prcm_interrupt_handler (int irq, void *dev_id)
+{
+       u32 irqstatus_mpu;
+       int c = 0;
+
+       do {
+               irqstatus_mpu = prm_read_mod_reg(OCP_MOD,
+                                       OMAP3_PRM_IRQSTATUS_MPU_OFFSET);
+
+               if (irqstatus_mpu & (OMAP3430_WKUP_ST | OMAP3430_IO_ST)) {
+                       c = _prcm_int_handle_wakeup();
+
+                       /*
+                        * Is the MPU PRCM interrupt handler racing with the
+                        * IVA2 PRCM interrupt handler ?
+                        */
+                       WARN(c == 0, "prcm: WARNING: PRCM indicated MPU wakeup "
+                            "but no wakeup sources are marked\n");
+               } else {
+                       /* XXX we need to expand our PRCM interrupt handler */
+                       WARN(1, "prcm: WARNING: PRCM interrupt received, but "
+                            "no code to handle it (%08x)\n", irqstatus_mpu);
+               }
+
+               prm_write_mod_reg(irqstatus_mpu, OCP_MOD,
+                                       OMAP3_PRM_IRQSTATUS_MPU_OFFSET);
 
-       while (prm_read_mod_reg(OCP_MOD, OMAP3_PRM_IRQSTATUS_MPU_OFFSET))
-               cpu_relax();
+       } while (prm_read_mod_reg(OCP_MOD, OMAP3_PRM_IRQSTATUS_MPU_OFFSET));
 
        return IRQ_HANDLED;
 }
@@ -624,6 +639,17 @@ static void __init prcm_setup_regs(void)
        prm_write_mod_reg(OMAP3430_IO_EN | OMAP3430_WKUP_EN,
                          OCP_MOD, OMAP3_PRM_IRQENABLE_MPU_OFFSET);
 
+       /* Enable wakeups in PER */
+       prm_write_mod_reg(OMAP3430_EN_GPIO2 | OMAP3430_EN_GPIO3 |
+                         OMAP3430_EN_GPIO4 | OMAP3430_EN_GPIO5 |
+                         OMAP3430_EN_GPIO6 | OMAP3430_EN_UART3,
+                         OMAP3430_PER_MOD, PM_WKEN);
+       /* and allow them to wake up MPU */
+       prm_write_mod_reg(OMAP3430_GRPSEL_GPIO2 | OMAP3430_EN_GPIO3 |
+                         OMAP3430_GRPSEL_GPIO4 | OMAP3430_EN_GPIO5 |
+                         OMAP3430_GRPSEL_GPIO6 | OMAP3430_EN_UART3,
+                         OMAP3430_PER_MOD, OMAP3430_PM_MPUGRPSEL);
+
        /* Don't attach IVA interrupts */
        prm_write_mod_reg(0, WKUP_MOD, OMAP3430_PM_IVAGRPSEL);
        prm_write_mod_reg(0, CORE_MOD, OMAP3430_PM_IVAGRPSEL1);
index 2594cbf..f00289a 100644 (file)
@@ -273,35 +273,50 @@ struct powerdomain *pwrdm_lookup(const char *name)
 }
 
 /**
- * pwrdm_for_each - call function on each registered clockdomain
+ * pwrdm_for_each_nolock - call function on each registered clockdomain
  * @fn: callback function *
  *
  * Call the supplied function for each registered powerdomain.  The
  * callback function can return anything but 0 to bail out early from
- * the iterator.  The callback function is called with the pwrdm_rwlock
- * held for reading, so no powerdomain structure manipulation
- * functions should be called from the callback, although hardware
- * powerdomain control functions are fine.  Returns the last return
- * value of the callback function, which should be 0 for success or
- * anything else to indicate failure; or -EINVAL if the function
- * pointer is null.
+ * the iterator.  Returns the last return value of the callback function, which
+ * should be 0 for success or anything else to indicate failure; or -EINVAL if
+ * the function pointer is null.
  */
-int pwrdm_for_each(int (*fn)(struct powerdomain *pwrdm, void *user),
-                       void *user)
+int pwrdm_for_each_nolock(int (*fn)(struct powerdomain *pwrdm, void *user),
+                               void *user)
 {
        struct powerdomain *temp_pwrdm;
-       unsigned long flags;
        int ret = 0;
 
        if (!fn)
                return -EINVAL;
 
-       read_lock_irqsave(&pwrdm_rwlock, flags);
        list_for_each_entry(temp_pwrdm, &pwrdm_list, node) {
                ret = (*fn)(temp_pwrdm, user);
                if (ret)
                        break;
        }
+
+       return ret;
+}
+
+/**
+ * pwrdm_for_each - call function on each registered clockdomain
+ * @fn: callback function *
+ *
+ * This function is the same as 'pwrdm_for_each_nolock()', but keeps the
+ * &pwrdm_rwlock locked for reading, so no powerdomain structure manipulation
+ * functions should be called from the callback, although hardware powerdomain
+ * control functions are fine.
+ */
+int pwrdm_for_each(int (*fn)(struct powerdomain *pwrdm, void *user),
+                       void *user)
+{
+       unsigned long flags;
+       int ret;
+
+       read_lock_irqsave(&pwrdm_rwlock, flags);
+       ret = pwrdm_for_each_nolock(fn, user);
        read_unlock_irqrestore(&pwrdm_rwlock, flags);
 
        return ret;
index ae21868..54dfeb5 100644 (file)
@@ -109,16 +109,6 @@ static struct plat_serial8250_port serial_platform_data2[] = {
                .regshift       = 2,
                .uartclk        = OMAP24XX_BASE_BAUD * 16,
        }, {
-#ifdef CONFIG_ARCH_OMAP4
-               .membase        = OMAP2_IO_ADDRESS(OMAP_UART4_BASE),
-               .mapbase        = OMAP_UART4_BASE,
-               .irq            = 70,
-               .flags          = UPF_BOOT_AUTOCONF,
-               .iotype         = UPIO_MEM,
-               .regshift       = 2,
-               .uartclk        = OMAP24XX_BASE_BAUD * 16,
-       }, {
-#endif
                .flags          = 0
        }
 };
index aac2cda..102916f 100644 (file)
 
 #define CM_X300_ETH_PHYS       0x08000010
 
-#define GPIO82_MMC2_IRQ                (82)
-#define GPIO85_MMC2_WP         (85)
+#define GPIO82_MMC_IRQ         (82)
+#define GPIO85_MMC_WP          (85)
 
-#define        CM_X300_MMC2_IRQ        IRQ_GPIO(GPIO82_MMC2_IRQ)
+#define        CM_X300_MMC_IRQ         IRQ_GPIO(GPIO82_MMC_IRQ)
 
 #define GPIO95_RTC_CS          (95)
 #define GPIO96_RTC_WR          (96)
@@ -292,37 +292,37 @@ static inline void cm_x300_init_nand(void) {}
 #endif
 
 #if defined(CONFIG_MMC) || defined(CONFIG_MMC_MODULE)
-/* The first MMC slot of CM-X300 is hardwired to Libertas card and has
+static struct pxamci_platform_data cm_x300_mci_platform_data = {
+       .detect_delay           = 20,
+       .ocr_mask               = MMC_VDD_32_33|MMC_VDD_33_34,
+       .gpio_card_detect       = GPIO82_MMC_IRQ,
+       .gpio_card_ro           = GPIO85_MMC_WP,
+       .gpio_power             = -1,
+};
+
+/* The second MMC slot of CM-X300 is hardwired to Libertas card and has
    no detection/ro pins */
-static int cm_x300_mci_init(struct device *dev,
-                           irq_handler_t cm_x300_detect_int,
-                           void *data)
+static int cm_x300_mci2_init(struct device *dev,
+                            irq_handler_t cm_x300_detect_int,
+       void *data)
 {
        return 0;
 }
 
-static void cm_x300_mci_exit(struct device *dev, void *data)
+static void cm_x300_mci2_exit(struct device *dev, void *data)
 {
 }
 
-static struct pxamci_platform_data cm_x300_mci_platform_data = {
+static struct pxamci_platform_data cm_x300_mci2_platform_data = {
        .detect_delay           = 20,
        .ocr_mask               = MMC_VDD_32_33|MMC_VDD_33_34,
-       .init                   = cm_x300_mci_init,
-       .exit                   = cm_x300_mci_exit,
+       .init                   = cm_x300_mci2_init,
+       .exit                   = cm_x300_mci2_exit,
        .gpio_card_detect       = -1,
        .gpio_card_ro           = -1,
        .gpio_power             = -1,
 };
 
-static struct pxamci_platform_data cm_x300_mci2_platform_data = {
-       .detect_delay           = 20,
-       .ocr_mask               = MMC_VDD_32_33|MMC_VDD_33_34,
-       .gpio_card_detect       = GPIO82_MMC2_IRQ,
-       .gpio_card_ro           = GPIO85_MMC2_WP,
-       .gpio_power             = -1,
-};
-
 static void __init cm_x300_init_mmc(void)
 {
        pxa_set_mci_info(&cm_x300_mci_platform_data);
index 3a8ee22..983cc8c 100644 (file)
@@ -155,7 +155,7 @@ MODULE_PARM_DESC(pxa255_turbo_table, "Selects the frequency table (0 = run table
 
 static pxa_freqs_t pxa27x_freqs[] = {
        {104000, 104000, PXA27x_CCCR(1,  8, 2), 0, CCLKCFG2(1, 0, 1),  900000, 1705000 },
-       {156000, 104000, PXA27x_CCCR(1,  8, 6), 0, CCLKCFG2(1, 1, 1), 1000000, 1705000 },
+       {156000, 104000, PXA27x_CCCR(1,  8, 3), 0, CCLKCFG2(1, 0, 1), 1000000, 1705000 },
        {208000, 208000, PXA27x_CCCR(0, 16, 2), 1, CCLKCFG2(0, 0, 1), 1180000, 1705000 },
        {312000, 208000, PXA27x_CCCR(1, 16, 3), 1, CCLKCFG2(1, 0, 1), 1250000, 1705000 },
        {416000, 208000, PXA27x_CCCR(1, 16, 4), 1, CCLKCFG2(1, 0, 1), 1350000, 1705000 },
index 79141f8..965480e 100644 (file)
@@ -238,7 +238,7 @@ static struct resource csb726_lan_resources[] = {
 };
 
 struct smsc911x_platform_config csb726_lan_config = {
-       .irq_type       = SMSC911X_IRQ_POLARITY_ACTIVE_LOW,
+       .irq_polarity   = SMSC911X_IRQ_POLARITY_ACTIVE_LOW,
        .irq_type       = SMSC911X_IRQ_TYPE_PUSH_PULL,
        .flags          = SMSC911X_USE_32BIT,
        .phy_interface  = PHY_INTERFACE_MODE_MII,
index ee8d603..82ff573 100644 (file)
@@ -15,6 +15,7 @@
 #include <linux/kernel.h>
 #include <linux/platform_device.h>
 #include <linux/delay.h>
+#include <linux/gpio_keys.h>
 #include <linux/gpio.h>
 #include <linux/leds.h>
 #include <linux/mtd/physmap.h>
@@ -375,6 +376,43 @@ static struct platform_device spitzkbd_device = {
 };
 
 
+static struct gpio_keys_button spitz_gpio_keys[] = {
+       {
+               .type   = EV_PWR,
+               .code   = KEY_SUSPEND,
+               .gpio   = SPITZ_GPIO_ON_KEY,
+               .desc   = "On/Off",
+               .wakeup = 1,
+       },
+       /* Two buttons detecting the lid state */
+       {
+               .type   = EV_SW,
+               .code   = 0,
+               .gpio   = SPITZ_GPIO_SWA,
+               .desc   = "Display Down",
+       },
+       {
+               .type   = EV_SW,
+               .code   = 1,
+               .gpio   = SPITZ_GPIO_SWB,
+               .desc   = "Lid Closed",
+       },
+};
+
+static struct gpio_keys_platform_data spitz_gpio_keys_platform_data = {
+       .buttons        = spitz_gpio_keys,
+       .nbuttons       = ARRAY_SIZE(spitz_gpio_keys),
+};
+
+static struct platform_device spitz_gpio_keys_device = {
+       .name   = "gpio-keys",
+       .id     = -1,
+       .dev    = {
+               .platform_data  = &spitz_gpio_keys_platform_data,
+       },
+};
+
+
 /*
  * Spitz LEDs
  */
@@ -689,6 +727,7 @@ static struct platform_device sharpsl_rom_device = {
 static struct platform_device *devices[] __initdata = {
        &spitzscoop_device,
        &spitzkbd_device,
+       &spitz_gpio_keys_device,
        &spitzled_device,
        &sharpsl_nand_device,
        &sharpsl_rom_device,
index 46cd6ac..699671f 100644 (file)
@@ -61,5 +61,5 @@ extern void realview_timer_init(unsigned int timer_irq);
 extern int realview_flash_register(struct resource *res, u32 num);
 extern int realview_eth_register(const char *name, struct resource *res);
 extern int realview_usb_register(struct resource *res);
-
+extern void (*realview_reset)(char);
 #endif
index 98f8e7e..34b80b7 100644 (file)
@@ -73,4 +73,9 @@
 #define REALVIEW_PB1176_GIC_DIST_BASE          0x10041000 /* GIC distributor, on FPGA */
 #define REALVIEW_PB1176_L220_BASE              0x10110000 /* L220 registers */
 
+/*
+ * Control register SYS_RESETCTL is set to 1 to force a soft reset
+ */
+#define REALVIEW_PB1176_SYS_LOCKVAL_RSTCTL    0x0100
+
 #endif /* __ASM_ARCH_BOARD_PB1176_H */
index f0d68e0..7abf918 100644 (file)
 #define REALVIEW_TC11MP_GIC_DIST_BASE          0x1F001000      /* Test chip interrupt controller distributor */
 #define REALVIEW_TC11MP_L220_BASE              0x1F002000      /* L220 registers */
 
+ /*
+ * Values for REALVIEW_SYS_RESET_CTRL
+ */
+#define REALVIEW_PB11MP_SYS_CTRL_RESET_CONFIGCLR    0x01
+#define REALVIEW_PB11MP_SYS_CTRL_RESET_CONFIGINIT   0x02
+#define REALVIEW_PB11MP_SYS_CTRL_RESET_DLLRESET     0x03
+#define REALVIEW_PB11MP_SYS_CTRL_RESET_PLLRESET     0x04
+#define REALVIEW_PB11MP_SYS_CTRL_RESET_POR          0x05
+#define REALVIEW_PB11MP_SYS_CTRL_RESET_DoC          0x06
+
+#define REALVIEW_PB11MP_SYS_CTRL_LED         (1 << 0)
+
 #endif /* __ASM_ARCH_BOARD_PB11MP_H */
index c8f5083..4f46bf7 100644 (file)
 #define REALVIEW_SYS_TEST_OSC3               (REALVIEW_SYS_BASE + REALVIEW_SYS_TEST_OSC3_OFFSET)
 #define REALVIEW_SYS_TEST_OSC4               (REALVIEW_SYS_BASE + REALVIEW_SYS_TEST_OSC4_OFFSET)
 
-/* 
- * Values for REALVIEW_SYS_RESET_CTRL
- */
-#define REALVIEW_SYS_CTRL_RESET_CONFIGCLR    0x01
-#define REALVIEW_SYS_CTRL_RESET_CONFIGINIT   0x02
-#define REALVIEW_SYS_CTRL_RESET_DLLRESET     0x03
-#define REALVIEW_SYS_CTRL_RESET_PLLRESET     0x04
-#define REALVIEW_SYS_CTRL_RESET_POR          0x05
-#define REALVIEW_SYS_CTRL_RESET_DoC          0x06
-
-#define REALVIEW_SYS_CTRL_LED         (1 << 0)
-
-
 /* ------------------------------------------------------------------------
  *  RealView control registers
  * ------------------------------------------------------------------------
  *     SYS_CLD, SYS_BOOTCS
  */
 #define REALVIEW_SYS_LOCK_LOCKED    (1 << 16)
-#define REALVIEW_SYS_LOCKVAL_MASK      0xFFFF          /* write 0xA05F to enable write access */
+#define REALVIEW_SYS_LOCKVAL_MASK      0xA05F         /* Enable write access */
 
 /*
  * REALVIEW_SYS_FLASH
index 1a15a44..a30f2e3 100644 (file)
@@ -25,6 +25,8 @@
 #include <mach/hardware.h>
 #include <mach/platform.h>
 
+void (*realview_reset)(char mode);
+
 static inline void arch_idle(void)
 {
        /*
@@ -36,16 +38,12 @@ static inline void arch_idle(void)
 
 static inline void arch_reset(char mode, const char *cmd)
 {
-       void __iomem *hdr_ctrl = __io_address(REALVIEW_SYS_BASE) + REALVIEW_SYS_RESETCTL_OFFSET;
-       unsigned int val;
-
        /*
         * To reset, we hit the on-board reset register
         * in the system FPGA
         */
-       val = __raw_readl(hdr_ctrl);
-       val |= REALVIEW_SYS_CTRL_RESET_CONFIGCLR;
-       __raw_writel(val, hdr_ctrl);
+       if (realview_reset)
+               realview_reset(mode);
 }
 
 #endif
index 2817fe0..a6ba147 100644 (file)
@@ -290,6 +290,16 @@ static struct sys_timer realview_pb1176_timer = {
        .init           = realview_pb1176_timer_init,
 };
 
+static void realview_pb1176_reset(char mode)
+{
+       void __iomem *hdr_ctrl = __io_address(REALVIEW_SYS_BASE) +
+               REALVIEW_SYS_RESETCTL_OFFSET;
+       void __iomem *rst_hdr_ctrl = __io_address(REALVIEW_SYS_BASE) +
+               REALVIEW_SYS_LOCK_OFFSET;
+       __raw_writel(REALVIEW_SYS_LOCKVAL_MASK, rst_hdr_ctrl);
+       __raw_writel(REALVIEW_PB1176_SYS_LOCKVAL_RSTCTL, hdr_ctrl);
+}
+
 static void __init realview_pb1176_init(void)
 {
        int i;
@@ -313,6 +323,7 @@ static void __init realview_pb1176_init(void)
 #ifdef CONFIG_LEDS
        leds_event = realview_leds_event;
 #endif
+       realview_reset = realview_pb1176_reset;
 }
 
 MACHINE_START(REALVIEW_PB1176, "ARM-RealView PB1176")
index 94680fc..070d284 100644 (file)
@@ -299,6 +299,21 @@ static struct sys_timer realview_pb11mp_timer = {
        .init           = realview_pb11mp_timer_init,
 };
 
+static void realview_pb11mp_reset(char mode)
+{
+       void __iomem *hdr_ctrl = __io_address(REALVIEW_SYS_BASE) +
+               REALVIEW_SYS_RESETCTL_OFFSET;
+       unsigned int val;
+
+       /*
+        * To reset, we hit the on-board reset register
+        * in the system FPGA
+        */
+       val = __raw_readl(hdr_ctrl);
+       val |= REALVIEW_PB11MP_SYS_CTRL_RESET_CONFIGCLR;
+       __raw_writel(val, hdr_ctrl);
+}
+
 static void __init realview_pb11mp_init(void)
 {
        int i;
@@ -324,6 +339,7 @@ static void __init realview_pb11mp_init(void)
 #ifdef CONFIG_LEDS
        leds_event = realview_leds_event;
 #endif
+       realview_reset = realview_pb11mp_reset;
 }
 
 MACHINE_START(REALVIEW_PB11MP, "ARM-RealView PB11MPCore")
index 7974afc..9664e01 100644 (file)
@@ -28,6 +28,7 @@
 #include <linux/io.h>
 
 #include <mach/hardware.h>
+#include <mach/gpio-fns.h>
 #include <asm/irq.h>
 
 #include <mach/regs-gpio.h>
index c3a2629..92e2687 100644 (file)
@@ -110,6 +110,8 @@ enum s3c2410_dma_loadst {
                                            * waiting for reloads */
 #define S3C2410_DMAF_AUTOSTART    (1<<1)   /* auto-start if buffer queued */
 
+#define S3C2410_DMAF_CIRCULAR  (1 << 2)        /* no circular dma support */
+
 /* dma buffer */
 
 struct s3c2410_dma_buf;
@@ -194,4 +196,9 @@ struct s3c2410_dma_chan {
 
 typedef unsigned long dma_device_t;
 
+static inline bool s3c_dma_has_circular(void)
+{
+       return false;
+}
+
 #endif /* __ASM_ARCH_DMA_H */
index d7bba91..a8b69d7 100644 (file)
@@ -103,6 +103,7 @@ config MACH_MINI2440
        select LEDS_TRIGGER_BACKLIGHT
        select SND_S3C24XX_SOC_S3C24XX_UDA134X
        select S3C_DEV_NAND
+       select S3C_DEV_USB_HOST
        help
          Say Y here to select support for the MINI2440. Is a 10cm x 10cm board
          available via various sources. It can come with a 3.5" or 7" touch LCD.
index ec71a69..1c3382f 100644 (file)
@@ -144,7 +144,7 @@ static struct s3c2410_udc_mach_info mini2440_udc_cfg __initdata = {
        .type           = (S3C2410_LCDCON1_TFT16BPP |\
                           S3C2410_LCDCON1_TFT)
 
-struct s3c2410fb_display mini2440_lcd_cfg[] __initdata = {
+static struct s3c2410fb_display mini2440_lcd_cfg[] __initdata = {
        [0] = { /* mini2440 + 3.5" TFT + touchscreen */
                _LCD_DECLARE(
                        7,                      /* The 3.5 is quite fast */
@@ -191,7 +191,7 @@ struct s3c2410fb_display mini2440_lcd_cfg[] __initdata = {
 #define S3C2410_GPCCON_MASK(x) (3 << ((x) * 2))
 #define S3C2410_GPDCON_MASK(x) (3 << ((x) * 2))
 
-struct s3c2410fb_mach_info mini2440_fb_info __initdata = {
+static struct s3c2410fb_mach_info mini2440_fb_info __initdata = {
        .displays        = &mini2440_lcd_cfg[0], /* not constant! see init */
        .num_displays    = 1,
        .default_display = 0,
index 1067619..004edab 100644 (file)
@@ -68,6 +68,11 @@ static __inline__ int s3c_dma_has_circular(void)
 
 #define S3C2410_DMAF_CIRCULAR          (1 << 0)
 
+static inline bool s3c_dma_has_circular(void)
+{
+       return false;
+}
+
 #include <plat/dma.h>
 
 #endif /* __ASM_ARCH_IRQ_H */
index 8a5546e..bb7b819 100644 (file)
@@ -25,6 +25,7 @@ led-$(CONFIG_SA1100_CERF)             += leds-cerf.o
 
 obj-$(CONFIG_SA1100_COLLIE)            += collie.o
 
+obj-$(CONFIG_SA1100_H3100)             += h3600.o
 obj-$(CONFIG_SA1100_H3600)             += h3600.o
 
 obj-$(CONFIG_SA1100_HACKKIT)           += hackkit.o
index e993140..9264d81 100644 (file)
@@ -122,10 +122,7 @@ config CPU_ARM920T
        select CPU_TLB_V4WBI if MMU
        help
          The ARM920T is licensed to be produced by numerous vendors,
-         and is used in the Maverick EP9312 and the Samsung S3C2410.
-
-         More information on the Maverick EP9312 at
-         <http://linuxdevices.com/products/PD2382866068.html>.
+         and is used in the Cirrus EP93xx and the Samsung S3C2410.
 
          Say Y if you want support for the ARM920T processor.
          Otherwise, say N.
index 8f5c13f..295e25d 100644 (file)
@@ -12,6 +12,7 @@
 #include <linux/linkage.h>
 #include <linux/init.h>
 #include <asm/assembler.h>
+#include <asm/unwind.h>
 
 #include "proc-macros.S"
 
@@ -121,11 +122,13 @@ ENTRY(v6_coherent_kern_range)
  *     - the Icache does not read data from the write buffer
  */
 ENTRY(v6_coherent_user_range)
-
+ UNWIND(.fnstart               )
 #ifdef HARVARD_CACHE
        bic     r0, r0, #CACHE_LINE_SIZE - 1
-1:     mcr     p15, 0, r0, c7, c10, 1          @ clean D line
+1:
+ USER( mcr     p15, 0, r0, c7, c10, 1  )       @ clean D line
        add     r0, r0, #CACHE_LINE_SIZE
+2:
        cmp     r0, r1
        blo     1b
 #endif
@@ -143,6 +146,19 @@ ENTRY(v6_coherent_user_range)
        mov     pc, lr
 
 /*
+ * Fault handling for the cache operation above. If the virtual address in r0
+ * isn't mapped, just try the next page.
+ */
+9001:
+       mov     r0, r0, lsr #12
+       mov     r0, r0, lsl #12
+       add     r0, r0, #4096
+       b       2b
+ UNWIND(.fnend         )
+ENDPROC(v6_coherent_user_range)
+ENDPROC(v6_coherent_kern_range)
+
+/*
  *     v6_flush_kern_dcache_page(kaddr)
  *
  *     Ensure that the data held in the page kaddr is written back
index bda0ec3..e1bd975 100644 (file)
@@ -13,6 +13,7 @@
 #include <linux/linkage.h>
 #include <linux/init.h>
 #include <asm/assembler.h>
+#include <asm/unwind.h>
 
 #include "proc-macros.S"
 
@@ -153,13 +154,16 @@ ENTRY(v7_coherent_kern_range)
  *     - the Icache does not read data from the write buffer
  */
 ENTRY(v7_coherent_user_range)
+ UNWIND(.fnstart               )
        dcache_line_size r2, r3
        sub     r3, r2, #1
        bic     r0, r0, r3
-1:     mcr     p15, 0, r0, c7, c11, 1          @ clean D line to the point of unification
+1:
+ USER( mcr     p15, 0, r0, c7, c11, 1  )       @ clean D line to the point of unification
        dsb
      mcr     p15, 0, r0, c7, c5, 1           @ invalidate I line
USER( mcr     p15, 0, r0, c7, c5, 1   )       @ invalidate I line
        add     r0, r0, r2
+2:
        cmp     r0, r1
        blo     1b
        mov     r0, #0
@@ -167,6 +171,17 @@ ENTRY(v7_coherent_user_range)
        dsb
        isb
        mov     pc, lr
+
+/*
+ * Fault handling for the cache operation above. If the virtual address in r0
+ * isn't mapped, just try the next page.
+ */
+9001:
+       mov     r0, r0, lsr #12
+       mov     r0, r0, lsl #12
+       add     r0, r0, #4096
+       b       2b
+ UNWIND(.fnend         )
 ENDPROC(v7_coherent_kern_range)
 ENDPROC(v7_coherent_user_range)
 
index 6bda76a..a9e22e3 100644 (file)
@@ -50,10 +50,7 @@ void __new_context(struct mm_struct *mm)
                isb();
                flush_tlb_all();
                if (icache_is_vivt_asid_tagged()) {
-                       asm("mcr        p15, 0, %0, c7, c5, 0   @ invalidate I-cache\n"
-                           "mcr        p15, 0, %0, c7, c5, 6   @ flush BTAC/BTB\n"
-                           :
-                           : "r" (0));
+                       __flush_icache_all();
                        dsb();
                }
        }
index b30925f..b9590a7 100644 (file)
@@ -205,7 +205,7 @@ __dma_alloc(struct device *dev, size_t size, dma_addr_t *handle, gfp_t gfp,
 
        order = get_order(size);
 
-       if (mask != 0xffffffff)
+       if (mask < 0xffffffffULL)
                gfp |= GFP_DMA;
 
        page = alloc_pages(gfp, order);
@@ -289,7 +289,7 @@ __dma_alloc(struct device *dev, size_t size, dma_addr_t *handle, gfp_t gfp,
        if (!mask)
                goto error;
 
-       if (mask != 0xffffffff)
+       if (mask < 0xffffffffULL)
                gfp |= GFP_DMA;
        virt = kmalloc(size, gfp);
        if (!virt)
index bc0099d..d0d17b6 100644 (file)
@@ -153,14 +153,11 @@ void update_mmu_cache(struct vm_area_struct *vma, unsigned long addr, pte_t pte)
 
        page = pfn_to_page(pfn);
        mapping = page_mapping(page);
-       if (mapping) {
 #ifndef CONFIG_SMP
-               int dirty = test_and_clear_bit(PG_dcache_dirty, &page->flags);
-
-               if (dirty)
-                       __flush_dcache_page(mapping, page);
+       if (test_and_clear_bit(PG_dcache_dirty, &page->flags))
+               __flush_dcache_page(mapping, page);
 #endif
-
+       if (mapping) {
                if (cache_is_vivt())
                        make_coherent(mapping, vma, addr, pfn);
                else if (vma->vm_flags & VM_EXEC)
index ae0e25f..10e0680 100644 (file)
@@ -292,6 +292,11 @@ do_page_fault(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
                 * down_read()
                 */
                might_sleep();
+#ifdef CONFIG_DEBUG_VM
+               if (!user_mode(regs) &&
+                   !search_exception_tables(regs->ARM_pc))
+                       goto no_context;
+#endif
        }
 
        fault = __do_page_fault(mm, addr, fsr, tsk);
index b279429..7f294f3 100644 (file)
 
 #include "mm.h"
 
-#ifdef CONFIG_ARM_ERRATA_411920
-extern void v6_icache_inval_all(void);
-#endif
-
 #ifdef CONFIG_CPU_CACHE_VIPT
 
 #define ALIAS_FLUSH_START      0xffff4000
@@ -35,16 +31,11 @@ static void flush_pfn_alias(unsigned long pfn, unsigned long vaddr)
        flush_tlb_kernel_page(to);
 
        asm(    "mcrr   p15, 0, %1, %0, c14\n"
-       "       mcr     p15, 0, %2, c7, c10, 4\n"
-#ifndef CONFIG_ARM_ERRATA_411920
-       "       mcr     p15, 0, %2, c7, c5, 0\n"
-#endif
+       "       mcr     p15, 0, %2, c7, c10, 4"
            :
            : "r" (to), "r" (to + PAGE_SIZE - L1_CACHE_BYTES), "r" (zero)
            : "cc");
-#ifdef CONFIG_ARM_ERRATA_411920
-       v6_icache_inval_all();
-#endif
+       __flush_icache_all();
 }
 
 void flush_cache_mm(struct mm_struct *mm)
@@ -57,16 +48,11 @@ void flush_cache_mm(struct mm_struct *mm)
 
        if (cache_is_vipt_aliasing()) {
                asm(    "mcr    p15, 0, %0, c7, c14, 0\n"
-               "       mcr     p15, 0, %0, c7, c10, 4\n"
-#ifndef CONFIG_ARM_ERRATA_411920
-               "       mcr     p15, 0, %0, c7, c5, 0\n"
-#endif
+               "       mcr     p15, 0, %0, c7, c10, 4"
                    :
                    : "r" (0)
                    : "cc");
-#ifdef CONFIG_ARM_ERRATA_411920
-               v6_icache_inval_all();
-#endif
+               __flush_icache_all();
        }
 }
 
@@ -81,16 +67,11 @@ void flush_cache_range(struct vm_area_struct *vma, unsigned long start, unsigned
 
        if (cache_is_vipt_aliasing()) {
                asm(    "mcr    p15, 0, %0, c7, c14, 0\n"
-               "       mcr     p15, 0, %0, c7, c10, 4\n"
-#ifndef CONFIG_ARM_ERRATA_411920
-               "       mcr     p15, 0, %0, c7, c5, 0\n"
-#endif
+               "       mcr     p15, 0, %0, c7, c10, 4"
                    :
                    : "r" (0)
                    : "cc");
-#ifdef CONFIG_ARM_ERRATA_411920
-               v6_icache_inval_all();
-#endif
+               __flush_icache_all();
        }
 }
 
index 73cae57..30f82fb 100644 (file)
@@ -46,6 +46,8 @@ void *kmap_atomic(struct page *page, enum km_type type)
        if (!PageHighMem(page))
                return page_address(page);
 
+       debug_kmap_atomic(type);
+
        kmap = kmap_high_get(page);
        if (kmap)
                return kmap;
index 877c492..52c40d1 100644 (file)
@@ -273,7 +273,6 @@ static void __init bootmem_init_node(int node, struct meminfo *mi,
                struct membank *bank = &mi->bank[i];
                if (!bank->highmem)
                        free_bootmem_node(pgdat, bank_phys_start(bank), bank_phys_size(bank));
-               memory_present(node, bank_pfn_start(bank), bank_pfn_end(bank));
        }
 
        /*
@@ -370,6 +369,19 @@ int pfn_valid(unsigned long pfn)
        return 0;
 }
 EXPORT_SYMBOL(pfn_valid);
+
+static void arm_memory_present(struct meminfo *mi, int node)
+{
+}
+#else
+static void arm_memory_present(struct meminfo *mi, int node)
+{
+       int i;
+       for_each_nodebank(i, mi, node) {
+               struct membank *bank = &mi->bank[i];
+               memory_present(node, bank_pfn_start(bank), bank_pfn_end(bank));
+       }
+}
 #endif
 
 static int __init meminfo_cmp(const void *_a, const void *_b)
@@ -427,6 +439,12 @@ void __init bootmem_init(void)
                 */
                if (node == initrd_node)
                        bootmem_reserve_initrd(node);
+
+               /*
+                * Sparsemem tries to allocate bootmem in memory_present(),
+                * so must be done after the fixed reservations
+                */
+               arm_memory_present(mi, node);
        }
 
        /*
@@ -483,7 +501,7 @@ free_memmap(int node, unsigned long start_pfn, unsigned long end_pfn)
        /*
         * Convert start_pfn/end_pfn to a struct page pointer.
         */
-       start_pg = pfn_to_page(start_pfn);
+       start_pg = pfn_to_page(start_pfn - 1) + 1;
        end_pg = pfn_to_page(end_pfn);
 
        /*
index 02243ee..ea67be0 100644 (file)
@@ -117,6 +117,13 @@ static void __init early_cachepolicy(char **p)
        }
        if (i == ARRAY_SIZE(cache_policies))
                printk(KERN_ERR "ERROR: unknown or unsupported cache policy\n");
+       /*
+        * This restriction is partly to do with the way we boot; it is
+        * unpredictable to have memory mapped using two different sets of
+        * memory attributes (shared, type, and cache attribs).  We can not
+        * change these attributes once the initial assembly has setup the
+        * page tables.
+        */
        if (cpu_architecture() >= CPU_ARCH_ARMv6) {
                printk(KERN_WARNING "Only cachepolicy=writeback supported on ARMv6 and later\n");
                cachepolicy = CPOLICY_WRITEBACK;
index 194737d..70f75d2 100644 (file)
 
 #ifndef CONFIG_SMP
 #define TTB_FLAGS      TTB_RGN_WBWA
+#define PMD_FLAGS      PMD_SECT_WB
 #else
 #define TTB_FLAGS      TTB_RGN_WBWA|TTB_S
+#define PMD_FLAGS      PMD_SECT_WBWA|PMD_SECT_S
 #endif
 
 ENTRY(cpu_v6_proc_init)
@@ -222,10 +224,9 @@ __v6_proc_info:
        .long   0x0007b000
        .long   0x0007f000
        .long   PMD_TYPE_SECT | \
-               PMD_SECT_BUFFERABLE | \
-               PMD_SECT_CACHEABLE | \
                PMD_SECT_AP_WRITE | \
-               PMD_SECT_AP_READ
+               PMD_SECT_AP_READ | \
+               PMD_FLAGS
        .long   PMD_TYPE_SECT | \
                PMD_SECT_XN | \
                PMD_SECT_AP_WRITE | \
index 23ebcf6..eeeed01 100644 (file)
 #ifndef CONFIG_SMP
 /* PTWs cacheable, inner WB not shareable, outer WB not shareable */
 #define TTB_FLAGS      TTB_IRGN_WB|TTB_RGN_OC_WB
+#define PMD_FLAGS      PMD_SECT_WB
 #else
 /* PTWs cacheable, inner WBWA shareable, outer WBWA not shareable */
 #define TTB_FLAGS      TTB_IRGN_WBWA|TTB_S|TTB_NOS|TTB_RGN_OC_WBWA
+#define PMD_FLAGS      PMD_SECT_WBWA|PMD_SECT_S
 #endif
 
 ENTRY(cpu_v7_proc_init)
@@ -326,10 +328,9 @@ __v7_proc_info:
        .long   0x000f0000              @ Required ID value
        .long   0x000f0000              @ Mask for ID
        .long   PMD_TYPE_SECT | \
-               PMD_SECT_BUFFERABLE | \
-               PMD_SECT_CACHEABLE | \
                PMD_SECT_AP_WRITE | \
-               PMD_SECT_AP_READ
+               PMD_SECT_AP_READ | \
+               PMD_FLAGS
        .long   PMD_TYPE_SECT | \
                PMD_SECT_XN | \
                PMD_SECT_AP_WRITE | \
index fe58138..f7d2ec5 100644 (file)
@@ -33,6 +33,9 @@ static int irqs[] = {
 #ifdef CONFIG_ARCH_OMAP2
        3,
 #endif
+#ifdef CONFIG_ARCH_BCMRING
+       IRQ_PMUIRQ, /* for BCMRING, ARM PMU interrupt is 43 */
+#endif
 };
 
 static void armv6_pmu_stop(void)
index fd3154a..b53125f 100644 (file)
@@ -829,10 +829,10 @@ EXPORT_SYMBOL(omap_free_dma);
  *
  * @param arb_rate
  * @param max_fifo_depth
- * @param tparams - Number of thereads to reserve : DMA_THREAD_RESERVE_NORM
- *                                                 DMA_THREAD_RESERVE_ONET
- *                                                 DMA_THREAD_RESERVE_TWOT
- *                                                 DMA_THREAD_RESERVE_THREET
+ * @param tparams - Number of threads to reserve : DMA_THREAD_RESERVE_NORM
+ *                                                DMA_THREAD_RESERVE_ONET
+ *                                                DMA_THREAD_RESERVE_TWOT
+ *                                                DMA_THREAD_RESERVE_THREET
  */
 void
 omap_dma_set_global_params(int arb_rate, int max_fifo_depth, int tparams)
@@ -844,11 +844,14 @@ omap_dma_set_global_params(int arb_rate, int max_fifo_depth, int tparams)
                return;
        }
 
+       if (max_fifo_depth == 0)
+               max_fifo_depth = 1;
        if (arb_rate == 0)
                arb_rate = 1;
 
-       reg = (arb_rate & 0xff) << 16;
-       reg |= (0xff & max_fifo_depth);
+       reg = 0xff & max_fifo_depth;
+       reg |= (0x3 & tparams) << 12;
+       reg |= (arb_rate & 0xff) << 16;
 
        dma_write(reg, GCR);
 }
@@ -975,6 +978,14 @@ void omap_stop_dma(int lch)
 {
        u32 l;
 
+       /* Disable all interrupts on the channel */
+       if (cpu_class_is_omap1())
+               dma_write(0, CICR(lch));
+
+       l = dma_read(CCR(lch));
+       l &= ~OMAP_DMA_CCR_EN;
+       dma_write(l, CCR(lch));
+
        if (!omap_dma_in_1510_mode() && dma_chan[lch].next_lch != -1) {
                int next_lch, cur_lch = lch;
                char dma_chan_link_map[OMAP_DMA4_LOGICAL_DMA_CH_COUNT];
@@ -992,18 +1003,8 @@ void omap_stop_dma(int lch)
                        next_lch = dma_chan[cur_lch].next_lch;
                        cur_lch = next_lch;
                } while (next_lch != -1);
-
-               return;
        }
 
-       /* Disable all interrupts on the channel */
-       if (cpu_class_is_omap1())
-               dma_write(0, CICR(lch));
-
-       l = dma_read(CCR(lch));
-       l &= ~OMAP_DMA_CCR_EN;
-       dma_write(l, CCR(lch));
-
        dma_chan[lch].flags &= ~OMAP_DMA_ACTIVE;
 }
 EXPORT_SYMBOL(omap_stop_dma);
index 11e73d9..f129efb 100644 (file)
@@ -303,32 +303,21 @@ IS_OMAP_TYPE(3430, 0x3430)
 #define cpu_is_omap2430()              0
 #define cpu_is_omap3430()              0
 
-#if defined(MULTI_OMAP1)
-# if defined(CONFIG_ARCH_OMAP730)
-#  undef  cpu_is_omap730
-#  define cpu_is_omap730()             is_omap730()
-# endif
-# if defined(CONFIG_ARCH_OMAP850)
-#  undef  cpu_is_omap850
-#  define cpu_is_omap850()             is_omap850()
-# endif
-#else
-# if defined(CONFIG_ARCH_OMAP730)
-#  undef  cpu_is_omap730
-#  define cpu_is_omap730()             1
-# endif
-#endif
-#else
-# if defined(CONFIG_ARCH_OMAP850)
-#  undef  cpu_is_omap850
-#  define cpu_is_omap850()             1
-# endif
-#endif
-
 /*
  * Whether we have MULTI_OMAP1 or not, we still need to distinguish
- * between 330 vs. 1510 and 1611B/5912 vs. 1710.
+ * between 730 vs 850, 330 vs. 1510 and 1611B/5912 vs. 1710.
  */
+
+#if defined(CONFIG_ARCH_OMAP730)
+# undef  cpu_is_omap730
+# define cpu_is_omap730()              is_omap730()
+#endif
+
+#if defined(CONFIG_ARCH_OMAP850)
+# undef  cpu_is_omap850
+# define cpu_is_omap850()              is_omap850()
+#endif
+
 #if defined(CONFIG_ARCH_OMAP15XX)
 # undef  cpu_is_omap310
 # undef  cpu_is_omap1510
@@ -433,3 +422,5 @@ IS_OMAP_TYPE(3430, 0x3430)
 
 int omap_chip_is(struct omap_chip_id oci);
 void omap2_check_revision(void);
+
+#endif
index d91b9be..3ae52cc 100644 (file)
@@ -10,7 +10,7 @@
 #ifndef ASMARM_ARCH_KEYPAD_H
 #define ASMARM_ARCH_KEYPAD_H
 
-#include <linux/input/matrix_keypad.h>
+#warning: Please update the board to use matrix_keypad.h instead
 
 struct omap_kp_platform_data {
        int rows;
@@ -37,6 +37,9 @@ struct omap_kp_platform_data {
 
 #define KEY_PERSISTENT         0x00800000
 #define KEYNUM_MASK            0x00EFFFFF
+#define KEY(col, row, val) (((col) << 28) | ((row) << 24) | (val))
+#define PERSISTENT_KEY(col, row) (((col) << 28) | ((row) << 24) | \
+                                               KEY_PERSISTENT)
 
 #endif
 
index 6271d85..fa64614 100644 (file)
@@ -135,6 +135,8 @@ struct powerdomain *pwrdm_lookup(const char *name);
 
 int pwrdm_for_each(int (*fn)(struct powerdomain *pwrdm, void *user),
                        void *user);
+int pwrdm_for_each_nolock(int (*fn)(struct powerdomain *pwrdm, void *user),
+                       void *user);
 
 int pwrdm_add_clkdm(struct powerdomain *pwrdm, struct clockdomain *clkdm);
 int pwrdm_del_clkdm(struct powerdomain *pwrdm, struct clockdomain *clkdm);
index 4b60127..94584f1 100644 (file)
@@ -664,7 +664,7 @@ static size_t iopgtable_clear_entry_core(struct iommu *obj, u32 da)
                nent = 1; /* for the next L1 entry */
        } else {
                bytes = IOPGD_SIZE;
-               if (*iopgd & IOPGD_SUPER) {
+               if ((*iopgd & IOPGD_SUPER) == IOPGD_SUPER) {
                        nent *= 16;
                        /* rewind to the 1st entry */
                        iopgd = (u32 *)((u32)iopgd & IOSUPER_MASK);
index 57f7122..dc3fac3 100644 (file)
@@ -47,7 +47,7 @@
  *     'va':   mpu virtual address
  *
  *     'c':    contiguous memory area
- *     'd':    dicontiguous memory area
+ *     'd':    discontiguous memory area
  *     'a':    anonymous memory allocation
  *     '()':   optional feature
  *
@@ -363,8 +363,9 @@ void *da_to_va(struct iommu *obj, u32 da)
                goto out;
        }
        va = area->va;
-       mutex_unlock(&obj->mmap_lock);
 out:
+       mutex_unlock(&obj->mmap_lock);
+
        return va;
 }
 EXPORT_SYMBOL_GPL(da_to_va);
@@ -398,7 +399,7 @@ static inline void sgtable_drain_vmalloc(struct sg_table *sgt)
 {
        /*
         * Actually this is not necessary at all, just exists for
-        * consistency of the code readibility.
+        * consistency of the code readability.
         */
        BUG_ON(!sgt);
 }
@@ -434,7 +435,7 @@ static inline void sgtable_drain_kmalloc(struct sg_table *sgt)
 {
        /*
         * Actually this is not necessary at all, just exists for
-        * consistency of the code readibility
+        * consistency of the code readability
         */
        BUG_ON(!sgt);
 }
index 88ac976..e664b91 100644 (file)
@@ -595,7 +595,7 @@ void omap_mcbsp_stop(unsigned int id, int tx, int rx)
        rx &= 1;
        if (cpu_is_omap2430() || cpu_is_omap34xx()) {
                w = OMAP_MCBSP_READ(io_base, RCCR);
-               w |= (tx ? RDISABLE : 0);
+               w |= (rx ? RDISABLE : 0);
                OMAP_MCBSP_WRITE(io_base, RCCR, w);
        }
        w = OMAP_MCBSP_READ(io_base, SPCR1);
index 925f647..75d1f26 100644 (file)
@@ -270,7 +270,8 @@ void * omap_sram_push(void * start, unsigned long size)
        omap_sram_ceil -= size;
        omap_sram_ceil = ROUND_DOWN(omap_sram_ceil, sizeof(void *));
        memcpy((void *)omap_sram_ceil, start, size);
-       flush_icache_range((unsigned long)start, (unsigned long)(start + size));
+       flush_icache_range((unsigned long)omap_sram_ceil,
+               (unsigned long)(omap_sram_ceil + size));
 
        return (void *)omap_sram_ceil;
 }
index 11117a7..df47322 100644 (file)
@@ -14,6 +14,7 @@
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/platform_device.h>
+#include <linux/sched.h>
 #include <linux/list.h>
 #include <linux/err.h>
 #include <linux/clk.h>
@@ -188,7 +189,7 @@ int s3c_adc_read(struct s3c_adc_client *client, unsigned int ch)
 err:
        return ret;
 }
-EXPORT_SYMBOL_GPL(s3c_adc_convert);
+EXPORT_SYMBOL_GPL(s3c_adc_read);
 
 static void s3c_adc_default_select(struct s3c_adc_client *client,
                                   unsigned select)
index 5447e60..4af9dd9 100644 (file)
@@ -61,6 +61,7 @@ static const char name_s3c2410[]  = "S3C2410";
 static const char name_s3c2412[]  = "S3C2412";
 static const char name_s3c2440[]  = "S3C2440";
 static const char name_s3c2442[]  = "S3C2442";
+static const char name_s3c2442b[]  = "S3C2442B";
 static const char name_s3c2443[]  = "S3C2443";
 static const char name_s3c2410a[] = "S3C2410A";
 static const char name_s3c2440a[] = "S3C2440A";
@@ -112,6 +113,15 @@ static struct cpu_table cpu_ids[] __initdata = {
                .name           = name_s3c2442
        },
        {
+               .idcode         = 0x32440aab,
+               .idmask         = 0xffffffff,
+               .map_io         = s3c244x_map_io,
+               .init_clocks    = s3c244x_init_clocks,
+               .init_uarts     = s3c244x_init_uarts,
+               .init           = s3c2442_init,
+               .name           = name_s3c2442b
+       },
+       {
                .idcode         = 0x32412001,
                .idmask         = 0xffffffff,
                .map_io         = s3c2412_map_io,
index 196b191..f046f8c 100644 (file)
@@ -208,14 +208,14 @@ s3c2410_dma_loadbuffer(struct s3c2410_dma_chan *chan,
 {
        unsigned long reload;
 
-       pr_debug("s3c2410_chan_loadbuffer: loading buff %p (0x%08lx,0x%06x)\n",
-                buf, (unsigned long)buf->data, buf->size);
-
        if (buf == NULL) {
                dmawarn("buffer is NULL\n");
                return -EINVAL;
        }
 
+       pr_debug("s3c2410_chan_loadbuffer: loading buff %p (0x%08lx,0x%06x)\n",
+                buf, (unsigned long)buf->data, buf->size);
+
        /* check the state of the channel before we do anything */
 
        if (chan->load_state == S3C2410_DMALOAD_1LOADED) {
index 95df059..5467470 100644 (file)
@@ -29,6 +29,7 @@
 #include <linux/io.h>
 
 #include <mach/hardware.h>
+#include <mach/gpio-fns.h>
 #include <asm/irq.h>
 
 #include <mach/regs-gpio.h>
index efeb025..c776120 100644 (file)
@@ -222,7 +222,9 @@ extern struct clk *s3c_cpufreq_clk_get(struct device *, const char *);
 /* S3C2410 and compatible exported functions */
 
 extern void s3c2410_cpufreq_setrefresh(struct s3c_cpufreq_config *cfg);
+extern void s3c2410_set_fvco(struct s3c_cpufreq_config *cfg);
 
+#ifdef CONFIG_S3C2410_IOTIMING
 extern int s3c2410_iotiming_calc(struct s3c_cpufreq_config *cfg,
                                 struct s3c_iotimings *iot);
 
@@ -231,8 +233,11 @@ extern int s3c2410_iotiming_get(struct s3c_cpufreq_config *cfg,
 
 extern void s3c2410_iotiming_set(struct s3c_cpufreq_config *cfg,
                                 struct s3c_iotimings *iot);
-
-extern void s3c2410_set_fvco(struct s3c_cpufreq_config *cfg);
+#else
+#define s3c2410_iotiming_calc NULL
+#define s3c2410_iotiming_get NULL
+#define s3c2410_iotiming_set NULL
+#endif /* CONFIG_S3C2410_IOTIMING */
 
 /* S3C2412 compatible routines */
 
index b6deeef..82ab4aa 100644 (file)
@@ -27,6 +27,7 @@ extern void s3c2410_init_clocks(int xtal);
 #define s3c2410_init_uarts NULL
 #define s3c2410_map_io NULL
 #define s3c2410_init NULL
+#define s3c2410a_init NULL
 #endif
 
 extern int s3c2410_baseclk_add(void);
index a8777a7..ff46e7f 100644 (file)
@@ -51,8 +51,8 @@
 #define S3C6400_CLKDIV0_HCLK_SHIFT     (8)
 #define S3C6400_CLKDIV0_MPLL_MASK      (0x1 << 4)
 #define S3C6400_CLKDIV0_MPLL_SHIFT     (4)
-#define S3C6400_CLKDIV0_ARM_MASK       (0x3 << 0)
-#define S3C6410_CLKDIV0_ARM_MASK       (0x7 << 0)
+#define S3C6400_CLKDIV0_ARM_MASK       (0x7 << 0)
+#define S3C6410_CLKDIV0_ARM_MASK       (0xf << 0)
 #define S3C6400_CLKDIV0_ARM_SHIFT      (0)
 
 /* CLKDIV1 */
index 9745852..6ffa21e 100644 (file)
@@ -677,6 +677,9 @@ void __init_or_cpufreq s3c6400_setup_clocks(void)
 
        printk(KERN_DEBUG "%s: xtal is %ld\n", __func__, xtal);
 
+       /* For now assume the mux always selects the crystal */
+       clk_ext_xtal_mux.parent = xtal_clk;
+
        epll = s3c6400_get_epll(xtal);
        mpll = s3c6400_get_pll(xtal, __raw_readl(S3C_MPLL_CON));
        apll = s3c6400_get_pll(xtal, __raw_readl(S3C_APLL_CON));
index 44d0bfa..9c96a13 100644 (file)
@@ -31,5 +31,8 @@
 #define cpu_is_at91sam9263()   (0)
 #define cpu_is_at91sam9rl()    (0)
 #define cpu_is_at91cap9()      (0)
+#define cpu_is_at91sam9g10()   (0)
+#define cpu_is_at91sam9g45()   (0)
+#define cpu_is_at91sam9g45es() (0)
 
 #endif /* __ASM_ARCH_CPU_H */
diff --git a/arch/blackfin/ADI_BSD.txt b/arch/blackfin/ADI_BSD.txt
new file mode 100644 (file)
index 0000000..501d0b6
--- /dev/null
@@ -0,0 +1,41 @@
+This BSD-Style License applies to a few files in ./arch/blackfin directory,
+and is included here, so people understand which code they can use outside
+the Linux kernel, in non-GPL based projects.
+
+Using the files released under the "ADI BSD" license, must comply with
+these license terms.
+
+--------------------------------------------------------------------------
+
+Copyright Analog Devices, Inc.
+
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+  - Redistributions of source code must retain the above copyright
+    notice, this list of conditions and the following disclaimer.
+  - Redistributions in binary form must reproduce the above copyright
+    notice, this list of conditions and the following disclaimer in
+    the documentation and/or other materials provided with the
+    distribution.
+  - Neither the name of Analog Devices, Inc. nor the names of its
+    contributors may be used to endorse or promote products derived
+    from this software without specific prior written permission.
+  - The use of this software may or may not infringe the patent rights
+    of one or more patent holders.  This license does not release you
+    from the requirement that you obtain separate licenses from these
+    patent holders to use this software.
+
+THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR
+IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT,
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+BUT NOT LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, 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
index 9a01d44..ae6a60f 100644 (file)
@@ -47,6 +47,9 @@ config GENERIC_HARDIRQS
 config GENERIC_IRQ_PROBE
        def_bool y
 
+config GENERIC_HARDIRQS_NO__DO_IRQ
+       def_bool y
+
 config GENERIC_GPIO
        def_bool y
 
@@ -229,7 +232,7 @@ endchoice
 
 config SMP
        depends on BF561
-       select GENERIC_TIME
+       select GENERIC_CLOCKEVENTS
        bool "Symmetric multi-processing support"
        ---help---
          This enables support for systems with more than one CPU,
@@ -613,12 +616,10 @@ comment "Kernel Timer/Scheduler"
 source kernel/Kconfig.hz
 
 config GENERIC_TIME
-       bool "Generic time"
-       default y
+       def_bool y
 
 config GENERIC_CLOCKEVENTS
        bool "Generic clock events"
-       depends on GENERIC_TIME
        default y
 
 choice
@@ -653,6 +654,10 @@ config GPTMR0_CLOCKSOURCE
        depends on GENERIC_CLOCKEVENTS
        depends on !TICKSOURCE_GPTMR0
 
+config ARCH_USES_GETTIMEOFFSET
+       depends on !GENERIC_CLOCKEVENTS
+       def_bool y
+
 source kernel/time/Kconfig
 
 comment "Misc"
index 88f36d5..d27c627 100644 (file)
@@ -1,3 +1,9 @@
+/*
+ * Copyright 2004-2009 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2 or later.
+ */
+
 #ifndef __ARCH_BLACKFIN_ATOMIC__
 #define __ARCH_BLACKFIN_ATOMIC__
 
index aef0594..10064f9 100644 (file)
@@ -1,29 +1,9 @@
 /*
- * File:         include/asm-blackfin/bfin-global.h
- * Based on:
- * Author: *
- * Created:
- * Description:  Global extern defines for blackfin
+ * Global extern defines for blackfin
  *
- * Modified:
- *               Copyright 2004-2006 Analog Devices Inc.
+ * Copyright 2006-2009 Analog Devices Inc.
  *
- * Bugs:         Enter bugs at http://blackfin.uclinux.org/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see the file COPYING, or write
- * to the Free Software Foundation, Inc.,
- * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ * Licensed under the GPL-2 or later.
  */
 
 #ifndef _BFIN_GLOBAL_H_
index c281c63..ed4f8c6 100644 (file)
@@ -3,8 +3,6 @@
  *
  * Copyright 2004-2008 Analog Devices Inc.
  *
- * Enter bugs at http://blackfin.uclinux.org/
- *
  * Licensed under the GPL-2 or later.
  */
 
index 425ece6..abdb2af 100644 (file)
@@ -1,6 +1,10 @@
 /*
  * board initialization should put one of these structures into platform_data
  * and place the bfin-rotary onto platform_bus named "bfin-rotary".
+ *
+ * Copyright 2008 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2 or later.
  */
 
 #ifndef _BFIN_ROTARY_H
index fccbb59..5248c13 100644 (file)
@@ -1,3 +1,9 @@
+/*
+ * Copyright 2006-2008 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2 or later.
+ */
+
 #ifndef _bfin_simple_timer_h_
 #define _bfin_simple_timer_h_
 
index daffa71..a2ff3fb 100644 (file)
@@ -1,3 +1,9 @@
+/*
+ * Copyright 2004-2009 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2 or later.
+ */
+
 #ifndef _BLACKFIN_BITOPS_H
 #define _BLACKFIN_BITOPS_H
 
index 4d44395..eb7c144 100644 (file)
@@ -1,6 +1,9 @@
 /*
- * Common header file for blackfin family of processors.
+ * Common header file for Blackfin family of processors.
  *
+ * Copyright 2004-2009 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2 or later.
  */
 
 #ifndef _BLACKFIN_H_
index 655e495..6f4548a 100644 (file)
@@ -1,3 +1,9 @@
+/*
+ * Copyright 2004-2009 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2 or later.
+ */
+
 #ifndef _BLACKFIN_BUG_H
 #define _BLACKFIN_BUG_H
 
index 3e69106..9558416 100644 (file)
@@ -1,6 +1 @@
-#ifndef _BLACKFIN_BYTEORDER_H
-#define _BLACKFIN_BYTEORDER_H
-
 #include <linux/byteorder/little_endian.h>
-
-#endif                         /* _BLACKFIN_BYTEORDER_H */
index 477050a..8542bc3 100644 (file)
@@ -1,6 +1,9 @@
 /*
- * include/asm-blackfin/cache.h
+ * Copyright 2004-2009 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2 or later.
  */
+
 #ifndef __ARCH_BLACKFIN_CACHE_H
 #define __ARCH_BLACKFIN_CACHE_H
 
 
 #if defined(CONFIG_SMP) && \
     !defined(CONFIG_BFIN_CACHE_COHERENT)
-# if defined(CONFIG_BFIN_ICACHEABLE) || defined(CONFIG_BFIN_L2_ICACHEABLE)
+# if defined(CONFIG_BFIN_EXTMEM_ICACHEABLE) || defined(CONFIG_BFIN_L2_ICACHEABLE)
 # define __ARCH_SYNC_CORE_ICACHE
 # endif
-# if defined(CONFIG_BFIN_DCACHEABLE) || defined(CONFIG_BFIN_L2_DCACHEABLE)
+# if defined(CONFIG_BFIN_EXTMEM_DCACHEABLE) || defined(CONFIG_BFIN_L2_DCACHEABLE)
 # define __ARCH_SYNC_CORE_DCACHE
 # endif
 #ifndef __ASSEMBLY__
index 7e55549..af03a36 100644 (file)
@@ -1,30 +1,9 @@
 /*
- * File:         include/asm-blackfin/cacheflush.h
- * Based on:    include/asm-m68knommu/cacheflush.h
- * Author:       LG Soft India
- *               Copyright (C) 2004 Analog Devices Inc.
- * Created:      Tue Sep 21 2004
- * Description:  Blackfin low-level cache routines adapted from the i386
- *              and PPC versions by Greg Ungerer (gerg@snapgear.com)
+ * Blackfin low-level cache routines
  *
- * Modified:
+ * Copyright 2004-2009 Analog Devices Inc.
  *
- * Bugs:         Enter bugs at http://blackfin.uclinux.org/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; see the file COPYING.
- * If not, write to the Free Software Foundation,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ * Licensed under the GPL-2 or later.
  */
 
 #ifndef _BLACKFIN_CACHEFLUSH_H
index 35f841b..8778e0f 100644 (file)
@@ -1,30 +1,8 @@
- /*
-  * File:        include/asm-blackfin/mach-common/cdef_LPBlackfin.h
-  * Based on:
-  * Author:      unknown
-  *              COPYRIGHT 2005 Analog Devices
-  * Created:     ?
-  * Description:
-  *
-  * Modified:
-  *
-  * Bugs:         Enter bugs at http://blackfin.uclinux.org/
-  *
-  * This program is free software; you can redistribute it and/or modify
-  * it under the terms of the GNU General Public License as published by
-  * the Free Software Foundation; either version 2, or (at your option)
-  * any later version.
-  *
-  * This program is distributed in the hope that it will be useful,
-  * but WITHOUT ANY WARRANTY; without even the implied warranty of
-  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-  * GNU General Public License for more details.
-  *
-  * You should have received a copy of the GNU General Public License
-  * along with this program; see the file COPYING.
-  * If not, write to the Free Software Foundation,
-  * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-  */
+/*
+ * Copyright 2005-2008 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2 or later.
+ */
 
 #ifndef _CDEF_LPBLACKFIN_H
 #define _CDEF_LPBLACKFIN_H
index 793581f..a23415b 100644 (file)
@@ -1,9 +1,14 @@
+/*
+ * Copyright 2004-2009 Analog Devices Inc.
+ *                     akbar.hussain@lineo.com
+ *
+ * Licensed under the GPL-2 or later.
+ */
+
 #ifndef _BFIN_CHECKSUM_H
 #define _BFIN_CHECKSUM_H
 
 /*
- * MODIFIED FOR BFIN April 30, 2001 akbar.hussain@lineo.com
- *
  * computes the checksum of a memory block at buff, length len,
  * and adds in "sum" (32-bit)
  *
index 033bba9..f80dad5 100644 (file)
@@ -1,30 +1,9 @@
 /*
- * File:         include/asm-blackfin/mach-common/clocks.h
- * Based on:     include/asm-blackfin/mach-bf537/bf537.h
- * Author:      Robin Getz <rgetz@blackfin.uclinux.org>
+ * Common Clock definitions for various kernel files
  *
- * Created:      25Jul07
- * Description:  Common Clock definitions for various kernel files
+ * Copyright 2007-2008 Analog Devices Inc.
  *
- * Modified:
- *               Copyright 2004-2007 Analog Devices Inc.
- *
- * Bugs:         Enter bugs at http://blackfin.uclinux.org/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see the file COPYING, or write
- * to the Free Software Foundation, Inc.,
- * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ * Licensed under the GPL-2 or later.
  */
 
 #ifndef _BFIN_CLOCKS_H
index f8a664f..5dffaf5 100644 (file)
@@ -1,30 +1,7 @@
 /*
- * File:         arch/blackfin/kernel/context.S
- * Based on:
- * Author:
+ * Copyright 2007-2009 Analog Devices Inc.
  *
- * Created:
- * Description:
- *
- * Modified:
- *               Copyright 2004-2007 Analog Devices Inc.
- *
- * Bugs:         Enter bugs at http://blackfin.uclinux.org/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see the file COPYING, or write
- * to the Free Software Foundation, Inc.,
- * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ * Licensed under the GPL-2 or later.
  */
 
 /*
index d18d168..fda9626 100644 (file)
@@ -1,30 +1,7 @@
 /*
- * File:         include/asm-blackfin/cplb.h
- * Based on:     include/asm-blackfin/mach-bf537/bf537.h
- * Author:       Robin Getz <rgetz@blackfin.uclinux.org>
+ * Copyright 2004-2009 Analog Devices Inc.
  *
- * Created:      2000
- * Description:  Common CPLB definitions for CPLB init
- *
- * Modified:
- *               Copyright 2004-2007 Analog Devices Inc.
- *
- * Bugs:         Enter bugs at http://blackfin.uclinux.org/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see the file COPYING, or write
- * to the Free Software Foundation, Inc.,
- * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ * Licensed under the GPL-2 or later.
  */
 
 #ifndef _CPLB_H
index 05b14a6..f315c83 100644 (file)
@@ -1,30 +1,9 @@
 /*
- * File:         include/asm-blackfin/cplbinit.h
- * Based on:
- * Author:
+ * Common CPLB definitions for CPLB init
  *
- * Created:
- * Description:
+ * Copyright 2006-2008 Analog Devices Inc.
  *
- * Modified:
- *               Copyright 2004-2006 Analog Devices Inc.
- *
- * Bugs:         Enter bugs at http://blackfin.uclinux.org/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see the file COPYING, or write
- * to the Free Software Foundation, Inc.,
- * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ * Licensed under the GPL-2 or later.
  */
 
 #ifndef __ASM_CPLBINIT_H__
index fadfa82..b191dc6 100644 (file)
@@ -1,23 +1,8 @@
 /*
- * File:         arch/blackfin/include/asm/cpu.h.
- * Author:       Philippe Gerum <rpm@xenomai.org>
+ * Copyright 2007-2009 Analog Devices Inc.
+ *                         Philippe Gerum <rpm@xenomai.org>
  *
- *               Copyright 2007 Analog Devices Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see the file COPYING, or write
- * to the Free Software Foundation, Inc.,
- * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ * Licensed under the GPL-2 or later.
  */
 
 #ifndef __ASM_BLACKFIN_CPU_H
index 6341eeb..2590646 100644 (file)
@@ -1,32 +1,10 @@
- /*
-  * File:        include/asm-blackfin/mach-common/def_LPBlackfin.h
-  * Based on:
-  * Author:      unknown
-  *              COPYRIGHT 2005 Analog Devices
-  * Created:     ?
-  * Description:
-  *
-  * Modified:
-  *
-  * Bugs:         Enter bugs at http://blackfin.uclinux.org/
-  *
-  * This program is free software; you can redistribute it and/or modify
-  * it under the terms of the GNU General Public License as published by
-  * the Free Software Foundation; either version 2, or (at your option)
-  * any later version.
-  *
-  * This program is distributed in the hope that it will be useful,
-  * but WITHOUT ANY WARRANTY; without even the implied warranty of
-  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-  * GNU General Public License for more details.
-  *
-  * You should have received a copy of the GNU General Public License
-  * along with this program; see the file COPYING.
-  * If not, write to the Free Software Foundation,
-  * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-  */
-
-/* LP Blackfin CORE REGISTER BIT & ADDRESS DEFINITIONS FOR ADSP-BF532/33 */
+/*
+ * Blackfin core register bit & address definitions
+ *
+ * Copyright 2005-2008 Analog Devices Inc.
+ *
+ * Licensed under the ADI BSD license or GPL-2 (or later).
+ */
 
 #ifndef _DEF_LPBLACKFIN_H
 #define _DEF_LPBLACKFIN_H
index ed6b1f3..7a23d82 100644 (file)
@@ -1,3 +1,9 @@
+/*
+ * Copyright 2004-2009 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2 or later.
+ */
+
 #ifndef _BLACKFIN_DMA_MAPPING_H
 #define _BLACKFIN_DMA_MAPPING_H
 
index 96e8208..925e66c 100644 (file)
@@ -1,9 +1,11 @@
 /*
- * include/asm-blackfin/dpmc.h -  Miscellaneous IOCTL commands for Dynamic Power
- *                             Management Controller Driver.
+ * Miscellaneous IOCTL commands for Dynamic Power Management Controller Driver
+ *
  * Copyright (C) 2004-2008 Analog Device Inc.
  *
+ * Licensed under the GPL-2
  */
+
 #ifndef _BLACKFIN_DPMC_H_
 #define _BLACKFIN_DPMC_H_
 
index 53a762b..68a910d 100644 (file)
@@ -1,27 +1,11 @@
 /*
- * File:         include/asm-blackfin/early_printk.h
- * Author:       Robin Getz <rgetz@blackfin.uclinux.org
+ * function prototpyes for early printk
  *
- * Created:      14Aug2007
- * Description:  function prototpyes for early printk
+ * Copyright 2007-2009 Analog Devices Inc.
  *
- * Modified:
- *               Copyright 2004-2007 Analog Devices Inc.
- *
- * Bugs:         Enter bugs at http://blackfin.uclinux.org/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
+ * Licensed under the GPL-2 or later.
  */
 
-
 #ifndef __ASM_EARLY_PRINTK_H__
 #define __ASM_EARLY_PRINTK_H__
 
index c823e8e..8e0764c 100644 (file)
@@ -1,4 +1,8 @@
-/* Changes made by  LG Soft Oct 2004*/
+/*
+ * Copyright 2004-2009 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2 or later.
+ */
 
 #ifndef __ASMBFIN_ELF_H
 #define __ASMBFIN_ELF_H
index 55b808f..a6886f6 100644 (file)
@@ -1,3 +1,9 @@
+/*
+ * Copyright 2004-2009 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2 or later.
+ */
+
 #ifndef __BFIN_ENTRY_H
 #define __BFIN_ENTRY_H
 
index 9c40371..8727b2b 100644 (file)
@@ -1,3 +1,9 @@
+/*
+ * Copyright 2004-2008 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2 or later.
+ */
+
 #ifndef _BFIN_FCNTL_H
 #define _BFIN_FCNTL_H
 
index 32c4d49..73fe53e 100644 (file)
@@ -1,5 +1,11 @@
-/* This file defines the fixed addresses where userspace programs can find
-   atomic code sequences.  */
+/*
+ * This file defines the fixed addresses where userspace programs
+ * can find atomic code sequences.
+ *
+ * Copyright 2007-2008 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2 or later.
+ */
 
 #ifndef __BFIN_ASM_FIXED_CODE_H__
 #define __BFIN_ASM_FIXED_CODE_H__
index 733a178..c1314c5 100644 (file)
@@ -1,8 +1,9 @@
 /*
- * include/asm-blackfin/flat.h -- uClinux flat-format executables
+ * uClinux flat-format executables
  *
- * Copyright (C) 2003,
+ * Copyright 2003-2009 Analog Devices Inc.
  *
+ * Licensed under the GPL-2
  */
 
 #ifndef __BLACKFIN_FLAT_H__
index fe13961..5b44d05 100644 (file)
@@ -1,30 +1,7 @@
 /*
- * File:         arch/blackfin/kernel/bfin_gpio.h
- * Based on:
- * Author:      Michael Hennerich (hennerich@blackfin.uclinux.org)
+ * Copyright 2006-2009 Analog Devices Inc.
  *
- * Created:
- * Description:
- *
- * Modified:
- *               Copyright 2004-2008 Analog Devices Inc.
- *
- * Bugs:         Enter bugs at http://blackfin.uclinux.org/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see the file COPYING, or write
- * to the Free Software Foundation, Inc.,
- * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ * Licensed under the GPL-2 or later.
  */
 
 #ifndef __ARCH_BLACKFIN_GPIO_H__
index 0b78b87..c078dd7 100644 (file)
@@ -1,3 +1,9 @@
+/*
+ * Copyright 2004-2009 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2 or later.
+ */
+
 #ifndef __BFIN_HARDIRQ_H
 #define __BFIN_HARDIRQ_H
 
index 37053ec..d1f5029 100644 (file)
@@ -1,3 +1,9 @@
+/*
+ * Copyright 2004-2009 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2 or later.
+ */
+
 #ifndef _BFIN_IO_H
 #define _BFIN_IO_H
 
index 42a15f5..e7c0623 100644 (file)
@@ -1,17 +1,10 @@
 /*
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file COPYING in the main directory of this archive
- * for more details.
+ * Copyright 2004-2009 Analog Devices Inc.
+ *                2003 HuTao
+ *                2002 Arcturus Networks Inc. (www.arcturusnetworks.com
+ *                       Ted Ma <mated@sympatico.ca>
  *
- * Changed by HuTao Apr18, 2003
- *
- * Copyright was missing when I got the code so took from MIPS arch ...MaTed---
- * Copyright (C) 1994 by Waldorf GMBH, written by Ralf Baechle
- * Copyright (C) 1995, 96, 97, 98, 99, 2000, 2001 by Ralf Baechle
- *
- * Adapted for BlackFin (ADI) by Ted Ma <mated@sympatico.ca>
- * Copyright (c) 2002 Arcturus Networks Inc. (www.arcturusnetworks.com)
- * Copyright (c) 2002 Lineo, Inc. <mattw@lineo.com>
+ * Licensed under the GPL-2
  */
 
 #ifndef _BFIN_IRQ_H_
@@ -19,6 +12,8 @@
 
 #include <linux/irqflags.h>
 
+#include <mach/anomaly.h>
+
 /* SYS_IRQS and NR_IRQS are defined in <mach-bf5xx/irq.h> */
 #include <mach/irq.h>
 
index 7d9e2d3..7fbe423 100644 (file)
@@ -1,3 +1,9 @@
+/*
+ * Copyright 2007-2009 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2 or later.
+ */
+
 #ifndef _IRQ_HANDLER_H
 #define _IRQ_HANDLER_H
 
index 79dbefa..c87e686 100644 (file)
@@ -1,6 +1,9 @@
 /*
- * l1layout.h
  * Defines a layout of L1 scratchpad memory that userspace can rely on.
+ *
+ * Copyright 2006-2008 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2 or later.
  */
 
 #ifndef _L1LAYOUT_H_
index 5a822bb..f7d6d47 100644 (file)
@@ -1,3 +1,9 @@
+/*
+ * Copyright 2004-2009 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2 or later.
+ */
+
 #ifndef __ASM_LINKAGE_H
 #define __ASM_LINKAGE_H
 
index dbfd686..26f6b70 100644 (file)
@@ -1,8 +1,13 @@
+/*
+ * Copyright 2004-2009 Analog Devices Inc.
+ *                2002 David McCullough <davidm@snapgear.com>
+ *
+ * Licensed under the GPL-2.
+ */
+
 #ifndef __MMU_H
 #define __MMU_H
 
-/* Copyright (C) 2002, David McCullough <davidm@snapgear.com> */
-
 struct sram_list_struct {
        struct sram_list_struct *next;
        void *addr;
index 040410b..4a3be37 100644 (file)
@@ -1,30 +1,7 @@
 /*
- * File:         include/asm-blackfin/mmu_context.h
- * Based on:
- * Author:
+ * Copyright 2004-2009 Analog Devices Inc.
  *
- * Created:
- * Description:
- *
- * Modified:
- *               Copyright 2004-2006 Analog Devices Inc.
- *
- * Bugs:         Enter bugs at http://blackfin.uclinux.org/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see the file COPYING, or write
- * to the Free Software Foundation, Inc.,
- * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ * Licensed under the GPL-2 or later.
  */
 
 #ifndef __BLACKFIN_MMU_CONTEXT_H__
index e3128df..9c1cfff 100644 (file)
@@ -1,3 +1,9 @@
+/*
+ * Copyright 2004-2008 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2 or later.
+ */
+
 #ifndef _ASM_BFIN_MODULE_H
 #define _ASM_BFIN_MODULE_H
 
index 5cc641c..f726e3a 100644 (file)
@@ -4,6 +4,10 @@
  * TODO: implement optimized primitives instead, or leave the generic
  * implementation in place, or pick the atomic_xchg() based generic
  * implementation. (see asm-generic/mutex-xchg.h for details)
+ *
+ * Copyright 2006-2009 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2 or later.
  */
 
 #ifndef _ASM_MUTEX_H
index afbaafa..3ae8b56 100644 (file)
@@ -1,13 +1,9 @@
-/* linux/include/asm-blackfin/nand.h
- *
- * Copyright (c) 2007 Analog Devices, Inc.
- *     Bryan Wu <bryan.wu@analog.com>
- *
+/*
  * BF5XX - NAND flash controller platfrom_device info
  *
- * 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.
+ * Copyright 2007-2008 Analog Devices, Inc.
+ *
+ * Licensed under the GPL-2
  */
 
 /* struct bf5xx_nand_platform
index 29dcf75..944a07c 100644 (file)
@@ -1,3 +1,9 @@
+/*
+ * Copyright 2004-2009 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2 or later.
+ */
+
 #ifndef _BLACKFIN_PAGE_H
 #define _BLACKFIN_PAGE_H
 
index cbaff24..d06a89b 100644 (file)
@@ -1,5 +1,10 @@
-
-/* This handles the memory map.. */
+/*
+ * This handles the memory map
+ *
+ * Copyright 2004-2008 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2 or later.
+ */
 
 #ifdef CONFIG_BLACKFIN
 #define PAGE_OFFSET_RAW                0x00000000
index a6f9569..d49bb26 100644 (file)
@@ -1,23 +1,8 @@
 /*
- * File:         arch/blackfin/include/asm/pda.h
- * Author:       Philippe Gerum <rpm@xenomai.org>
+ * Copyright 2007-2009 Analog Devices Inc.
+ *                         Philippe Gerum <rpm@xenomai.org>
  *
- *               Copyright 2007 Analog Devices Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see the file COPYING, or write
- * to the Free Software Foundation, Inc.,
- * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ * Licensed under the GPL-2 or later.
  */
 
 #ifndef _ASM_BLACKFIN_PDA_H
index 783c8f7..821c699 100644 (file)
@@ -1,3 +1,9 @@
+/*
+ * Copyright 2004-2009 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2 or later.
+ */
+
 #ifndef _BLACKFIN_PGTABLE_H
 #define _BLACKFIN_PGTABLE_H
 
@@ -92,6 +98,12 @@ extern unsigned int kobjsize(const void *objp);
 #define        VMALLOC_START   0
 #define        VMALLOC_END     0xffffffff
 
+/* provide a special get_unmapped_area for framebuffer mmaps of nommu */
+extern unsigned long get_fb_unmapped_area(struct file *filp, unsigned long,
+                                         unsigned long, unsigned long,
+                                         unsigned long);
+#define HAVE_ARCH_FB_UNMAPPED_AREA
+
 #include <asm-generic/pgtable.h>
 
 #endif                         /* _BLACKFIN_PGTABLE_H */
index a055667..072d896 100644 (file)
@@ -1,3 +1,10 @@
+/*
+ * Copyright 2004-2009 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2 or later.
+ *
+ */
+
 #ifndef __BFIN_POLL_H
 #define __BFIN_POLL_H
 
index 88eb5c0..edd8ef3 100644 (file)
@@ -1,6 +1,9 @@
 /*
- * Common header file for blackfin family of processors.
+ * Common header file for Blackfin family of processors
  *
+ * Copyright 2007-2008 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2 or later.
  */
 
 #ifndef _PORTMUX_H_
index 80c9d64..41bc187 100644 (file)
@@ -1,3 +1,9 @@
+/*
+ * Copyright 2004-2009 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2 or later.
+ */
+
 #ifndef __ARCH_BFIN_POSIX_TYPES_H
 #define __ARCH_BFIN_POSIX_TYPES_H
 
index a36ad8d..aea8802 100644 (file)
@@ -1,3 +1,9 @@
+/*
+ * Copyright 2004-2009 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2 or later.
+ */
+
 #ifndef __ASM_BFIN_PROCESSOR_H
 #define __ASM_BFIN_PROCESSOR_H
 
index e3f086d..27290c9 100644 (file)
@@ -1,3 +1,9 @@
+/*
+ * Copyright 2004-2008 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2 or later.
+ */
+
 #ifndef _BFIN_PTRACE_H
 #define _BFIN_PTRACE_H
 
index ae4dae1..1f5381f 100644 (file)
@@ -1,3 +1,9 @@
+/*
+ * Copyright 2004-2009 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2 or later.
+ */
+
 #ifndef _BLACKFIN_SECTIONS_H
 #define _BLACKFIN_SECTIONS_H
 
index 02cfd09..f8e1984 100644 (file)
@@ -1,3 +1,9 @@
+/*
+ * Copyright 2004-2008 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2 or later.
+ */
+
 #ifndef _BFIN_SEGMENT_H
 #define _BFIN_SEGMENT_H
 
index ce00b03..ce4081a 100644 (file)
@@ -1,3 +1,9 @@
+/*
+ * Copyright 2004-2008 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2 or later.
+ */
+
 #ifndef _ASM_BLACKFIN_SIGCONTEXT_H
 #define _ASM_BLACKFIN_SIGCONTEXT_H
 
index eca4565..3e81306 100644 (file)
@@ -1,3 +1,9 @@
+/*
+ * Copyright 2004-2008 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2 or later.
+ */
+
 #ifndef _BFIN_SIGINFO_H
 #define _BFIN_SIGINFO_H
 
index 118deee..6a0fe94 100644 (file)
@@ -1,23 +1,8 @@
 /*
- * File:         arch/blackfin/include/asm/smp.h
- * Author:       Philippe Gerum <rpm@xenomai.org>
+ * Copyright 2007-2009 Analog Devices Inc.
+ *                          Philippe Gerum <rpm@xenomai.org>
  *
- *               Copyright 2007 Analog Devices Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see the file COPYING, or write
- * to the Free Software Foundation, Inc.,
- * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ * Licensed under the GPL-2 or later.
  */
 
 #ifndef __ASM_BLACKFIN_SMP_H
index d6ff4b5..b0c7f0e 100644 (file)
@@ -1,3 +1,9 @@
+/*
+ * Copyright 2004-2009 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2 or later.
+ */
+
 #ifndef __BFIN_SPINLOCK_H
 #define __BFIN_SPINLOCK_H
 
index b1e3c4c..be75762 100644 (file)
@@ -1,3 +1,9 @@
+/*
+ * Copyright 2008 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2 or later.
+ */
+
 #ifndef __ASM_SPINLOCK_TYPES_H
 #define __ASM_SPINLOCK_TYPES_H
 
index d2b6f11..2e27665 100644 (file)
@@ -1,3 +1,9 @@
+/*
+ * Copyright 2004-2006 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2.
+ */
+
 #ifndef _BFIN_STAT_H
 #define _BFIN_STAT_H
 
index 321f4d9..d7f0ccb 100644 (file)
@@ -1,3 +1,9 @@
+/*
+ * Copyright 2004-2008 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2 or later.
+ */
+
 #ifndef _BLACKFIN_STRING_H_
 #define _BLACKFIN_STRING_H_
 
index d442113..89de650 100644 (file)
@@ -1,3 +1,9 @@
+/*
+ * Copyright 2009 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2 or later.
+ */
+
 #ifndef _BLACKFIN_SWAB_H
 #define _BLACKFIN_SWAB_H
 
index 85e8f16..dde19b1 100644 (file)
@@ -1,34 +1,8 @@
 /*
- * File:        include/asm/system.h
- * Based on:
- * Author:      Tony Kou (tonyko@lineo.ca)
- *              Copyright (c) 2002 Arcturus Networks Inc.
- *                    (www.arcturusnetworks.com)
- *              Copyright (c) 2003 Metrowerks (www.metrowerks.com)
- *              Copyright (c) 2004 Analog Device Inc.
- * Created:     25Jan2001 - Tony Kou
- * Description: system.h include file
+ * Copyright 2004-2009 Analog Devices Inc.
+ *               Tony Kou (tonyko@lineo.ca)
  *
- * Modified:     22Sep2006 - Robin Getz
- *                - move include blackfin.h down, so I can get access to
- *                   irq functions in other include files.
- *
- * Bugs:         Enter bugs at http://blackfin.uclinux.org/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; see the file COPYING.
- * If not, write to the Free Software Foundation,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ * Licensed under the GPL-2 or later
  */
 
 #ifndef _BLACKFIN_SYSTEM_H
index 2bbfdd9..afb3a86 100644 (file)
@@ -1,27 +1,7 @@
 /*
- * File:         include/asm-blackfin/thread_info.h
- * Based on:     include/asm-m68knommu/thread_info.h
- * Author:       LG Soft India
- *               Copyright (C) 2004-2005 Analog Devices Inc.
- * Created:      Tue Sep 21 2004
- * Description:  Blackfin low-level thread information
- * Modified:
- * Bugs:         Enter bugs at http://blackfin.uclinux.org/
+ * Copyright 2004-2009 Analog Devices Inc.
  *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; see the file COPYING.
- * If not, write to the Free Software Foundation,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ * Licensed under the GPL-2 or later.
  */
 
 #ifndef _ASM_THREAD_INFO_H
index 89a12ee..a74ae08 100644 (file)
@@ -1,3 +1,9 @@
+/*
+ * Copyright 2004-2008 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2 or later.
+ */
+
 #ifndef _BLACKFIN_TLB_H
 #define _BLACKFIN_TLB_H
 
index 312b596..609ad3c 100644 (file)
@@ -1,6 +1,9 @@
 /*
- * Common header file for blackfin family of processors.
+ * header file for hardware trace functions
  *
+ * Copyright 2007-2008 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2 or later.
  */
 
 #ifndef _BLACKFIN_TRACE_
index 3cdc454..9fe0da6 100644 (file)
@@ -1,13 +1,10 @@
 /*
- *  linux/include/asm/traps.h
+ *  Copyright 2004-2009 Analog Devices Inc.
+ *                 2001 Lineo, Inc
+ *                        Tony Kou
+ *                 1993 Hamish Macdonald
  *
- *  Copyright (C) 1993        Hamish Macdonald
- *
- *  Lineo, Inc    Jul 2001    Tony Kou
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file COPYING in the main directory of this archive
- * for more details.
+ * Licensed under the GPL-2
  */
 
 #ifndef _BFIN_TRAPS_H
index 2f469a1..c03b853 100644 (file)
@@ -1,4 +1,7 @@
-/* Changes made by Lineo Inc.    May 2001
+/*
+ * Copyright 2004-2009 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2 or later.
  *
  * Based on: include/asm-m68knommu/uaccess.h
  */
index 02b1529..779be02 100644 (file)
@@ -1,3 +1,9 @@
+/*
+ * Copyright 2004-2009 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2 or later.
+ */
+
 #ifndef __ASM_BFIN_UNISTD_H
 #define __ASM_BFIN_UNISTD_H
 /*
index f05d1b9..bd32c09 100644 (file)
@@ -1,30 +1,9 @@
 /*
- * File:         arch/blackfin/kernel/asm-offsets.c
- * Based on:
- * Author:
+ * generate definitions needed by assembly language modules
  *
- * Created:
- * Description:  generate definitions needed by assembly language modules.
+ * Copyright 2004-2009 Analog Devices Inc.
  *
- * Modified:
- *               Copyright 2004-2006 Analog Devices Inc.
- *
- * Bugs:         Enter bugs at http://blackfin.uclinux.org/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see the file COPYING, or write
- * to the Free Software Foundation, Inc.,
- * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ * Licensed under the GPL-2 or later
  */
 
 #include <linux/stddef.h>
index 384868d..1f17021 100644 (file)
@@ -2,6 +2,7 @@
  * bfin_dma_5xx.c - Blackfin DMA implementation
  *
  * Copyright 2004-2008 Analog Devices Inc.
+ *
  * Licensed under the GPL-2 or later.
  */
 
index fc4681c..22705ee 100644 (file)
@@ -1,30 +1,9 @@
 /*
- * File:         arch/blackfin/kernel/bfin_gpio.c
- * Based on:
- * Author:       Michael Hennerich (hennerich@blackfin.uclinux.org)
+ * GPIO Abstraction Layer
  *
- * Created:
- * Description:  GPIO Abstraction Layer
+ * Copyright 2006-2009 Analog Devices Inc.
  *
- * Modified:
- *               Copyright 2008 Analog Devices Inc.
- *
- * Bugs:         Enter bugs at http://blackfin.uclinux.org/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see the file COPYING, or write
- * to the Free Software Foundation, Inc.,
- * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ * Licensed under the GPL-2 or later
  */
 
 #include <linux/delay.h>
index 36193ee..f7b9cdc 100644 (file)
@@ -1,25 +1,11 @@
 /*
  * Blackfin CPLB initialization
  *
- *               Copyright 2004-2007 Analog Devices Inc.
+ * Copyright 2008-2009 Analog Devices Inc.
  *
- * Bugs:         Enter bugs at http://blackfin.uclinux.org/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see the file COPYING, or write
- * to the Free Software Foundation, Inc.,
- * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ * Licensed under the GPL-2 or later.
  */
+
 #include <linux/module.h>
 
 #include <asm/blackfin.h>
index 8e1e9e9..69e0e53 100644 (file)
@@ -1,22 +1,11 @@
 /*
- *               Blackfin CPLB exception handling.
- *               Copyright 2004-2007 Analog Devices Inc.
+ * Blackfin CPLB exception handling for when MPU in on
  *
- * 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.
+ * Copyright 2008-2009 Analog Devices Inc.
  *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see the file COPYING, or write
- * to the Free Software Foundation, Inc.,
- * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ * Licensed under the GPL-2 or later.
  */
+
 #include <linux/module.h>
 #include <linux/mm.h>
 
index 5d8ad50..fd9a2f3 100644 (file)
@@ -1,24 +1,9 @@
 /*
  * Blackfin CPLB initialization
  *
- *               Copyright 2004-2007 Analog Devices Inc.
+ * Copyright 2007-2009 Analog Devices Inc.
  *
- * Bugs:         Enter bugs at http://blackfin.uclinux.org/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see the file COPYING, or write
- * to the Free Software Foundation, Inc.,
- * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ * Licensed under the GPL-2 or later.
  */
 
 #include <linux/module.h>
index d9ea46c..5b88861 100644 (file)
@@ -1,26 +1,14 @@
 /*
- * File:         arch/blackfin/kernel/cplb-nompu-c/cplbmgr.c
  * Based on:     arch/blackfin/kernel/cplb-mpu/cplbmgr.c
  * Author:       Michael McTernan <mmcternan@airvana.com>
  *
- * Created:      01Nov2008
  * Description:  CPLB miss handler.
  *
  * Modified:
  *               Copyright 2008 Airvana Inc.
- *               Copyright 2004-2007 Analog Devices Inc.
+ *               Copyright 2008-2009 Analog Devices Inc.
  *
- * Bugs:         Enter bugs at http://blackfin.uclinux.org/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
+ * Licensed under the GPL-2 or later
  */
 
 #include <linux/kernel.h>
index 64d7830..0bdaa51 100644 (file)
@@ -2,6 +2,7 @@
  * arch/blackfin/kernel/cplbinfo.c - display CPLB status
  *
  * Copyright 2004-2008 Analog Devices Inc.
+ *
  * Licensed under the GPL-2 or later.
  */
 
@@ -111,24 +112,21 @@ static const struct seq_operations cplbinfo_sops = {
        .show  = cplbinfo_show,
 };
 
+#define CPLBINFO_DCPLB_FLAG 0x80000000
+
 static int cplbinfo_open(struct inode *inode, struct file *file)
 {
-       char buf[256], *path, *p;
+       struct proc_dir_entry *pde = PDE(file->f_path.dentry->d_inode);
+       char cplb_type;
        unsigned int cpu;
-       char *s_cpu, *s_cplb;
        int ret;
        struct seq_file *m;
        struct cplbinfo_data *cdata;
 
-       path = d_path(&file->f_path, buf, sizeof(buf));
-       if (IS_ERR(path))
-               return PTR_ERR(path);
-       s_cpu = strstr(path, "/cpu");
-       s_cplb = strrchr(path, '/');
-       if (!s_cpu || !s_cplb)
-               return -EINVAL;
+       cpu = (unsigned int)pde->data;
+       cplb_type = cpu & CPLBINFO_DCPLB_FLAG ? 'D' : 'I';
+       cpu &= ~CPLBINFO_DCPLB_FLAG;
 
-       cpu = simple_strtoul(s_cpu + 4, &p, 10);
        if (!cpu_online(cpu))
                return -ENODEV;
 
@@ -139,7 +137,7 @@ static int cplbinfo_open(struct inode *inode, struct file *file)
        cdata = m->private;
 
        cdata->pos = 0;
-       cdata->cplb_type = toupper(s_cplb[1]);
+       cdata->cplb_type = cplb_type;
        cplbinfo_seq_init(cdata, cpu);
 
        return 0;
@@ -168,8 +166,10 @@ static int __init cplbinfo_init(void)
                if (!cpu_dir)
                        return -ENOMEM;
 
-               proc_create("icplb", S_IRUGO, cpu_dir, &cplbinfo_fops);
-               proc_create("dcplb", S_IRUGO, cpu_dir, &cplbinfo_fops);
+               proc_create_data("icplb", S_IRUGO, cpu_dir, &cplbinfo_fops,
+                       (void *)cpu);
+               proc_create_data("dcplb", S_IRUGO, cpu_dir, &cplbinfo_fops,
+                       (void *)(cpu | CPLBINFO_DCPLB_FLAG));
        }
 
        return 0;
index 2f62a9f..e74e74d 100644 (file)
@@ -1,30 +1,9 @@
 /*
- * File:         arch/blackfin/kernel/dma-mapping.c
- * Based on:
- * Author:
+ * Dynamic DMA mapping support
  *
- * Created:
- * Description:  Dynamic DMA mapping support.
+ * Copyright 2005-2009 Analog Devices Inc.
  *
- * Modified:
- *               Copyright 2004-2006 Analog Devices Inc.
- *
- * Bugs:         Enter bugs at http://blackfin.uclinux.org/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see the file COPYING, or write
- * to the Free Software Foundation, Inc.,
- * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ * Licensed under the GPL-2 or later
  */
 
 #include <linux/types.h>
index 931c78b..84ed837 100644 (file)
@@ -1,25 +1,10 @@
 /*
- * File:         arch/blackfin/kernel/early_printk.c
- * Based on:     arch/x86_64/kernel/early_printk.c
- * Author:       Robin Getz <rgetz@blackfin.uclinux.org
+ * allow a console to be used for early printk
+ * derived from arch/x86/kernel/early_printk.c
  *
- * Created:      14Aug2007
- * Description:  allow a console to be used for early printk
+ * Copyright 2007-2009 Analog Devices Inc.
  *
- * Modified:
- *               Copyright 2004-2007 Analog Devices Inc.
- *
- * Bugs:         Enter bugs at http://blackfin.uclinux.org/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
+ * Licensed under the GPL-2
  */
 
 #include <linux/kernel.h>
index 3f8769b..f27dc22 100644 (file)
@@ -1,30 +1,7 @@
 /*
- * File:         arch/blackfin/kernel/entry.S
- * Based on:
- * Author:
+ * Copyright 2004-2009 Analog Devices Inc.
  *
- * Created:
- * Description:
- *
- * Modified:
- *               Copyright 2004-2006 Analog Devices Inc.
- *
- * Bugs:         Enter bugs at http://blackfin.uclinux.org/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see the file COPYING, or write
- * to the Free Software Foundation, Inc.,
- * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ * Licensed under the GPL-2 or later
  */
 
 #include <linux/linkage.h>
index 0d2d9e0..0565917 100644 (file)
@@ -6,7 +6,12 @@
  * These are aligned to 16 bytes, so that we have some space to replace
  * these sequences with something else (e.g. kernel traps if we ever do
  * BF561 SMP).
+ *
+ * Copyright 2007-2008 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2 or later.
  */
+
 #include <linux/linkage.h>
 #include <linux/init.h>
 #include <linux/unistd.h>
index d188b24..a88dadd 100644 (file)
@@ -1,21 +1,7 @@
 /*
- *  arch/blackfin/kernel/flat.c
+ * Copyright 2007 Analog Devices Inc.
  *
- *  Copyright (C) 2007 Analog Devices, Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * Licensed under the GPL-2.
  */
 
 #include <linux/module.h>
index c26c34d..118c5b9 100644 (file)
@@ -1,30 +1,7 @@
 /*
- * File:         arch/blackfin/kernel/init_task.c
- * Based on:
- * Author:
+ * Copyright 2004-2009 Analog Devices Inc.
  *
- * Created:
- * Description:  This file contains the simple DMA Implementation for Blackfin
- *
- * Modified:
- *               Copyright 2004-2006 Analog Devices Inc.
- *
- * Bugs:         Enter bugs at http://blackfin.uclinux.org/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see the file COPYING, or write
- * to the Free Software Foundation, Inc.,
- * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ * Licensed under the GPL-2 or later
  */
 
 #include <linux/mm.h>
index 4b5fd36..db9f9c9 100644 (file)
@@ -1,30 +1,7 @@
 /*
- * File:         arch/blackfin/kernel/irqchip.c
- * Based on:
- * Author:
+ * Copyright 2005-2009 Analog Devices Inc.
  *
- * Created:
- * Description:  This file contains the simple DMA Implementation for Blackfin
- *
- * Modified:
- *               Copyright 2004-2006 Analog Devices Inc.
- *
- * Bugs:         Enter bugs at http://blackfin.uclinux.org/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see the file COPYING, or write
- * to the Free Software Foundation, Inc.,
- * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ * Licensed under the GPL-2 or later
  */
 
 #include <linux/kernel_stat.h>
index 67fc7a5..a6dfa6b 100644 (file)
@@ -1,30 +1,7 @@
 /*
- * File:         arch/blackfin/kernel/module.c
- * Based on:
- * Author:
+ * Copyright 2004-2009 Analog Devices Inc.
  *
- * Created:
- * Description:
- *
- * Modified:
- *               Copyright 2004-2006 Analog Devices Inc.
- *
- * Bugs:         Enter bugs at http://blackfin.uclinux.org/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see the file COPYING, or write
- * to the Free Software Foundation, Inc.,
- * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ * Licensed under the GPL-2 or later
  */
 
 #define pr_fmt(fmt) "module %s: " fmt
index f5b2861..430ae39 100644 (file)
@@ -1,30 +1,9 @@
 /*
- * File:         arch/blackfin/kernel/process.c
- * Based on:
- * Author:
+ * Blackfin architecture-dependent process handling
  *
- * Created:
- * Description:  Blackfin architecture-dependent process handling.
+ * Copyright 2004-2009 Analog Devices Inc.
  *
- * Modified:
- *               Copyright 2004-2006 Analog Devices Inc.
- *
- * Bugs:         Enter bugs at http://blackfin.uclinux.org/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see the file COPYING, or write
- * to the Free Software Foundation, Inc.,
- * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ * Licensed under the GPL-2 or later
  */
 
 #include <linux/module.h>
index 30f4828..0982b5d 100644 (file)
@@ -1,30 +1,8 @@
 /*
- * File:         arch/blackfin/kernel/ptrace.c
- * Based on:     Taken from linux/kernel/ptrace.c
- * Author:       linux/kernel/ptrace.c is by Ross Biro 1/23/92, edited by Linus Torvalds
+ * linux/kernel/ptrace.c is by Ross Biro 1/23/92, edited by Linus Torvalds
+ * these modifications are Copyright 2004-2009 Analog Devices Inc.
  *
- * Created:      1/23/92
- * Description:
- *
- * Modified:
- *               Copyright 2004-2006 Analog Devices Inc.
- *
- * Bugs:         Enter bugs at http://blackfin.uclinux.org/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see the file COPYING, or write
- * to the Free Software Foundation, Inc.,
- * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ * Licensed under the GPL-2
  */
 
 #include <linux/kernel.h>
index 369535b..c202a44 100644 (file)
@@ -1,9 +1,5 @@
 /*
- * arch/blackfin/kernel/setup.c
- *
- * Copyright 2004-2006 Analog Devices Inc.
- *
- * Enter bugs at http://blackfin.uclinux.org/
+ * Copyright 2004-2009 Analog Devices Inc.
  *
  * Licensed under the GPL-2 or later.
  */
index 8b8c710..557e9fe 100644 (file)
@@ -4,8 +4,6 @@
  *
  * Copyright 2009 Analog Devices Inc.
  *
- * Enter bugs at http://blackfin.uclinux.org/
- *
  * Licensed under the GPL-2 or later.
  */
 
index dbc3bbf..9d90c18 100644 (file)
@@ -1,30 +1,7 @@
 /*
- * File:         arch/blackfin/kernel/signal.c
- * Based on:
- * Author:
+ * Copyright 2004-2009 Analog Devices Inc.
  *
- * Created:
- * Description:
- *
- * Modified:
- *               Copyright 2004-2006 Analog Devices Inc.
- *
- * Bugs:         Enter bugs at http://blackfin.uclinux.org/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see the file COPYING, or write
- * to the Free Software Foundation, Inc.,
- * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ * Licensed under the GPL-2 or later
  */
 
 #include <linux/signal.h>
index 3da60fb..afcef12 100644 (file)
@@ -1,32 +1,10 @@
 /*
- * File:         arch/blackfin/kernel/sys_bfin.c
- * Based on:
- * Author:
+ * contains various random system calls that have a non-standard
+ * calling sequence on the Linux/Blackfin platform.
  *
- * Created:
- * Description:  This file contains various random system calls that
- *               have a non-standard calling sequence on the Linux/bfin
- *               platform.
+ * Copyright 2004-2009 Analog Devices Inc.
  *
- * Modified:
- *               Copyright 2004-2006 Analog Devices Inc.
- *
- * Bugs:         Enter bugs at http://blackfin.uclinux.org/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see the file COPYING, or write
- * to the Free Software Foundation, Inc.,
- * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ * Licensed under the GPL-2 or later
  */
 
 #include <linux/spinlock.h>
@@ -91,3 +69,14 @@ asmlinkage void *sys_dma_memcpy(void *dest, const void *src, size_t len)
 {
        return safe_dma_memcpy(dest, src, len);
 }
+
+#if defined(CONFIG_FB) || defined(CONFIG_FB_MODULE)
+#include <linux/fb.h>
+unsigned long get_fb_unmapped_area(struct file *filp, unsigned long orig_addr,
+       unsigned long len, unsigned long pgoff, unsigned long flags)
+{
+       struct fb_info *info = filp->private_data;
+       return (unsigned long)info->screen_base;
+}
+EXPORT_SYMBOL(get_fb_unmapped_area);
+#endif
index f971576..359cfb1 100644 (file)
@@ -1,13 +1,13 @@
 /*
- * linux/arch/kernel/time-ts.c
- *
  * Based on arm clockevents implementation and old bfin time tick.
  *
- * Copyright(C) 2008, GeoTechnologies, Vitja Makarov
+ * Copyright 2008-2009 Analog Devics Inc.
+ *                2008 GeoTechnologies
+ *                     Vitja Makarov
  *
- * This code is licenced under the GPL version 2. For details see
- * kernel-base/COPYING.
+ * Licensed under the GPL-2
  */
+
 #include <linux/module.h>
 #include <linux/profile.h>
 #include <linux/interrupt.h>
index adb54aa..bd3b53d 100644 (file)
@@ -14,6 +14,7 @@
 #include <linux/time.h>
 #include <linux/irq.h>
 #include <linux/delay.h>
+#include <linux/sched.h>
 
 #include <asm/blackfin.h>
 #include <asm/time.h>
@@ -81,11 +82,11 @@ time_sched_init(irqreturn_t(*timer_routine) (int, void *))
 #endif
 }
 
+#ifdef CONFIG_ARCH_USES_GETTIMEOFFSET
 /*
  * Should return useconds since last timer tick
  */
-#ifndef CONFIG_GENERIC_TIME
-static unsigned long gettimeoffset(void)
+u32 arch_gettimeoffset(void)
 {
        unsigned long offset;
        unsigned long clocks_per_jiffy;
@@ -184,65 +185,6 @@ void __init time_init(void)
        time_sched_init(timer_interrupt);
 }
 
-#ifndef CONFIG_GENERIC_TIME
-void do_gettimeofday(struct timeval *tv)
-{
-       unsigned long flags;
-       unsigned long seq;
-       unsigned long usec, sec;
-
-       do {
-               seq = read_seqbegin_irqsave(&xtime_lock, flags);
-               usec = gettimeoffset();
-               sec = xtime.tv_sec;
-               usec += (xtime.tv_nsec / NSEC_PER_USEC);
-       }
-       while (read_seqretry_irqrestore(&xtime_lock, seq, flags));
-
-       while (usec >= USEC_PER_SEC) {
-               usec -= USEC_PER_SEC;
-               sec++;
-       }
-
-       tv->tv_sec = sec;
-       tv->tv_usec = usec;
-}
-EXPORT_SYMBOL(do_gettimeofday);
-
-int do_settimeofday(struct timespec *tv)
-{
-       time_t wtm_sec, sec = tv->tv_sec;
-       long wtm_nsec, nsec = tv->tv_nsec;
-
-       if ((unsigned long)tv->tv_nsec >= NSEC_PER_SEC)
-               return -EINVAL;
-
-       write_seqlock_irq(&xtime_lock);
-       /*
-        * This is revolting. We need to set the xtime.tv_usec
-        * correctly. However, the value in this location is
-        * is value at the last tick.
-        * Discover what correction gettimeofday
-        * would have done, and then undo it!
-        */
-       nsec -= (gettimeoffset() * NSEC_PER_USEC);
-
-       wtm_sec = wall_to_monotonic.tv_sec + (xtime.tv_sec - sec);
-       wtm_nsec = wall_to_monotonic.tv_nsec + (xtime.tv_nsec - nsec);
-
-       set_normalized_timespec(&xtime, sec, nsec);
-       set_normalized_timespec(&wall_to_monotonic, wtm_sec, wtm_nsec);
-
-       ntp_clear();
-
-       write_sequnlock_irq(&xtime_lock);
-       clock_was_set();
-
-       return 0;
-}
-EXPORT_SYMBOL(do_settimeofday);
-#endif /* !CONFIG_GENERIC_TIME */
-
 /*
  * Scheduler clock - returns current time in nanosec units.
  */
index 56464cb..6b7325d 100644 (file)
@@ -1,30 +1,7 @@
 /*
- * File:         arch/blackfin/kernel/traps.c
- * Based on:
- * Author:       Hamish Macdonald
+ * Copyright 2004-2009 Analog Devices Inc.
  *
- * Created:
- * Description:  uses S/W interrupt 15 for the system calls
- *
- * Modified:
- *               Copyright 2004-2006 Analog Devices Inc.
- *
- * Bugs:         Enter bugs at http://blackfin.uclinux.org/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see the file COPYING, or write
- * to the Free Software Foundation, Inc.,
- * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ * Licensed under the GPL-2 or later
  */
 
 #include <linux/bug.h>
index ffd90fb..10e1253 100644 (file)
@@ -1,30 +1,7 @@
 /*
- * File:         arch/blackfin/kernel/vmlinux.lds.S
- * Based on:     none - original work
- * Author:
+ * Copyright 2004-2009 Analog Devices Inc.
  *
- * Created:      Tue Sep 21 2004
- * Description:  Master linker script for blackfin architecture
- *
- * Modified:
- *               Copyright 2004-2007 Analog Devices Inc.
- *
- * Bugs:         Enter bugs at http://blackfin.uclinux.org/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see the file COPYING, or write
- * to the Free Software Foundation, Inc.,
- * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ * Licensed under the GPL-2 or later
  */
 
 #define VMLINUX_SYMBOL(_sym_) _##_sym_
index a8c279e..ab69d87 100644 (file)
@@ -1,30 +1,7 @@
 /*
- * File:         arch/blackfin/lib/ashldi3.c
- * Based on:
- * Author:
+ * Copyright 2004-2009 Analog Devices Inc.
  *
- * Created:
- * Description:
- *
- * Modified:
- *               Copyright 2004-2006 Analog Devices Inc.
- *
- * Bugs:         Enter bugs at http://blackfin.uclinux.org/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see the file COPYING, or write
- * to the Free Software Foundation, Inc.,
- * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ * Licensed under the GPL-2 or later.
  */
 
 #include "gcclib.h"
index a0d3419..b5b351e 100644 (file)
@@ -1,30 +1,7 @@
 /*
- * File:         arch/blackfin/lib/ashrdi3.c
- * Based on:
- * Author:
+ * Copyright 2004-2009 Analog Devices Inc.
  *
- * Created:
- * Description:
- *
- * Modified:
- *               Copyright 2004-2006 Analog Devices Inc.
- *
- * Bugs:         Enter bugs at http://blackfin.uclinux.org/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see the file COPYING, or write
- * to the Free Software Foundation, Inc.,
- * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ * Licensed under the GPL-2 or later.
  */
 
 #include "gcclib.h"
index cd605e7..c62969d 100644 (file)
@@ -1,32 +1,12 @@
 /*
- * File:         arch/blackfin/lib/checksum.c
- * Based on:     none - original work
- * Author:
+ * Copyright 2004-2009 Analog Devices Inc.
  *
- * Created:
- * Description:  An implementation of the TCP/IP protocol suite for the LINUX
- *               operating system.  INET is implemented using the  BSD Socket
- *               interface as the means of communication with the user level.
+ * Licensed under the GPL-2 or later.
  *
- * Modified:
- *               Copyright 2004-2006 Analog Devices Inc.
+ * An implementation of the TCP/IP protocol suite for the LINUX operating
+ * system. INET is implemented using the BSD Socket interface as the
+ * means of communication with the user level.
  *
- * Bugs:         Enter bugs at http://blackfin.uclinux.org/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see the file COPYING, or write
- * to the Free Software Foundation, Inc.,
- * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
  */
 
 #include <linux/module.h>
index 2ac59c7..f89c5a4 100644 (file)
@@ -1,10 +1,9 @@
 /*
- * File:         arch/blackfin/lib/divsi3.S
- * Based on:
- * Author:
+ * Copyright 2004-2009 Analog Devices Inc.
  *
- * Created:
- * Description:  16 / 32 bit signed division.
+ * Licensed under the ADI BSD license or the GPL-2 (or later)
+ *
+ * 16 / 32 bit signed division.
  *                 Special cases :
  *                      1)  If(numerator == 0)
  *                             return 0
  *                                   R0 - Quotient    (o)
  *                 Registers Used : R2-R7,P0-P2
  *
- * Modified:
- *               Copyright 2004-2006 Analog Devices Inc.
- *
- * Bugs:         Enter bugs at http://blackfin.uclinux.org/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see the file COPYING, or write
- * to the Free Software Foundation, Inc.,
- * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
  */
 
 .global   ___divsi3;
index 9ccd39a..724f07f 100644 (file)
@@ -1,30 +1,7 @@
 /*
- * File:         arch/blackfin/lib/gcclib.h
- * Based on:
- * Author:
+ * Copyright 2004-2009 Analog Devices Inc.
  *
- * Created:
- * Description:
- *
- * Modified:
- *               Copyright 2004-2006 Analog Devices Inc.
- *
- * Bugs:         Enter bugs at http://blackfin.uclinux.org/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see the file COPYING, or write
- * to the Free Software Foundation, Inc.,
- * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ * Licensed under the GPL-2 or later.
  */
 
 #define BITS_PER_UNIT  8
index e57bf6f..53f1741 100644 (file)
@@ -1,30 +1,7 @@
 /*
- * File:         arch/blackfin/lib/lshrdi3.c
- * Based on:
- * Author:
+ * Copyright 2004-2009 Analog Devices Inc.
  *
- * Created:
- * Description:
- *
- * Modified:
- *               Copyright 2004-2006 Analog Devices Inc.
- *
- * Bugs:         Enter bugs at http://blackfin.uclinux.org/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see the file COPYING, or write
- * to the Free Software Foundation, Inc.,
- * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ * Licensed under the GPL-2 or later.
  */
 
 #include "gcclib.h"
index 5da4281..542e40f 100644 (file)
@@ -1,30 +1,7 @@
 /*
- * File:         arch/blackfin/lib/memchr.S
- * Based on:
- * Author:
+ * Copyright 2005-2009 Analog Devices Inc.
  *
- * Created:
- * Description:
- *
- * Modified:
- *               Copyright 2004-2006 Analog Devices Inc.
- *
- * Bugs:         Enter bugs at http://blackfin.uclinux.org/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see the file COPYING, or write
- * to the Free Software Foundation, Inc.,
- * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ * Licensed under the ADI BSD license or the GPL-2 (or later)
  */
 
 #include <linux/linkage.h>
index 219fa28..ce5b9f1 100644 (file)
@@ -1,30 +1,7 @@
 /*
- * File:         arch/blackfin/lib/memcmp.S
- * Based on:
- * Author:
+ * Copyright 2004-2009 Analog Devices Inc.
  *
- * Created:
- * Description:
- *
- * Modified:
- *               Copyright 2004-2006 Analog Devices Inc.
- *
- * Bugs:         Enter bugs at http://blackfin.uclinux.org/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see the file COPYING, or write
- * to the Free Software Foundation, Inc.,
- * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ * Licensed under the ADI BSD license or the GPL-2 (or later)
  */
 
 #include <linux/linkage.h>
index e654a18..c31bf22 100644 (file)
@@ -1,36 +1,13 @@
 /*
- * File:         arch/blackfin/lib/memcpy.S
- * Based on:
- * Author:
+ * internal version of memcpy(), issued by the compiler to copy blocks of
+ * data around. This is really memmove() - it has to be able to deal with
+ * possible overlaps, because that ambiguity is when the compiler gives up
+ * and calls a function. We have our own, internal version so that we get
+ * something we trust, even if the user has redefined the normal symbol.
  *
- * Created:
- * Description:  internal version of memcpy(), issued by the compiler
- *               to copy blocks of data around.
- *               This is really memmove() - it has to be able to deal with
- *               possible overlaps, because that ambiguity is when the compiler
- *               gives up and calls a function. We have our own, internal version
- *               so that we get something we trust, even if the user has redefined
- *               the normal symbol.
+ * Copyright 2004-2009 Analog Devices Inc.
  *
- * Modified:
- *               Copyright 2004-2006 Analog Devices Inc.
- *
- * Bugs:         Enter bugs at http://blackfin.uclinux.org/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see the file COPYING, or write
- * to the Free Software Foundation, Inc.,
- * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ * Licensed under the ADI BSD license or the GPL-2 (or later)
  */
 
 #include <linux/linkage.h>
index 33f8653..80c240a 100644 (file)
@@ -1,30 +1,7 @@
 /*
- * File:         arch/blackfin/lib/memmove.S
- * Based on:
- * Author:
+ * Copyright 2005-2009 Analog Devices Inc.
  *
- * Created:
- * Description:
- *
- * Modified:
- *               Copyright 2004-2006 Analog Devices Inc.
- *
- * Bugs:         Enter bugs at http://blackfin.uclinux.org/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see the file COPYING, or write
- * to the Free Software Foundation, Inc.,
- * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ * Licensed under the ADI BSD license or the GPL-2 (or later)
  */
 
 #include <linux/linkage.h>
index 8159136..c30d99b 100644 (file)
@@ -1,30 +1,7 @@
 /*
- * File:         arch/blackfin/lib/memset.S
- * Based on:
- * Author:
+ * Copyright 2004-2009 Analog Devices Inc.
  *
- * Created:
- * Description:
- *
- * Modified:
- *               Copyright 2004-2006 Analog Devices Inc.
- *
- * Bugs:         Enter bugs at http://blackfin.uclinux.org/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see the file COPYING, or write
- * to the Free Software Foundation, Inc.,
- * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ * Licensed under the ADI BSD license or the GPL-2 (or later)
  */
 
 #include <linux/linkage.h>
index ca1dd39..8b0c7d4 100644 (file)
@@ -1,36 +1,12 @@
 /*
- * File:         arch/blackfin/lib/modsi3.S
- * Based on:
- * Author:
+ * This program computes 32 bit signed remainder. It calls div32 function
+ * for quotient estimation.
+ *   Registers in:  R0, R1 = Numerator/ Denominator
+ *   Registers out: R0     = Remainder
  *
- * Created:
- * Description:  This program computes 32 bit signed remainder. It calls div32 function
- *               for quotient estimation.
+ * Copyright 2004-2009 Analog Devices Inc.
  *
- *               Registers used :
- *               Numerator/ Denominator in  R0, R1
- *                 R0  -  returns remainder.
- *                 R2-R7
- *
- * Modified:
- *               Copyright 2004-2006 Analog Devices Inc.
- *
- * Bugs:         Enter bugs at http://blackfin.uclinux.org/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see the file COPYING, or write
- * to the Free Software Foundation, Inc.,
- * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ * Licensed under the ADI BSD license or the GPL-2 (or later)
  */
 
 .global ___modsi3;
index abde120..953a38a 100644 (file)
@@ -1,3 +1,9 @@
+/*
+ * Copyright 2008 Analog Devices Inc.
+ *
+ * Licensed under the ADI BSD license or the GPL-2 (or later)
+ */
+
 .align 2
 .global ___muldi3;
 .type ___muldi3, STT_FUNC;
index 4685b7a..250f4d4 100644 (file)
@@ -1,30 +1,11 @@
 /*
- * File:         arch/blackfin/lib/outs.S
- * Based on:
- * Author:       Bas Vermeulen <bas@buyways.nl>
+ * Implementation of outs{bwl} for BlackFin processors using zero overhead loops.
  *
- * Created:      Tue Mar 22 15:27:24 CEST 2005
- * Description:  Implementation of outs{bwl} for BlackFin processors using zero overhead loops.
+ * Copyright 2005-2009 Analog Devices Inc.
+ *                2005 BuyWays BV
+ *                      Bas Vermeulen <bas@buyways.nl>
  *
- * Modified:     Copyright (C) 2005 Bas Vermeulen, BuyWays BV <bas@buyways.nl>
- *               Copyright 2004-2008 Analog Devices Inc.
- *
- * Bugs:         Enter bugs at http://blackfin.uclinux.org/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see the file COPYING, or write
- * to the Free Software Foundation, Inc.,
- * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ * Licensed under the GPL-2.
  */
 
 #include <linux/linkage.h>
index e383cd3..99ee8c5 100644 (file)
@@ -1,3 +1,9 @@
+/*
+ * Copyright 2007 Analog Devices Inc.
+ *
+ * Licensed under the ADI BSD license or the GPL-2 (or later)
+ */
+
 .align 2
 .global ___smulsi3_highpart;
 .type ___smulsi3_highpart, STT_FUNC;
index 58fd96d..97e9043 100644 (file)
@@ -1,30 +1,7 @@
 /*
- * File:         arch/blackfin/lib/udivsi3.S
- * Based on:
- * Author:
+ * Copyright 2004-2009 Analog Devices Inc.
  *
- * Created:
- * Description:
- *
- * Modified:
- *               Copyright 2004-2006 Analog Devices Inc.
- *
- * Bugs:         Enter bugs at http://blackfin.uclinux.org/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see the file COPYING, or write
- * to the Free Software Foundation, Inc.,
- * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ * Licensed under the ADI BSD license or the GPL-2 (or later)
  */
 
 #include <linux/linkage.h>
index 4f2b76e..168eba7 100644 (file)
@@ -1,30 +1,9 @@
 /*
- * File:         arch/blackfin/lib/umodsi3.S
- * Based on:
- * Author:
+ * libgcc1 routines for Blackfin 5xx
  *
- * Created:
- * Description:  libgcc1 routines for Blackfin 5xx
+ * Copyright 2004-2009 Analog Devices Inc.
  *
- * Modified:
- *               Copyright 2004-2006 Analog Devices Inc.
- *
- * Bugs:         Enter bugs at http://blackfin.uclinux.org/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see the file COPYING, or write
- * to the Free Software Foundation, Inc.,
- * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ * Licensed under the ADI BSD license or the GPL-2 (or later)
  */
 
 #ifdef CONFIG_ARITHMETIC_OPS_L1
index 67b7993..051824a 100644 (file)
@@ -1,3 +1,9 @@
+/*
+ * Copyright 2007 Analog Devices Inc.
+ *
+ * Licensed under the ADI BSD license or the GPL-2 (or later)
+ */
+
 .align 2
 .global ___umulsi3_highpart;
 .type ___umulsi3_highpart, STT_FUNC;
index 03e4a99..01975c0 100644 (file)
@@ -1,31 +1,9 @@
 /*
- * File:         arch/blackfin/mach-bf518/boards/ezbrd.c
- * Based on:     arch/blackfin/mach-bf527/boards/ezbrd.c
- * Author:       Bryan Wu <cooloney@kernel.org>
+ * Copyright 2004-2009 Analog Devices Inc.
+ *                2005 National ICT Australia (NICTA)
+ *                      Aidan Williams <aidan@nicta.com.au>
  *
- * Created:
- * Description:
- *
- * Modified:
- *               Copyright 2005 National ICT Australia (NICTA)
- *               Copyright 2004-2008 Analog Devices Inc.
- *
- * Bugs:         Enter bugs at http://blackfin.uclinux.org/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see the file COPYING, or write
- * to the Free Software Foundation, Inc.,
- * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ * Licensed under the GPL-2 or later.
  */
 
 #include <linux/device.h>
@@ -571,19 +549,6 @@ static struct platform_device bf51x_sdh_device = {
 };
 #endif
 
-static struct resource bfin_gpios_resources = {
-       .start = 0,
-       .end   = MAX_BLACKFIN_GPIOS - 1,
-       .flags = IORESOURCE_IRQ,
-};
-
-static struct platform_device bfin_gpios_device = {
-       .name = "simple-gpio",
-       .id = -1,
-       .num_resources = 1,
-       .resource = &bfin_gpios_resources,
-};
-
 static const unsigned int cclk_vlev_datasheet[] =
 {
        VRPAIR(VLEV_100, 400000000),
@@ -660,8 +625,6 @@ static struct platform_device *stamp_devices[] __initdata = {
 #if defined(CONFIG_MTD_PHYSMAP) || defined(CONFIG_MTD_PHYSMAP_MODULE)
        &ezbrd_flash_device,
 #endif
-
-       &bfin_gpios_device,
 };
 
 static int __init ezbrd_init(void)
index 698e88c..78b4360 100644 (file)
@@ -1,31 +1,11 @@
 /*
- * File:         arch/blackfin/mach-bf518/dma.c
- * Based on:
- * Author:       Bryan Wu <cooloney@kernel.org>
+ * the simple DMA Implementation for Blackfin
  *
- * Created:
- * Description:  This file contains the simple DMA Implementation for Blackfin
+ * Copyright 2008 Analog Devices Inc.
  *
- * Modified:
- *               Copyright 2004-2008 Analog Devices Inc.
- *
- * Bugs:         Enter bugs at http://blackfin.uclinux.org/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see the file COPYING, or write
- * to the Free Software Foundation, Inc.,
- * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ * Licensed under the GPL-2 or later.
  */
+
 #include <linux/module.h>
 
 #include <asm/blackfin.h>
index 78da1a0..856b330 100644 (file)
@@ -1,30 +1,7 @@
 /*
- * File:         include/asm-blackfin/mach-bf518/bf518.h
- * Based on:   include/asm-blackfin/mach-bf527/bf527.h
- * Author:     Michael Hennerich (michael.hennerich@analog.com)
+ * Copyright 2008 Analog Devices Inc.
  *
- * Created:
- * Description:  SYSTEM MMR REGISTER AND MEMORY MAP FOR ADSP-BF518
- *
- * Modified:
- *               Copyright 2004-2007 Analog Devices Inc.
- *
- * Bugs:         Enter bugs at http://blackfin.uclinux.org/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see the file COPYING, or write
- * to the Free Software Foundation, Inc.,
- * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ * Licensed under the GPL-2 or later.
  */
 
 #ifndef __MACH_BF518_H__
index dbade93..970d310 100644 (file)
@@ -1,32 +1,7 @@
 /*
- * file:        include/asm-blackfin/mach-bf518/bfin_serial_5xx.h
- * based on:
- * author:
+ * Copyright 2008-2009 Analog Devices Inc.
  *
- * created:
- * description:
- *     blackfin serial driver head file
- * rev:
- *
- * modified:
- *
- *
- * bugs:         enter bugs at http://blackfin.uclinux.org/
- *
- * this program is free software; you can redistribute it and/or modify
- * it under the terms of the gnu general public license as published by
- * the free software foundation; either version 2, or (at your option)
- * any later version.
- *
- * this program is distributed in the hope that it will be useful,
- * but without any warranty; without even the implied warranty of
- * merchantability or fitness for a particular purpose.  see the
- * gnu general public license for more details.
- *
- * you should have received a copy of the gnu general public license
- * along with this program; see the file copying.
- * if not, write to the free software foundation,
- * 59 temple place - suite 330, boston, ma 02111-1307, usa.
+ * Licensed under the GPL-2 or later
  */
 
 #include <linux/serial.h>
index 83421d3..6cfb246 100644 (file)
@@ -1,32 +1,7 @@
 /*
- * File:         include/asm-blackfin/mach-bf518/blackfin.h
- * Based on:
- * Author:
+ * Copyright 2008-2009 Analog Devices Inc.
  *
- * Created:
- * Description:
- *
- * Rev:
- *
- * Modified:
- *
- *
- * Bugs:         Enter bugs at http://blackfin.uclinux.org/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; see the file COPYING.
- * If not, write to the Free Software Foundation,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ * Licensed under the GPL-2 or later
  */
 
 #ifndef _MACH_BLACKFIN_H_
index 820c13c..493020d 100644 (file)
@@ -1,32 +1,7 @@
 /*
- * File:         include/asm-blackfin/mach-bf518/cdefbf512.h
- * Based on:
- * Author:
+ * Copyright 2008-2009 Analog Devices Inc.
  *
- * Created:
- * Description:  system mmr register map
- *
- * Rev:
- *
- * Modified:
- *
- *
- * Bugs:         Enter bugs at http://blackfin.uclinux.org/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; see the file COPYING.
- * If not, write to the Free Software Foundation,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ * Licensed under the ADI BSD license or the GPL-2 (or later)
  */
 
 #ifndef _CDEF_BF512_H
index dfe492d..e1d9991 100644 (file)
@@ -1,32 +1,7 @@
 /*
- * File:         include/asm-blackfin/mach-bf518/cdefbf514.h
- * Based on:
- * Author:
+ * Copyright 2008-2009 Analog Devices Inc.
  *
- * Created:
- * Description:  system mmr register map
- *
- * Rev:
- *
- * Modified:
- *
- *
- * Bugs:         Enter bugs at http://blackfin.uclinux.org/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; see the file COPYING.
- * If not, write to the Free Software Foundation,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ * Licensed under the GPL-2 or later
  */
 
 #ifndef _CDEF_BF514_H
index 14df43d..6b364ed 100644 (file)
@@ -1,32 +1,7 @@
 /*
- * File:         include/asm-blackfin/mach-bf518/cdefbf516.h
- * Based on:
- * Author:
+ * Copyright 2008-2009 Analog Devices Inc.
  *
- * Created:
- * Description:  system mmr register map
- *
- * Rev:
- *
- * Modified:
- *
- *
- * Bugs:         Enter bugs at http://blackfin.uclinux.org/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; see the file COPYING.
- * If not, write to the Free Software Foundation,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ * Licensed under the GPL-2 or later
  */
 
 #ifndef _CDEF_BF516_H
index bafb370..929b906 100644 (file)
@@ -1,32 +1,7 @@
 /*
- * File:         include/asm-blackfin/mach-bf518/cdefbf518.h
- * Based on:
- * Author:
+ * Copyright 2008-2009 Analog Devices Inc.
  *
- * Created:
- * Description:  system mmr register map
- *
- * Rev:
- *
- * Modified:
- *
- *
- * Bugs:         Enter bugs at http://blackfin.uclinux.org/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; see the file COPYING.
- * If not, write to the Free Software Foundation,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ * Licensed under the GPL-2 or later
  */
 
 #ifndef _CDEF_BF518_H
 #define bfin_read_EMAC_TXC_ABORT()             bfin_read32(EMAC_TXC_ABORT)
 #define bfin_write_EMAC_TXC_ABORT(val)         bfin_write32(EMAC_TXC_ABORT, val)
 
+#define bfin_read_EMAC_PTP_CTL()                bfin_read16(EMAC_PTP_CTL)
+#define bfin_write_EMAC_PTP_CTL(val)            bfin_write16(EMAC_PTP_CTL, val)
+#define bfin_read_EMAC_PTP_IE()                 bfin_read16(EMAC_PTP_IE)
+#define bfin_write_EMAC_PTP_IE(val)             bfin_write16(EMAC_PTP_IE, val)
+#define bfin_read_EMAC_PTP_ISTAT()              bfin_read16(EMAC_PTP_ISTAT)
+#define bfin_write_EMAC_PTP_ISTAT(val)          bfin_write16(EMAC_PTP_ISTAT, val)
+#define bfin_read_EMAC_PTP_FOFF()               bfin_read32(EMAC_PTP_FOFF)
+#define bfin_write_EMAC_PTP_FOFF(val)           bfin_write32(EMAC_PTP_FOFF, val)
+#define bfin_read_EMAC_PTP_FV1()                bfin_read32(EMAC_PTP_FV1)
+#define bfin_write_EMAC_PTP_FV1(val)            bfin_write32(EMAC_PTP_FV1, val)
+#define bfin_read_EMAC_PTP_FV2()                bfin_read32(EMAC_PTP_FV2)
+#define bfin_write_EMAC_PTP_FV2(val)            bfin_write32(EMAC_PTP_FV2, val)
+#define bfin_read_EMAC_PTP_FV3()                bfin_read32(EMAC_PTP_FV3)
+#define bfin_write_EMAC_PTP_FV3(val)            bfin_write32(EMAC_PTP_FV3, val)
+#define bfin_read_EMAC_PTP_ADDEND()             bfin_read32(EMAC_PTP_ADDEND)
+#define bfin_write_EMAC_PTP_ADDEND(val)         bfin_write32(EMAC_PTP_ADDEND, val)
+#define bfin_read_EMAC_PTP_ACCR()               bfin_read32(EMAC_PTP_ACCR)
+#define bfin_write_EMAC_PTP_ACCR(val)           bfin_write32(EMAC_PTP_ACCR, val)
+#define bfin_read_EMAC_PTP_OFFSET()             bfin_read32(EMAC_PTP_OFFSET)
+#define bfin_write_EMAC_PTP_OFFSET(val)         bfin_write32(EMAC_PTP_OFFSET, val)
+#define bfin_read_EMAC_PTP_TIMELO()             bfin_read32(EMAC_PTP_TIMELO)
+#define bfin_write_EMAC_PTP_TIMELO(val)         bfin_write32(EMAC_PTP_TIMELO, val)
+#define bfin_read_EMAC_PTP_TIMEHI()             bfin_read32(EMAC_PTP_TIMEHI)
+#define bfin_write_EMAC_PTP_TIMEHI(val)         bfin_write32(EMAC_PTP_TIMEHI, val)
+#define bfin_read_EMAC_PTP_RXSNAPLO()           bfin_read32(EMAC_PTP_RXSNAPLO)
+#define bfin_read_EMAC_PTP_RXSNAPHI()           bfin_read32(EMAC_PTP_RXSNAPHI)
+#define bfin_read_EMAC_PTP_TXSNAPLO()           bfin_read32(EMAC_PTP_TXSNAPLO)
+#define bfin_read_EMAC_PTP_TXSNAPHI()           bfin_read32(EMAC_PTP_TXSNAPHI)
+#define bfin_read_EMAC_PTP_ALARMLO()            bfin_read32(EMAC_PTP_ALARMLO)
+#define bfin_write_EMAC_PTP_ALARMLO(val)        bfin_write32(EMAC_PTP_ALARMLO, val)
+#define bfin_read_EMAC_PTP_ALARMHI()            bfin_read32(EMAC_PTP_ALARMHI)
+#define bfin_write_EMAC_PTP_ALARMHI(val)        bfin_write32(EMAC_PTP_ALARMHI, val)
+#define bfin_read_EMAC_PTP_ID_OFF()             bfin_read16(EMAC_PTP_ID_OFF)
+#define bfin_write_EMAC_PTP_ID_OFF(val)         bfin_write16(EMAC_PTP_ID_OFF, val)
+#define bfin_read_EMAC_PTP_ID_SNAP()            bfin_read32(EMAC_PTP_ID_SNAP)
+#define bfin_write_EMAC_PTP_ID_SNAP(val)        bfin_write32(EMAC_PTP_ID_SNAP, val)
+#define bfin_read_EMAC_PTP_PPS_STARTHI()        bfin_read32(EMAC_PTP_PPS_STARTHI)
+#define bfin_write_EMAC_PTP_PPS_STARTHI(val)    bfin_write32(EMAC_PTP_PPS_STARTHI, val)
+#define bfin_read_EMAC_PTP_PPS_PERIOD()         bfin_read32(EMAC_PTP_PPS_PERIOD)
+#define bfin_write_EMAC_PTP_PPS_PERIOD(val)     bfin_write32(EMAC_PTP_PPS_PERIOD, val)
+
 /* Removable Storage Interface Registers */
 
 #define bfin_read_RSI_PWR_CTL()        bfin_read16(RSI_PWR_CONTROL)
index ee3d473..1d970df 100644 (file)
@@ -1,31 +1,7 @@
 /*
- * File:         include/asm-blackfin/mach-bf518/cdefBF51x_base.h
- * Based on:
- * Author:
+ * Copyright 2008 Analog Devices Inc.
  *
- * Created:
- * Description:
- *
- * Rev:
- *
- * Modified:
- *
- * Bugs:         Enter bugs at http://blackfin.uclinux.org/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; see the file COPYING.
- * If not, write to the Free Software Foundation,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ * Licensed under the GPL-2 or later
  */
 
 #ifndef _CDEF_BF52X_H
index a96ca90..9b505bb 100644 (file)
@@ -1,31 +1,7 @@
 /*
- * File:         include/asm-blackfin/mach-bf518/defBF512.h
- * Based on:
- * Author:
+ * Copyright 2008 Analog Devices Inc.
  *
- * Created:
- * Description:
- *
- * Rev:
- *
- * Modified:
- *
- * Bugs:         Enter bugs at http://blackfin.uclinux.org/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; see the file COPYING.
- * If not, write to the Free Software Foundation,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ * Licensed under the ADI BSD license or the GPL-2 (or later)
  */
 
 #ifndef _DEF_BF512_H
index 56ee5a7..b5adca2 100644 (file)
@@ -1,31 +1,7 @@
 /*
- * File:         include/asm-blackfin/mach-bf518/defBF514.h
- * Based on:
- * Author:
+ * Copyright 2008-2009 Analog Devices Inc.
  *
- * Created:
- * Description:
- *
- * Rev:
- *
- * Modified:
- *
- * Bugs:         Enter bugs at http://blackfin.uclinux.org/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; see the file COPYING.
- * If not, write to the Free Software Foundation,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ * Licensed under the ADI BSD license or the GPL-2 (or later)
  */
 
 #ifndef _DEF_BF514_H
index dfc9384..7eb1877 100644 (file)
@@ -1,31 +1,7 @@
 /*
- * File:         include/asm-blackfin/mach-bf518/defBF516.h
- * Based on:
- * Author:
+ * Copyright 2008-2009 Analog Devices Inc.
  *
- * Created:
- * Description:
- *
- * Rev:
- *
- * Modified:
- *
- * Bugs:         Enter bugs at http://blackfin.uclinux.org/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; see the file COPYING.
- * If not, write to the Free Software Foundation,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ * Licensed under the ADI BSD license or the GPL-2 (or later)
  */
 
 #ifndef _DEF_BF516_H
index 6e982ab..794cf06 100644 (file)
@@ -1,31 +1,7 @@
 /*
- * File:         include/asm-blackfin/mach-bf518/defBF518.h
- * Based on:
- * Author:
+ * Copyright 2008-2009 Analog Devices Inc.
  *
- * Created:
- * Description:
- *
- * Rev:
- *
- * Modified:
- *
- * Bugs:         Enter bugs at http://blackfin.uclinux.org/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; see the file COPYING.
- * If not, write to the Free Software Foundation,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ * Licensed under the ADI BSD license or the GPL-2 (or later)
  */
 
 #ifndef _DEF_BF518_H
 
 #define                       RWR  0x1        /* Read Wait Request */
 
+/* Bit masks for EMAC_PTP_CTL */
+
+#define                    PTP_EN  0x1        /* Enable the PTP_TSYNC module */
+#define                        TL  0x2        /* Timestamp lock control */
+#define                      ASEN  0x10       /* Auxiliary snapshot control */
+#define                     PPSEN  0x80       /* Pulse-per-second (PPS) control */
+#define                     CKOEN  0x2000     /* Clock output control */
+
+/* Bit masks for EMAC_PTP_IE */
+
+#define                      ALIE  0x1        /* Alarm interrupt enable */
+#define                     RXEIE  0x2        /* Receive event interrupt enable */
+#define                     RXGIE  0x4        /* Receive general interrupt enable */
+#define                      TXIE  0x8        /* Transmit interrupt enable */
+#define                     RXOVE  0x10       /* Receive overrun error interrupt enable */
+#define                     TXOVE  0x20       /* Transmit overrun error interrupt enable */
+#define                      ASIE  0x40       /* Auxiliary snapshot interrupt enable */
+
+/* Bit masks for EMAC_PTP_ISTAT */
+
+#define                       ALS  0x1        /* Alarm status */
+#define                      RXEL  0x2        /* Receive event interrupt status */
+#define                      RXGL  0x4        /* Receive general interrupt status */
+#define                      TXTL  0x8        /* Transmit snapshot status */
+#define                      RXOV  0x10       /* Receive snapshot overrun status */
+#define                      TXOV  0x20       /* Transmit snapshot overrun status */
+#define                       ASL  0x40       /* Auxiliary snapshot interrupt status */
+
 #endif /* _DEF_BF518_H */
index 1bec8d1..e06f411 100644 (file)
@@ -1,31 +1,7 @@
 /*
- * File:         include/asm-blackfin/mach-bf518/defBF51x_base.h
- * Based on:
- * Author:
+ * Copyright 2008 Analog Devices Inc.
  *
- * Created:
- * Description:
- *
- * Rev:
- *
- * Modified:
- *
- * Bugs:         Enter bugs at http://blackfin.uclinux.org/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; see the file COPYING.
- * If not, write to the Free Software Foundation,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ * Licensed under the ADI BSD license or the GPL-2 (or later)
  */
 
 #ifndef _DEF_BF51X_H
index 9757683..bbab2d7 100644 (file)
@@ -1,7 +1,4 @@
 /*
- * File: arch/blackfin/mach-bf518/include/mach/gpio.h
- * Bugs: Enter bugs at http://blackfin.uclinux.org/
- *
  * Copyright (C) 2008 Analog Devices Inc.
  * Licensed under the GPL-2 or later.
  */
index 3ff0f09..14e52ec 100644 (file)
@@ -1,32 +1,7 @@
 /*
- * file:       include/asm-blackfin/mach-bf518/irq.h
- * based on:   include/asm-blackfin/mach-bf527/irq.h
- * author:     Michael Hennerich (michael.hennerich@analog.com)
+ * Copyright 2008 Analog Devices Inc.
  *
- * created:
- * description:
- *     system mmr register map
- * rev:
- *
- * modified:
- *
- *
- * bugs:         enter bugs at http://blackfin.uclinux.org/
- *
- * this program is free software; you can redistribute it and/or modify
- * it under the terms of the gnu general public license as published by
- * the free software foundation; either version 2, or (at your option)
- * any later version.
- *
- * this program is distributed in the hope that it will be useful,
- * but without any warranty; without even the implied warranty of
- * merchantability or fitness for a particular purpose.  see the
- * gnu general public license for more details.
- *
- * you should have received a copy of the gnu general public license
- * along with this program; see the file copying.
- * if not, write to the free software foundation,
- * 59 temple place - suite 330, boston, ma 02111-1307, usa.
+ * Licensed under the GPL-2 or later
  */
 
 #ifndef _BF518_IRQ_H_
index a0fc77f..e352910 100644 (file)
@@ -1,3 +1,9 @@
+/*
+ * Copyright 2008-2009 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2 or later
+ */
+
 #ifndef _MACH_PORTMUX_H_
 #define _MACH_PORTMUX_H_
 
index 3151fd5..bb05bef 100644 (file)
@@ -1,30 +1,9 @@
 /*
- * File:         arch/blackfin/mach-bf518/ints-priority.c
- * Based on:     arch/blackfin/mach-bf527/ints-priority.c
- * Author:       Bryan Wu <cooloney@kernel.org>
+ * Set up the interrupt priorities
  *
- * Created:
- * Description:  Set up the interrupt priorities
+ * Copyright 2008 Analog Devices Inc.
  *
- * Modified:
- *               Copyright 2004-2007 Analog Devices Inc.
- *
- * Bugs:         Enter bugs at http://blackfin.uclinux.org/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see the file COPYING, or write
- * to the Free Software Foundation, Inc.,
- * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ * Licensed under the GPL-2 or later.
  */
 
 #include <linux/module.h>
index 08a3f01..f1996b1 100644 (file)
@@ -1,31 +1,10 @@
 /*
- * File:         arch/blackfin/mach-bf527/boards/cm-bf527.c
- * Based on:     arch/blackfin/mach-bf537/boards/stamp.c
- * Author:       Aidan Williams <aidan@nicta.com.au>
+ * Copyright 2004-2009 Analog Devices Inc.
+ *           2008-2009 Bluetechnix
+ *                2005 National ICT Australia (NICTA)
+ *                      Aidan Williams <aidan@nicta.com.au>
  *
- * Created:
- * Description:
- *
- * Modified:
- *               Copyright 2005 National ICT Australia (NICTA)
- *               Copyright 2004-2008 Analog Devices Inc.
- *
- * Bugs:         Enter bugs at http://blackfin.uclinux.org/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see the file COPYING, or write
- * to the Free Software Foundation, Inc.,
- * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ * Licensed under the GPL-2 or later.
  */
 
 #include <linux/device.h>
@@ -616,12 +595,6 @@ static struct platform_device bfin_spi0_device = {
 };
 #endif  /* spi master and devices */
 
-#if defined(CONFIG_FB_BFIN_7393) || defined(CONFIG_FB_BFIN_7393_MODULE)
-static struct platform_device bfin_fb_adv7393_device = {
-       .name = "bfin-adv7393",
-};
-#endif
-
 #if defined(CONFIG_MTD_GPIO_ADDR) || defined(CONFIG_MTD_GPIO_ADDR_MODULE)
 static struct mtd_partition cm_partitions[] = {
        {
@@ -786,6 +759,11 @@ static struct i2c_board_info __initdata bfin_i2c_board_info[] = {
                .irq = IRQ_PF8,
        },
 #endif
+#if defined(CONFIG_FB_BFIN_7393) || defined(CONFIG_FB_BFIN_7393_MODULE)
+       {
+               I2C_BOARD_INFO("bfin-adv7393", 0x2B),
+       },
+#endif
 };
 
 #if defined(CONFIG_SERIAL_BFIN_SPORT) || defined(CONFIG_SERIAL_BFIN_SPORT_MODULE)
@@ -821,19 +799,6 @@ static struct platform_device bfin_device_gpiokeys = {
 };
 #endif
 
-static struct resource bfin_gpios_resources = {
-       .start = 0,
-       .end   = MAX_BLACKFIN_GPIOS - 1,
-       .flags = IORESOURCE_IRQ,
-};
-
-static struct platform_device bfin_gpios_device = {
-       .name = "simple-gpio",
-       .id = -1,
-       .num_resources = 1,
-       .resource = &bfin_gpios_resources,
-};
-
 static const unsigned int cclk_vlev_datasheet[] =
 {
        VRPAIR(VLEV_100, 400000000),
@@ -909,10 +874,6 @@ static struct platform_device *cmbf527_devices[] __initdata = {
        &bfin_spi0_device,
 #endif
 
-#if defined(CONFIG_FB_BFIN_7393) || defined(CONFIG_FB_BFIN_7393_MODULE)
-       &bfin_fb_adv7393_device,
-#endif
-
 #if defined(CONFIG_SERIAL_BFIN) || defined(CONFIG_SERIAL_BFIN_MODULE)
        &bfin_uart_device,
 #endif
@@ -942,8 +903,6 @@ static struct platform_device *cmbf527_devices[] __initdata = {
 #if defined(CONFIG_MTD_GPIO_ADDR) || defined(CONFIG_MTD_GPIO_ADDR_MODULE)
        &cm_flash_device,
 #endif
-
-       &bfin_gpios_device,
 };
 
 static int __init cm_init(void)
index 68b4c80..cad23b1 100644 (file)
@@ -1,31 +1,9 @@
 /*
- * File:         arch/blackfin/mach-bf527/boards/ezbrd.c
- * Based on:     arch/blackfin/mach-bf537/boards/stamp.c
- * Author:       Aidan Williams <aidan@nicta.com.au>
+ * Copyright 2004-2009 Analog Devices Inc.
+ *                2005 National ICT Australia (NICTA)
+ *                      Aidan Williams <aidan@nicta.com.au>
  *
- * Created:
- * Description:
- *
- * Modified:
- *               Copyright 2005 National ICT Australia (NICTA)
- *               Copyright 2004-2008 Analog Devices Inc.
- *
- * Bugs:         Enter bugs at http://blackfin.uclinux.org/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see the file COPYING, or write
- * to the Free Software Foundation, Inc.,
- * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ * Licensed under the GPL-2 or later.
  */
 
 #include <linux/device.h>
@@ -611,19 +589,6 @@ static struct platform_device bfin_device_gpiokeys = {
 };
 #endif
 
-static struct resource bfin_gpios_resources = {
-       .start = 0,
-       .end   = MAX_BLACKFIN_GPIOS - 1,
-       .flags = IORESOURCE_IRQ,
-};
-
-static struct platform_device bfin_gpios_device = {
-       .name = "simple-gpio",
-       .id = -1,
-       .num_resources = 1,
-       .resource = &bfin_gpios_resources,
-};
-
 static const unsigned int cclk_vlev_datasheet[] =
 {
        VRPAIR(VLEV_100, 400000000),
@@ -732,8 +697,6 @@ static struct platform_device *stamp_devices[] __initdata = {
 #if defined(CONFIG_MTD_PHYSMAP) || defined(CONFIG_MTD_PHYSMAP_MODULE)
        &ezbrd_flash_device,
 #endif
-
-       &bfin_gpios_device,
 };
 
 static int __init ezbrd_init(void)
index 2849b09..f09665f 100644 (file)
@@ -1,31 +1,9 @@
 /*
- * File:         arch/blackfin/mach-bf527/boards/ezkit.c
- * Based on:     arch/blackfin/mach-bf537/boards/stamp.c
- * Author:       Aidan Williams <aidan@nicta.com.au>
+ * Copyright 2004-2009 Analog Devices Inc.
+ *                2005 National ICT Australia (NICTA)
+ *                      Aidan Williams <aidan@nicta.com.au>
  *
- * Created:
- * Description:
- *
- * Modified:
- *               Copyright 2005 National ICT Australia (NICTA)
- *               Copyright 2004-2008 Analog Devices Inc.
- *
- * Bugs:         Enter bugs at http://blackfin.uclinux.org/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see the file COPYING, or write
- * to the Free Software Foundation, Inc.,
- * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ * Licensed under the GPL-2 or later.
  */
 
 #include <linux/device.h>
@@ -716,12 +694,6 @@ static struct platform_device bfin_fb_device = {
 };
 #endif
 
-#if defined(CONFIG_FB_BFIN_7393) || defined(CONFIG_FB_BFIN_7393_MODULE)
-static struct platform_device bfin_fb_adv7393_device = {
-       .name = "bfin-adv7393",
-};
-#endif
-
 #if defined(CONFIG_SERIAL_BFIN) || defined(CONFIG_SERIAL_BFIN_MODULE)
 static struct resource bfin_uart_resources[] = {
 #ifdef CONFIG_SERIAL_BFIN_UART0
@@ -837,6 +809,11 @@ static struct i2c_board_info __initdata bfin_i2c_board_info[] = {
                .irq = IRQ_PF8,
        },
 #endif
+#if defined(CONFIG_FB_BFIN_7393) || defined(CONFIG_FB_BFIN_7393_MODULE)
+       {
+               I2C_BOARD_INFO("bfin-adv7393", 0x2B),
+       },
+#endif
 };
 
 #if defined(CONFIG_SERIAL_BFIN_SPORT) || defined(CONFIG_SERIAL_BFIN_SPORT_MODULE)
@@ -905,19 +882,6 @@ static struct platform_device bfin_rotary_device = {
 };
 #endif
 
-static struct resource bfin_gpios_resources = {
-       .start = 0,
-       .end   = MAX_BLACKFIN_GPIOS - 1,
-       .flags = IORESOURCE_IRQ,
-};
-
-static struct platform_device bfin_gpios_device = {
-       .name = "simple-gpio",
-       .id = -1,
-       .num_resources = 1,
-       .resource = &bfin_gpios_resources,
-};
-
 static const unsigned int cclk_vlev_datasheet[] =
 {
        VRPAIR(VLEV_100, 400000000),
@@ -1001,10 +965,6 @@ static struct platform_device *stamp_devices[] __initdata = {
        &bf52x_t350mcqb_device,
 #endif
 
-#if defined(CONFIG_FB_BFIN_7393) || defined(CONFIG_FB_BFIN_7393_MODULE)
-       &bfin_fb_adv7393_device,
-#endif
-
 #if defined(CONFIG_SERIAL_BFIN) || defined(CONFIG_SERIAL_BFIN_MODULE)
        &bfin_uart_device,
 #endif
@@ -1038,8 +998,6 @@ static struct platform_device *stamp_devices[] __initdata = {
 #if defined(CONFIG_MTD_PHYSMAP) || defined(CONFIG_MTD_PHYSMAP_MODULE)
        &ezkit_flash_device,
 #endif
-
-       &bfin_gpios_device,
 };
 
 static int __init ezkit_init(void)
index 2318775..7bc7577 100644 (file)
@@ -1,31 +1,11 @@
 /*
- * File:         arch/blackfin/mach-bf527/dma.c
- * Based on:
- * Author:
+ * This file contains the simple DMA Implementation for Blackfin
  *
- * Created:
- * Description:  This file contains the simple DMA Implementation for Blackfin
+ * Copyright 2007-2008 Analog Devices Inc.
  *
- * Modified:
- *               Copyright 2004-2007 Analog Devices Inc.
- *
- * Bugs:         Enter bugs at http://blackfin.uclinux.org/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see the file COPYING, or write
- * to the Free Software Foundation, Inc.,
- * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ * Licensed under the GPL-2 or later.
  */
+
 #include <linux/module.h>
 
 #include <asm/blackfin.h>
index 3832aab..ff68c88 100644 (file)
@@ -1,30 +1,7 @@
 /*
- * File:         include/asm-blackfin/mach-bf527/bf527.h
- * Based on:   include/asm-blackfin/mach-bf537/bf537.h
- * Author:     Michael Hennerich (michael.hennerich@analog.com)
+ * Copyright 2007-2009 Analog Devices Inc.
  *
- * Created:
- * Description:  SYSTEM MMR REGISTER AND MEMORY MAP FOR ADSP-BF527
- *
- * Modified:
- *               Copyright 2004-2007 Analog Devices Inc.
- *
- * Bugs:         Enter bugs at http://blackfin.uclinux.org/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see the file COPYING, or write
- * to the Free Software Foundation, Inc.,
- * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ * Licensed under the GPL-2 or later.
  */
 
 #ifndef __MACH_BF527_H__
index ebd6ceb..c1d55b8 100644 (file)
@@ -1,32 +1,7 @@
 /*
- * file:        include/asm-blackfin/mach-bf527/bfin_serial_5xx.h
- * based on:
- * author:
+ * Copyright 2007-2009 Analog Devices Inc.
  *
- * created:
- * description:
- *     blackfin serial driver head file
- * rev:
- *
- * modified:
- *
- *
- * bugs:         enter bugs at http://blackfin.uclinux.org/
- *
- * this program is free software; you can redistribute it and/or modify
- * it under the terms of the gnu general public license as published by
- * the free software foundation; either version 2, or (at your option)
- * any later version.
- *
- * this program is distributed in the hope that it will be useful,
- * but without any warranty; without even the implied warranty of
- * merchantability or fitness for a particular purpose.  see the
- * gnu general public license for more details.
- *
- * you should have received a copy of the gnu general public license
- * along with this program; see the file copying.
- * if not, write to the free software foundation,
- * 59 temple place - suite 330, boston, ma 02111-1307, usa.
+ * Licensed under the GPL-2 or later
  */
 
 #include <linux/serial.h>
index ea9cb0f..e7d6034 100644 (file)
@@ -1,32 +1,7 @@
 /*
- * File:         include/asm-blackfin/mach-bf527/blackfin.h
- * Based on:
- * Author:
+ * Copyright 2007-2009 Analog Devices Inc.
  *
- * Created:
- * Description:
- *
- * Rev:
- *
- * Modified:
- *
- *
- * Bugs:         Enter bugs at http://blackfin.uclinux.org/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; see the file COPYING.
- * If not, write to the Free Software Foundation,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ * Licensed under the GPL-2 or later
  */
 
 #ifndef _MACH_BLACKFIN_H_
index 663c2bb..1079af8 100644 (file)
@@ -1,32 +1,7 @@
 /*
- * File:         include/asm-blackfin/mach-bf527/cdefbf522.h
- * Based on:
- * Author:
+ * Copyright 2007-2008 Analog Devices Inc.
  *
- * Created:
- * Description:  system mmr register map
- *
- * Rev:
- *
- * Modified:
- *
- *
- * Bugs:         Enter bugs at http://blackfin.uclinux.org/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; see the file COPYING.
- * If not, write to the Free Software Foundation,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ * Licensed under the GPL-2 or later
  */
 
 #ifndef _CDEF_BF522_H
index 00377eb..dc3119e 100644 (file)
@@ -1,32 +1,7 @@
 /*
- * File:         include/asm-blackfin/mach-bf527/cdefbf525.h
- * Based on:
- * Author:
+ * Copyright 2007-2008 Analog Devices Inc.
  *
- * Created:
- * Description:  system mmr register map
- *
- * Rev:
- *
- * Modified:
- *
- *
- * Bugs:         Enter bugs at http://blackfin.uclinux.org/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; see the file COPYING.
- * If not, write to the Free Software Foundation,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ * Licensed under the GPL-2 or later
  */
 
 #ifndef _CDEF_BF525_H
index fca8db7..d657944 100644 (file)
@@ -1,32 +1,7 @@
 /*
- * File:         include/asm-blackfin/mach-bf527/cdefbf527.h
- * Based on:
- * Author:
+ * Copyright 2007-2008 Analog Devices Inc.
  *
- * Created:
- * Description:  system mmr register map
- *
- * Rev:
- *
- * Modified:
- *
- *
- * Bugs:         Enter bugs at http://blackfin.uclinux.org/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; see the file COPYING.
- * If not, write to the Free Software Foundation,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ * Licensed under the GPL-2 or later
  */
 
 #ifndef _CDEF_BF527_H
index 1fe76d8..7014dde 100644 (file)
@@ -1,31 +1,7 @@
 /*
- * File:         include/asm-blackfin/mach-bf527/cdefBF52x_base.h
- * Based on:
- * Author:
+ * Copyright 2007-2008 Analog Devices Inc.
  *
- * Created:
- * Description:
- *
- * Rev:
- *
- * Modified:
- *
- * Bugs:         Enter bugs at http://blackfin.uclinux.org/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; see the file COPYING.
- * If not, write to the Free Software Foundation,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ * Licensed under the GPL-2 or later
  */
 
 #ifndef _CDEF_BF52X_H
index 0a8cdcd..cb139a2 100644 (file)
@@ -1,31 +1,7 @@
 /*
- * File:         include/asm-blackfin/mach-bf527/defBF522.h
- * Based on:
- * Author:
+ * Copyright 2007-2008 Analog Devices Inc.
  *
- * Created:
- * Description:
- *
- * Rev:
- *
- * Modified:
- *
- * Bugs:         Enter bugs at http://blackfin.uclinux.org/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; see the file COPYING.
- * If not, write to the Free Software Foundation,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ * Licensed under the ADI BSD license or the GPL-2 (or later)
  */
 
 #ifndef _DEF_BF522_H
index 5cd7576..82abefc 100644 (file)
@@ -1,31 +1,7 @@
 /*
- * File:         include/asm-blackfin/mach-bf527/defBF525.h
- * Based on:
- * Author:
+ * Copyright 2007-2008 Analog Devices Inc.
  *
- * Created:
- * Description:
- *
- * Rev:
- *
- * Modified:
- *
- * Bugs:         Enter bugs at http://blackfin.uclinux.org/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; see the file COPYING.
- * If not, write to the Free Software Foundation,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ * Licensed under the ADI BSD license or the GPL-2 (or later)
  */
 
 #ifndef _DEF_BF525_H
index f040f36..570a125 100644 (file)
@@ -1,31 +1,7 @@
 /*
- * File:         include/asm-blackfin/mach-bf527/defBF527.h
- * Based on:
- * Author:
+ * Copyright 2007-2008 Analog Devices Inc.
  *
- * Created:
- * Description:
- *
- * Rev:
- *
- * Modified:
- *
- * Bugs:         Enter bugs at http://blackfin.uclinux.org/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; see the file COPYING.
- * If not, write to the Free Software Foundation,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ * Licensed under the ADI BSD license or the GPL-2 (or later)
  */
 
 #ifndef _DEF_BF527_H
index 68b55d0..f821700 100644 (file)
@@ -1,31 +1,7 @@
 /*
- * File:         include/asm-blackfin/mach-bf527/defBF52x_base.h
- * Based on:
- * Author:
+ * Copyright 2007-2008 Analog Devices Inc.
  *
- * Created:
- * Description:
- *
- * Rev:
- *
- * Modified:
- *
- * Bugs:         Enter bugs at http://blackfin.uclinux.org/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; see the file COPYING.
- * If not, write to the Free Software Foundation,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ * Licensed under the ADI BSD license or the GPL-2 (or later)
  */
 
 #ifndef _DEF_BF52X_H
index 06b6eeb..104bff8 100644 (file)
@@ -1,7 +1,4 @@
 /*
- * File: arch/blackfin/mach-bf527/include/mach/gpio.h
- * Bugs: Enter bugs at http://blackfin.uclinux.org/
- *
  * Copyright (C) 2008 Analog Devices Inc.
  * Licensed under the GPL-2 or later.
  */
index 8ea660d..aa6579a 100644 (file)
@@ -1,32 +1,7 @@
 /*
- * file:       include/asm-blackfin/mach-bf527/irq.h
- * based on:   include/asm-blackfin/mach-bf537/irq.h
- * author:     Michael Hennerich (michael.hennerich@analog.com)
+ * Copyright 2007-2008 Analog Devices Inc.
  *
- * created:
- * description:
- *     system mmr register map
- * rev:
- *
- * modified:
- *
- *
- * bugs:         enter bugs at http://blackfin.uclinux.org/
- *
- * this program is free software; you can redistribute it and/or modify
- * it under the terms of the gnu general public license as published by
- * the free software foundation; either version 2, or (at your option)
- * any later version.
- *
- * this program is distributed in the hope that it will be useful,
- * but without any warranty; without even the implied warranty of
- * merchantability or fitness for a particular purpose.  see the
- * gnu general public license for more details.
- *
- * you should have received a copy of the gnu general public license
- * along with this program; see the file copying.
- * if not, write to the free software foundation,
- * 59 temple place - suite 330, boston, ma 02111-1307, usa.
+ * Licensed under the GPL-2 or later
  */
 
 #ifndef _BF527_IRQ_H_
index 72b1652..d4518b6 100644 (file)
@@ -1,3 +1,9 @@
+/*
+ * Copyright 2007-2009 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2 or later
+ */
+
 #ifndef _MACH_PORTMUX_H_
 #define _MACH_PORTMUX_H_
 
index f8c8acd..44ca215 100644 (file)
@@ -1,30 +1,9 @@
 /*
- * File:         arch/blackfin/mach-bf537/ints-priority.c
- * Based on:     arch/blackfin/mach-bf533/ints-priority.c
- * Author:       Michael Hennerich (michael.hennerich@analog.com)
+ * Set up the interrupt priorities
  *
- * Created:
- * Description:  Set up the interrupt priorities
+ * Copyright 2007-2008 Analog Devices Inc.
  *
- * Modified:
- *               Copyright 2004-2007 Analog Devices Inc.
- *
- * Bugs:         Enter bugs at http://blackfin.uclinux.org/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see the file COPYING, or write
- * to the Free Software Foundation, Inc.,
- * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ * Licensed under the GPL-2 or later.
  */
 
 #include <linux/module.h>
index 6c2b47f..43f43a0 100644 (file)
@@ -1,32 +1,11 @@
 /*
- * File:         arch/blackfin/mach-bf533/H8606.c
- * Based on:     arch/blackfin/mach-bf533/stamp.c
- * Author:       Javier Herrero <jherrero@hvsistemas.es>
+ * Copyright 2004-2009 Analog Devices Inc.
+ *           2007-2008 HV Sistemas S.L.
+ *                      Javier Herrero <jherrero@hvsistemas.es>
+ *                2005 National ICT Australia (NICTA)
+ *                      Aidan Williams <aidan@nicta.com.au>
  *
- * Created:      2007
- * Description:  Board Info File for the HV Sistemas H8606 board
- *
- * Modified:
- *               Copyright 2005 National ICT Australia (NICTA)
- *               Copyright 2004-2006 Analog Devices Inc
- *              Copyright 2007,2008 HV Sistemas S.L.
- *
- * Bugs:         Enter bugs at http://blackfin.uclinux.org/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see the file COPYING, or write
- * to the Free Software Foundation, Inc.,
- * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ * Licensed under the GPL-2 or later.
  */
 
 #include <linux/device.h>
index 8208d67..b580884 100644 (file)
@@ -1,16 +1,10 @@
 /*
- * File:         arch/blackfin/mach-bf533/blackstamp.c
- * Based on:     arch/blackfin/mach-bf533/stamp.c
- * Author:       Benjamin Matthews <bmat@lle.rochester.edu>
- *               Aidan Williams <aidan@nicta.com.au>
+ * Board Info File for the BlackStamp
  *
- * Created:      2008
- * Description:  Board Info File for the BlackStamp
- *
- * Copyright 2005 National ICT Australia (NICTA)
  * Copyright 2004-2008 Analog Devices Inc.
- *
- * Enter bugs at http://blackfin.uclinux.org/
+ *                2008 Benjamin Matthews <bmat@lle.rochester.edu>
+ *                2005 National ICT Australia (NICTA)
+ *                      Aidan Williams <aidan@nicta.com.au>
  *
  * More info about the BlackStamp at:
  *     http://blackfin.uclinux.org/gf/project/blackstamp/
@@ -281,19 +275,6 @@ static struct platform_device bfin_device_gpiokeys = {
 };
 #endif
 
-static struct resource bfin_gpios_resources = {
-       .start = 0,
-       .end   = MAX_BLACKFIN_GPIOS - 1,
-       .flags = IORESOURCE_IRQ,
-};
-
-static struct platform_device bfin_gpios_device = {
-       .name = "simple-gpio",
-       .id = -1,
-       .num_resources = 1,
-       .resource = &bfin_gpios_resources,
-};
-
 #if defined(CONFIG_I2C_GPIO) || defined(CONFIG_I2C_GPIO_MODULE)
 #include <linux/i2c-gpio.h>
 
@@ -384,8 +365,6 @@ static struct platform_device *stamp_devices[] __initdata = {
 #if defined(CONFIG_I2C_GPIO) || defined(CONFIG_I2C_GPIO_MODULE)
        &i2c_gpio_device,
 #endif
-
-       &bfin_gpios_device,
 };
 
 static int __init blackstamp_init(void)
index 7443b26..7fc3b86 100644 (file)
@@ -1,30 +1,10 @@
 /*
- * File:         arch/blackfin/mach-bf533/boards/cm_bf533.c
- * Based on:     arch/blackfin/mach-bf533/boards/ezkit.c
- * Author:       Aidan Williams <aidan@nicta.com.au> Copyright 2005
+ * Copyright 2004-2009 Analog Devices Inc.
+ *           2008-2009 Bluetechnix
+ *                2005 National ICT Australia (NICTA)
+ *                      Aidan Williams <aidan@nicta.com.au>
  *
- * Created:      2005
- * Description:  Board description file
- *
- * Modified:
- *               Copyright 2004-2006 Analog Devices Inc.
- *
- * Bugs:         Enter bugs at http://blackfin.uclinux.org/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see the file COPYING, or write
- * to the Free Software Foundation, Inc.,
- * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ * Licensed under the GPL-2 or later.
  */
 
 #include <linux/device.h>
@@ -261,19 +241,6 @@ static struct platform_device smsc911x_device = {
 };
 #endif
 
-static struct resource bfin_gpios_resources = {
-       .start = 0,
-       .end   = MAX_BLACKFIN_GPIOS - 1,
-       .flags = IORESOURCE_IRQ,
-};
-
-static struct platform_device bfin_gpios_device = {
-       .name = "simple-gpio",
-       .id = -1,
-       .num_resources = 1,
-       .resource = &bfin_gpios_resources,
-};
-
 #if defined(CONFIG_SERIAL_BFIN) || defined(CONFIG_SERIAL_BFIN_MODULE)
 static struct resource bfin_uart_resources[] = {
        {
@@ -506,8 +473,6 @@ static struct platform_device *cm_bf533_devices[] __initdata = {
 #if defined(CONFIG_MTD_PHYSMAP) || defined(CONFIG_MTD_PHYSMAP_MODULE)
        &para_flash_device,
 #endif
-
-       &bfin_gpios_device,
 };
 
 static int __init cm_bf533_init(void)
index fd518e3..d4689dc 100644 (file)
@@ -1,31 +1,9 @@
 /*
- * File:         arch/blackfin/mach-bf533/ezkit.c
- * Based on:     Original Work
- * Author:       Aidan Williams <aidan@nicta.com.au>
+ * Copyright 2004-2009 Analog Devices Inc.
+ *                2005 National ICT Australia (NICTA)
+ *                      Aidan Williams <aidan@nicta.com.au>
  *
- * Created:      2005
- * Description:
- *
- * Modified:     Robin Getz <rgetz@blackfin.uclinux.org> - Named the boards
- *               Copyright 2005 National ICT Australia (NICTA)
- *               Copyright 2004-2006 Analog Devices Inc.
- *
- * Bugs:         Enter bugs at http://blackfin.uclinux.org/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see the file COPYING, or write
- * to the Free Software Foundation, Inc.,
- * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ * Licensed under the GPL-2 or later.
  */
 
 #include <linux/device.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/partitions.h>
 #include <linux/mtd/plat-ram.h>
+#include <linux/mtd/physmap.h>
 #include <linux/spi/spi.h>
 #include <linux/spi/flash.h>
 #if defined(CONFIG_USB_ISP1362_HCD) || defined(CONFIG_USB_ISP1362_HCD_MODULE)
 #include <linux/usb/isp1362.h>
 #endif
 #include <linux/irq.h>
+#include <linux/i2c.h>
 #include <asm/dma.h>
 #include <asm/bfin5xx_spi.h>
 #include <asm/portmux.h>
@@ -56,12 +36,6 @@ static struct platform_device rtc_device = {
 };
 #endif
 
-#if defined(CONFIG_FB_BFIN_7393) || defined(CONFIG_FB_BFIN_7393_MODULE)
-static struct platform_device bfin_fb_adv7393_device = {
-       .name = "bfin-adv7393",
-};
-#endif
-
 /*
  *  USB-LAN EzExtender board
  *  Driver needs to know address, irq and flag pin.
@@ -98,54 +72,69 @@ static struct platform_device smc91x_device = {
 };
 #endif
 
-#if defined(CONFIG_MTD_PSD4256G) || defined(CONFIG_MTD_PSD4256G_MODULE)
-static const char *map_probes[] = {
-       "stm_flash",
-       NULL,
+#if defined(CONFIG_MTD_PHYSMAP) || defined(CONFIG_MTD_PHYSMAP_MODULE)
+static struct mtd_partition ezkit_partitions_a[] = {
+       {
+               .name       = "bootloader(nor a)",
+               .size       = 0x40000,
+               .offset     = 0,
+       }, {
+               .name       = "linux kernel(nor a)",
+               .size       = MTDPART_SIZ_FULL,
+               .offset     = MTDPART_OFS_APPEND,
+       },
 };
 
-static struct platdata_mtd_ram stm_pri_data_a = {
-       .mapname    = "Flash A Primary",
-       .map_probes = map_probes,
-       .bankwidth  = 2,
+static struct physmap_flash_data ezkit_flash_data_a = {
+       .width      = 2,
+       .parts      = ezkit_partitions_a,
+       .nr_parts   = ARRAY_SIZE(ezkit_partitions_a),
 };
 
-static struct resource stm_pri_resource_a = {
+static struct resource ezkit_flash_resource_a = {
        .start = 0x20000000,
        .end   = 0x200fffff,
        .flags = IORESOURCE_MEM,
 };
 
-static struct platform_device stm_pri_device_a = {
-       .name          = "mtd-ram",
+static struct platform_device ezkit_flash_device_a = {
+       .name          = "physmap-flash",
        .id            = 0,
        .dev = {
-               .platform_data = &stm_pri_data_a,
+               .platform_data = &ezkit_flash_data_a,
        },
        .num_resources = 1,
-       .resource      = &stm_pri_resource_a,
+       .resource      = &ezkit_flash_resource_a,
+};
+
+static struct mtd_partition ezkit_partitions_b[] = {
+       {
+               .name   = "file system(nor b)",
+               .size   = MTDPART_SIZ_FULL,
+               .offset = MTDPART_OFS_APPEND,
+       },
 };
 
-static struct platdata_mtd_ram stm_pri_data_b = {
-       .mapname    = "Flash B Primary",
-       .map_probes = map_probes,
-       .bankwidth  = 2,
+static struct physmap_flash_data ezkit_flash_data_b = {
+       .width      = 2,
+       .parts      = ezkit_partitions_b,
+       .nr_parts   = ARRAY_SIZE(ezkit_partitions_b),
 };
 
-static struct resource stm_pri_resource_b = {
+static struct resource ezkit_flash_resource_b = {
        .start = 0x20100000,
        .end   = 0x201fffff,
        .flags = IORESOURCE_MEM,
 };
 
-static struct platform_device stm_pri_device_b = {
-       .name          = "mtd-ram",
+static struct platform_device ezkit_flash_device_b = {
+       .name          = "physmap-flash",
        .id            = 4,
        .dev = {
-               .platform_data = &stm_pri_data_b,
+               .platform_data = &ezkit_flash_data_b,
        },
        .num_resources = 1,
-       .resource      = &stm_pri_resource_b,
+       .resource      = &ezkit_flash_resource_b,
 };
 #endif
 
@@ -400,19 +389,6 @@ static struct platform_device bfin_device_gpiokeys = {
 };
 #endif
 
-static struct resource bfin_gpios_resources = {
-       .start = 0,
-       .end   = MAX_BLACKFIN_GPIOS - 1,
-       .flags = IORESOURCE_IRQ,
-};
-
-static struct platform_device bfin_gpios_device = {
-       .name = "simple-gpio",
-       .id = -1,
-       .num_resources = 1,
-       .resource = &bfin_gpios_resources,
-};
-
 #if defined(CONFIG_I2C_GPIO) || defined(CONFIG_I2C_GPIO_MODULE)
 #include <linux/i2c-gpio.h>
 
@@ -460,13 +436,21 @@ static struct platform_device bfin_dpmc = {
        },
 };
 
+static struct i2c_board_info __initdata bfin_i2c_board_info[] = {
+#if defined(CONFIG_FB_BFIN_7393) || defined(CONFIG_FB_BFIN_7393_MODULE)
+       {
+               I2C_BOARD_INFO("bfin-adv7393", 0x2B),
+       },
+#endif
+};
+
 static struct platform_device *ezkit_devices[] __initdata = {
 
        &bfin_dpmc,
 
-#if defined(CONFIG_MTD_PSD4256G) || defined(CONFIG_MTD_PSD4256G_MODULE)
-       &stm_pri_device_a,
-       &stm_pri_device_b,
+#if defined(CONFIG_MTD_PHYSMAP) || defined(CONFIG_MTD_PHYSMAP_MODULE)
+       &ezkit_flash_device_a,
+       &ezkit_flash_device_b,
 #endif
 
 #if defined(CONFIG_MTD_PLATRAM) || defined(CONFIG_MTD_PLATRAM_MODULE)
@@ -482,10 +466,6 @@ static struct platform_device *ezkit_devices[] __initdata = {
        &bfin_spi0_device,
 #endif
 
-#if defined(CONFIG_FB_BFIN_7393) || defined(CONFIG_FB_BFIN_7393_MODULE)
-       &bfin_fb_adv7393_device,
-#endif
-
 #if defined(CONFIG_RTC_DRV_BFIN) || defined(CONFIG_RTC_DRV_BFIN_MODULE)
        &rtc_device,
 #endif
@@ -507,8 +487,6 @@ static struct platform_device *ezkit_devices[] __initdata = {
 #if defined(CONFIG_I2C_GPIO) || defined(CONFIG_I2C_GPIO_MODULE)
        &i2c_gpio_device,
 #endif
-
-       &bfin_gpios_device,
 };
 
 static int __init ezkit_init(void)
@@ -516,6 +494,8 @@ static int __init ezkit_init(void)
        printk(KERN_INFO "%s(): registering device resources\n", __func__);
        platform_add_devices(ezkit_devices, ARRAY_SIZE(ezkit_devices));
        spi_register_board_info(bfin_spi_board_info, ARRAY_SIZE(bfin_spi_board_info));
+       i2c_register_board_info(0, bfin_i2c_board_info,
+                               ARRAY_SIZE(bfin_i2c_board_info));
        return 0;
 }
 
index f19b633..644be5e 100644 (file)
@@ -1,34 +1,12 @@
 /*
- * File:         arch/blackfin/mach-bf533/ip0x.c
- * Based on:     arch/blackfin/mach-bf533/bf1.c
- * Based on:     arch/blackfin/mach-bf533/stamp.c
- * Author:       Ivan Danov <idanov@gmail.com>
- *               Modified for IP0X David Rowe
+ * Copyright 2004-2009 Analog Devices Inc.
+ *                2007 David Rowe
+ *                2006 Intratrade Ltd.
+ *                     Ivan Danov <idanov@gmail.com>
+ *                2005 National ICT Australia (NICTA)
+ *                     Aidan Williams <aidan@nicta.com.au>
  *
- * Created:      2007
- * Description:  Board info file for the IP04/IP08 boards, which
- *               are derived from the BlackfinOne V2.0 boards.
- *
- * Modified:
- *               COpyright 2007 David Rowe
- *               Copyright 2006 Intratrade Ltd.
- *               Copyright 2005 National ICT Australia (NICTA)
- *               Copyright 2004-2006 Analog Devices Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see the file COPYING, or write
- * to the Free Software Foundation, Inc.,
- * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ * Licensed under the GPL-2 or later.
  */
 
 #include <linux/device.h>
@@ -145,7 +123,6 @@ static struct bfin5xx_spi_chip mmc_spi_chip_info = {
        .ctl_reg = 0x1000,              /* CPOL=0,CPHA=0,Sandisk 1G work */
        .enable_dma = 0,                /* if 1 - block!!! */
        .bits_per_word = 8,
-       .cs_change_per_word = 0,
 };
 #endif
 
index 729fd7c..82f70ef 100644 (file)
@@ -1,31 +1,9 @@
 /*
- * File:         arch/blackfin/mach-bf533/stamp.c
- * Based on:     arch/blackfin/mach-bf533/ezkit.c
- * Author:       Aidan Williams <aidan@nicta.com.au>
+ * Copyright 2004-2009 Analog Devices Inc.
+ *                2005 National ICT Australia (NICTA)
+ *                      Aidan Williams <aidan@nicta.com.au>
  *
- * Created:      2005
- * Description:  Board Info File for the BF533-STAMP
- *
- * Modified:
- *               Copyright 2005 National ICT Australia (NICTA)
- *               Copyright 2004-2006 Analog Devices Inc.
- *
- * Bugs:         Enter bugs at http://blackfin.uclinux.org/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see the file COPYING, or write
- * to the Free Software Foundation, Inc.,
- * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ * Licensed under the GPL-2 or later.
  */
 
 #include <linux/device.h>
@@ -95,12 +73,6 @@ static struct platform_device smc91x_device = {
 };
 #endif
 
-#if defined(CONFIG_FB_BFIN_7393) || defined(CONFIG_FB_BFIN_7393_MODULE)
-static struct platform_device bfin_fb_adv7393_device = {
-       .name = "bfin-adv7393",
-};
-#endif
-
 #if defined(CONFIG_USB_NET2272) || defined(CONFIG_USB_NET2272_MODULE)
 static struct resource net2272_bfin_resources[] = {
        {
@@ -436,19 +408,6 @@ static struct platform_device bfin_device_gpiokeys = {
 };
 #endif
 
-static struct resource bfin_gpios_resources = {
-       .start = 0,
-       .end   = MAX_BLACKFIN_GPIOS - 1,
-       .flags = IORESOURCE_IRQ,
-};
-
-static struct platform_device bfin_gpios_device = {
-       .name = "simple-gpio",
-       .id = -1,
-       .num_resources = 1,
-       .resource = &bfin_gpios_resources,
-};
-
 #if defined(CONFIG_I2C_GPIO) || defined(CONFIG_I2C_GPIO_MODULE)
 #include <linux/i2c-gpio.h>
 
@@ -487,6 +446,11 @@ static struct i2c_board_info __initdata bfin_i2c_board_info[] = {
                .irq = 39,
        },
 #endif
+#if defined(CONFIG_FB_BFIN_7393) || defined(CONFIG_FB_BFIN_7393_MODULE)
+       {
+               I2C_BOARD_INFO("bfin-adv7393", 0x2B),
+       },
+#endif
 };
 
 static const unsigned int cclk_vlev_datasheet[] =
@@ -528,10 +492,6 @@ static struct platform_device *stamp_devices[] __initdata = {
        &smc91x_device,
 #endif
 
-#if defined(CONFIG_FB_BFIN_7393) || defined(CONFIG_FB_BFIN_7393_MODULE)
-       &bfin_fb_adv7393_device,
-#endif
-
 #if defined(CONFIG_USB_NET2272) || defined(CONFIG_USB_NET2272_MODULE)
        &net2272_bfin_device,
 #endif
@@ -563,8 +523,6 @@ static struct platform_device *stamp_devices[] __initdata = {
        &i2c_gpio_device,
 #endif
 
-       &bfin_gpios_device,
-
 #if defined(CONFIG_MTD_BFIN_ASYNC) || defined(CONFIG_MTD_BFIN_ASYNC_MODULE)
        &stamp_flash_device,
 #endif
index 7a443c3..4a14a46 100644 (file)
@@ -1,31 +1,11 @@
 /*
- * File:         arch/blackfin/mach-bf533/dma.c
- * Based on:
- * Author:
+ * simple DMA Implementation for Blackfin
  *
- * Created:
- * Description:  This file contains the simple DMA Implementation for Blackfin
+ * Copyright 2007-2009 Analog Devices Inc.
  *
- * Modified:
- *               Copyright 2004-2006 Analog Devices Inc.
- *
- * Bugs:         Enter bugs at http://blackfin.uclinux.org/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see the file COPYING, or write
- * to the Free Software Foundation, Inc.,
- * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ * Licensed under the GPL-2 or later.
  */
+
 #include <linux/module.h>
 
 #include <asm/blackfin.h>
index cf4427c..e3e05f8 100644 (file)
@@ -1,30 +1,9 @@
 /*
- * File:         include/asm-blackfin/mach-bf533/bf533.h
- * Based on:
- * Author:
+ * SYSTEM MMR REGISTER AND MEMORY MAP FOR ADSP-BF561
  *
- * Created:
- * Description:  SYSTEM MMR REGISTER AND MEMORY MAP FOR ADSP-BF561
+ * Copyright 2005-2008 Analog Devices Inc.
  *
- * Modified:
- *               Copyright 2004-2006 Analog Devices Inc.
- *
- * Bugs:         Enter bugs at http://blackfin.uclinux.org/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see the file COPYING, or write
- * to the Free Software Foundation, Inc.,
- * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ * Licensed under the GPL-2 or later.
  */
 
 #ifndef __MACH_BF533_H__
index 6965b40..9e1f3de 100644 (file)
@@ -1,32 +1,7 @@
 /*
- * file:        include/asm-blackfin/mach-bf533/bfin_serial_5xx.h
- * based on:
- * author:
+ * Copyright 2006-2009 Analog Devices Inc.
  *
- * created:
- * description:
- *     blackfin serial driver head file
- * rev:
- *
- * modified:
- *
- *
- * bugs:         enter bugs at http://blackfin.uclinux.org/
- *
- * this program is free software; you can redistribute it and/or modify
- * it under the terms of the gnu general public license as published by
- * the free software foundation; either version 2, or (at your option)
- * any later version.
- *
- * this program is distributed in the hope that it will be useful,
- * but without any warranty; without even the implied warranty of
- * merchantability or fitness for a particular purpose.  see the
- * gnu general public license for more details.
- *
- * you should have received a copy of the gnu general public license
- * along with this program; see the file copying.
- * if not, write to the free software foundation,
- * 59 temple place - suite 330, boston, ma 02111-1307, usa.
+ * Licensed under the GPL-2 or later
  */
 
 #include <linux/serial.h>
index 499e897..f4bd6df 100644 (file)
@@ -1,31 +1,7 @@
 /*
- * File:         include/asm-blackfin/mach-bf533/blackfin.h
- * Based on:
- * Author:
+ * Copyright 2005-2009 Analog Devices Inc.
  *
- * Created:
- * Description:
- *
- * Rev:
- *
- * Modified:
- *
- * Bugs:         Enter bugs at http://blackfin.uclinux.org/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; see the file COPYING.
- * If not, write to the Free Software Foundation,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ * Licensed under the GPL-2 or later
  */
 
 #ifndef _MACH_BLACKFIN_H_
index bbc3c83..feb2392 100644 (file)
@@ -1,31 +1,7 @@
 /*
- * File:         include/asm-blackfin/mach-bf533/cdefBF532.h
- * Based on:
- * Author:
+ * Copyright 2005-2008 Analog Devices Inc.
  *
- * Created:
- * Description:
- *
- * Rev:
- *
- * Modified:
- *
- * Bugs:         Enter bugs at http://blackfin.uclinux.org/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; see the file COPYING.
- * If not, write to the Free Software Foundation,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ * Licensed under the GPL-2 or later
  */
 
 #ifndef _CDEF_BF532_H
index 7f46332..02b328e 100644 (file)
@@ -1,48 +1,10 @@
-/************************************************************************
- *
- * This file is subject to the terms and conditions of the GNU Public
- * License. See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Non-GPL License also available as part of VisualDSP++
- * http://www.analog.com/processors/resources/crosscore/visualDspDevSoftware.html
- *
- * (c) Copyright 2001-2005 Analog Devices, Inc. All rights reserved
- *
- * This file under source code control, please send bugs or changes to:
- * dsptools.support@analog.com
- *
- ************************************************************************/
 /*
- * File:         include/asm-blackfin/mach-bf533/defBF532.h
- * Based on:
- * Author:
- *
- * Created:
- * Description:
- *
- * Rev:
- *
- * Modified:
- *
- * Bugs:         Enter bugs at http://blackfin.uclinux.org/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
+ * System & MMR bit and Address definitions for ADSP-BF532
  *
- * 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.
+ * Copyright 2005-2008 Analog Devices Inc.
  *
- * You should have received a copy of the GNU General Public License
- * along with this program; see the file COPYING.
- * If not, write to the Free Software Foundation,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ * Licensed under the ADI BSD license or the GPL-2 (or later)
  */
-/* SYSTEM & MM REGISTER BIT & ADDRESS DEFINITIONS FOR ADSP-BF532 */
 
 #ifndef _DEF_BF532_H
 #define _DEF_BF532_H
index e45c170..2af19d6 100644 (file)
@@ -1,7 +1,4 @@
 /*
- * File: arch/blackfin/mach-bf533/include/mach/gpio.h
- * Bugs: Enter bugs at http://blackfin.uclinux.org/
- *
  * Copyright (C) 2008 Analog Devices Inc.
  * Licensed under the GPL-2 or later.
  */
index db1e346..c31498b 100644 (file)
@@ -1,31 +1,7 @@
 /*
- * File:         include/asm-blackfin/mach-bf533/defBF532.h
- * Based on:
- * Author:
+ * Copyright 2005-2008 Analog Devices Inc.
  *
- * Created:
- * Description:
- *
- * Rev:
- *
- * Modified:
- *
- * Bugs:         Enter bugs at http://blackfin.uclinux.org/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; see the file COPYING.
- * If not, write to the Free Software Foundation,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ * Licensed under the GPL-2 or later
  */
 
 #ifndef _BF533_IRQ_H_
index 2f59ce0..075dae1 100644 (file)
@@ -1,3 +1,9 @@
+/*
+ * Copyright 2007-2009 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2 or later
+ */
+
 #ifndef _MACH_PORTMUX_H_
 #define _MACH_PORTMUX_H_
 
index f51994b..8f714cf 100644 (file)
@@ -1,30 +1,9 @@
 /*
- * File:         arch/blackfin/mach-bf533/ints-priority.c
- * Based on:
- * Author:       Michael Hennerich
+ * Set up the interrupt priorities
  *
- * Created:      ?
- * Description:  Set up the interrupt priorities
+ * Copyright 2005-2009 Analog Devices Inc.
  *
- * Modified:
- *               Copyright 2004-2006 Analog Devices Inc.
- *
- * Bugs:         Enter bugs at http://blackfin.uclinux.org/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see the file COPYING, or write
- * to the Free Software Foundation, Inc.,
- * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ * Licensed under the GPL-2 or later.
  */
 
 #include <linux/module.h>
index 87acb7d..c85f4d7 100644 (file)
@@ -1,31 +1,10 @@
 /*
- * File:         arch/blackfin/mach-bf537/boards/cm_bf537.c
- * Based on:     arch/blackfin/mach-bf533/boards/ezkit.c
- * Author:       Aidan Williams <aidan@nicta.com.au>
+ * Copyright 2004-2009 Analog Devices Inc.
+ *           2008-2009 Bluetechnix
+ *                2005 National ICT Australia (NICTA)
+ *                      Aidan Williams <aidan@nicta.com.au>
  *
- * Created:      2005
- * Description:  Board description file
- *
- * Modified:
- *               Copyright 2005 National ICT Australia (NICTA)
- *               Copyright 2004-2006 Analog Devices Inc.
- *
- * Bugs:         Enter bugs at http://blackfin.uclinux.org/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see the file COPYING, or write
- * to the Free Software Foundation, Inc.,
- * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ * Licensed under the GPL-2 or later.
  */
 
 #include <linux/device.h>
@@ -297,19 +276,6 @@ static struct platform_device net2272_bfin_device = {
 };
 #endif
 
-static struct resource bfin_gpios_resources = {
-       .start = 0,
-       .end   = MAX_BLACKFIN_GPIOS - 1,
-       .flags = IORESOURCE_IRQ,
-};
-
-static struct platform_device bfin_gpios_device = {
-       .name = "simple-gpio",
-       .id = -1,
-       .num_resources = 1,
-       .resource = &bfin_gpios_resources,
-};
-
 #if defined(CONFIG_MTD_GPIO_ADDR) || defined(CONFIG_MTD_GPIO_ADDR_MODULE)
 static struct mtd_partition cm_partitions[] = {
        {
@@ -699,8 +665,6 @@ static struct platform_device *cm_bf537e_devices[] __initdata = {
 #if defined(CONFIG_MTD_GPIO_ADDR) || defined(CONFIG_MTD_GPIO_ADDR_MODULE)
        &cm_flash_device,
 #endif
-
-       &bfin_gpios_device,
 };
 
 static int __init cm_bf537e_init(void)
index 8219dc3..ea11aa8 100644 (file)
@@ -1,31 +1,10 @@
 /*
- * File:         arch/blackfin/mach-bf537/boards/cm_bf537u.c
- * Based on:     arch/blackfin/mach-bf533/boards/ezkit.c
- * Author:       Aidan Williams <aidan@nicta.com.au>
+ * Copyright 2004-2009 Analog Devices Inc.
+ *           2008-2009 Bluetechnix
+ *                2005 National ICT Australia (NICTA)
+ *                      Aidan Williams <aidan@nicta.com.au>
  *
- * Created:      2005
- * Description:  Board description file
- *
- * Modified:
- *               Copyright 2005 National ICT Australia (NICTA)
- *               Copyright 2004-2006 Analog Devices Inc.
- *
- * Bugs:         Enter bugs at http://blackfin.uclinux.org/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see the file COPYING, or write
- * to the Free Software Foundation, Inc.,
- * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ * Licensed under the GPL-2 or later.
  */
 
 #include <linux/device.h>
@@ -298,19 +277,6 @@ static struct platform_device net2272_bfin_device = {
 };
 #endif
 
-static struct resource bfin_gpios_resources = {
-       .start = 0,
-       .end   = MAX_BLACKFIN_GPIOS - 1,
-       .flags = IORESOURCE_IRQ,
-};
-
-static struct platform_device bfin_gpios_device = {
-       .name = "simple-gpio",
-       .id = -1,
-       .num_resources = 1,
-       .resource = &bfin_gpios_resources,
-};
-
 #if defined(CONFIG_MTD_GPIO_ADDR) || defined(CONFIG_MTD_GPIO_ADDR_MODULE)
 static struct mtd_partition cm_partitions[] = {
        {
@@ -605,8 +571,6 @@ static struct platform_device *cm_bf537u_devices[] __initdata = {
 #if defined(CONFIG_MTD_GPIO_ADDR) || defined(CONFIG_MTD_GPIO_ADDR_MODULE)
        &cm_flash_device,
 #endif
-
-       &bfin_gpios_device,
 };
 
 static int __init cm_bf537u_init(void)
index 399f81d..0da9272 100644 (file)
@@ -1,4 +1,10 @@
 /*
+ * Copyright 2004-2009 Analog Devices Inc.
+ *           2008-2009 Cambridge Signal Processing
+ *                2005 National ICT Australia (NICTA)
+ *                      Aidan Williams <aidan@nicta.com.au>
+ *
+ * Licensed under the GPL-2 or later.
  */
 
 #include <linux/device.h>
index 10b35b8..9ba2904 100644 (file)
@@ -1,31 +1,9 @@
 /*
- * File:         arch/blackfin/mach-bf537/boards/stamp.c
- * Based on:     arch/blackfin/mach-bf533/boards/ezkit.c
- * Author:       Aidan Williams <aidan@nicta.com.au>
+ * Copyright 2004-2009 Analog Devices Inc.
+ *                2005 National ICT Australia (NICTA)
+ *                      Aidan Williams <aidan@nicta.com.au>
  *
- * Created:
- * Description:
- *
- * Modified:
- *               Copyright 2005 National ICT Australia (NICTA)
- *               Copyright 2004-2008 Analog Devices Inc.
- *
- * Bugs:         Enter bugs at http://blackfin.uclinux.org/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see the file COPYING, or write
- * to the Free Software Foundation, Inc.,
- * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ * Licensed under the GPL-2 or later.
  */
 
 #include <linux/device.h>
@@ -302,7 +280,6 @@ static struct bfin5xx_spi_chip mmc_spi_chip_info = {
 
 #if defined(CONFIG_TOUCHSCREEN_AD7877) || defined(CONFIG_TOUCHSCREEN_AD7877_MODULE)
 static struct bfin5xx_spi_chip spi_ad7877_chip_info = {
-       .cs_change_per_word = 0,
        .enable_dma = 0,
        .bits_per_word = 16,
 };
index 9db6b40..c46baa5 100644 (file)
@@ -1,31 +1,9 @@
 /*
- * File:         arch/blackfin/mach-bf537/boards/stamp.c
- * Based on:     arch/blackfin/mach-bf533/boards/ezkit.c
- * Author:       Aidan Williams <aidan@nicta.com.au>
+ * Copyright 2004-2009 Analog Devices Inc.
+ *                2005 National ICT Australia (NICTA)
+ *                      Aidan Williams <aidan@nicta.com.au>
  *
- * Created:
- * Description:
- *
- * Modified:
- *               Copyright 2005 National ICT Australia (NICTA)
- *               Copyright 2004-2006 Analog Devices Inc.
- *
- * Bugs:         Enter bugs at http://blackfin.uclinux.org/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see the file COPYING, or write
- * to the Free Software Foundation, Inc.,
- * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ * Licensed under the GPL-2 or later.
  */
 
 #include <linux/device.h>
@@ -121,19 +99,6 @@ static struct platform_device bfin_device_gpiokeys = {
 };
 #endif
 
-static struct resource bfin_gpios_resources = {
-       .start = 0,
-       .end   = MAX_BLACKFIN_GPIOS - 1,
-       .flags = IORESOURCE_IRQ,
-};
-
-static struct platform_device bfin_gpios_device = {
-       .name = "simple-gpio",
-       .id = -1,
-       .num_resources = 1,
-       .resource = &bfin_gpios_resources,
-};
-
 #if defined(CONFIG_BFIN_CFPCMCIA) || defined(CONFIG_BFIN_CFPCMCIA_MODULE)
 static struct resource bfin_pcmcia_cf_resources[] = {
        {
@@ -1078,12 +1043,6 @@ static struct platform_device bfin_fb_device = {
 };
 #endif
 
-#if defined(CONFIG_FB_BFIN_7393) || defined(CONFIG_FB_BFIN_7393_MODULE)
-static struct platform_device bfin_fb_adv7393_device = {
-       .name = "bfin-adv7393",
-};
-#endif
-
 #if defined(CONFIG_FB_BFIN_LQ035Q1) || defined(CONFIG_FB_BFIN_LQ035Q1_MODULE)
 #include <asm/bfin-lq035q1.h>
 
@@ -1498,6 +1457,11 @@ static struct i2c_board_info __initdata bfin_i2c_board_info[] = {
                .platform_data = (void *)&adp5588_gpio_data,
        },
 #endif
+#if defined(CONFIG_FB_BFIN_7393) || defined(CONFIG_FB_BFIN_7393_MODULE)
+       {
+               I2C_BOARD_INFO("bfin-adv7393", 0x2B),
+       },
+#endif
 };
 
 #if defined(CONFIG_SERIAL_BFIN_SPORT) || defined(CONFIG_SERIAL_BFIN_SPORT_MODULE)
@@ -1668,10 +1632,6 @@ static struct platform_device *stamp_devices[] __initdata = {
        &bfin_lq035q1_device,
 #endif
 
-#if defined(CONFIG_FB_BFIN_7393) || defined(CONFIG_FB_BFIN_7393_MODULE)
-       &bfin_fb_adv7393_device,
-#endif
-
 #if defined(CONFIG_SERIAL_BFIN) || defined(CONFIG_SERIAL_BFIN_MODULE)
        &bfin_uart_device,
 #endif
@@ -1702,8 +1662,6 @@ static struct platform_device *stamp_devices[] __initdata = {
        &bfin_device_gpiokeys,
 #endif
 
-       &bfin_gpios_device,
-
 #if defined(CONFIG_MTD_NAND_PLATFORM) || defined(CONFIG_MTD_NAND_PLATFORM_MODULE)
        &bfin_async_nand_device,
 #endif
index 61353f7..57163b6 100644 (file)
@@ -1,31 +1,10 @@
 /*
- * File:         arch/blackfin/mach-bf537/boards/tcm_bf537.c
- * Based on:     arch/blackfin/mach-bf533/boards/cm_bf537.c
- * Author:       Aidan Williams <aidan@nicta.com.au>
+ * Copyright 2004-2009 Analog Devices Inc.
+ *           2008-2009 Bluetechnix
+ *                2005 National ICT Australia (NICTA)
+ *                      Aidan Williams <aidan@nicta.com.au>
  *
- * Created:      2005
- * Description:  Board description file
- *
- * Modified:
- *               Copyright 2005 National ICT Australia (NICTA)
- *               Copyright 2004-2006 Analog Devices Inc.
- *
- * Bugs:         Enter bugs at http://blackfin.uclinux.org/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see the file COPYING, or write
- * to the Free Software Foundation, Inc.,
- * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ * Licensed under the GPL-2 or later.
  */
 
 #include <linux/device.h>
@@ -298,19 +277,6 @@ static struct platform_device net2272_bfin_device = {
 };
 #endif
 
-static struct resource bfin_gpios_resources = {
-       .start = 0,
-       .end   = MAX_BLACKFIN_GPIOS - 1,
-       .flags = IORESOURCE_IRQ,
-};
-
-static struct platform_device bfin_gpios_device = {
-       .name = "simple-gpio",
-       .id = -1,
-       .num_resources = 1,
-       .resource = &bfin_gpios_resources,
-};
-
 #if defined(CONFIG_MTD_GPIO_ADDR) || defined(CONFIG_MTD_GPIO_ADDR_MODULE)
 static struct mtd_partition cm_partitions[] = {
        {
@@ -607,8 +573,6 @@ static struct platform_device *cm_bf537_devices[] __initdata = {
 #if defined(CONFIG_MTD_GPIO_ADDR) || defined(CONFIG_MTD_GPIO_ADDR_MODULE)
        &cm_flash_device,
 #endif
-
-       &bfin_gpios_device,
 };
 
 static int __init tcm_bf537_init(void)
index d23fc0e..5c8c4ed 100644 (file)
@@ -1,31 +1,11 @@
 /*
- * File:         arch/blackfin/mach-bf537/dma.c
- * Based on:
- * Author:
+ * Copyright 2007-2009 Analog Devices Inc.
  *
- * Created:
- * Description:  This file contains the simple DMA Implementation for Blackfin
+ * Licensed under the GPL-2 or later.
  *
- * Modified:
- *               Copyright 2004-2007 Analog Devices Inc.
- *
- * Bugs:         Enter bugs at http://blackfin.uclinux.org/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see the file COPYING, or write
- * to the Free Software Foundation, Inc.,
- * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ * This file contains the simple DMA Implementation for Blackfin
  */
+
 #include <linux/module.h>
 
 #include <asm/blackfin.h>
index f194a84..17fab44 100644 (file)
@@ -1,30 +1,9 @@
 /*
- * File:         include/asm-blackfin/mach-bf537/bf537.h
- * Based on:
- * Author:
+ * System MMR Register and memory map for ADSP-BF537
  *
- * Created:
- * Description:  SYSTEM MMR REGISTER AND MEMORY MAP FOR ADSP-BF537
+ * Copyright 2005-2008 Analog Devices Inc.
  *
- * Modified:
- *               Copyright 2004-2006 Analog Devices Inc.
- *
- * Bugs:         Enter bugs at http://blackfin.uclinux.org/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see the file COPYING, or write
- * to the Free Software Foundation, Inc.,
- * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ * Licensed under the GPL-2 or later.
  */
 
 #ifndef __MACH_BF537_H__
index e95d54f..635c91c 100644 (file)
@@ -1,32 +1,7 @@
 /*
- * file:         include/asm-blackfin/mach-bf537/bfin_serial_5xx.h
- * based on:
- * author:
+ * Copyright 2006-2009 Analog Devices Inc.
  *
- * created:
- * description:
- *     blackfin serial driver header files
- * rev:
- *
- * modified:
- *
- *
- * bugs:         enter bugs at http://blackfin.uclinux.org/
- *
- * this program is free software; you can redistribute it and/or modify
- * it under the terms of the gnu general public license as published by
- * the free software foundation; either version 2, or (at your option)
- * any later version.
- *
- * this program is distributed in the hope that it will be useful,
- * but without any warranty; without even the implied warranty of
- * merchantability or fitness for a particular purpose.  see the
- * gnu general public license for more details.
- *
- * you should have received a copy of the gnu general public license
- * along with this program; see the file copying.
- * if not, write to the free software foundation,
- * 59 temple place - suite 330, boston, ma 02111-1307, usa.
+ * Licensed under the GPL-2 or later
  */
 
 #include <linux/serial.h>
index 9ee8834..eab006d 100644 (file)
@@ -1,32 +1,7 @@
 /*
- * File:         include/asm-blackfin/mach-bf537/blackfin.h
- * Based on:
- * Author:
+ * Copyright 2005-2009 Analog Devices Inc.
  *
- * Created:
- * Description:
- *
- * Rev:
- *
- * Modified:
- *
- *
- * Bugs:         Enter bugs at http://blackfin.uclinux.org/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; see the file COPYING.
- * If not, write to the Free Software Foundation,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ * Licensed under the GPL-2 or later
  */
 
 #ifndef _MACH_BLACKFIN_H_
index 5f8b5f8..91825c9 100644 (file)
@@ -1,32 +1,7 @@
 /*
- * File:         include/asm-blackfin/mach-bf537/cdefbf534.h
- * Based on:
- * Author:
+ * Copyright 2005-2008 Analog Devices Inc.
  *
- * Created:
- * Description:  system mmr register map
- *
- * Rev:
- *
- * Modified:
- *
- *
- * Bugs:         Enter bugs at http://blackfin.uclinux.org/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; see the file COPYING.
- * If not, write to the Free Software Foundation,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ * Licensed under the GPL-2 or later
  */
 
 #ifndef _CDEF_BF534_H
index b8fc949..9363c39 100644 (file)
@@ -1,32 +1,7 @@
 /*
- * File:         include/asm-blackfin/mach-bf537/cdefBF537.h
- * Based on:
- * Author:
+ * Copyright 2005-2008 Analog Devices Inc.
  *
- * Created:
- * Description:
- *     System MMR Register Map
- * Rev:
- *
- * Modified:
- *
- *
- * Bugs:         Enter bugs at http://blackfin.uclinux.org/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; see the file COPYING.
- * If not, write to the Free Software Foundation,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ * Licensed under the GPL-2 or later
  */
 
 #ifndef _CDEF_BF537_H
index a3227f9..cebb14f 100644 (file)
@@ -1,31 +1,7 @@
 /*
- * File:         include/asm-blackfin/mach-bf537/cdefBF537.h
- * Based on:
- * Author:
+ * Copyright 2005-2008 Analog Devices Inc.
  *
- * Created:
- * Description:
- *
- * Rev:
- *
- * Modified:
- *
- * Bugs:         Enter bugs at http://blackfin.uclinux.org/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; see the file COPYING.
- * If not, write to the Free Software Foundation,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ * Licensed under the ADI BSD license or the GPL-2 (or later)
  */
 
 #ifndef _DEF_BF534_H
index 3d6c83e..8cb5d5c 100644 (file)
@@ -1,32 +1,7 @@
 /*
- * file:         include/asm-blackfin/mach-bf537/defbf537.h
- * based on:
- * author:
+ * Copyright 2005-2008 Analog Devices Inc.
  *
- * created:
- * description:
- *     system mmr register map
- * rev:
- *
- * modified:
- *
- *
- * bugs:         enter bugs at http://blackfin.uclinux.org/
- *
- * this program is free software; you can redistribute it and/or modify
- * it under the terms of the gnu general public license as published by
- * the free software foundation; either version 2, or (at your option)
- * any later version.
- *
- * this program is distributed in the hope that it will be useful,
- * but without any warranty; without even the implied warranty of
- * merchantability or fitness for a particular purpose.  see the
- * gnu general public license for more details.
- *
- * you should have received a copy of the gnu general public license
- * along with this program; see the file copying.
- * if not, write to the free software foundation,
- * 59 temple place - suite 330, boston, ma 02111-1307, usa.
+ * Licensed under the ADI BSD license or the GPL-2 (or later)
  */
 
 #ifndef _DEF_BF537_H
index d77a31e..104bff8 100644 (file)
@@ -1,7 +1,4 @@
 /*
- * File: arch/blackfin/mach-bf537/include/mach/gpio.h
- * Bugs: Enter bugs at http://blackfin.uclinux.org/
- *
  * Copyright (C) 2008 Analog Devices Inc.
  * Licensed under the GPL-2 or later.
  */
index b2a71d5..0defa94 100644 (file)
@@ -1,32 +1,7 @@
 /*
- * file:         include/asm-blackfin/mach-bf537/irq.h
- * based on:
- * author:
+ * Copyright 2005-2008 Analog Devices Inc.
  *
- * created:
- * description:
- *     system mmr register map
- * rev:
- *
- * modified:
- *
- *
- * bugs:         enter bugs at http://blackfin.uclinux.org/
- *
- * this program is free software; you can redistribute it and/or modify
- * it under the terms of the gnu general public license as published by
- * the free software foundation; either version 2, or (at your option)
- * any later version.
- *
- * this program is distributed in the hope that it will be useful,
- * but without any warranty; without even the implied warranty of
- * merchantability or fitness for a particular purpose.  see the
- * gnu general public license for more details.
- *
- * you should have received a copy of the gnu general public license
- * along with this program; see the file copying.
- * if not, write to the free software foundation,
- * 59 temple place - suite 330, boston, ma 02111-1307, usa.
+ * Licensed under the GPL-2 or later
  */
 
 #ifndef _BF537_IRQ_H_
index 87285e7..da97603 100644 (file)
@@ -1,3 +1,9 @@
+/*
+ * Copyright 2007-2009 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2 or later
+ */
+
 #ifndef _MACH_PORTMUX_H_
 #define _MACH_PORTMUX_H_
 
index 51c4808..f650062 100644 (file)
@@ -1,30 +1,9 @@
 /*
- * File:         arch/blackfin/mach-bf537/ints-priority.c
- * Based on:     arch/blackfin/mach-bf533/ints-priority.c
- * Author:       Michael Hennerich
+ * Copyright 2005-2009 Analog Devices Inc.
  *
- * Created:
- * Description:  Set up the interrupt priorities
+ * Licensed under the GPL-2 or later.
  *
- * Modified:
- *               Copyright 2004-2006 Analog Devices Inc.
- *
- * Bugs:         Enter bugs at http://blackfin.uclinux.org/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see the file COPYING, or write
- * to the Free Software Foundation, Inc.,
- * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ * Set up the interrupt priorities
  */
 
 #include <linux/module.h>
index f2ac3b0..14af5c2 100644 (file)
@@ -1,31 +1,9 @@
 /*
- * File:         arch/blackfin/mach-bf538/boards/ezkit.c
- * Based on:     arch/blackfin/mach-bf537/boards/ezkit.c
- * Author:       Aidan Williams <aidan@nicta.com.au>
+ * Copyright 2004-2009 Analog Devices Inc.
+ *                2005 National ICT Australia (NICTA)
+ *                      Aidan Williams <aidan@nicta.com.au>
  *
- * Created:
- * Description:
- *
- * Modified:
- *               Copyright 2005 National ICT Australia (NICTA)
- *               Copyright 2004-2008 Analog Devices Inc.
- *
- * Bugs:         Enter bugs at http://blackfin.uclinux.org/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see the file COPYING, or write
- * to the Free Software Foundation, Inc.,
- * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ * Licensed under the GPL-2
  */
 
 #include <linux/device.h>
@@ -237,7 +215,6 @@ static struct flash_platform_data bfin_spi_flash_data = {
 static struct bfin5xx_spi_chip spi_flash_chip_info = {
        .enable_dma = 0,         /* use dma transfer with this chip*/
        .bits_per_word = 8,
-       .cs_change_per_word = 0,
 };
 #endif
 
@@ -506,19 +483,6 @@ static struct platform_device i2c_bfin_twi1_device = {
 #endif
 #endif
 
-static struct resource bfin_gpios_resources = {
-       .start = 0,
-       .end   = MAX_BLACKFIN_GPIOS - 1,
-       .flags = IORESOURCE_IRQ,
-};
-
-static struct platform_device bfin_gpios_device = {
-       .name = "simple-gpio",
-       .id = -1,
-       .num_resources = 1,
-       .resource = &bfin_gpios_resources,
-};
-
 #if defined(CONFIG_KEYBOARD_GPIO) || defined(CONFIG_KEYBOARD_GPIO_MODULE)
 #include <linux/gpio_keys.h>
 
@@ -658,8 +622,6 @@ static struct platform_device *cm_bf538_devices[] __initdata = {
        &bfin_device_gpiokeys,
 #endif
 
-       &bfin_gpios_device,
-
 #if defined(CONFIG_MTD_PHYSMAP) || defined(CONFIG_MTD_PHYSMAP_MODULE)
        &ezkit_flash_device,
 #endif
index d6837fb..5dc0225 100644 (file)
@@ -1,31 +1,11 @@
 /*
- * File:         arch/blackfin/mach-bf538/dma.c
- * Based on:
- * Author:
+ * the simple DMA Implementation for Blackfin
  *
- * Created:
- * Description:  This file contains the simple DMA Implementation for Blackfin
+ * Copyright 2008 Analog Devices Inc.
  *
- * Modified:
- *               Copyright 2008 Analog Devices Inc.
- *
- * Bugs:         Enter bugs at http://blackfin.uclinux.org/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see the file COPYING, or write
- * to the Free Software Foundation, Inc.,
- * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ * Licensed under the GPL-2 or later.
  */
+
 #include <linux/module.h>
 
 #include <asm/blackfin.h>
index 9c8abb3..0cf5bf8 100644 (file)
@@ -1,30 +1,9 @@
 /*
- * File:         include/asm-blackfin/mach-bf538/bf538.h
- * Based on:   include/asm-blackfin/mach-bf537/bf537.h
- * Author:     Michael Hennerich (michael.hennerich@analog.com)
+ * SYSTEM MMR REGISTER AND MEMORY MAP FOR ADSP-BF538
  *
- * Created:
- * Description:  SYSTEM MMR REGISTER AND MEMORY MAP FOR ADSP-BF527
+ * Copyright 2008 Analog Devices Inc.
  *
- * Modified:
- *               Copyright 2004-2007 Analog Devices Inc.
- *
- * Bugs:         Enter bugs at http://blackfin.uclinux.org/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see the file COPYING, or write
- * to the Free Software Foundation, Inc.,
- * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ * Licensed under the GPL-2 or later.
  */
 
 #ifndef __MACH_BF538_H__
index 999f239..5c14814 100644 (file)
@@ -1,32 +1,7 @@
 /*
- * file:         include/asm-blackfin/mach-bf538/bfin_serial_5xx.h
- * based on:
- * author:
+ * Copyright 2008-2009 Analog Devices Inc.
  *
- * created:
- * description:
- *     blackfin serial driver header files
- * rev:
- *
- * modified:
- *
- *
- * bugs:         enter bugs at http://blackfin.uclinux.org/
- *
- * this program is free software; you can redistribute it and/or modify
- * it under the terms of the gnu general public license as published by
- * the free software foundation; either version 2, or (at your option)
- * any later version.
- *
- * this program is distributed in the hope that it will be useful,
- * but without any warranty; without even the implied warranty of
- * merchantability or fitness for a particular purpose.  see the
- * gnu general public license for more details.
- *
- * you should have received a copy of the gnu general public license
- * along with this program; see the file copying.
- * if not, write to the free software foundation,
- * 59 temple place - suite 330, boston, ma 02111-1307, usa.
+ * Licensed under the GPL-2 or later.
  */
 
 #include <linux/serial.h>
index 5ecee16..278e894 100644 (file)
@@ -1,32 +1,7 @@
 /*
- * File:         include/asm-blackfin/mach-bf538/blackfin.h
- * Based on:
- * Author:
+ * Copyright 2008-2009 Analog Devices Inc.
  *
- * Created:
- * Description:
- *
- * Rev:
- *
- * Modified:
- *
- *
- * Bugs:         Enter bugs at http://blackfin.uclinux.org/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; see the file COPYING.
- * If not, write to the Free Software Foundation,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ * Licensed under the GPL-2 or later.
  */
 
 #ifndef _MACH_BLACKFIN_H_
index 1de6751..401ebd7 100644 (file)
@@ -1,31 +1,7 @@
 /*
- * File:         include/asm-blackfin/mach-bf538/cdefBF538.h
- * Based on:
- * Author:
+ * Copyright 2008-2009 Analog Devices Inc.
  *
- * Created:
- * Description:
- *
- * Rev:
- *
- * Modified:
- *
- * Bugs:         Enter bugs at http://blackfin.uclinux.org/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; see the file COPYING.
- * If not, write to the Free Software Foundation,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ * Licensed under the GPL-2 or later.
  */
 
 #ifndef _CDEF_BF538_H
index 1c58914..5f6c34d 100644 (file)
@@ -1,47 +1,9 @@
-/************************************************************************
- *
- * This file is subject to the terms and conditions of the GNU Public
- * License. See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Non-GPL License also available as part of VisualDSP++
- * http://www.analog.com/processors/resources/crosscore/visualDspDevSoftware.html
- *
- * (c) Copyright 2001-2005 Analog Devices, Inc. All rights reserved
- *
- * This file under source code control, please send bugs or changes to:
- * dsptools.support@analog.com
- *
- ************************************************************************/
 /*
- * File:         include/asm-blackfin/mach-bf538/defBF539.h
- * Based on:
- * Author:
- *
- * Created:
- * Description:
+ * Copyright 2008-2009 Analog Devices Inc.
  *
- * Rev:
- *
- * Modified:
- *
- * Bugs:         Enter bugs at http://blackfin.uclinux.org/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; see the file COPYING.
- * If not, write to the Free Software Foundation,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ * Licensed under the ADI BSD license or the GPL-2 (or later)
  */
+
 /* SYSTEM & MM REGISTER BIT & ADDRESS DEFINITIONS FOR ADSP-BF538/9 */
 
 #ifndef _DEF_BF539_H
index 30f4f72..295c78a 100644 (file)
@@ -1,7 +1,4 @@
 /*
- * File: arch/blackfin/mach-bf538/include/mach/gpio.h
- * Bugs: Enter bugs at http://blackfin.uclinux.org/
- *
  * Copyright (C) 2008 Analog Devices Inc.
  * Licensed under the GPL-2 or later.
  */
index fdc87fe..a4b7fcb 100644 (file)
@@ -1,32 +1,7 @@
 /*
- * file:       include/asm-blackfin/mach-bf538/irq.h
- * based on:   include/asm-blackfin/mach-bf537/irq.h
- * author:     Michael Hennerich (michael.hennerich@analog.com)
+ * Copyright 2008 Analog Devices Inc.
  *
- * created:
- * description:
- *     system mmr register map
- * rev:
- *
- * modified:
- *
- *
- * bugs:         enter bugs at http://blackfin.uclinux.org/
- *
- * this program is free software; you can redistribute it and/or modify
- * it under the terms of the gnu general public license as published by
- * the free software foundation; either version 2, or (at your option)
- * any later version.
- *
- * this program is distributed in the hope that it will be useful,
- * but without any warranty; without even the implied warranty of
- * merchantability or fitness for a particular purpose.  see the
- * gnu general public license for more details.
- *
- * you should have received a copy of the gnu general public license
- * along with this program; see the file copying.
- * if not, write to the free software foundation,
- * 59 temple place - suite 330, boston, ma 02111-1307, usa.
+ * Licensed under the GPL-2 or later.
  */
 
 #ifndef _BF538_IRQ_H_
index c8db264..6121cf8 100644 (file)
@@ -1,3 +1,9 @@
+/*
+ * Copyright 2008-2009 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2 or later.
+ */
+
 #ifndef _MACH_PORTMUX_H_
 #define _MACH_PORTMUX_H_
 
index 70d17e5..1fa793c 100644 (file)
@@ -1,30 +1,9 @@
 /*
- * File:         arch/blackfin/mach-bf538/ints-priority.c
- * Based on:     arch/blackfin/mach-bf533/ints-priority.c
- * Author:       Michael Hennerich
+ * Set up the interrupt priorities
  *
- * Created:
- * Description:  Set up the interrupt priorities
+ * Copyright 2008 Analog Devices Inc.
  *
- * Modified:
- *               Copyright 2008 Analog Devices Inc.
- *
- * Bugs:         Enter bugs at http://blackfin.uclinux.org/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see the file COPYING, or write
- * to the Free Software Foundation, Inc.,
- * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ * Licensed under the GPL-2 or later.
  */
 
 #include <linux/module.h>
index e565aae..ccdcd6d 100644 (file)
@@ -1,31 +1,10 @@
 /*
- * File:         arch/blackfin/mach-bf548/boards/cm_bf548.c
- * Based on:     arch/blackfin/mach-bf537/boards/ezkit.c
- * Author:       Aidan Williams <aidan@nicta.com.au>
+ * Copyright 2004-2009 Analog Devices Inc.
+ *           2008-2009 Bluetechnix
+ *                2005 National ICT Australia (NICTA)
+ *                      Aidan Williams <aidan@nicta.com.au>
  *
- * Created:
- * Description:
- *
- * Modified:
- *               Copyright 2005 National ICT Australia (NICTA)
- *               Copyright 2004-2008 Analog Devices Inc.
- *
- * Bugs:         Enter bugs at http://blackfin.uclinux.org/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see the file COPYING, or write
- * to the Free Software Foundation, Inc.,
- * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ * Licensed under the GPL-2 or later.
  */
 
 #include <linux/device.h>
@@ -380,19 +359,6 @@ static struct platform_device musb_device = {
 };
 #endif
 
-static struct resource bfin_gpios_resources = {
-       .start = 0,
-       .end   = MAX_BLACKFIN_GPIOS - 1,
-       .flags = IORESOURCE_IRQ,
-};
-
-static struct platform_device bfin_gpios_device = {
-       .name = "simple-gpio",
-       .id = -1,
-       .num_resources = 1,
-       .resource = &bfin_gpios_resources,
-};
-
 #if defined(CONFIG_PATA_BF54X) || defined(CONFIG_PATA_BF54X_MODULE)
 static struct resource bfin_atapi_resources[] = {
        {
@@ -546,13 +512,11 @@ static struct flash_platform_data bfin_spi_flash_data = {
 static struct bfin5xx_spi_chip spi_flash_chip_info = {
        .enable_dma = 0,         /* use dma transfer with this chip*/
        .bits_per_word = 8,
-       .cs_change_per_word = 0,
 };
 #endif
 
 #if defined(CONFIG_TOUCHSCREEN_AD7877) || defined(CONFIG_TOUCHSCREEN_AD7877_MODULE)
 static struct bfin5xx_spi_chip spi_ad7877_chip_info = {
-       .cs_change_per_word = 0,
        .enable_dma = 0,
        .bits_per_word = 16,
 };
@@ -853,8 +817,6 @@ static struct platform_device *cm_bf548_devices[] __initdata = {
 #if defined(CONFIG_MTD_PHYSMAP) || defined(CONFIG_MTD_PHYSMAP_MODULE)
        &para_flash_device,
 #endif
-
-       &bfin_gpios_device,
 };
 
 static int __init cm_bf548_init(void)
index c66f380..1a5286b 100644 (file)
@@ -1,31 +1,9 @@
 /*
- * File:         arch/blackfin/mach-bf548/boards/ezkit.c
- * Based on:     arch/blackfin/mach-bf537/boards/ezkit.c
- * Author:       Aidan Williams <aidan@nicta.com.au>
+ * Copyright 2004-2009 Analog Devices Inc.
+ *                2005 National ICT Australia (NICTA)
+ *                      Aidan Williams <aidan@nicta.com.au>
  *
- * Created:
- * Description:
- *
- * Modified:
- *               Copyright 2005 National ICT Australia (NICTA)
- *               Copyright 2004-2007 Analog Devices Inc.
- *
- * Bugs:         Enter bugs at http://blackfin.uclinux.org/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see the file COPYING, or write
- * to the Free Software Foundation, Inc.,
- * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ * Licensed under the GPL-2 or later.
  */
 
 #include <linux/device.h>
@@ -208,7 +186,6 @@ static struct platform_device bfin_rotary_device = {
 #endif
 
 #if defined(CONFIG_INPUT_ADXL34X) || defined(CONFIG_INPUT_ADXL34X_MODULE)
-#include <linux/input.h>
 #include <linux/spi/adxl34x.h>
 static const struct adxl34x_platform_data adxl34x_info = {
        .x_axis_offset = 0,
@@ -636,7 +613,6 @@ static struct flash_platform_data bfin_spi_flash_data = {
 static struct bfin5xx_spi_chip spi_flash_chip_info = {
        .enable_dma = 0,         /* use dma transfer with this chip*/
        .bits_per_word = 8,
-       .cs_change_per_word = 0,
 };
 #endif
 
@@ -650,7 +626,6 @@ static struct bfin5xx_spi_chip ad1836_spi_chip_info = {
 
 #if defined(CONFIG_TOUCHSCREEN_AD7877) || defined(CONFIG_TOUCHSCREEN_AD7877_MODULE)
 static struct bfin5xx_spi_chip spi_ad7877_chip_info = {
-       .cs_change_per_word = 0,
        .enable_dma = 0,
        .bits_per_word = 16,
 };
@@ -681,7 +656,6 @@ static struct bfin5xx_spi_chip spidev_chip_info = {
 static struct bfin5xx_spi_chip spi_adxl34x_chip_info = {
        .enable_dma = 0,         /* use dma transfer with this chip*/
        .bits_per_word = 8,
-       .cs_change_per_word = 0,
 };
 #endif
 
@@ -908,19 +882,6 @@ static struct platform_device bfin_device_gpiokeys = {
 };
 #endif
 
-static struct resource bfin_gpios_resources = {
-       .start = 0,
-       .end   = MAX_BLACKFIN_GPIOS - 1,
-       .flags = IORESOURCE_IRQ,
-};
-
-static struct platform_device bfin_gpios_device = {
-       .name = "simple-gpio",
-       .id = -1,
-       .num_resources = 1,
-       .resource = &bfin_gpios_resources,
-};
-
 static const unsigned int cclk_vlev_datasheet[] =
 {
 /*
@@ -1028,8 +989,6 @@ static struct platform_device *ezkit_devices[] __initdata = {
        &bfin_device_gpiokeys,
 #endif
 
-       &bfin_gpios_device,
-
 #if defined(CONFIG_MTD_PHYSMAP) || defined(CONFIG_MTD_PHYSMAP_MODULE)
        &ezkit_flash_device,
 #endif
index d9239bc..039a6d9 100644 (file)
@@ -1,30 +1,9 @@
 /*
- * File:         arch/blackfin/mach-bf548/dma.c
- * Based on:
- * Author:
+ * the simple DMA Implementation for Blackfin
  *
- * Created:
- * Description:  This file contains the simple DMA Implementation for Blackfin
+ * Copyright 2007-2009 Analog Devices Inc.
  *
- * Modified:
- *               Copyright 2004-2008 Analog Devices Inc.
- *
- * Bugs:         Enter bugs at http://blackfin.uclinux.org/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see the file COPYING, or write
- * to the Free Software Foundation, Inc.,
- * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ * Licensed under the GPL-2 or later.
  */
 
 #include <linux/module.h>
index cd31f72..7bead5c 100644 (file)
@@ -1,30 +1,7 @@
 /*
- * File:         include/asm-blackfin/mach-bf548/bf548.h
- * Based on:
- * Author:
+ * Copyright 2007-2009 Analog Devices Inc.
  *
- * Created:
- * Description:  System MMR register and memory map for ADSP-BF548
- *
- * Modified:
- *               Copyright 2004-2007 Analog Devices Inc.
- *
- * Bugs:         Enter bugs at http://blackfin.uclinux.org/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see the file COPYING, or write
- * to the Free Software Foundation, Inc.,
- * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ * Licensed under the GPL-2 or later.
  */
 
 #ifndef __MACH_BF548_H__
index 9c7ca62..8821efe 100644 (file)
@@ -1,3 +1,9 @@
+/*
+ * Copyright 2007-2008 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2 or later.
+ */
+
 #ifndef BF54X_LQ043_H
 #define BF54X_LQ043_H
 
index 1fb4ec7..49338ae 100644 (file)
@@ -1,3 +1,9 @@
+/*
+ * Copyright 2007-2008 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2 or later.
+ */
+
 #ifndef _BFIN_KPAD_H
 #define _BFIN_KPAD_H
 
index 2d1b5fa..dd44aa7 100644 (file)
@@ -1,32 +1,7 @@
 /*
- * file:        include/asm-blackfin/mach-bf548/bfin_serial_5xx.h
- * based on:
- * author:
+ * Copyright 2007-2009 Analog Devices Inc.
  *
- * created:
- * description:
- *     blackfin serial driver head file
- * rev:
- *
- * modified:
- *
- *
- * bugs:         enter bugs at http://blackfin.uclinux.org/
- *
- * this program is free software; you can redistribute it and/or modify
- * it under the terms of the gnu general public license as published by
- * the free software foundation; either version 2, or (at your option)
- * any later version.
- *
- * this program is distributed in the hope that it will be useful,
- * but without any warranty; without even the implied warranty of
- * merchantability or fitness for a particular purpose.  see the
- * gnu general public license for more details.
- *
- * you should have received a copy of the gnu general public license
- * along with this program; see the file copying.
- * if not, write to the free software foundation,
- * 59 temple place - suite 330, boston, ma 02111-1307, usa.
+ * Licensed under the GPL-2 or later.
  */
 
 #include <linux/serial.h>
index 318667b..13302b6 100644 (file)
@@ -1,32 +1,7 @@
 /*
- * File:         include/asm-blackfin/mach-bf548/blackfin.h
- * Based on:
- * Author:
+ * Copyright 2007-2009 Analog Devices Inc.
  *
- * Created:
- * Description:
- *
- * Rev:
- *
- * Modified:
- *
- *
- * Bugs:         Enter bugs at http://blackfin.uclinux.org/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; see the file COPYING.
- * If not, write to the Free Software Foundation,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ * Licensed under the GPL-2 or later.
  */
 
 #ifndef _MACH_BLACKFIN_H_
index 07aefb9..42f4a94 100644 (file)
@@ -1,31 +1,7 @@
 /*
- * File:         include/asm-blackfin/mach-bf548/cdefBF542.h
- * Based on:
- * Author:
+ * Copyright 2007-2008 Analog Devices Inc.
  *
- * Created:
- * Description:
- *
- * Rev:
- *
- * Modified:
- *
- * Bugs:         Enter bugs at http://blackfin.uclinux.org/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; see the file COPYING.
- * If not, write to the Free Software Foundation,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ * Licensed under the GPL-2 or later.
  */
 
 #ifndef _CDEF_BF542_H
index 431a692..2207799 100644 (file)
@@ -1,31 +1,7 @@
 /*
- * File:         include/asm-blackfin/mach-bf548/cdefBF544.h
- * Based on:
- * Author:
+ * Copyright 2007-2008 Analog Devices Inc.
  *
- * Created:
- * Description:
- *
- * Rev:
- *
- * Modified:
- *
- * Bugs:         Enter bugs at http://blackfin.uclinux.org/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; see the file COPYING.
- * If not, write to the Free Software Foundation,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ * Licensed under the GPL-2 or later.
  */
 
 #ifndef _CDEF_BF544_H
index 93376e9..4234215 100644 (file)
@@ -1,31 +1,7 @@
 /*
- * File:         include/asm-blackfin/mach-bf548/cdefBF547.h
- * Based on:
- * Author:
+ * Copyright 2008 Analog Devices Inc.
  *
- * Created:
- * Description:
- *
- * Rev:
- *
- * Modified:
- *
- * Bugs:         Enter bugs at http://blackfin.uclinux.org/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; see the file COPYING.
- * If not, write to the Free Software Foundation,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ * Licensed under the GPL-2 or later.
  */
 
 #ifndef _CDEF_BF548_H
index 9cd7438..df84180 100644 (file)
@@ -1,31 +1,7 @@
 /*
- * File:         include/asm-blackfin/mach-bf548/cdefBF548.h
- * Based on:
- * Author:
+ * Copyright 2007-2008 Analog Devices Inc.
  *
- * Created:
- * Description:
- *
- * Rev:
- *
- * Modified:
- *
- * Bugs:         Enter bugs at http://blackfin.uclinux.org/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; see the file COPYING.
- * If not, write to the Free Software Foundation,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ * Licensed under the GPL-2 or later.
  */
 
 #ifndef _CDEF_BF548_H
index ead360b..34c84c7 100644 (file)
@@ -1,31 +1,7 @@
 /*
- * File:         include/asm-blackfin/mach-bf549/cdefBF549.h
- * Based on:
- * Author:
+ * Copyright 2007-2008 Analog Devices Inc.
  *
- * Created:
- * Description:
- *
- * Rev:
- *
- * Modified:
- *
- * Bugs:         Enter bugs at http://blackfin.uclinux.org/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; see the file COPYING.
- * If not, write to the Free Software Foundation,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ * Licensed under the GPL-2 or later.
  */
 
 #ifndef _CDEF_BF549_H
index 6e636c4..a2e9d98 100644 (file)
@@ -1,31 +1,7 @@
 /*
- * File:         include/asm-blackfin/mach-bf548/cdefBF54x_base.h
- * Based on:
- * Author:
+ * Copyright 2007-2008 Analog Devices Inc.
  *
- * Created:
- * Description:
- *
- * Rev:
- *
- * Modified:
- *
- * Bugs:         Enter bugs at http://blackfin.uclinux.org/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; see the file COPYING.
- * If not, write to the Free Software Foundation,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ * Licensed under the GPL-2 or later.
  */
 
 #ifndef _CDEF_BF54X_H
index b131654..d3bc6d1 100644 (file)
@@ -1,31 +1,7 @@
 /*
- * File:         include/asm-blackfin/mach-bf548/defBF542.h
- * Based on:
- * Author:
+ * Copyright 2007-2008 Analog Devices Inc.
  *
- * Created:
- * Description:
- *
- * Rev:
- *
- * Modified:
- *
- * Bugs:         Enter bugs at http://blackfin.uclinux.org/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; see the file COPYING.
- * If not, write to the Free Software Foundation,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ * Licensed under the ADI BSD license or the GPL-2 (or later)
  */
 
 #ifndef _DEF_BF542_H
index c2c785b..dd414ae 100644 (file)
@@ -1,31 +1,7 @@
 /*
- * File:         include/asm-blackfin/mach-bf548/defBF544.h
- * Based on:
- * Author:
+ * Copyright 2007-2008 Analog Devices Inc.
  *
- * Created:
- * Description:
- *
- * Rev:
- *
- * Modified:
- *
- * Bugs:         Enter bugs at http://blackfin.uclinux.org/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; see the file COPYING.
- * If not, write to the Free Software Foundation,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ * Licensed under the ADI BSD license or the GPL-2 (or later)
  */
 
 #ifndef _DEF_BF544_H
index 661f0d8..5a9dbab 100644 (file)
@@ -1,31 +1,7 @@
 /*
- * File:         include/asm-blackfin/mach-bf548/defBF547.h
- * Based on:
- * Author:
+ * Copyright 2008 Analog Devices Inc.
  *
- * Created:
- * Description:
- *
- * Rev:
- *
- * Modified:
- *
- * Bugs:         Enter bugs at http://blackfin.uclinux.org/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; see the file COPYING.
- * If not, write to the Free Software Foundation,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ * Licensed under the ADI BSD license or the GPL-2 (or later)
  */
 
 #ifndef _DEF_BF548_H
index 85d4bad..82cd593 100644 (file)
@@ -1,31 +1,7 @@
 /*
- * File:         include/asm-blackfin/mach-bf548/defBF548.h
- * Based on:
- * Author:
+ * Copyright 2007-2008 Analog Devices Inc.
  *
- * Created:
- * Description:
- *
- * Rev:
- *
- * Modified:
- *
- * Bugs:         Enter bugs at http://blackfin.uclinux.org/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; see the file COPYING.
- * If not, write to the Free Software Foundation,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ * Licensed under the ADI BSD license or the GPL-2 (or later)
  */
 
 #ifndef _DEF_BF548_H
index 0967345..6fc6e39 100644 (file)
@@ -1,31 +1,7 @@
 /*
- * File:         include/asm-blackfin/mach-bf548/defBF549.h
- * Based on:
- * Author:
+ * Copyright 2007-2008 Analog Devices Inc.
  *
- * Created:
- * Description:
- *
- * Rev:
- *
- * Modified:
- *
- * Bugs:         Enter bugs at http://blackfin.uclinux.org/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; see the file COPYING.
- * If not, write to the Free Software Foundation,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ * Licensed under the ADI BSD license or the GPL-2 (or later)
  */
 
 #ifndef _DEF_BF549_H
index e022e89..8590c8c 100644 (file)
@@ -1,31 +1,7 @@
 /*
- * File:         include/asm-blackfin/mach-bf548/defBF54x_base.h
- * Based on:
- * Author:
+ * Copyright 2007-2008 Analog Devices Inc.
  *
- * Created:
- * Description:
- *
- * Rev:
- *
- * Modified:
- *
- * Bugs:         Enter bugs at http://blackfin.uclinux.org/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; see the file COPYING.
- * If not, write to the Free Software Foundation,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ * Licensed under the ADI BSD license or the GPL-2 (or later)
  */
 
 #ifndef _DEF_BF54X_H
index 3a20517..850e39d 100644 (file)
@@ -1,34 +1,8 @@
 /*
- * File:         include/asm-blackfin/mach-bf548/gpio.h
- * Based on:
- * Author:      Michael Hennerich (hennerich@blackfin.uclinux.org)
- *
- * Created:
- * Description:
- *
- * Modified:
- *               Copyright 2004-2007 Analog Devices Inc.
- *
- * Bugs:         Enter bugs at http://blackfin.uclinux.org/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see the file COPYING, or write
- * to the Free Software Foundation, Inc.,
- * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ * Copyright 2007-2009 Analog Devices Inc.
+ * Licensed under the GPL-2 or later.
  */
 
-
-
 #define GPIO_PA0       0
 #define GPIO_PA1       1
 #define GPIO_PA2       2
index f194625..106db05 100644 (file)
@@ -1,32 +1,7 @@
 /*
- * file:       include/asm-blackfin/mach-bf548/irq.h
- * based on:   include/asm-blackfin/mach-bf537/irq.h
- * author:     Roy Huang (roy.huang@analog.com)
+ * Copyright 2007-2009 Analog Devices Inc.
  *
- * created:
- * description:
- *     system mmr register map
- * rev:
- *
- * modified:
- *
- *
- * bugs:         enter bugs at http://blackfin.uclinux.org/
- *
- * this program is free software; you can redistribute it and/or modify
- * it under the terms of the gnu general public license as published by
- * the free software foundation; either version 2, or (at your option)
- * any later version.
- *
- * this program is distributed in the hope that it will be useful,
- * but without any warranty; without even the implied warranty of
- * merchantability or fitness for a particular purpose.  see the
- * gnu general public license for more details.
- *
- * you should have received a copy of the gnu general public license
- * along with this program; see the file copying.
- * if not, write to the free software foundation,
- * 59 temple place - suite 330, boston, ma 02111-1307, usa.
+ * Licensed under the GPL-2 or later.
  */
 
 #ifndef _BF548_IRQ_H_
index ce372ba..89ad6a8 100644 (file)
@@ -1,3 +1,9 @@
+/*
+ * Copyright 2007-2009 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2 or later.
+ */
+
 #ifndef _MACH_PORTMUX_H_
 #define _MACH_PORTMUX_H_
 
index 9dd0fa3..48dd3a4 100644 (file)
@@ -1,30 +1,9 @@
 /*
- * File:         arch/blackfin/mach-bf537/ints-priority.c
- * Based on:     arch/blackfin/mach-bf533/ints-priority.c
- * Author:       Michael Hennerich
+ * Copyright 2007-2008 Analog Devices Inc.
  *
- * Created:
- * Description:  Set up the interrupt priorities
+ * Licensed under the GPL-2 or later.
  *
- * Modified:
- *               Copyright 2004-2006 Analog Devices Inc.
- *
- * Bugs:         Enter bugs at http://blackfin.uclinux.org/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see the file COPYING, or write
- * to the Free Software Foundation, Inc.,
- * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ * Set up the interrupt priorities
  */
 
 #include <linux/module.h>
index 9439bc6..0261a5e 100644 (file)
@@ -1,23 +1,8 @@
 /*
- * File:         arch/blackfin/mach-bf561/atomic.S
- * Author:       Philippe Gerum <rpm@xenomai.org>
+ * Copyright 2007-2008 Analog Devices Inc.
+ *              Philippe Gerum <rpm@xenomai.org>
  *
- *               Copyright 2007 Analog Devices Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see the file COPYING, or write
- * to the Free Software Foundation, Inc.,
- * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ * Licensed under the GPL-2 or later.
  */
 
 #include <linux/linkage.h>
index 6577ecf..dfc8d5b 100644 (file)
@@ -1,30 +1,10 @@
 /*
- * File:         arch/blackfin/mach-bf533/boards/cm_bf561.c
- * Based on:     arch/blackfin/mach-bf533/boards/ezkit.c
- * Author:       Aidan Williams <aidan@nicta.com.au> Copyright 2005
+ * Copyright 2004-2009 Analog Devices Inc.
+ *               2008-2009 Bluetechnix
+ *               2005 National ICT Australia (NICTA)
+ *                    Aidan Williams <aidan@nicta.com.au>
  *
- * Created:      2006
- * Description:  Board description file
- *
- * Modified:
- *               Copyright 2004-2006 Analog Devices Inc.
- *
- * Bugs:         Enter bugs at http://blackfin.uclinux.org/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see the file COPYING, or write
- * to the Free Software Foundation, Inc.,
- * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ * Licensed under the GPL-2 or later.
  */
 
 #include <linux/device.h>
@@ -285,19 +265,6 @@ static struct platform_device net2272_bfin_device = {
 };
 #endif
 
-static struct resource bfin_gpios_resources = {
-       .start = 0,
-       .end   = MAX_BLACKFIN_GPIOS - 1,
-       .flags = IORESOURCE_IRQ,
-};
-
-static struct platform_device bfin_gpios_device = {
-       .name = "simple-gpio",
-       .id = -1,
-       .num_resources = 1,
-       .resource = &bfin_gpios_resources,
-};
-
 #if defined(CONFIG_USB_ISP1362_HCD) || defined(CONFIG_USB_ISP1362_HCD_MODULE)
 static struct resource isp1362_hcd_resources[] = {
        {
@@ -532,8 +499,6 @@ static struct platform_device *cm_bf561_devices[] __initdata = {
 #if defined(CONFIG_MTD_PHYSMAP) || defined(CONFIG_MTD_PHYSMAP_MODULE)
        &para_flash_device,
 #endif
-
-       &bfin_gpios_device,
 };
 
 static int __init cm_bf561_init(void)
index caed96b..9e2d8cf 100644 (file)
@@ -1,30 +1,9 @@
 /*
- * File:         arch/blackfin/mach-bf561/ezkit.c
- * Based on:
- * Author:
+ * Copyright 2004-2009 Analog Devices Inc.
+ *               2005 National ICT Australia (NICTA)
+ *                    Aidan Williams <aidan@nicta.com.au>
  *
- * Created:
- * Description:
- *
- * Modified:
- *               Copyright 2004-2006 Analog Devices Inc.
- *
- * Bugs:         Enter bugs at http://blackfin.uclinux.org/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see the file COPYING, or write
- * to the Free Software Foundation, Inc.,
- * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ * Licensed under the GPL-2 or later.
  */
 
 #include <linux/device.h>
@@ -387,19 +366,6 @@ static struct platform_device bfin_device_gpiokeys = {
 };
 #endif
 
-static struct resource bfin_gpios_resources = {
-       .start = 0,
-       .end   = MAX_BLACKFIN_GPIOS - 1,
-       .flags = IORESOURCE_IRQ,
-};
-
-static struct platform_device bfin_gpios_device = {
-       .name = "simple-gpio",
-       .id = -1,
-       .num_resources = 1,
-       .resource = &bfin_gpios_resources,
-};
-
 #if defined(CONFIG_I2C_GPIO) || defined(CONFIG_I2C_GPIO_MODULE)
 #include <linux/i2c-gpio.h>
 
@@ -493,8 +459,6 @@ static struct platform_device *ezkit_devices[] __initdata = {
        &isp1362_hcd_device,
 #endif
 
-       &bfin_gpios_device,
-
 #if defined(CONFIG_MTD_PHYSMAP) || defined(CONFIG_MTD_PHYSMAP_MODULE)
        &ezkit_flash_device,
 #endif
index 6f77dbe..8ba7252 100644 (file)
@@ -1,15 +1,13 @@
 /*
- *  File: arch/blackfin/mach-bf561/tepla.c
+ * Copyright 2004-2007 Analog Devices Inc.
+ *                2005 National ICT Australia (NICTA)
+ *                      Aidan Williams <aidan@nicta.com.au>
  *
- *  Copyright 2004-2007 Analog Devices Inc.
- *  Only SMSC91C1111 was registered, may do more later.
+ * Thanks to Jamey Hicks.
  *
- *  Copyright 2005 National ICT Australia (NICTA), Aidan Williams <aidan@nicta.com.au>
- *  Thanks to Jamey Hicks.
+ * Only SMSC91C1111 was registered, may do more later.
  *
- *  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.
+ * Licensed under the GPL-2
  */
 
 #include <linux/device.h>
index 42b0037..c938c3c 100644 (file)
@@ -1,31 +1,11 @@
 /*
- * File:         arch/blackfin/mach-bf561/dma.c
- * Based on:
- * Author:
+ * the simple DMA Implementation for Blackfin
  *
- * Created:
- * Description:  This file contains the simple DMA Implementation for Blackfin
+ * Copyright 2007-2008 Analog Devices Inc.
  *
- * Modified:
- *               Copyright 2004-2007 Analog Devices Inc.
- *
- * Bugs:         Enter bugs at http://blackfin.uclinux.org/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see the file COPYING, or write
- * to the Free Software Foundation, Inc.,
- * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ * Licensed under the GPL-2 or later.
  */
+
 #include <linux/module.h>
 
 #include <asm/blackfin.h>
index 9968362..9f9a367 100644 (file)
@@ -1,30 +1,9 @@
 /*
- * File:         include/asm-blackfin/mach-bf561/bf561.h
- * Based on:
- * Author:
+ * SYSTEM MMR REGISTER AND MEMORY MAP FOR ADSP-BF561
  *
- * Created:
- * Description:  SYSTEM MMR REGISTER AND MEMORY MAP FOR ADSP-BF561
+ * Copyright 2005-2008 Analog Devices Inc.
  *
- * Modified:
- *               Copyright 2004-2006 Analog Devices Inc.
- *
- * Bugs:         Enter bugs at http://blackfin.uclinux.org/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see the file COPYING, or write
- * to the Free Software Foundation, Inc.,
- * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ * Licensed under the GPL-2 or later.
  */
 
 #ifndef __MACH_BF561_H__
index fd5e887..e33e158 100644 (file)
@@ -1,32 +1,7 @@
 /*
- * file:        include/asm-blackfin/mach-bf561/bfin_serial_5xx.h
- * based on:
- * author:
+ * Copyright 2006-2009 Analog Devices Inc.
  *
- * created:
- * description:
- *     blackfin serial driver head file
- * rev:
- *
- * modified:
- *
- *
- * bugs:         enter bugs at http://blackfin.uclinux.org/
- *
- * this program is free software; you can redistribute it and/or modify
- * it under the terms of the gnu general public license as published by
- * the free software foundation; either version 2, or (at your option)
- * any later version.
- *
- * this program is distributed in the hope that it will be useful,
- * but without any warranty; without even the implied warranty of
- * merchantability or fitness for a particular purpose.  see the
- * gnu general public license for more details.
- *
- * you should have received a copy of the gnu general public license
- * along with this program; see the file copying.
- * if not, write to the free software foundation,
- * 59 temple place - suite 330, boston, ma 02111-1307, usa.
+ * Licensed under the GPL-2 or later.
  */
 
 #include <linux/serial.h>
index 8be3135..67d6bdc 100644 (file)
@@ -1,31 +1,7 @@
 /*
- * File:         include/asm-blackfin/mach-bf561/blackfin.h
- * Based on:
- * Author:
+ * Copyright 2005-2009 Analog Devices Inc.
  *
- * Created:
- * Description:
- *
- * Rev:
- *
- * Modified:
- *
- * Bugs:         Enter bugs at http://blackfin.uclinux.org/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; see the file COPYING.
- * If not, write to the Free Software Foundation,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ * Licensed under the GPL-2 or later.
  */
 
 #ifndef _MACH_BLACKFIN_H_
index 9d9858c..81ecdb7 100644 (file)
@@ -1,31 +1,7 @@
 /*
- * File:         include/asm-blackfin/mach-bf561/cdefBF561.h
- * Based on:
- * Author:
+ * Copyright 2005-2009 Analog Devices Inc.
  *
- * Created:
- * Description:  C POINTERS TO SYSTEM MMR REGISTER AND MEMORY MAP FOR ADSP-BF561
- *
- * Rev:
- *
- * Modified:
- *
- * Bugs:         Enter bugs at http://blackfin.uclinux.org/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; see the file COPYING.
- * If not, write to the Free Software Foundation,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ * Licensed under the GPL-2 or later.
  */
 
 #ifndef _CDEF_BF561_H
index 5fc0f05..a31e509 100644 (file)
@@ -1,32 +1,7 @@
-
 /*
- * File:         include/asm-blackfin/mach-bf561/defBF561.h
- * Based on:
- * Author:
- *
- * Created:
- * Description:
- * SYSTEM MMR REGISTER AND MEMORY MAP FOR ADSP-BF561
- * Rev:
- *
- * Modified:
- *
- * Bugs:         Enter bugs at http://blackfin.uclinux.org/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
+ * Copyright 2005-2009 Analog Devices Inc.
  *
- * You should have received a copy of the GNU General Public License
- * along with this program; see the file COPYING.
- * If not, write to the Free Software Foundation,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ * Licensed under the ADI BSD license or the GPL-2 (or later)
  */
 
 #ifndef _DEF_BF561_H
index 7882f79..a651a8c 100644 (file)
@@ -1,7 +1,4 @@
 /*
- * File: arch/blackfin/mach-bf561/include/mach/gpio.h
- * Bugs: Enter bugs at http://blackfin.uclinux.org/
- *
  * Copyright (C) 2008 Analog Devices Inc.
  * Licensed under the GPL-2 or later.
  */
index 6698389..7b208db 100644 (file)
@@ -1,32 +1,7 @@
-
 /*
- * File:         include/asm-blackfin/mach-bf561/irq.h
- * Based on:
- * Author:
- *
- * Created:
- * Description:
- *
- * Rev:
- *
- * Modified:
- *
- * Bugs:         Enter bugs at http://blackfin.uclinux.org/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
+ * Copyright 2005-2008 Analog Devices Inc.
  *
- * You should have received a copy of the GNU General Public License
- * along with this program; see the file COPYING.
- * If not, write to the Free Software Foundation,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ * Licensed under the GPL-2 or later.
  */
 
 #ifndef _BF561_IRQ_H_
index 2e5ad63..3a7b46b 100644 (file)
@@ -1,3 +1,9 @@
+/*
+ * Copyright 2007-2009 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2 or later.
+ */
+
 #ifndef _MACH_PORTMUX_H_
 #define _MACH_PORTMUX_H_
 
index f9e65eb..390c7f4 100644 (file)
@@ -1,3 +1,9 @@
+/*
+ * Copyright 2007-2008 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2 or later.
+ */
+
 #ifndef _MACH_BF561_SMP
 #define _MACH_BF561_SMP
 
index 9d2f233..b442417 100644 (file)
@@ -1,30 +1,9 @@
 /*
- * File:         arch/blackfin/mach-bf561/ints-priority.c
- * Based on:     arch/blackfin/mach-bf537/ints-priority.c
- * Author:       Michael Hennerich
+ * Set up the interrupt priorities
  *
- * Created:
- * Description:  Set up the interrupt priorities
+ * Copyright 2005-2009 Analog Devices Inc.
  *
- * Modified:
- *               Copyright 2004-2006 Analog Devices Inc.
- *
- * Bugs:         Enter bugs at http://blackfin.uclinux.org/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see the file COPYING, or write
- * to the Free Software Foundation, Inc.,
- * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ * Licensed under the GPL-2 or later.
  */
 
 #include <linux/module.h>
index f72a6af..8e60503 100644 (file)
@@ -1,26 +1,10 @@
 /*
- * File:         arch/blackfin/mach-bf561/secondary.S
- * Based on:     arch/blackfin/mach-bf561/head.S
- * Author:       Philippe Gerum <rpm@xenomai.org>
+ * BF561 coreB bootstrap file
  *
- *               Copyright 2007 Analog Devices Inc.
+ * Copyright 2007-2009 Analog Devices Inc.
+ *               Philippe Gerum <rpm@xenomai.org>
  *
- * Description:  BF561 coreB bootstrap file
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see the file COPYING, or write
- * to the Free Software Foundation, Inc.,
- * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ * Licensed under the GPL-2 or later.
  */
 
 #include <linux/linkage.h>
index 8c10701..510f576 100644 (file)
@@ -1,23 +1,8 @@
 /*
- * File:         arch/blackfin/mach-bf561/smp.c
- * Author:       Philippe Gerum <rpm@xenomai.org>
+ * Copyright 2007-2009 Analog Devices Inc.
+ *               Philippe Gerum <rpm@xenomai.org>
  *
- *               Copyright 2007 Analog Devices Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see the file COPYING, or write
- * to the Free Software Foundation, Inc.,
- * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ * Licensed under the GPL-2 or later.
  */
 
 #include <linux/init.h>
index 5998d86..9dbafcd 100644 (file)
@@ -1,30 +1,9 @@
 /*
- * File:         arch/blackfin/mach-common/arch_checks.c
- * Based on:
- * Author:      Robin Getz <rgetz@blackfin.uclinux.org>
+ * Do some checking to make sure things are OK
  *
- * Created:      25Jul07
- * Description:  Do some checking to make sure things are OK
+ * Copyright 2007-2009 Analog Devices Inc.
  *
- * Modified:
- *               Copyright 2004-2007 Analog Devices Inc.
- *
- * Bugs:         Enter bugs at http://blackfin.uclinux.org/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see the file COPYING, or write
- * to the Free Software Foundation, Inc.,
- * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ * Licensed under the GPL-2 or later.
  */
 
 #include <asm/fixed_code.h>
index 4ebbd78..a60a24f 100644 (file)
@@ -3,8 +3,6 @@
  *
  * Copyright 2004-2009 Analog Devices Inc.
  *
- * Enter bugs at http://blackfin.uclinux.org/
- *
  * Licensed under the GPL-2 or later.
  */
 
index d9666fe..ea54031 100644 (file)
@@ -3,8 +3,6 @@
  *
  * Copyright 2004-2008 Analog Devices Inc.
  *
- * Enter bugs at http://blackfin.uclinux.org/
- *
  * Licensed under the GPL-2 or later.
  */
 
index 85c6580..0150650 100644 (file)
@@ -1,30 +1,9 @@
 /*
- * File:        arch/blackfin/mach-common/cpufreq.c
- * Based on:
- * Author:
+ * Blackfin core clock scaling
  *
- * Created:
- * Description:         Blackfin core clock scaling
+ * Copyright 2008-2009 Analog Devices Inc.
  *
- * Modified:
- *              Copyright 2004-2008 Analog Devices Inc.
- *
- * Bugs:        Enter bugs at http://blackfin.uclinux.org/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.         See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see the file COPYING, or write
- * to the Free Software Foundation, Inc.,
- * 51 Franklin St, Fifth Floor, Boston, MA     02110-1301      USA
+ * Licensed under the GPL-2 or later.
  */
 
 #include <linux/kernel.h>
index 1e7cac2..94a0375 100644 (file)
@@ -1,32 +1,11 @@
 /*
- * File:         arch/blackfin/mach-common/entry.S
- * Based on:
- * Author:       Linus Torvalds
+ * Contains the system-call and fault low-level handling routines.
+ * This also contains the timer-interrupt handler, as well as all
+ * interrupts and faults that can result in a task-switch.
  *
- * Created:      ?
- * Description:  contains the system-call and fault low-level handling routines.
- *               This also contains the timer-interrupt handler, as well as all
- *               interrupts and faults that can result in a task-switch.
+ * Copyright 2005-2009 Analog Devices Inc.
  *
- * Modified:
- *               Copyright 2004-2006 Analog Devices Inc.
- *
- * Bugs:         Enter bugs at http://blackfin.uclinux.org/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see the file COPYING, or write
- * to the Free Software Foundation, Inc.,
- * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ * Licensed under the GPL-2 or later.
  */
 
 /* NOTE: This code handles signal-recognition, which happens every time
index 9c79dfe..cab0a00 100644 (file)
@@ -3,8 +3,6 @@
  *
  * Copyright 2004-2008 Analog Devices Inc.
  *
- * Enter bugs at http://blackfin.uclinux.org/
- *
  * Licensed under the GPL-2 or later.
  */
 
index 82d417e..8085ff1 100644 (file)
@@ -1,31 +1,11 @@
 /*
- * File:         arch/blackfin/mach-common/interrupt.S
- * Based on:
- * Author:       D. Jeff Dionne <jeff@ryeham.ee.ryerson.ca>
- *               Kenneth Albanowski <kjahds@kjahds.com>
- *
- * Created:      ?
- * Description:  Interrupt Entries
- *
- * Modified:
- *               Copyright 2004-2006 Analog Devices Inc.
+ * Interrupt Entries
  *
- * Bugs:         Enter bugs at http://blackfin.uclinux.org/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
+ * Copyright 2005-2009 Analog Devices Inc.
+ *               D. Jeff Dionne <jeff@ryeham.ee.ryerson.ca>
+ *               Kenneth Albanowski <kjahds@kjahds.com>
  *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see the file COPYING, or write
- * to the Free Software Foundation, Inc.,
- * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ * Licensed under the GPL-2 or later.
  */
 
 #include <asm/blackfin.h>
index 6ffda78..660ea1b 100644 (file)
@@ -1,33 +1,14 @@
 /*
- * File:         arch/blackfin/mach-common/ints-priority.c
+ * Set up the interrupt priorities
  *
- * Description:  Set up the interrupt priorities
+ * Copyright  2004-2009 Analog Devices Inc.
+ *                 2003 Bas Vermeulen <bas@buyways.nl>
+ *                 2002 Arcturus Networks Inc. MaTed <mated@sympatico.ca>
+ *            2000-2001 Lineo, Inc. D. Jefff Dionne <jeff@lineo.ca>
+ *                 1999 D. Jeff Dionne <jeff@uclinux.org>
+ *                 1996 Roman Zippel
  *
- * Modified:
- *               1996 Roman Zippel
- *               1999 D. Jeff Dionne <jeff@uclinux.org>
- *               2000-2001 Lineo, Inc. D. Jefff Dionne <jeff@lineo.ca>
- *               2002 Arcturus Networks Inc. MaTed <mated@sympatico.ca>
- *               2003 Metrowerks/Motorola
- *               2003 Bas Vermeulen <bas@buyways.nl>
- *               Copyright 2004-2008 Analog Devices Inc.
- *
- * Bugs:         Enter bugs at http://blackfin.uclinux.org/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see the file COPYING, or write
- * to the Free Software Foundation, Inc.,
- * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ * Licensed under the GPL-2
  */
 
 #include <linux/module.h>
index 883e324..c649624 100644 (file)
@@ -1,30 +1,9 @@
 /*
- * File:         arch/blackfin/mach-common/irqpanic.c
- * Based on:
- * Author:
+ * panic kernel with dump information
  *
- * Created:      ?
- * Description:  panic kernel with dump information
+ * Copyright 2005-2009 Analog Devices Inc.
  *
- * Modified:     rgetz - added cache checking code 14Feb06
- *               Copyright 2004-2006 Analog Devices Inc.
- *
- * Bugs:         Enter bugs at http://blackfin.uclinux.org/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see the file COPYING, or write
- * to the Free Software Foundation, Inc.,
- * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ * Licensed under the GPL-2 or later.
  */
 
 #include <linux/module.h>
index 0e3d4ff..8837be4 100644 (file)
@@ -1,35 +1,11 @@
 /*
- * File:         arch/blackfin/mach-common/pm.c
- * Based on:     arm/mach-omap/pm.c
- * Author:       Cliff Brake <cbrake@accelent.com> Copyright (c) 2001
+ * Blackfin power management
  *
- * Created:      2001
- * Description:  Blackfin power management
+ * Copyright 2006-2009 Analog Devices Inc.
  *
- * Modified:     Nicolas Pitre - PXA250 support
- *                Copyright (c) 2002 Monta Vista Software, Inc.
- *               David Singleton - OMAP1510
- *                Copyright (c) 2002 Monta Vista Software, Inc.
- *               Dirk Behme <dirk.behme@de.bosch.com> - OMAP1510/1610
- *                Copyright 2004
- *               Copyright 2004-2008 Analog Devices Inc.
- *
- * Bugs:         Enter bugs at http://blackfin.uclinux.org/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see the file COPYING, or write
- * to the Free Software Foundation, Inc.,
- * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ * Licensed under the GPL-2
+ * based on arm/mach-omap/pm.c
+ *    Copyright 2001, Cliff Brake <cbrake@accelent.com> and others
  */
 
 #include <linux/suspend.h>
index 349ee3f..d98585f 100644 (file)
@@ -1,24 +1,10 @@
 /*
- * File:         arch/blackfin/kernel/smp.c
- * Author:       Philippe Gerum <rpm@xenomai.org>
- * IPI management based on arch/arm/kernel/smp.c.
+ * IPI management based on arch/arm/kernel/smp.c (Copyright 2002 ARM Limited)
  *
- *               Copyright 2007 Analog Devices Inc.
+ * Copyright 2007-2009 Analog Devices Inc.
+ *                         Philippe Gerum <rpm@xenomai.org>
  *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see the file COPYING, or write
- * to the Free Software Foundation, Inc.,
- * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ * Licensed under the GPL-2.
  */
 
 #include <linux/module.h>
index bc00628..fb0b159 100644 (file)
@@ -1,30 +1,9 @@
 /*
- * File:         arch/blackfin/mm/blackfin_sram.h
- * Based on:     arch/blackfin/mm/blackfin_sram.c
- * Author:       Mike Frysinger
+ * Local prototypes meant for internal use only
  *
- * Created:      Aug 2006
- * Description:  Local prototypes meant for internal use only
+ * Copyright 2006-2009 Analog Devices Inc.
  *
- * Modified:
- *               Copyright 2006 Analog Devices Inc.
- *
- * Bugs:         Enter bugs at http://blackfin.uclinux.org/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see the file COPYING, or write
- * to the Free Software Foundation, Inc.,
- * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ * Licensed under the GPL-2 or later.
  */
 
 #ifndef __BLACKFIN_SRAM_H__
index b88ce7f..bb9c98f 100644 (file)
@@ -1,30 +1,7 @@
 /*
- * File:         arch/blackfin/mm/init.c
- * Based on:
- * Author:
+ * Copyright 2004-2009 Analog Devices Inc.
  *
- * Created:
- * Description:
- *
- * Modified:
- *               Copyright 2004-2007 Analog Devices Inc.
- *
- * Bugs:         Enter bugs at http://blackfin.uclinux.org/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see the file COPYING, or write
- * to the Free Software Foundation, Inc.,
- * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ * Licensed under the GPL-2 or later.
  */
 
 #include <linux/swap.h>
index beb1a60..84cdc5a 100644 (file)
@@ -1,19 +1,9 @@
 /*
- * Description: Instruction SRAM accessor functions for the Blackfin
+ * Instruction SRAM accessor functions for the Blackfin
  *
  * Copyright 2008 Analog Devices Inc.
  *
- * Bugs: Enter bugs at http://blackfin.uclinux.org/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see the file COPYING, or write
- * to the Free Software Foundation, Inc.,
- * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ * Licensed under the GPL-2 or later
  */
 
 #define pr_fmt(fmt) "isram: " fmt
index eb63ab3..f068c11 100644 (file)
@@ -1,30 +1,9 @@
 /*
- * File:         arch/blackfin/mm/sram-alloc.c
- * Based on:
- * Author:
+ * SRAM allocator for Blackfin on-chip memory
  *
- * Created:
- * Description:  SRAM allocator for Blackfin L1 and L2 memory
+ * Copyright 2004-2009 Analog Devices Inc.
  *
- * Modified:
- *               Copyright 2004-2008 Analog Devices Inc.
- *
- * Bugs:         Enter bugs at http://blackfin.uclinux.org/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see the file COPYING, or write
- * to the Free Software Foundation, Inc.,
- * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ * Licensed under the GPL-2 or later.
  */
 
 #include <linux/module.h>
index 6b0a2b6..0974c0e 100644 (file)
@@ -527,7 +527,7 @@ static void do_signal(void)
 
 no_signal:
        /* Did we come from a system call? */
-       if (__frame->syscallno >= 0) {
+       if (__frame->syscallno != -1) {
                /* Restart the system call - no handlers present */
                switch (__frame->gr8) {
                case -ERESTARTNOHAND:
index 30bb930..239ecdc 100644 (file)
  * by atomically noting the tail and incrementing it by one (thus adding
  * ourself to the queue and noting our position), then waiting until the head
  * becomes equal to the the initial value of the tail.
+ * The pad bits in the middle are used to prevent the next_ticket number
+ * overflowing into the now_serving number.
  *
- *   63                     32  31                      0
+ *   31             17  16    15  14                    0
  *  +----------------------------------------------------+
- *  |  next_ticket_number      |     now_serving         |
+ *  |  now_serving     | padding |   next_ticket         |
  *  +----------------------------------------------------+
  */
 
-#define TICKET_SHIFT   32
+#define TICKET_SHIFT   17
+#define TICKET_BITS    15
+#define        TICKET_MASK     ((1 << TICKET_BITS) - 1)
 
 static __always_inline void __ticket_spin_lock(raw_spinlock_t *lock)
 {
-       int     *p = (int *)&lock->lock, turn, now_serving;
+       int     *p = (int *)&lock->lock, ticket, serve;
 
-       now_serving = *p;
-       turn = ia64_fetchadd(1, p+1, acq);
+       ticket = ia64_fetchadd(1, p, acq);
 
-       if (turn == now_serving)
+       if (!(((ticket >> TICKET_SHIFT) ^ ticket) & TICKET_MASK))
                return;
 
-       do {
+       ia64_invala();
+
+       for (;;) {
+               asm volatile ("ld4.c.nc %0=[%1]" : "=r"(serve) : "r"(p) : "memory");
+
+               if (!(((serve >> TICKET_SHIFT) ^ ticket) & TICKET_MASK))
+                       return;
                cpu_relax();
-       } while (ACCESS_ONCE(*p) != turn);
+       }
 }
 
 static __always_inline int __ticket_spin_trylock(raw_spinlock_t *lock)
 {
-       long tmp = ACCESS_ONCE(lock->lock), try;
-
-       if (!(((tmp >> TICKET_SHIFT) ^ tmp) & ((1L << TICKET_SHIFT) - 1))) {
-               try = tmp + (1L << TICKET_SHIFT);
+       int tmp = ACCESS_ONCE(lock->lock);
 
-               return ia64_cmpxchg(acq, &lock->lock, tmp, try, sizeof (tmp)) == tmp;
-       }
+       if (!(((tmp >> TICKET_SHIFT) ^ tmp) & TICKET_MASK))
+               return ia64_cmpxchg(acq, &lock->lock, tmp, tmp + 1, sizeof (tmp)) == tmp;
        return 0;
 }
 
 static __always_inline void __ticket_spin_unlock(raw_spinlock_t *lock)
 {
-       int     *p = (int *)&lock->lock;
+       unsigned short  *p = (unsigned short *)&lock->lock + 1, tmp;
 
-       (void)ia64_fetchadd(1, p, rel);
+       asm volatile ("ld2.bias %0=[%1]" : "=r"(tmp) : "r"(p));
+       ACCESS_ONCE(*p) = (tmp + 2) & ~1;
+}
+
+static __always_inline void __ticket_spin_unlock_wait(raw_spinlock_t *lock)
+{
+       int     *p = (int *)&lock->lock, ticket;
+
+       ia64_invala();
+
+       for (;;) {
+               asm volatile ("ld4.c.nc %0=[%1]" : "=r"(ticket) : "r"(p) : "memory");
+               if (!(((ticket >> TICKET_SHIFT) ^ ticket) & TICKET_MASK))
+                       return;
+               cpu_relax();
+       }
 }
 
 static inline int __ticket_spin_is_locked(raw_spinlock_t *lock)
 {
        long tmp = ACCESS_ONCE(lock->lock);
 
-       return !!(((tmp >> TICKET_SHIFT) ^ tmp) & ((1L << TICKET_SHIFT) - 1));
+       return !!(((tmp >> TICKET_SHIFT) ^ tmp) & TICKET_MASK);
 }
 
 static inline int __ticket_spin_is_contended(raw_spinlock_t *lock)
 {
        long tmp = ACCESS_ONCE(lock->lock);
 
-       return (((tmp >> TICKET_SHIFT) - tmp) & ((1L << TICKET_SHIFT) - 1)) > 1;
+       return ((tmp - (tmp >> TICKET_SHIFT)) & TICKET_MASK) > 1;
 }
 
 static inline int __raw_spin_is_locked(raw_spinlock_t *lock)
@@ -116,8 +137,7 @@ static __always_inline void __raw_spin_lock_flags(raw_spinlock_t *lock,
 
 static inline void __raw_spin_unlock_wait(raw_spinlock_t *lock)
 {
-       while (__raw_spin_is_locked(lock))
-               cpu_relax();
+       __ticket_spin_unlock_wait(lock);
 }
 
 #define __raw_read_can_lock(rw)                (*(volatile int *)(rw) >= 0)
index b61d136..474e46f 100644 (file)
@@ -6,7 +6,7 @@
 #endif
 
 typedef struct {
-       volatile unsigned long lock;
+       volatile unsigned int lock;
 } raw_spinlock_t;
 
 #define __RAW_SPIN_LOCK_UNLOCKED       { 0 }
index d2877a7..496ac7a 100644 (file)
@@ -887,6 +887,60 @@ ia64_mca_modify_comm(const struct task_struct *previous_current)
        memcpy(current->comm, comm, sizeof(current->comm));
 }
 
+static void
+finish_pt_regs(struct pt_regs *regs, const pal_min_state_area_t *ms,
+               unsigned long *nat)
+{
+       const u64 *bank;
+
+       /* If ipsr.ic then use pmsa_{iip,ipsr,ifs}, else use
+        * pmsa_{xip,xpsr,xfs}
+        */
+       if (ia64_psr(regs)->ic) {
+               regs->cr_iip = ms->pmsa_iip;
+               regs->cr_ipsr = ms->pmsa_ipsr;
+               regs->cr_ifs = ms->pmsa_ifs;
+       } else {
+               regs->cr_iip = ms->pmsa_xip;
+               regs->cr_ipsr = ms->pmsa_xpsr;
+               regs->cr_ifs = ms->pmsa_xfs;
+       }
+       regs->pr = ms->pmsa_pr;
+       regs->b0 = ms->pmsa_br0;
+       regs->ar_rsc = ms->pmsa_rsc;
+       copy_reg(&ms->pmsa_gr[1-1], ms->pmsa_nat_bits, &regs->r1, nat);
+       copy_reg(&ms->pmsa_gr[2-1], ms->pmsa_nat_bits, &regs->r2, nat);
+       copy_reg(&ms->pmsa_gr[3-1], ms->pmsa_nat_bits, &regs->r3, nat);
+       copy_reg(&ms->pmsa_gr[8-1], ms->pmsa_nat_bits, &regs->r8, nat);
+       copy_reg(&ms->pmsa_gr[9-1], ms->pmsa_nat_bits, &regs->r9, nat);
+       copy_reg(&ms->pmsa_gr[10-1], ms->pmsa_nat_bits, &regs->r10, nat);
+       copy_reg(&ms->pmsa_gr[11-1], ms->pmsa_nat_bits, &regs->r11, nat);
+       copy_reg(&ms->pmsa_gr[12-1], ms->pmsa_nat_bits, &regs->r12, nat);
+       copy_reg(&ms->pmsa_gr[13-1], ms->pmsa_nat_bits, &regs->r13, nat);
+       copy_reg(&ms->pmsa_gr[14-1], ms->pmsa_nat_bits, &regs->r14, nat);
+       copy_reg(&ms->pmsa_gr[15-1], ms->pmsa_nat_bits, &regs->r15, nat);
+       if (ia64_psr(regs)->bn)
+               bank = ms->pmsa_bank1_gr;
+       else
+               bank = ms->pmsa_bank0_gr;
+       copy_reg(&bank[16-16], ms->pmsa_nat_bits, &regs->r16, nat);
+       copy_reg(&bank[17-16], ms->pmsa_nat_bits, &regs->r17, nat);
+       copy_reg(&bank[18-16], ms->pmsa_nat_bits, &regs->r18, nat);
+       copy_reg(&bank[19-16], ms->pmsa_nat_bits, &regs->r19, nat);
+       copy_reg(&bank[20-16], ms->pmsa_nat_bits, &regs->r20, nat);
+       copy_reg(&bank[21-16], ms->pmsa_nat_bits, &regs->r21, nat);
+       copy_reg(&bank[22-16], ms->pmsa_nat_bits, &regs->r22, nat);
+       copy_reg(&bank[23-16], ms->pmsa_nat_bits, &regs->r23, nat);
+       copy_reg(&bank[24-16], ms->pmsa_nat_bits, &regs->r24, nat);
+       copy_reg(&bank[25-16], ms->pmsa_nat_bits, &regs->r25, nat);
+       copy_reg(&bank[26-16], ms->pmsa_nat_bits, &regs->r26, nat);
+       copy_reg(&bank[27-16], ms->pmsa_nat_bits, &regs->r27, nat);
+       copy_reg(&bank[28-16], ms->pmsa_nat_bits, &regs->r28, nat);
+       copy_reg(&bank[29-16], ms->pmsa_nat_bits, &regs->r29, nat);
+       copy_reg(&bank[30-16], ms->pmsa_nat_bits, &regs->r30, nat);
+       copy_reg(&bank[31-16], ms->pmsa_nat_bits, &regs->r31, nat);
+}
+
 /* On entry to this routine, we are running on the per cpu stack, see
  * mca_asm.h.  The original stack has not been touched by this event.  Some of
  * the original stack's registers will be in the RBS on this stack.  This stack
@@ -921,7 +975,6 @@ ia64_mca_modify_original_stack(struct pt_regs *regs,
        u64 r12 = ms->pmsa_gr[12-1], r13 = ms->pmsa_gr[13-1];
        u64 ar_bspstore = regs->ar_bspstore;
        u64 ar_bsp = regs->ar_bspstore + (loadrs >> 16);
-       const u64 *bank;
        const char *msg;
        int cpu = smp_processor_id();
 
@@ -1024,54 +1077,9 @@ ia64_mca_modify_original_stack(struct pt_regs *regs,
        p = (char *)r12 - sizeof(*regs);
        old_regs = (struct pt_regs *)p;
        memcpy(old_regs, regs, sizeof(*regs));
-       /* If ipsr.ic then use pmsa_{iip,ipsr,ifs}, else use
-        * pmsa_{xip,xpsr,xfs}
-        */
-       if (ia64_psr(regs)->ic) {
-               old_regs->cr_iip = ms->pmsa_iip;
-               old_regs->cr_ipsr = ms->pmsa_ipsr;
-               old_regs->cr_ifs = ms->pmsa_ifs;
-       } else {
-               old_regs->cr_iip = ms->pmsa_xip;
-               old_regs->cr_ipsr = ms->pmsa_xpsr;
-               old_regs->cr_ifs = ms->pmsa_xfs;
-       }
-       old_regs->pr = ms->pmsa_pr;
-       old_regs->b0 = ms->pmsa_br0;
        old_regs->loadrs = loadrs;
-       old_regs->ar_rsc = ms->pmsa_rsc;
        old_unat = old_regs->ar_unat;
-       copy_reg(&ms->pmsa_gr[1-1], ms->pmsa_nat_bits, &old_regs->r1, &old_unat);
-       copy_reg(&ms->pmsa_gr[2-1], ms->pmsa_nat_bits, &old_regs->r2, &old_unat);
-       copy_reg(&ms->pmsa_gr[3-1], ms->pmsa_nat_bits, &old_regs->r3, &old_unat);
-       copy_reg(&ms->pmsa_gr[8-1], ms->pmsa_nat_bits, &old_regs->r8, &old_unat);
-       copy_reg(&ms->pmsa_gr[9-1], ms->pmsa_nat_bits, &old_regs->r9, &old_unat);
-       copy_reg(&ms->pmsa_gr[10-1], ms->pmsa_nat_bits, &old_regs->r10, &old_unat);
-       copy_reg(&ms->pmsa_gr[11-1], ms->pmsa_nat_bits, &old_regs->r11, &old_unat);
-       copy_reg(&ms->pmsa_gr[12-1], ms->pmsa_nat_bits, &old_regs->r12, &old_unat);
-       copy_reg(&ms->pmsa_gr[13-1], ms->pmsa_nat_bits, &old_regs->r13, &old_unat);
-       copy_reg(&ms->pmsa_gr[14-1], ms->pmsa_nat_bits, &old_regs->r14, &old_unat);
-       copy_reg(&ms->pmsa_gr[15-1], ms->pmsa_nat_bits, &old_regs->r15, &old_unat);
-       if (ia64_psr(old_regs)->bn)
-               bank = ms->pmsa_bank1_gr;
-       else
-               bank = ms->pmsa_bank0_gr;
-       copy_reg(&bank[16-16], ms->pmsa_nat_bits, &old_regs->r16, &old_unat);
-       copy_reg(&bank[17-16], ms->pmsa_nat_bits, &old_regs->r17, &old_unat);
-       copy_reg(&bank[18-16], ms->pmsa_nat_bits, &old_regs->r18, &old_unat);
-       copy_reg(&bank[19-16], ms->pmsa_nat_bits, &old_regs->r19, &old_unat);
-       copy_reg(&bank[20-16], ms->pmsa_nat_bits, &old_regs->r20, &old_unat);
-       copy_reg(&bank[21-16], ms->pmsa_nat_bits, &old_regs->r21, &old_unat);
-       copy_reg(&bank[22-16], ms->pmsa_nat_bits, &old_regs->r22, &old_unat);
-       copy_reg(&bank[23-16], ms->pmsa_nat_bits, &old_regs->r23, &old_unat);
-       copy_reg(&bank[24-16], ms->pmsa_nat_bits, &old_regs->r24, &old_unat);
-       copy_reg(&bank[25-16], ms->pmsa_nat_bits, &old_regs->r25, &old_unat);
-       copy_reg(&bank[26-16], ms->pmsa_nat_bits, &old_regs->r26, &old_unat);
-       copy_reg(&bank[27-16], ms->pmsa_nat_bits, &old_regs->r27, &old_unat);
-       copy_reg(&bank[28-16], ms->pmsa_nat_bits, &old_regs->r28, &old_unat);
-       copy_reg(&bank[29-16], ms->pmsa_nat_bits, &old_regs->r29, &old_unat);
-       copy_reg(&bank[30-16], ms->pmsa_nat_bits, &old_regs->r30, &old_unat);
-       copy_reg(&bank[31-16], ms->pmsa_nat_bits, &old_regs->r31, &old_unat);
+       finish_pt_regs(old_regs, ms, &old_unat);
 
        /* Next stack a struct switch_stack.  mca_asm.S built a partial
         * switch_stack, copy it and fill in the blanks using pt_regs and
@@ -1141,6 +1149,8 @@ ia64_mca_modify_original_stack(struct pt_regs *regs,
 no_mod:
        mprintk(KERN_INFO "cpu %d, %s %s, original stack not modified\n",
                        smp_processor_id(), type, msg);
+       old_unat = regs->ar_unat;
+       finish_pt_regs(regs, ms, &old_unat);
        return previous_current;
 }
 
index 6db0859..776dd40 100644 (file)
@@ -60,7 +60,6 @@ dump (const char *str, void *vp, size_t len)
  */
 int no_unaligned_warning;
 int unaligned_dump_stack;
-static int noprint_warning;
 
 /*
  * For M-unit:
@@ -1357,9 +1356,8 @@ ia64_handle_unaligned (unsigned long ifa, struct pt_regs *regs)
                        /* watch for command names containing %s */
                        printk(KERN_WARNING "%s", buf);
                } else {
-                       if (no_unaligned_warning && !noprint_warning) {
-                               noprint_warning = 1;
-                               printk(KERN_WARNING "%s(%d) encountered an "
+                       if (no_unaligned_warning) {
+                               printk_once(KERN_WARNING "%s(%d) encountered an "
                                       "unaligned exception which required\n"
                                       "kernel assistance, which degrades "
                                       "the performance of the application.\n"
index f426dc7..ee09d26 100644 (file)
@@ -100,24 +100,36 @@ wrap_mmu_context (struct mm_struct *mm)
  * this primitive it can be moved up to a spinaphore.h header.
  */
 struct spinaphore {
-       atomic_t        cur;
+       unsigned long   ticket;
+       unsigned long   serve;
 };
 
 static inline void spinaphore_init(struct spinaphore *ss, int val)
 {
-       atomic_set(&ss->cur, val);
+       ss->ticket = 0;
+       ss->serve = val;
 }
 
 static inline void down_spin(struct spinaphore *ss)
 {
-       while (unlikely(!atomic_add_unless(&ss->cur, -1, 0)))
-               while (atomic_read(&ss->cur) == 0)
-                       cpu_relax();
+       unsigned long t = ia64_fetchadd(1, &ss->ticket, acq), serve;
+
+       if (time_before(t, ss->serve))
+               return;
+
+       ia64_invala();
+
+       for (;;) {
+               asm volatile ("ld4.c.nc %0=[%1]" : "=r"(serve) : "r"(&ss->serve) : "memory");
+               if (time_before(t, serve))
+                       return;
+               cpu_relax();
+       }
 }
 
 static inline void up_spin(struct spinaphore *ss)
 {
-       atomic_add(1, &ss->cur);
+       ia64_fetchadd(1, &ss->serve, rel);
 }
 
 static struct spinaphore ptcg_sem;
index 7de76dd..c0fca2c 100644 (file)
@@ -56,10 +56,13 @@ int raw_pci_read(unsigned int seg, unsigned int bus, unsigned int devfn,
        if ((seg | reg) <= 255) {
                addr = PCI_SAL_ADDRESS(seg, bus, devfn, reg);
                mode = 0;
-       } else {
+       } else if (sal_revision >= SAL_VERSION_CODE(3,2)) {
                addr = PCI_SAL_EXT_ADDRESS(seg, bus, devfn, reg);
                mode = 1;
+       } else {
+               return -EINVAL;
        }
+
        result = ia64_sal_pci_config_read(addr, mode, len, &data);
        if (result != 0)
                return -EINVAL;
@@ -80,9 +83,11 @@ int raw_pci_write(unsigned int seg, unsigned int bus, unsigned int devfn,
        if ((seg | reg) <= 255) {
                addr = PCI_SAL_ADDRESS(seg, bus, devfn, reg);
                mode = 0;
-       } else {
+       } else if (sal_revision >= SAL_VERSION_CODE(3,2)) {
                addr = PCI_SAL_EXT_ADDRESS(seg, bus, devfn, reg);
                mode = 1;
+       } else {
+               return -EINVAL;
        }
        result = ia64_sal_pci_config_write(addr, mode, len, value);
        if (result != 0)
index 25831c4..308e659 100644 (file)
@@ -119,7 +119,6 @@ sn_pcidev_info_get(struct pci_dev *dev)
  * Additionally note that the struct sn_flush_device_war also has to be
  * removed from arch/ia64/sn/include/xtalk/hubdev.h
  */
-static u8 war_implemented = 0;
 
 static s64 sn_device_fixup_war(u64 nasid, u64 widget, int device,
                               struct sn_flush_device_common *common)
@@ -128,11 +127,8 @@ static s64 sn_device_fixup_war(u64 nasid, u64 widget, int device,
        struct sn_flush_device_war *dev_entry;
        struct ia64_sal_retval isrv = {0,0,0,0};
 
-       if (!war_implemented) {
-               printk(KERN_WARNING "PROM version < 4.50 -- implementing old "
-                      "PROM flush WAR\n");
-               war_implemented = 1;
-       }
+       printk_once(KERN_WARNING
+               "PROM version < 4.50 -- implementing old PROM flush WAR\n");
 
        war_list = kzalloc(DEV_PER_WIDGET * sizeof(*war_list), GFP_KERNEL);
        BUG_ON(!war_list);
index 4c7e747..55ac3c4 100644 (file)
@@ -786,17 +786,18 @@ sn_hwperf_ioctl(struct inode *in, struct file *fp, u32 op, unsigned long arg)
                break;
 
        case SN_HWPERF_GET_OBJ_NODE:
-               if (a.sz != sizeof(u64) || a.arg < 0) {
+               i = a.arg;
+               if (a.sz != sizeof(u64) || i < 0) {
                        r = -EINVAL;
                        goto error;
                }
                if ((r = sn_hwperf_enum_objects(&nobj, &objs)) == 0) {
-                       if (a.arg >= nobj) {
+                       if (i >= nobj) {
                                r = -EINVAL;
                                vfree(objs);
                                goto error;
                        }
-                       if (objs[(i = a.arg)].id != a.arg) {
+                       if (objs[i].id != a.arg) {
                                for (i = 0; i < nobj; i++) {
                                        if (objs[i].id == a.arg)
                                                break;
index 1b7598e..8a88f1f 100644 (file)
@@ -17,6 +17,7 @@
 
 #include <linux/irq.h>
 #include <linux/interrupt.h>
+#include <linux/sched.h>
 #include <linux/spinlock.h>
 #include <linux/mm.h>
 #include <linux/smp.h>
index 29dd848..ecdc19a 100644 (file)
@@ -561,7 +561,7 @@ config HPAPCI
 
 config MVME147_SCC
        bool "SCC support for MVME147 serial ports"
-       depends on MVME147
+       depends on MVME147 && BROKEN
        help
          This is the driver for the serial ports on the Motorola MVME147
          boards.  Everyone using one of these boards should say Y here.
@@ -576,14 +576,14 @@ config SERIAL167
 
 config MVME162_SCC
        bool "SCC support for MVME162 serial ports"
-       depends on MVME16x
+       depends on MVME16x && BROKEN
        help
          This is the driver for the serial ports on the Motorola MVME162 and
          172 boards.  Everyone using one of these boards should say Y here.
 
 config BVME6000_SCC
        bool "SCC support for BVME6000 serial ports"
-       depends on BVME6000
+       depends on BVME6000 && BROKEN
        help
          This is the driver for the serial ports on the BVME4000 and BVME6000
          boards from BVM Ltd.  Everyone using one of these boards should say
index 594ee0e..9a8876f 100644 (file)
@@ -45,25 +45,25 @@ int main(void)
        DEFINE(THREAD_FPSTATE, offsetof(struct thread_struct, fpstate));
 
        /* offsets into the pt_regs */
-       DEFINE(PT_D0, offsetof(struct pt_regs, d0));
-       DEFINE(PT_ORIG_D0, offsetof(struct pt_regs, orig_d0));
-       DEFINE(PT_D1, offsetof(struct pt_regs, d1));
-       DEFINE(PT_D2, offsetof(struct pt_regs, d2));
-       DEFINE(PT_D3, offsetof(struct pt_regs, d3));
-       DEFINE(PT_D4, offsetof(struct pt_regs, d4));
-       DEFINE(PT_D5, offsetof(struct pt_regs, d5));
-       DEFINE(PT_A0, offsetof(struct pt_regs, a0));
-       DEFINE(PT_A1, offsetof(struct pt_regs, a1));
-       DEFINE(PT_A2, offsetof(struct pt_regs, a2));
-       DEFINE(PT_PC, offsetof(struct pt_regs, pc));
-       DEFINE(PT_SR, offsetof(struct pt_regs, sr));
+       DEFINE(PT_OFF_D0, offsetof(struct pt_regs, d0));
+       DEFINE(PT_OFF_ORIG_D0, offsetof(struct pt_regs, orig_d0));
+       DEFINE(PT_OFF_D1, offsetof(struct pt_regs, d1));
+       DEFINE(PT_OFF_D2, offsetof(struct pt_regs, d2));
+       DEFINE(PT_OFF_D3, offsetof(struct pt_regs, d3));
+       DEFINE(PT_OFF_D4, offsetof(struct pt_regs, d4));
+       DEFINE(PT_OFF_D5, offsetof(struct pt_regs, d5));
+       DEFINE(PT_OFF_A0, offsetof(struct pt_regs, a0));
+       DEFINE(PT_OFF_A1, offsetof(struct pt_regs, a1));
+       DEFINE(PT_OFF_A2, offsetof(struct pt_regs, a2));
+       DEFINE(PT_OFF_PC, offsetof(struct pt_regs, pc));
+       DEFINE(PT_OFF_SR, offsetof(struct pt_regs, sr));
 
 #ifdef CONFIG_COLDFIRE
        /* bitfields are a bit difficult */
-       DEFINE(PT_FORMATVEC, offsetof(struct pt_regs, sr) - 2);
+       DEFINE(PT_OFF_FORMATVEC, offsetof(struct pt_regs, sr) - 2);
 #else
        /* bitfields are a bit difficult */
-       DEFINE(PT_VECTOR, offsetof(struct pt_regs, pc) + 4);
+       DEFINE(PT_OFF_VECTOR, offsetof(struct pt_regs, pc) + 4);
 #endif
 
        /* signal defines */
index f56faa5..56043ad 100644 (file)
@@ -46,7 +46,7 @@
 ENTRY(buserr)
        SAVE_ALL
        moveq   #-1,%d0
-       movel   %d0,%sp@(PT_ORIG_D0)
+       movel   %d0,%sp@(PT_OFF_ORIG_D0)
        movel   %sp,%sp@-               /* stack frame pointer argument */
        jsr     buserr_c
        addql   #4,%sp
@@ -55,7 +55,7 @@ ENTRY(buserr)
 ENTRY(trap)
        SAVE_ALL
        moveq   #-1,%d0
-       movel   %d0,%sp@(PT_ORIG_D0)
+       movel   %d0,%sp@(PT_OFF_ORIG_D0)
        movel   %sp,%sp@-               /* stack frame pointer argument */
        jsr     trap_c
        addql   #4,%sp
@@ -67,7 +67,7 @@ ENTRY(trap)
 ENTRY(dbginterrupt)
        SAVE_ALL
        moveq   #-1,%d0
-       movel   %d0,%sp@(PT_ORIG_D0)
+       movel   %d0,%sp@(PT_OFF_ORIG_D0)
        movel   %sp,%sp@-               /* stack frame pointer argument */
        jsr     dbginterrupt_c
        addql   #4,%sp
index b1703c6..f3236d0 100644 (file)
@@ -162,7 +162,7 @@ void free_initrd_mem(unsigned long start, unsigned long end)
                totalram_pages++;
                pages++;
        }
-       printk (KERN_NOTICE "Freeing initrd memory: %dk freed\n", pages);
+       printk (KERN_NOTICE "Freeing initrd memory: %dk freed\n", pages * (PAGE_SIZE / 1024));
 }
 #endif
 
index 0f41ba8..9423979 100644 (file)
@@ -17,7 +17,6 @@
 #include <asm/mcfsim.h>
 #include <asm/mcfuart.h>
 #include <asm/mcfdma.h>
-#include <asm/mcfuart.h>
 
 /***************************************************************************/
 
index b1aef72..9d80d2c 100644 (file)
 .globl inthandler7
 
 badsys:
-       movel   #-ENOSYS,%sp@(PT_D0)
+       movel   #-ENOSYS,%sp@(PT_OFF_D0)
        jra     ret_from_exception
 
 do_trace:
-       movel   #-ENOSYS,%sp@(PT_D0)    /* needed for strace*/
+       movel   #-ENOSYS,%sp@(PT_OFF_D0)        /* needed for strace*/
        subql   #4,%sp
        SAVE_SWITCH_STACK
        jbsr    syscall_trace
        RESTORE_SWITCH_STACK
        addql   #4,%sp
-       movel   %sp@(PT_ORIG_D0),%d1
+       movel   %sp@(PT_OFF_ORIG_D0),%d1
        movel   #-ENOSYS,%d0
        cmpl    #NR_syscalls,%d1
        jcc     1f
@@ -57,7 +57,7 @@ do_trace:
        lea     sys_call_table, %a0
        jbsr    %a0@(%d1)
 
-1:     movel   %d0,%sp@(PT_D0)         /* save the return value */
+1:     movel   %d0,%sp@(PT_OFF_D0)             /* save the return value */
        subql   #4,%sp                  /* dummy return address */
        SAVE_SWITCH_STACK
        jbsr    syscall_trace
@@ -75,7 +75,7 @@ ENTRY(system_call)
        jbsr    set_esp0
        addql   #4,%sp
 
-       movel   %sp@(PT_ORIG_D0),%d0
+       movel   %sp@(PT_OFF_ORIG_D0),%d0
 
        movel   %sp,%d1                 /* get thread_info pointer */
        andl    #-THREAD_SIZE,%d1
@@ -88,10 +88,10 @@ ENTRY(system_call)
        lea     sys_call_table,%a0
        movel   %a0@(%d0), %a0
        jbsr    %a0@
-       movel   %d0,%sp@(PT_D0)         /* save the return value*/
+       movel   %d0,%sp@(PT_OFF_D0)             /* save the return value*/
 
 ret_from_exception:
-       btst    #5,%sp@(PT_SR)          /* check if returning to kernel*/
+       btst    #5,%sp@(PT_OFF_SR)              /* check if returning to kernel*/
        jeq     Luser_return            /* if so, skip resched, signals*/
 
 Lkernel_return:
@@ -133,7 +133,7 @@ Lreturn:
  */
 inthandler1:
        SAVE_ALL
-       movew   %sp@(PT_VECTOR), %d0
+       movew   %sp@(PT_OFF_VECTOR), %d0
        and     #0x3ff, %d0
 
        movel   %sp,%sp@-
@@ -144,7 +144,7 @@ inthandler1:
 
 inthandler2:
        SAVE_ALL
-       movew   %sp@(PT_VECTOR), %d0
+       movew   %sp@(PT_OFF_VECTOR), %d0
        and     #0x3ff, %d0
 
        movel   %sp,%sp@-
@@ -155,7 +155,7 @@ inthandler2:
 
 inthandler3:
        SAVE_ALL
-       movew   %sp@(PT_VECTOR), %d0
+       movew   %sp@(PT_OFF_VECTOR), %d0
        and     #0x3ff, %d0
 
        movel   %sp,%sp@-
@@ -166,7 +166,7 @@ inthandler3:
 
 inthandler4:
        SAVE_ALL
-       movew   %sp@(PT_VECTOR), %d0
+       movew   %sp@(PT_OFF_VECTOR), %d0
        and     #0x3ff, %d0
 
        movel   %sp,%sp@-
@@ -177,7 +177,7 @@ inthandler4:
 
 inthandler5:
        SAVE_ALL
-       movew   %sp@(PT_VECTOR), %d0
+       movew   %sp@(PT_OFF_VECTOR), %d0
        and     #0x3ff, %d0
 
        movel   %sp,%sp@-
@@ -188,7 +188,7 @@ inthandler5:
 
 inthandler6:
        SAVE_ALL
-       movew   %sp@(PT_VECTOR), %d0
+       movew   %sp@(PT_OFF_VECTOR), %d0
        and     #0x3ff, %d0
 
        movel   %sp,%sp@-
@@ -199,7 +199,7 @@ inthandler6:
 
 inthandler7:
        SAVE_ALL
-       movew   %sp@(PT_VECTOR), %d0
+       movew   %sp@(PT_OFF_VECTOR), %d0
        and     #0x3ff, %d0
 
        movel   %sp,%sp@-
@@ -210,7 +210,7 @@ inthandler7:
 
 inthandler:
        SAVE_ALL
-       movew   %sp@(PT_VECTOR), %d0
+       movew   %sp@(PT_OFF_VECTOR), %d0
        and     #0x3ff, %d0
 
        movel   %sp,%sp@-
@@ -224,7 +224,7 @@ ret_from_interrupt:
 2:
        RESTORE_ALL
 1:
-       moveb   %sp@(PT_SR), %d0
+       moveb   %sp@(PT_OFF_SR), %d0
        and     #7, %d0
        jhi     2b
 
index 55dfefe..6d3460a 100644 (file)
 .globl inthandler
 
 badsys:
-       movel   #-ENOSYS,%sp@(PT_D0)
+       movel   #-ENOSYS,%sp@(PT_OFF_D0)
        jra     ret_from_exception
 
 do_trace:
-       movel   #-ENOSYS,%sp@(PT_D0)    /* needed for strace*/
+       movel   #-ENOSYS,%sp@(PT_OFF_D0) /* needed for strace*/
        subql   #4,%sp
        SAVE_SWITCH_STACK
        jbsr    syscall_trace
        RESTORE_SWITCH_STACK
        addql   #4,%sp
-       movel   %sp@(PT_ORIG_D0),%d1
+       movel   %sp@(PT_OFF_ORIG_D0),%d1
        movel   #-ENOSYS,%d0
        cmpl    #NR_syscalls,%d1
        jcc     1f
@@ -53,7 +53,7 @@ do_trace:
        lea     sys_call_table, %a0
        jbsr    %a0@(%d1)
 
-1:     movel   %d0,%sp@(PT_D0)         /* save the return value */
+1:     movel   %d0,%sp@(PT_OFF_D0)     /* save the return value */
        subql   #4,%sp                  /* dummy return address */
        SAVE_SWITCH_STACK
        jbsr    syscall_trace
@@ -79,10 +79,10 @@ ENTRY(system_call)
        lea     sys_call_table,%a0
        movel   %a0@(%d0), %a0
        jbsr    %a0@
-       movel   %d0,%sp@(PT_D0)         /* save the return value*/
+       movel   %d0,%sp@(PT_OFF_D0)     /* save the return value*/
 
 ret_from_exception:
-       btst    #5,%sp@(PT_SR)          /* check if returning to kernel*/
+       btst    #5,%sp@(PT_OFF_SR)      /* check if returning to kernel*/
        jeq     Luser_return            /* if so, skip resched, signals*/
 
 Lkernel_return:
@@ -124,7 +124,7 @@ Lreturn:
  */
 inthandler:
        SAVE_ALL
-       movew   %sp@(PT_VECTOR), %d0
+       movew   %sp@(PT_OFF_VECTOR), %d0
        and.l   #0x3ff, %d0
        lsr.l   #0x02,  %d0
 
@@ -139,7 +139,7 @@ ret_from_interrupt:
 2:
        RESTORE_ALL
 1:
-       moveb   %sp@(PT_SR), %d0
+       moveb   %sp@(PT_OFF_SR), %d0
        and     #7, %d0
        jhi     2b
        /* check if we need to do software interrupts */
index 3b471c0..dd7d591 100644 (file)
@@ -81,11 +81,11 @@ ENTRY(system_call)
 
        movel   %d3,%a0
        jbsr    %a0@
-       movel   %d0,%sp@(PT_D0)         /* save the return value */
+       movel   %d0,%sp@(PT_OFF_D0)     /* save the return value */
        jra     ret_from_exception
 1:
-       movel   #-ENOSYS,%d2            /* strace needs -ENOSYS in PT_D0 */
-       movel   %d2,PT_D0(%sp)          /* on syscall entry */
+       movel   #-ENOSYS,%d2            /* strace needs -ENOSYS in PT_OFF_D0 */
+       movel   %d2,PT_OFF_D0(%sp)      /* on syscall entry */
        subql   #4,%sp
        SAVE_SWITCH_STACK
        jbsr    syscall_trace
@@ -93,7 +93,7 @@ ENTRY(system_call)
        addql   #4,%sp
        movel   %d3,%a0
        jbsr    %a0@
-       movel   %d0,%sp@(PT_D0)         /* save the return value */
+       movel   %d0,%sp@(PT_OFF_D0)             /* save the return value */
        subql   #4,%sp                  /* dummy return address */
        SAVE_SWITCH_STACK
        jbsr    syscall_trace
@@ -104,7 +104,7 @@ ret_from_signal:
 
 ret_from_exception:
        move    #0x2700,%sr             /* disable intrs */
-       btst    #5,%sp@(PT_SR)          /* check if returning to kernel */
+       btst    #5,%sp@(PT_OFF_SR)      /* check if returning to kernel */
        jeq     Luser_return            /* if so, skip resched, signals */
 
 #ifdef CONFIG_PREEMPT
@@ -142,8 +142,8 @@ Luser_return:
 Lreturn:
        move    #0x2700,%sr             /* disable intrs */
        movel   sw_usp,%a0              /* get usp */
-       movel   %sp@(PT_PC),%a0@-       /* copy exception program counter */
-       movel   %sp@(PT_FORMATVEC),%a0@-/* copy exception format/vector/sr */
+       movel   %sp@(PT_OFF_PC),%a0@-   /* copy exception program counter */
+       movel   %sp@(PT_OFF_FORMATVEC),%a0@- /* copy exception format/vector/sr */
        moveml  %sp@,%d1-%d5/%a0-%a2
        lea     %sp@(32),%sp            /* space for 8 regs */
        movel   %sp@+,%d0
@@ -181,9 +181,9 @@ Lsignal_return:
 ENTRY(inthandler)
        SAVE_ALL
        moveq   #-1,%d0
-       movel   %d0,%sp@(PT_ORIG_D0)
+       movel   %d0,%sp@(PT_OFF_ORIG_D0)
 
-       movew   %sp@(PT_FORMATVEC),%d0  /* put exception # in d0 */
+       movew   %sp@(PT_OFF_FORMATVEC),%d0 /* put exception # in d0 */
        andl    #0x03fc,%d0             /* mask out vector only */
 
        movel   %sp,%sp@-               /* push regs arg */
@@ -203,7 +203,7 @@ ENTRY(inthandler)
 ENTRY(fasthandler)
        SAVE_LOCAL
 
-       movew   %sp@(PT_FORMATVEC),%d0
+       movew   %sp@(PT_OFF_FORMATVEC),%d0
        andl    #0x03fc,%d0             /* mask out vector only */
 
        movel   %sp,%sp@-               /* push regs arg */
index acc1f05..e3ecb36 100644 (file)
@@ -592,6 +592,8 @@ C_ENTRY(full_exception_trap):
        nop
        mfs     r7, rfsr;               /* save FSR */
        nop
+       mts     rfsr, r0;       /* Clear sticky fsr */
+       nop
        la      r12, r0, full_exception
        set_vms;
        rtbd    r12, 0;
index 6b0288e..2b86c03 100644 (file)
@@ -384,7 +384,7 @@ handle_other_ex: /* Handle Other exceptions here */
        addk    r8, r17, r0; /* Load exception address */
        bralid  r15, full_exception; /* Branch to the handler */
        nop;
-       mts     r0, rfsr;       /* Clear sticky fsr */
+       mts     rfsr, r0;       /* Clear sticky fsr */
        nop
 
        /*
index 4201c74..c592d47 100644 (file)
@@ -235,7 +235,9 @@ void start_thread(struct pt_regs *regs, unsigned long pc, unsigned long usp)
        regs->pc = pc;
        regs->r1 = usp;
        regs->pt_mode = 0;
+#ifdef CONFIG_MMU
        regs->msr |= MSR_UMS;
+#endif
 }
 
 #ifdef CONFIG_MMU
index 705a7a9..03bd56a 100644 (file)
@@ -1012,9 +1012,9 @@ config BOOT_ELF32
 
 config MIPS_L1_CACHE_SHIFT
        int
-       default "4" if MACH_DECSTATION || MIKROTIK_RB532
+       default "4" if MACH_DECSTATION || MIKROTIK_RB532 || PMC_MSP4200_EVAL
+       default "6" if MIPS_CPU_SCACHE
        default "7" if SGI_IP22 || SGI_IP27 || SGI_IP28 || SNI_RM || CPU_CAVIUM_OCTEON
-       default "4" if PMC_MSP4200_EVAL
        default "5"
 
 config HAVE_STD_PC_SERIAL_PORT
index c88c821..d670928 100644 (file)
@@ -354,6 +354,28 @@ static void au1x_ic1_ack(unsigned int irq_nr)
        au_sync();
 }
 
+static void au1x_ic0_maskack(unsigned int irq_nr)
+{
+       unsigned int bit = irq_nr - AU1000_INTC0_INT_BASE;
+
+       au_writel(1 << bit, IC0_WAKECLR);
+       au_writel(1 << bit, IC0_MASKCLR);
+       au_writel(1 << bit, IC0_RISINGCLR);
+       au_writel(1 << bit, IC0_FALLINGCLR);
+       au_sync();
+}
+
+static void au1x_ic1_maskack(unsigned int irq_nr)
+{
+       unsigned int bit = irq_nr - AU1000_INTC1_INT_BASE;
+
+       au_writel(1 << bit, IC1_WAKECLR);
+       au_writel(1 << bit, IC1_MASKCLR);
+       au_writel(1 << bit, IC1_RISINGCLR);
+       au_writel(1 << bit, IC1_FALLINGCLR);
+       au_sync();
+}
+
 static int au1x_ic1_setwake(unsigned int irq, unsigned int on)
 {
        unsigned int bit = irq - AU1000_INTC1_INT_BASE;
@@ -379,25 +401,21 @@ static int au1x_ic1_setwake(unsigned int irq, unsigned int on)
 /*
  * irq_chips for both ICs; this way the mask handlers can be
  * as short as possible.
- *
- * NOTE: the ->ack() callback is used by the handle_edge_irq
- *      flowhandler only, the ->mask_ack() one by handle_level_irq,
- *      so no need for an irq_chip for each type of irq (level/edge).
  */
 static struct irq_chip au1x_ic0_chip = {
        .name           = "Alchemy-IC0",
-       .ack            = au1x_ic0_ack,         /* edge */
+       .ack            = au1x_ic0_ack,
        .mask           = au1x_ic0_mask,
-       .mask_ack       = au1x_ic0_mask,        /* level */
+       .mask_ack       = au1x_ic0_maskack,
        .unmask         = au1x_ic0_unmask,
        .set_type       = au1x_ic_settype,
 };
 
 static struct irq_chip au1x_ic1_chip = {
        .name           = "Alchemy-IC1",
-       .ack            = au1x_ic1_ack,         /* edge */
+       .ack            = au1x_ic1_ack,
        .mask           = au1x_ic1_mask,
-       .mask_ack       = au1x_ic1_mask,        /* level */
+       .mask_ack       = au1x_ic1_maskack,
        .unmask         = au1x_ic1_unmask,
        .set_type       = au1x_ic_settype,
        .set_wake       = au1x_ic1_setwake,
index cc32c69..45b61c9 100644 (file)
@@ -69,6 +69,7 @@ void __init board_setup(void)
 #else
        au_writel(0xf, Au1500_PCI_CFG);
 #endif
+       board_pci_idsel = mtx1_pci_idsel;
 #endif
 
        /* Initialize sys_pinfunc */
@@ -85,8 +86,6 @@ void __init board_setup(void)
        alchemy_gpio_direction_output(211, 1);  /* green on */
        alchemy_gpio_direction_output(212, 0);  /* red off */
 
-       board_pci_idsel = mtx1_pci_idsel;
-
        printk(KERN_INFO "4G Systems MTX-1 Board\n");
 }
 
index e2278c0..835f3f0 100644 (file)
@@ -503,6 +503,7 @@ static int __init ar7_register_devices(void)
 {
        u16 chip_id;
        int res;
+       u32 *bootcr, val;
 #ifdef CONFIG_SERIAL_8250
        static struct uart_port uart_port[2];
 
@@ -595,7 +596,13 @@ static int __init ar7_register_devices(void)
 
        ar7_wdt_res.end = ar7_wdt_res.start + 0x20;
 
-       res = platform_device_register(&ar7_wdt);
+       bootcr = (u32 *)ioremap_nocache(AR7_REGS_DCL, 4);
+       val = *bootcr;
+       iounmap(bootcr);
+
+       /* Register watchdog only if enabled in hardware */
+       if (val & AR7_WDT_HW_ENA)
+               res = platform_device_register(&ar7_wdt);
 
        return res;
 }
index c146d1e..00064b6 100644 (file)
@@ -1,5 +1,5 @@
 obj-y          += clk.o cpu.o cs.o gpio.o irq.o prom.o setup.o timer.o \
-                  dev-dsp.o dev-enet.o dev-pcmcia.o dev-uart.o
+                  dev-dsp.o dev-enet.o dev-pcmcia.o dev-uart.o dev-wdt.o
 obj-$(CONFIG_EARLY_PRINTK)     += early_printk.o
 
 obj-y          += boards/
index 78e155d..05a35cf 100644 (file)
@@ -24,7 +24,6 @@
 #include <bcm63xx_dev_enet.h>
 #include <bcm63xx_dev_dsp.h>
 #include <bcm63xx_dev_pcmcia.h>
-#include <bcm63xx_dev_uart.h>
 #include <board_bcm963xx.h>
 
 #define PFX    "board_bcm963xx: "
@@ -794,8 +793,6 @@ int __init board_register_devices(void)
 {
        u32 val;
 
-       bcm63xx_uart_register();
-
        if (board.has_pccard)
                bcm63xx_pcmcia_register();
 
index 6dc43f0..70378bb 100644 (file)
@@ -10,6 +10,7 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/cpu.h>
+#include <asm/cpu-info.h>
 #include <bcm63xx_cpu.h>
 #include <bcm63xx_regs.h>
 #include <bcm63xx_io.h>
@@ -284,6 +285,7 @@ void __init bcm63xx_cpu_init(void)
 {
        unsigned int tmp, expected_cpu_id;
        struct cpuinfo_mips *c = &current_cpu_data;
+       unsigned int cpu = smp_processor_id();
 
        /* soc registers location depends on cpu type */
        expected_cpu_id = 0;
@@ -293,6 +295,7 @@ void __init bcm63xx_cpu_init(void)
         * BCM6338 as the same PrId as BCM3302 see arch/mips/kernel/cpu-probe.c
         */
        case CPU_BCM3302:
+               __cpu_name[cpu] = "Broadcom BCM6338";
                expected_cpu_id = BCM6338_CPU_ID;
                bcm63xx_regs_base = bcm96338_regs_base;
                bcm63xx_irqs = bcm96338_irqs;
index 5f3d89c..b051946 100644 (file)
@@ -10,7 +10,6 @@
 #include <linux/kernel.h>
 #include <linux/platform_device.h>
 #include <bcm63xx_cpu.h>
-#include <bcm63xx_dev_uart.h>
 
 static struct resource uart_resources[] = {
        {
@@ -39,3 +38,4 @@ int __init bcm63xx_uart_register(void)
        uart_resources[1].start = bcm63xx_get_irq_number(IRQ_UART0);
        return platform_device_register(&bcm63xx_uart_device);
 }
+arch_initcall(bcm63xx_uart_register);
diff --git a/arch/mips/bcm63xx/dev-wdt.c b/arch/mips/bcm63xx/dev-wdt.c
new file mode 100644 (file)
index 0000000..3e6c716
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2008 Florian Fainelli <florian@openwrt.org>
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/platform_device.h>
+#include <bcm63xx_cpu.h>
+
+static struct resource wdt_resources[] = {
+       {
+               .start          = -1, /* filled at runtime */
+               .end            = -1, /* filled at runtime */
+               .flags          = IORESOURCE_MEM,
+       },
+};
+
+static struct platform_device bcm63xx_wdt_device = {
+       .name           = "bcm63xx-wdt",
+       .id             = 0,
+       .num_resources  = ARRAY_SIZE(wdt_resources),
+       .resource       = wdt_resources,
+};
+
+int __init bcm63xx_wdt_register(void)
+{
+       wdt_resources[0].start = bcm63xx_regset_address(RSET_WDT);
+       wdt_resources[0].end = wdt_resources[0].start;
+       wdt_resources[0].end += RSET_WDT_SIZE - 1;
+
+       return platform_device_register(&bcm63xx_wdt_device);
+}
+arch_initcall(bcm63xx_wdt_register);
index b18a0ca..d005659 100644 (file)
@@ -75,7 +75,9 @@ void bcm63xx_machine_reboot(void)
                bcm6348_a1_reboot();
 
        printk(KERN_INFO "triggering watchdog soft-reset...\n");
-       bcm_perf_writel(SYS_PLL_SOFT_RESET, PERF_SYS_PLL_CTL_REG);
+       reg = bcm_perf_readl(PERF_SYS_PLL_CTL_REG);
+       reg |= SYS_PLL_SOFT_RESET;
+       bcm_perf_writel(reg, PERF_SYS_PLL_CTL_REG);
        while (1)
                ;
 }
index 384f184..6f2acf0 100644 (file)
@@ -17,6 +17,15 @@ DEFINE_RWLOCK(octeon_irq_ciu0_rwlock);
 DEFINE_RWLOCK(octeon_irq_ciu1_rwlock);
 DEFINE_SPINLOCK(octeon_irq_msi_lock);
 
+static int octeon_coreid_for_cpu(int cpu)
+{
+#ifdef CONFIG_SMP
+       return cpu_logical_map(cpu);
+#else
+       return cvmx_get_core_num();
+#endif
+}
+
 static void octeon_irq_core_ack(unsigned int irq)
 {
        unsigned int bit = irq - OCTEON_IRQ_SW0;
@@ -152,11 +161,10 @@ static void octeon_irq_ciu0_disable(unsigned int irq)
        int bit = irq - OCTEON_IRQ_WORKQ0;      /* Bit 0-63 of EN0 */
        unsigned long flags;
        uint64_t en0;
-#ifdef CONFIG_SMP
        int cpu;
        write_lock_irqsave(&octeon_irq_ciu0_rwlock, flags);
        for_each_online_cpu(cpu) {
-               int coreid = cpu_logical_map(cpu);
+               int coreid = octeon_coreid_for_cpu(cpu);
                en0 = cvmx_read_csr(CVMX_CIU_INTX_EN0(coreid * 2));
                en0 &= ~(1ull << bit);
                cvmx_write_csr(CVMX_CIU_INTX_EN0(coreid * 2), en0);
@@ -167,26 +175,57 @@ static void octeon_irq_ciu0_disable(unsigned int irq)
         */
        cvmx_read_csr(CVMX_CIU_INTX_EN0(cvmx_get_core_num() * 2));
        write_unlock_irqrestore(&octeon_irq_ciu0_rwlock, flags);
-#else
-       int coreid = cvmx_get_core_num();
-       local_irq_save(flags);
-       en0 = cvmx_read_csr(CVMX_CIU_INTX_EN0(coreid * 2));
-       en0 &= ~(1ull << bit);
-       cvmx_write_csr(CVMX_CIU_INTX_EN0(coreid * 2), en0);
-       cvmx_read_csr(CVMX_CIU_INTX_EN0(coreid * 2));
-       local_irq_restore(flags);
-#endif
+}
+
+/*
+ * Enable the irq on the current core for chips that have the EN*_W1{S,C}
+ * registers.
+ */
+static void octeon_irq_ciu0_enable_v2(unsigned int irq)
+{
+       int index = cvmx_get_core_num() * 2;
+       u64 mask = 1ull << (irq - OCTEON_IRQ_WORKQ0);
+
+       cvmx_write_csr(CVMX_CIU_INTX_EN0_W1S(index), mask);
+}
+
+/*
+ * Disable the irq on the current core for chips that have the EN*_W1{S,C}
+ * registers.
+ */
+static void octeon_irq_ciu0_disable_v2(unsigned int irq)
+{
+       int index = cvmx_get_core_num() * 2;
+       u64 mask = 1ull << (irq - OCTEON_IRQ_WORKQ0);
+
+       cvmx_write_csr(CVMX_CIU_INTX_EN0_W1C(index), mask);
+}
+
+/*
+ * Disable the irq on the all cores for chips that have the EN*_W1{S,C}
+ * registers.
+ */
+static void octeon_irq_ciu0_disable_all_v2(unsigned int irq)
+{
+       u64 mask = 1ull << (irq - OCTEON_IRQ_WORKQ0);
+       int index;
+       int cpu;
+       for_each_online_cpu(cpu) {
+               index = octeon_coreid_for_cpu(cpu) * 2;
+               cvmx_write_csr(CVMX_CIU_INTX_EN0_W1C(index), mask);
+       }
 }
 
 #ifdef CONFIG_SMP
 static int octeon_irq_ciu0_set_affinity(unsigned int irq, const struct cpumask *dest)
 {
        int cpu;
+       unsigned long flags;
        int bit = irq - OCTEON_IRQ_WORKQ0;      /* Bit 0-63 of EN0 */
 
-       write_lock(&octeon_irq_ciu0_rwlock);
+       write_lock_irqsave(&octeon_irq_ciu0_rwlock, flags);
        for_each_online_cpu(cpu) {
-               int coreid = cpu_logical_map(cpu);
+               int coreid = octeon_coreid_for_cpu(cpu);
                uint64_t en0 =
                        cvmx_read_csr(CVMX_CIU_INTX_EN0(coreid * 2));
                if (cpumask_test_cpu(cpu, dest))
@@ -200,11 +239,45 @@ static int octeon_irq_ciu0_set_affinity(unsigned int irq, const struct cpumask *
         * of them are done.
         */
        cvmx_read_csr(CVMX_CIU_INTX_EN0(cvmx_get_core_num() * 2));
-       write_unlock(&octeon_irq_ciu0_rwlock);
+       write_unlock_irqrestore(&octeon_irq_ciu0_rwlock, flags);
 
        return 0;
 }
+
+/*
+ * Set affinity for the irq for chips that have the EN*_W1{S,C}
+ * registers.
+ */
+static int octeon_irq_ciu0_set_affinity_v2(unsigned int irq,
+                                          const struct cpumask *dest)
+{
+       int cpu;
+       int index;
+       u64 mask = 1ull << (irq - OCTEON_IRQ_WORKQ0);
+       for_each_online_cpu(cpu) {
+               index = octeon_coreid_for_cpu(cpu) * 2;
+               if (cpumask_test_cpu(cpu, dest))
+                       cvmx_write_csr(CVMX_CIU_INTX_EN0_W1S(index), mask);
+               else
+                       cvmx_write_csr(CVMX_CIU_INTX_EN0_W1C(index), mask);
+       }
+       return 0;
+}
+#endif
+
+/*
+ * Newer octeon chips have support for lockless CIU operation.
+ */
+static struct irq_chip octeon_irq_chip_ciu0_v2 = {
+       .name = "CIU0",
+       .enable = octeon_irq_ciu0_enable_v2,
+       .disable = octeon_irq_ciu0_disable_all_v2,
+       .ack = octeon_irq_ciu0_disable_v2,
+       .eoi = octeon_irq_ciu0_enable_v2,
+#ifdef CONFIG_SMP
+       .set_affinity = octeon_irq_ciu0_set_affinity_v2,
 #endif
+};
 
 static struct irq_chip octeon_irq_chip_ciu0 = {
        .name = "CIU0",
@@ -269,11 +342,10 @@ static void octeon_irq_ciu1_disable(unsigned int irq)
        int bit = irq - OCTEON_IRQ_WDOG0;       /* Bit 0-63 of EN1 */
        unsigned long flags;
        uint64_t en1;
-#ifdef CONFIG_SMP
        int cpu;
        write_lock_irqsave(&octeon_irq_ciu1_rwlock, flags);
        for_each_online_cpu(cpu) {
-               int coreid = cpu_logical_map(cpu);
+               int coreid = octeon_coreid_for_cpu(cpu);
                en1 = cvmx_read_csr(CVMX_CIU_INTX_EN1(coreid * 2 + 1));
                en1 &= ~(1ull << bit);
                cvmx_write_csr(CVMX_CIU_INTX_EN1(coreid * 2 + 1), en1);
@@ -284,26 +356,58 @@ static void octeon_irq_ciu1_disable(unsigned int irq)
         */
        cvmx_read_csr(CVMX_CIU_INTX_EN1(cvmx_get_core_num() * 2 + 1));
        write_unlock_irqrestore(&octeon_irq_ciu1_rwlock, flags);
-#else
-       int coreid = cvmx_get_core_num();
-       local_irq_save(flags);
-       en1 = cvmx_read_csr(CVMX_CIU_INTX_EN1(coreid * 2 + 1));
-       en1 &= ~(1ull << bit);
-       cvmx_write_csr(CVMX_CIU_INTX_EN1(coreid * 2 + 1), en1);
-       cvmx_read_csr(CVMX_CIU_INTX_EN1(coreid * 2 + 1));
-       local_irq_restore(flags);
-#endif
+}
+
+/*
+ * Enable the irq on the current core for chips that have the EN*_W1{S,C}
+ * registers.
+ */
+static void octeon_irq_ciu1_enable_v2(unsigned int irq)
+{
+       int index = cvmx_get_core_num() * 2 + 1;
+       u64 mask = 1ull << (irq - OCTEON_IRQ_WDOG0);
+
+       cvmx_write_csr(CVMX_CIU_INTX_EN1_W1S(index), mask);
+}
+
+/*
+ * Disable the irq on the current core for chips that have the EN*_W1{S,C}
+ * registers.
+ */
+static void octeon_irq_ciu1_disable_v2(unsigned int irq)
+{
+       int index = cvmx_get_core_num() * 2 + 1;
+       u64 mask = 1ull << (irq - OCTEON_IRQ_WDOG0);
+
+       cvmx_write_csr(CVMX_CIU_INTX_EN1_W1C(index), mask);
+}
+
+/*
+ * Disable the irq on the all cores for chips that have the EN*_W1{S,C}
+ * registers.
+ */
+static void octeon_irq_ciu1_disable_all_v2(unsigned int irq)
+{
+       u64 mask = 1ull << (irq - OCTEON_IRQ_WDOG0);
+       int index;
+       int cpu;
+       for_each_online_cpu(cpu) {
+               index = octeon_coreid_for_cpu(cpu) * 2 + 1;
+               cvmx_write_csr(CVMX_CIU_INTX_EN1_W1C(index), mask);
+       }
 }
 
 #ifdef CONFIG_SMP
-static int octeon_irq_ciu1_set_affinity(unsigned int irq, const struct cpumask *dest)
+static int octeon_irq_ciu1_set_affinity(unsigned int irq,
+                                       const struct cpumask *dest)
 {
        int cpu;
+       unsigned long flags;
        int bit = irq - OCTEON_IRQ_WDOG0;       /* Bit 0-63 of EN1 */
 
-       write_lock(&octeon_irq_ciu1_rwlock);
+       write_lock_irqsave(&octeon_irq_ciu1_rwlock, flags);
        for_each_online_cpu(cpu) {
-               int coreid = cpu_logical_map(cpu);
+               int coreid = octeon_coreid_for_cpu(cpu);
                uint64_t en1 =
                        cvmx_read_csr(CVMX_CIU_INTX_EN1
                                (coreid * 2 + 1));
@@ -318,12 +422,46 @@ static int octeon_irq_ciu1_set_affinity(unsigned int irq, const struct cpumask *
         * of them are done.
         */
        cvmx_read_csr(CVMX_CIU_INTX_EN1(cvmx_get_core_num() * 2 + 1));
-       write_unlock(&octeon_irq_ciu1_rwlock);
+       write_unlock_irqrestore(&octeon_irq_ciu1_rwlock, flags);
+
+       return 0;
+}
 
+/*
+ * Set affinity for the irq for chips that have the EN*_W1{S,C}
+ * registers.
+ */
+static int octeon_irq_ciu1_set_affinity_v2(unsigned int irq,
+                                          const struct cpumask *dest)
+{
+       int cpu;
+       int index;
+       u64 mask = 1ull << (irq - OCTEON_IRQ_WDOG0);
+       for_each_online_cpu(cpu) {
+               index = octeon_coreid_for_cpu(cpu) * 2 + 1;
+               if (cpumask_test_cpu(cpu, dest))
+                       cvmx_write_csr(CVMX_CIU_INTX_EN1_W1S(index), mask);
+               else
+                       cvmx_write_csr(CVMX_CIU_INTX_EN1_W1C(index), mask);
+       }
        return 0;
 }
 #endif
 
+/*
+ * Newer octeon chips have support for lockless CIU operation.
+ */
+static struct irq_chip octeon_irq_chip_ciu1_v2 = {
+       .name = "CIU0",
+       .enable = octeon_irq_ciu1_enable_v2,
+       .disable = octeon_irq_ciu1_disable_all_v2,
+       .ack = octeon_irq_ciu1_disable_v2,
+       .eoi = octeon_irq_ciu1_enable_v2,
+#ifdef CONFIG_SMP
+       .set_affinity = octeon_irq_ciu1_set_affinity_v2,
+#endif
+};
+
 static struct irq_chip octeon_irq_chip_ciu1 = {
        .name = "CIU1",
        .enable = octeon_irq_ciu1_enable,
@@ -420,6 +558,8 @@ static struct irq_chip octeon_irq_chip_msi = {
 void __init arch_init_irq(void)
 {
        int irq;
+       struct irq_chip *chip0;
+       struct irq_chip *chip1;
 
 #ifdef CONFIG_SMP
        /* Set the default affinity to the boot cpu. */
@@ -430,6 +570,16 @@ void __init arch_init_irq(void)
        if (NR_IRQS < OCTEON_IRQ_LAST)
                pr_err("octeon_irq_init: NR_IRQS is set too low\n");
 
+       if (OCTEON_IS_MODEL(OCTEON_CN58XX_PASS2_X) ||
+           OCTEON_IS_MODEL(OCTEON_CN56XX_PASS2_X) ||
+           OCTEON_IS_MODEL(OCTEON_CN52XX_PASS2_X)) {
+               chip0 = &octeon_irq_chip_ciu0_v2;
+               chip1 = &octeon_irq_chip_ciu1_v2;
+       } else {
+               chip0 = &octeon_irq_chip_ciu0;
+               chip1 = &octeon_irq_chip_ciu1;
+       }
+
        /* 0 - 15 reserved for i8259 master and slave controller. */
 
        /* 17 - 23 Mips internal */
@@ -440,14 +590,12 @@ void __init arch_init_irq(void)
 
        /* 24 - 87 CIU_INT_SUM0 */
        for (irq = OCTEON_IRQ_WORKQ0; irq <= OCTEON_IRQ_BOOTDMA; irq++) {
-               set_irq_chip_and_handler(irq, &octeon_irq_chip_ciu0,
-                                        handle_percpu_irq);
+               set_irq_chip_and_handler(irq, chip0, handle_percpu_irq);
        }
 
        /* 88 - 151 CIU_INT_SUM1 */
        for (irq = OCTEON_IRQ_WDOG0; irq <= OCTEON_IRQ_RESERVED151; irq++) {
-               set_irq_chip_and_handler(irq, &octeon_irq_chip_ciu1,
-                                        handle_percpu_irq);
+               set_irq_chip_and_handler(irq, chip1, handle_percpu_irq);
        }
 
 #ifdef CONFIG_PCI_MSI
@@ -505,14 +653,10 @@ asmlinkage void plat_irq_dispatch(void)
 #ifdef CONFIG_HOTPLUG_CPU
 static int is_irq_enabled_on_cpu(unsigned int irq, unsigned int cpu)
 {
-       unsigned int isset;
-#ifdef CONFIG_SMP
-       int coreid = cpu_logical_map(cpu);
-#else
-       int coreid = cvmx_get_core_num();
-#endif
+       unsigned int isset;
+       int coreid = octeon_coreid_for_cpu(cpu);
        int bit = (irq < OCTEON_IRQ_WDOG0) ?
-               irq - OCTEON_IRQ_WORKQ0 : irq - OCTEON_IRQ_WDOG0;
+                  irq - OCTEON_IRQ_WORKQ0 : irq - OCTEON_IRQ_WDOG0;
        if (irq < 64) {
                isset = (cvmx_read_csr(CVMX_CIU_INTX_EN0(coreid * 2)) &
                        (1ull << bit)) >> bit;
index 32d51a3..c198efd 100644 (file)
@@ -65,11 +65,12 @@ void octeon_send_ipi_single(int cpu, unsigned int action)
        cvmx_write_csr(CVMX_CIU_MBOX_SETX(coreid), action);
 }
 
-static inline void octeon_send_ipi_mask(cpumask_t mask, unsigned int action)
+static inline void octeon_send_ipi_mask(const struct cpumask *mask,
+                                       unsigned int action)
 {
        unsigned int i;
 
-       for_each_cpu_mask(i, mask)
+       for_each_cpu_mask(i, *mask)
                octeon_send_ipi_single(i, action);
 }
 
index efeddc8..0b89b83 100644 (file)
@@ -48,9 +48,9 @@ enum fixed_addresses {
 #define FIX_N_COLOURS 8
        FIX_CMAP_BEGIN,
 #ifdef CONFIG_MIPS_MT_SMTC
-       FIX_CMAP_END = FIX_CMAP_BEGIN + (FIX_N_COLOURS * NR_CPUS),
+       FIX_CMAP_END = FIX_CMAP_BEGIN + (FIX_N_COLOURS * NR_CPUS * 2),
 #else
-       FIX_CMAP_END = FIX_CMAP_BEGIN + FIX_N_COLOURS,
+       FIX_CMAP_END = FIX_CMAP_BEGIN + (FIX_N_COLOURS * 2),
 #endif
 #ifdef CONFIG_HIGHMEM
        /* reserved pte's for temporary kernel mappings */
index 36fd969..c0cf76a 100644 (file)
 #define GCMP_GDB_OFS           0x8000 /* Global Debug Block */
 
 /* Offsets to individual GCMP registers from GCMP base */
-#define GCMPOFS(block, tag, reg)       (GCMP_##block##_OFS + GCMP_##tag##_##reg##_OFS)
+#define GCMPOFS(block, tag, reg)       \
+       (GCMP_##block##_OFS + GCMP_##tag##_##reg##_OFS)
+#define GCMPOFSn(block, tag, reg, n) \
+       (GCMP_##block##_OFS + GCMP_##tag##_##reg##_OFS(n))
 
 #define GCMPGCBOFS(reg)                GCMPOFS(GCB, GCB, reg)
+#define GCMPGCBOFSn(reg, n)    GCMPOFSn(GCB, GCB, reg, n)
 #define GCMPCLCBOFS(reg)       GCMPOFS(CLCB, CCB, reg)
 #define GCMPCOCBOFS(reg)       GCMPOFS(COCB, CCB, reg)
 #define GCMPGDBOFS(reg)                GCMPOFS(GDB, GDB, reg)
 
 /* GCMP register access */
 #define GCMPGCB(reg)                   REGP(_gcmp_base, GCMPGCBOFS(reg))
+#define GCMPGCBn(reg, n)               REGP(_gcmp_base, GCMPGCBOFSn(reg, n))
 #define GCMPCLCB(reg)                  REGP(_gcmp_base, GCMPCLCBOFS(reg))
 #define GCMPCOCB(reg)                  REGP(_gcmp_base, GCMPCOCBOFS(reg))
 #define GCMPGDB(reg)                   REGP(_gcmp_base, GCMPGDBOFS(reg))
 #define  GCMP_GCB_GCMPB_GCMPBASE_MSK   GCMPGCBMSK(GCMPB_GCMPBASE, 17)
 #define  GCMP_GCB_GCMPB_CMDEFTGT_SHF   0
 #define  GCMP_GCB_GCMPB_CMDEFTGT_MSK   GCMPGCBMSK(GCMPB_CMDEFTGT, 2)
-#define  GCMP_GCB_GCMPB_CMDEFTGT_MEM   0
-#define  GCMP_GCB_GCMPB_CMDEFTGT_MEM1  1
-#define  GCMP_GCB_GCMPB_CMDEFTGT_IOCU1 2
-#define  GCMP_GCB_GCMPB_CMDEFTGT_IOCU2 3
+#define  GCMP_GCB_GCMPB_CMDEFTGT_DISABLED      0
+#define  GCMP_GCB_GCMPB_CMDEFTGT_MEM           1
+#define  GCMP_GCB_GCMPB_CMDEFTGT_IOCU1         2
+#define  GCMP_GCB_GCMPB_CMDEFTGT_IOCU2         3
 #define GCMP_GCB_CCMC_OFS              0x0010  /* Global CM Control */
 #define GCMP_GCB_GCSRAP_OFS            0x0020  /* Global CSR Access Privilege */
 #define  GCMP_GCB_GCSRAP_CMACCESS_SHF  0
 #define GCMP_CCB_DBGGROUP_OFS          0x0100          /* DebugBreak Group */
 
 extern int __init gcmp_probe(unsigned long, unsigned long);
-
+extern int __init gcmp_niocu(void);
+extern void __init gcmp_setregion(int, unsigned long, unsigned long, int);
 #endif /* _ASM_GCMPREGS_H */
index a8f5734..9b9436a 100644 (file)
@@ -12,7 +12,6 @@
 #define _ASM_GICREGS_H
 
 #undef GICISBYTELITTLEENDIAN
-#define GICISWORDLITTLEENDIAN
 
 /* Constants */
 #define GIC_POL_POS                    1
 #define GIC_TRIG_EDGE                  1
 #define GIC_TRIG_LEVEL                 0
 
-#ifdef CONFIG_SMP
 #define GIC_NUM_INTRS                  (24 + NR_CPUS * 2)
-#else
-#define GIC_NUM_INTRS                  32
-#endif
 
 #define MSK(n) ((1 << (n)) - 1)
 #define REG32(addr)            (*(volatile unsigned int *) (addr))
 #define USM_VISIBLE_SECTION_SIZE       0x10000
 
 /* Register Map for Shared Section */
-#if defined(CONFIG_CPU_LITTLE_ENDIAN) || defined(GICISWORDLITTLEENDIAN)
 
 #define        GIC_SH_CONFIG_OFS               0x0000
 
 /* Shared Global Counter */
 #define GIC_SH_COUNTER_31_00_OFS       0x0010
 #define GIC_SH_COUNTER_63_32_OFS       0x0014
+#define GIC_SH_REVISIONID_OFS          0x0020
 
 /* Interrupt Polarity */
 #define GIC_SH_POL_31_0_OFS            0x0100
        (GIC_SH_INTR_MAP_TO_VPE_BASE_OFS + (32 * (intr)) + (((vpe) / 32) * 4))
 #define GIC_SH_MAP_TO_VPE_REG_BIT(vpe) (1 << ((vpe) % 32))
 
+/* Convert an interrupt number to a byte offset/bit for multi-word registers */
+#define GIC_INTR_OFS(intr) (((intr) / 32)*4)
+#define GIC_INTR_BIT(intr) ((intr) % 32)
+
 /* Polarity : Reset Value is always 0 */
 #define GIC_SH_SET_POLARITY_OFS                0x0100
 #define GIC_SET_POLARITY(intr, pol) \
-       GICBIS(GIC_REG_ADDR(SHARED, GIC_SH_SET_POLARITY_OFS + (((intr) / 32) * 4)), (pol) << ((intr) % 32))
+       GICBIS(GIC_REG_ADDR(SHARED, GIC_SH_SET_POLARITY_OFS + \
+               GIC_INTR_OFS(intr)), (pol) << GIC_INTR_BIT(intr))
 
 /* Triggering : Reset Value is always 0 */
 #define GIC_SH_SET_TRIGGER_OFS         0x0180
 #define GIC_SET_TRIGGER(intr, trig) \
-       GICBIS(GIC_REG_ADDR(SHARED, GIC_SH_SET_TRIGGER_OFS + (((intr) / 32) * 4)), (trig) << ((intr) % 32))
+       GICBIS(GIC_REG_ADDR(SHARED, GIC_SH_SET_TRIGGER_OFS + \
+               GIC_INTR_OFS(intr)), (trig) << GIC_INTR_BIT(intr))
 
 /* Mask manipulation */
 #define GIC_SH_SMASK_OFS               0x0380
-#define GIC_SET_INTR_MASK(intr, val) \
-       GICWRITE(GIC_REG_ADDR(SHARED, GIC_SH_SMASK_OFS + (((intr) / 32) * 4)), ((val) << ((intr) % 32)))
-
+#define GIC_SET_INTR_MASK(intr) \
+       GICWRITE(GIC_REG_ADDR(SHARED, GIC_SH_SMASK_OFS + \
+               GIC_INTR_OFS(intr)), 1 << GIC_INTR_BIT(intr))
 #define GIC_SH_RMASK_OFS               0x0300
-#define GIC_CLR_INTR_MASK(intr, val) \
-       GICWRITE(GIC_REG_ADDR(SHARED, GIC_SH_RMASK_OFS + (((intr) / 32) * 4)), ((val) << ((intr) % 32)))
+#define GIC_CLR_INTR_MASK(intr) \
+       GICWRITE(GIC_REG_ADDR(SHARED, GIC_SH_RMASK_OFS + \
+               GIC_INTR_OFS(intr)), 1 << GIC_INTR_BIT(intr))
 
 /* Register Map for Local Section */
 #define GIC_VPE_CTL_OFS                        0x0000
 #define GIC_UMV_SH_COUNTER_31_00_OFS   0x0000
 #define GIC_UMV_SH_COUNTER_63_32_OFS   0x0004
 
-#else /* CONFIG_CPU_BIG_ENDIAN */
-
-#define        GIC_SH_CONFIG_OFS               0x0000
-
-/* Shared Global Counter */
-#define GIC_SH_COUNTER_31_00_OFS       0x0014
-#define GIC_SH_COUNTER_63_32_OFS       0x0010
-
-/* Interrupt Polarity */
-#define GIC_SH_POL_31_0_OFS            0x0104
-#define GIC_SH_POL_63_32_OFS           0x0100
-#define GIC_SH_POL_95_64_OFS           0x010c
-#define GIC_SH_POL_127_96_OFS          0x0108
-#define GIC_SH_POL_159_128_OFS         0x0114
-#define GIC_SH_POL_191_160_OFS         0x0110
-#define GIC_SH_POL_223_192_OFS         0x011c
-#define GIC_SH_POL_255_224_OFS         0x0118
-
-/* Edge/Level Triggering */
-#define GIC_SH_TRIG_31_0_OFS           0x0184
-#define GIC_SH_TRIG_63_32_OFS          0x0180
-#define GIC_SH_TRIG_95_64_OFS          0x018c
-#define GIC_SH_TRIG_127_96_OFS         0x0188
-#define GIC_SH_TRIG_159_128_OFS                0x0194
-#define GIC_SH_TRIG_191_160_OFS                0x0190
-#define GIC_SH_TRIG_223_192_OFS                0x019c
-#define GIC_SH_TRIG_255_224_OFS                0x0198
-
-/* Dual Edge Triggering */
-#define GIC_SH_DUAL_31_0_OFS           0x0204
-#define GIC_SH_DUAL_63_32_OFS          0x0200
-#define GIC_SH_DUAL_95_64_OFS          0x020c
-#define GIC_SH_DUAL_127_96_OFS         0x0208
-#define GIC_SH_DUAL_159_128_OFS                0x0214
-#define GIC_SH_DUAL_191_160_OFS                0x0210
-#define GIC_SH_DUAL_223_192_OFS                0x021c
-#define GIC_SH_DUAL_255_224_OFS                0x0218
-
-/* Set/Clear corresponding bit in Edge Detect Register */
-#define GIC_SH_WEDGE_OFS               0x0280
-
-/* Reset Mask - Disables Interrupt */
-#define GIC_SH_RMASK_31_0_OFS          0x0304
-#define GIC_SH_RMASK_63_32_OFS         0x0300
-#define GIC_SH_RMASK_95_64_OFS         0x030c
-#define GIC_SH_RMASK_127_96_OFS                0x0308
-#define GIC_SH_RMASK_159_128_OFS       0x0314
-#define GIC_SH_RMASK_191_160_OFS       0x0310
-#define GIC_SH_RMASK_223_192_OFS       0x031c
-#define GIC_SH_RMASK_255_224_OFS       0x0318
-
-/* Set Mask (WO) - Enables Interrupt */
-#define GIC_SH_SMASK_31_0_OFS          0x0384
-#define GIC_SH_SMASK_63_32_OFS         0x0380
-#define GIC_SH_SMASK_95_64_OFS         0x038c
-#define GIC_SH_SMASK_127_96_OFS                0x0388
-#define GIC_SH_SMASK_159_128_OFS       0x0394
-#define GIC_SH_SMASK_191_160_OFS       0x0390
-#define GIC_SH_SMASK_223_192_OFS       0x039c
-#define GIC_SH_SMASK_255_224_OFS       0x0398
-
-/* Global Interrupt Mask Register (RO) - Bit Set == Interrupt enabled */
-#define GIC_SH_MASK_31_0_OFS           0x0404
-#define GIC_SH_MASK_63_32_OFS          0x0400
-#define GIC_SH_MASK_95_64_OFS          0x040c
-#define GIC_SH_MASK_127_96_OFS         0x0408
-#define GIC_SH_MASK_159_128_OFS                0x0414
-#define GIC_SH_MASK_191_160_OFS                0x0410
-#define GIC_SH_MASK_223_192_OFS                0x041c
-#define GIC_SH_MASK_255_224_OFS                0x0418
-
-/* Pending Global Interrupts (RO) */
-#define GIC_SH_PEND_31_0_OFS           0x0484
-#define GIC_SH_PEND_63_32_OFS          0x0480
-#define GIC_SH_PEND_95_64_OFS          0x048c
-#define GIC_SH_PEND_127_96_OFS         0x0488
-#define GIC_SH_PEND_159_128_OFS                0x0494
-#define GIC_SH_PEND_191_160_OFS                0x0490
-#define GIC_SH_PEND_223_192_OFS                0x049c
-#define GIC_SH_PEND_255_224_OFS                0x0498
-
-#define GIC_SH_INTR_MAP_TO_PIN_BASE_OFS        0x0500
-
-/* Maps Interrupt X to a Pin */
-#define GIC_SH_MAP_TO_PIN(intr) \
-       (GIC_SH_INTR_MAP_TO_PIN_BASE_OFS + (4 * intr))
-
-#define GIC_SH_INTR_MAP_TO_VPE_BASE_OFS        0x2004
-
-/*
- * Maps Interrupt X to a VPE.  This is more complex than the LE case, as
- * odd and even registers need to be transposed.  It does work - trust me!
- */
-#define GIC_SH_MAP_TO_VPE_REG_OFF(intr, vpe) \
-       (GIC_SH_INTR_MAP_TO_VPE_BASE_OFS + (32 * (intr)) + \
-       (((((vpe) / 32) ^ 1) - 1) * 4))
-#define GIC_SH_MAP_TO_VPE_REG_BIT(vpe) (1 << ((vpe) % 32))
-
-/* Polarity */
-#define GIC_SH_SET_POLARITY_OFS                0x0100
-#define GIC_SET_POLARITY(intr, pol) \
-       GICBIS(GIC_REG_ADDR(SHARED, GIC_SH_SET_POLARITY_OFS + 4 + (((((intr) / 32) ^ 1) - 1) * 4)), (pol) << ((intr) % 32))
-
-/* Triggering */
-#define GIC_SH_SET_TRIGGER_OFS         0x0180
-#define GIC_SET_TRIGGER(intr, trig) \
-       GICBIS(GIC_REG_ADDR(SHARED, GIC_SH_SET_TRIGGER_OFS + 4 + (((((intr) / 32) ^ 1) - 1) * 4)), (trig) << ((intr) % 32))
-
-/* Mask manipulation */
-#define GIC_SH_SMASK_OFS               0x0380
-#define GIC_SET_INTR_MASK(intr, val) \
-       GICWRITE(GIC_REG_ADDR(SHARED, GIC_SH_SMASK_OFS + 4 + (((((intr) / 32) ^ 1) - 1) * 4)), ((val) << ((intr) % 32)))
-
-#define GIC_SH_RMASK_OFS               0x0300
-#define GIC_CLR_INTR_MASK(intr, val) \
-       GICWRITE(GIC_REG_ADDR(SHARED, GIC_SH_RMASK_OFS + 4 + (((((intr) / 32) ^ 1) - 1) * 4)), ((val) << ((intr) % 32)))
-
-/* Register Map for Local Section */
-#define GIC_VPE_CTL_OFS                        0x0000
-#define GIC_VPE_PEND_OFS               0x0004
-#define GIC_VPE_MASK_OFS               0x0008
-#define GIC_VPE_RMASK_OFS              0x000c
-#define GIC_VPE_SMASK_OFS              0x0010
-#define GIC_VPE_WD_MAP_OFS             0x0040
-#define GIC_VPE_COMPARE_MAP_OFS                0x0044
-#define GIC_VPE_TIMER_MAP_OFS          0x0048
-#define GIC_VPE_PERFCTR_MAP_OFS                0x0050
-#define GIC_VPE_SWINT0_MAP_OFS         0x0054
-#define GIC_VPE_SWINT1_MAP_OFS         0x0058
-#define GIC_VPE_OTHER_ADDR_OFS         0x0080
-#define GIC_VPE_WD_CONFIG0_OFS         0x0090
-#define GIC_VPE_WD_COUNT0_OFS          0x0094
-#define GIC_VPE_WD_INITIAL0_OFS                0x0098
-#define GIC_VPE_COMPARE_LO_OFS         0x00a4
-#define GIC_VPE_COMPARE_HI_OFS         0x00a0
-
-#define GIC_VPE_EIC_SHADOW_SET_BASE    0x0100
-#define GIC_VPE_EIC_SS(intr) \
-       (GIC_EIC_SHADOW_SET_BASE + (4 * intr))
-
-#define GIC_VPE_EIC_VEC_BASE           0x0800
-#define GIC_VPE_EIC_VEC(intr) \
-       (GIC_VPE_EIC_VEC_BASE + (4 * intr))
-
-#define GIC_VPE_TENABLE_NMI_OFS                0x1000
-#define GIC_VPE_TENABLE_YQ_OFS         0x1004
-#define GIC_VPE_TENABLE_INT_31_0_OFS   0x1080
-#define GIC_VPE_TENABLE_INT_63_32_OFS  0x1084
-
-/* User Mode Visible Section Register Map */
-#define GIC_UMV_SH_COUNTER_31_00_OFS   0x0004
-#define GIC_UMV_SH_COUNTER_63_32_OFS   0x0000
-
-#endif /* !LE */
-
 /* Masks */
 #define GIC_SH_CONFIG_COUNTSTOP_SHF    28
 #define GIC_SH_CONFIG_COUNTSTOP_MSK    (MSK(1) << GIC_SH_CONFIG_COUNTSTOP_SHF)
@@ -473,12 +320,13 @@ struct gic_intrmask_regs {
  * in building ipi_map.
  */
 struct gic_intr_map {
-       unsigned int intrnum;   /* Ext Intr Num         */
        unsigned int cpunum;    /* Directed to this CPU */
        unsigned int pin;       /* Directed to this Pin */
        unsigned int polarity;  /* Polarity : +/-       */
        unsigned int trigtype;  /* Trigger  : Edge/Levl */
-       unsigned int ipiflag;   /* Is used for IPI ?    */
+       unsigned int flags;     /* Misc flags   */
+#define GIC_FLAG_IPI           0x01
+#define GIC_FLAG_TRANSPARENT   0x02
 };
 
 extern void gic_init(unsigned long gic_base_addr,
index de71694..21cbbc7 100644 (file)
@@ -78,6 +78,9 @@
 #define AR7_REF_CLOCK  25000000
 #define AR7_XTAL_CLOCK 24000000
 
+/* DCL */
+#define AR7_WDT_HW_ENA 0x10
+
 struct plat_cpmac_data {
        int reset_bit;
        int power_bit;
index feea001..91595fa 100644 (file)
@@ -104,6 +104,8 @@ static inline int au1100_gpio2_to_irq(int gpio)
 
        if ((gpio >= 8) && (gpio <= 15))
                return MAKE_IRQ(0, 29);         /* shared GPIO208_215 */
+
+       return -ENXIO;
 }
 
 #ifdef CONFIG_SOC_AU1100
diff --git a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_dev_uart.h b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_dev_uart.h
deleted file mode 100644 (file)
index bf348f5..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef BCM63XX_DEV_UART_H_
-#define BCM63XX_DEV_UART_H_
-
-int bcm63xx_uart_register(void);
-
-#endif /* BCM63XX_DEV_UART_H_ */
index f683742..09a59bc 100644 (file)
@@ -44,8 +44,8 @@ extern unsigned char __node_distances[MAX_COMPACT_NODES][MAX_COMPACT_NODES];
        .busy_factor            = 32,                   \
        .imbalance_pct          = 125,                  \
        .cache_nice_tries       = 1,                    \
-       .flags                  = SD_LOAD_BALANCE       \
-                               | SD_BALANCE_EXEC       \
+       .flags                  = SD_LOAD_BALANCE |     \
+                                 SD_BALANCE_EXEC,      \
        .last_balance           = jiffies,              \
        .balance_interval       = 1,                    \
        .nr_balance_failed      = 0,                    \
index ce5b6e2..9947e57 100644 (file)
@@ -29,7 +29,7 @@
 #define cpu_has_cache_cdex_p   0
 #define cpu_has_cache_cdex_s   0
 #define cpu_has_counter                1
-#define cpu_has_dc_aliases     1
+#define cpu_has_dc_aliases     (PAGE_SIZE < 0x4000)
 #define cpu_has_divec          0
 #define cpu_has_dsp            0
 #define cpu_has_ejtag          0
@@ -54,6 +54,5 @@
 #define cpu_has_vce            0
 #define cpu_has_vtag_icache    0
 #define cpu_has_watch          1
-#define cpu_icache_snoops_remote_store 1
 
 #endif /* __ASM_MACH_LOONGSON_CPU_FEATURE_OVERRIDES_H */
index d974353..6083db5 100644 (file)
@@ -16,6 +16,7 @@
 #include <linux/smp.h>
 #include <linux/slab.h>
 #include <asm/cacheflush.h>
+#include <asm/hazards.h>
 #include <asm/tlbflush.h>
 #ifdef CONFIG_MIPS_MT_SMTC
 #include <asm/mipsmtregs.h>
@@ -36,11 +37,13 @@ extern unsigned long pgd_current[];
 #ifdef CONFIG_32BIT
 #define TLBMISS_HANDLER_SETUP()                                                \
        write_c0_context((unsigned long) smp_processor_id() << 25);     \
+       back_to_back_c0_hazard();                                       \
        TLBMISS_HANDLER_SETUP_PGD(swapper_pg_dir)
 #endif
 #ifdef CONFIG_64BIT
 #define TLBMISS_HANDLER_SETUP()                                                \
        write_c0_context((unsigned long) smp_processor_id() << 26);     \
+       back_to_back_c0_hazard();                                       \
        TLBMISS_HANDLER_SETUP_PGD(swapper_pg_dir)
 #endif
 
@@ -165,12 +168,12 @@ static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next,
         * having ASID_MASK smaller than the hardware maximum,
         * make sure no "soft" bits become "hard"...
         */
-       write_c0_entryhi((read_c0_entryhi() & ~HW_ASID_MASK)
-                       | (cpu_context(cpu, next) & ASID_MASK));
+       write_c0_entryhi((read_c0_entryhi() & ~HW_ASID_MASK) |
+                        cpu_asid(cpu, next));
        ehb(); /* Make sure it propagates to TCStatus */
        evpe(mtflags);
 #else
-       write_c0_entryhi(cpu_context(cpu, next));
+       write_c0_entryhi(cpu_asid(cpu, next));
 #endif /* CONFIG_MIPS_MT_SMTC */
        TLBMISS_HANDLER_SETUP_PGD(next->pgd);
 
@@ -226,11 +229,11 @@ activate_mm(struct mm_struct *prev, struct mm_struct *next)
        }
        /* See comments for similar code above */
        write_c0_entryhi((read_c0_entryhi() & ~HW_ASID_MASK) |
-                        (cpu_context(cpu, next) & ASID_MASK));
+                        cpu_asid(cpu, next));
        ehb(); /* Make sure it propagates to TCStatus */
        evpe(mtflags);
 #else
-       write_c0_entryhi(cpu_context(cpu, next));
+       write_c0_entryhi(cpu_asid(cpu, next));
 #endif /* CONFIG_MIPS_MT_SMTC */
        TLBMISS_HANDLER_SETUP_PGD(next->pgd);
 
index e600ced..50511aa 100644 (file)
@@ -1,7 +1,7 @@
 #ifndef _MIPS_SETUP_H
 #define _MIPS_SETUP_H
 
-#define COMMAND_LINE_SIZE      256
+#define COMMAND_LINE_SIZE      4096
 
 #ifdef  __KERNEL__
 extern void setup_early_printk(void);
index 8ce5175..15278db 100644 (file)
@@ -45,6 +45,7 @@ struct smtc_ipi_q {
        spinlock_t lock;
        struct smtc_ipi *tail;
        int depth;
+       int resched_flag;       /* reschedule already queued */
 };
 
 static inline void smtc_ipi_nq(struct smtc_ipi_q *q, struct smtc_ipi *p)
diff --git a/arch/mips/include/asm/spram.h b/arch/mips/include/asm/spram.h
new file mode 100644 (file)
index 0000000..0b89006
--- /dev/null
@@ -0,0 +1,10 @@
+#ifndef _MIPS_SPRAM_H
+#define _MIPS_SPRAM_H
+
+#ifdef CONFIG_CPU_MIPSR2
+extern __init void spram_config(void);
+#else
+static inline void spram_config(void) { };
+#endif /* CONFIG_CPU_MIPSR2 */
+
+#endif /* _MIPS_SPRAM_H */
index 01cc163..845da21 100644 (file)
@@ -86,14 +86,7 @@ register struct thread_info *__current_thread_info __asm__("$28");
 #define __HAVE_ARCH_THREAD_INFO_ALLOCATOR
 
 #ifdef CONFIG_DEBUG_STACK_USAGE
-#define alloc_thread_info(tsk)                                 \
-({                                                             \
-       struct thread_info *ret;                                \
-                                                               \
-       ret = kzalloc(THREAD_SIZE, GFP_KERNEL);                 \
-                                                               \
-       ret;                                                    \
-})
+#define alloc_thread_info(tsk) kzalloc(THREAD_SIZE, GFP_KERNEL)
 #else
 #define alloc_thread_info(tsk) kmalloc(THREAD_SIZE, GFP_KERNEL)
 #endif
index 7fd170d..7bd32d0 100644 (file)
@@ -134,7 +134,7 @@ static irqreturn_t r4030_timer_interrupt(int irq, void *dev_id)
 
 static struct irqaction r4030_timer_irqaction = {
        .handler        = r4030_timer_interrupt,
-       .flags          = IRQF_DISABLED,
+       .flags          = IRQF_DISABLED | IRQF_TIMER,
        .name           = "R4030 timer",
 };
 
index e02f79b..bfea327 100644 (file)
@@ -144,7 +144,7 @@ void __cpuinit sb1480_clockevent_init(void)
        bcm1480_unmask_irq(cpu, irq);
 
        action->handler = sibyte_counter_handler;
-       action->flags   = IRQF_DISABLED | IRQF_PERCPU;
+       action->flags   = IRQF_DISABLED | IRQF_PERCPU | IRQF_TIMER;
        action->name    = name;
        action->dev_id  = cd;
 
index 6996da4..00a4da2 100644 (file)
@@ -107,7 +107,7 @@ static irqreturn_t ds1287_interrupt(int irq, void *dev_id)
 
 static struct irqaction ds1287_irqaction = {
        .handler        = ds1287_interrupt,
-       .flags          = IRQF_DISABLED | IRQF_PERCPU,
+       .flags          = IRQF_DISABLED | IRQF_PERCPU | IRQF_TIMER,
        .name           = "ds1287",
 };
 
index 92351e0..f5d265e 100644 (file)
@@ -113,7 +113,7 @@ static irqreturn_t gt641xx_timer0_interrupt(int irq, void *dev_id)
 
 static struct irqaction gt641xx_timer0_irqaction = {
        .handler        = gt641xx_timer0_interrupt,
-       .flags          = IRQF_DISABLED | IRQF_PERCPU,
+       .flags          = IRQF_DISABLED | IRQF_PERCPU | IRQF_TIMER,
        .name           = "gt641xx_timer0",
 };
 
index 2652362..b469ad0 100644 (file)
@@ -83,7 +83,7 @@ out:
 
 struct irqaction c0_compare_irqaction = {
        .handler = c0_compare_interrupt,
-       .flags = IRQF_DISABLED | IRQF_PERCPU,
+       .flags = IRQF_DISABLED | IRQF_PERCPU | IRQF_TIMER,
        .name = "timer",
 };
 
index ac5903d..da78eea 100644 (file)
@@ -143,7 +143,7 @@ void __cpuinit sb1250_clockevent_init(void)
        sb1250_unmask_irq(cpu, irq);
 
        action->handler = sibyte_counter_handler;
-       action->flags   = IRQF_DISABLED | IRQF_PERCPU;
+       action->flags   = IRQF_DISABLED | IRQF_PERCPU | IRQF_TIMER;
        action->name    = name;
        action->dev_id  = cd;
 
index 0037f21..218ee6b 100644 (file)
@@ -146,7 +146,7 @@ static irqreturn_t txx9tmr_interrupt(int irq, void *dev_id)
 
 static struct irqaction txx9tmr_irq = {
        .handler        = txx9tmr_interrupt,
-       .flags          = IRQF_DISABLED | IRQF_PERCPU,
+       .flags          = IRQF_DISABLED | IRQF_PERCPU | IRQF_TIMER,
        .name           = "txx9tmr",
        .dev_id         = &txx9_clock_event_device,
 };
index f709657..7a51866 100644 (file)
@@ -23,7 +23,7 @@
 #include <asm/mipsregs.h>
 #include <asm/system.h>
 #include <asm/watch.h>
-
+#include <asm/spram.h>
 /*
  * Not all of the MIPS CPUs have the "wait" instruction available. Moreover,
  * the implementation of the "wait" feature differs between CPU families. This
@@ -711,12 +711,6 @@ static void __cpuinit decode_configs(struct cpuinfo_mips *c)
        mips_probe_watch_registers(c);
 }
 
-#ifdef CONFIG_CPU_MIPSR2
-extern void spram_config(void);
-#else
-static inline void spram_config(void) {}
-#endif
-
 static inline void cpu_probe_mips(struct cpuinfo_mips *c, unsigned int cpu)
 {
        decode_configs(c);
index 531ce7b..ea695d9 100644 (file)
@@ -191,6 +191,7 @@ NESTED(kernel_entry, 16, sp)                        # kernel entry point
        /* Set the SP after an empty pt_regs.  */
        PTR_LI          sp, _THREAD_SIZE - 32 - PT_SIZE
        PTR_ADDU        sp, $28
+       back_to_back_c0_hazard
        set_saved_sp    sp, t0, t1
        PTR_SUBU        sp, 4 * SZREG           # init stack pointer
 
index f7d8d5d..ed5c441 100644 (file)
@@ -98,7 +98,7 @@ static irqreturn_t timer_interrupt(int irq, void *dev_id)
 
 static struct irqaction irq0  = {
        .handler = timer_interrupt,
-       .flags = IRQF_DISABLED | IRQF_NOBALANCING,
+       .flags = IRQF_DISABLED | IRQF_NOBALANCING | IRQF_TIMER,
        .name = "timer"
 };
 
index d2072cd..b181f2f 100644 (file)
 
 
 static unsigned long _gic_base;
-static unsigned int _irqbase, _mapsize, numvpes, numintrs;
-static struct gic_intr_map *_intrmap;
+static unsigned int _irqbase;
+static unsigned int gic_irq_flags[GIC_NUM_INTRS];
+#define GIC_IRQ_FLAG_EDGE      0x0001
 
-static struct gic_pcpu_mask pcpu_masks[NR_CPUS];
+struct gic_pcpu_mask pcpu_masks[NR_CPUS];
 static struct gic_pending_regs pending_regs[NR_CPUS];
 static struct gic_intrmask_regs intrmask_regs[NR_CPUS];
 
-#define gic_wedgeb2bok 0       /*
-                                * Can GIC handle b2b writes to wedge register?
-                                */
-#if gic_wedgeb2bok == 0
-static DEFINE_SPINLOCK(gic_wedgeb2b_lock);
-#endif
-
 void gic_send_ipi(unsigned int intr)
 {
-#if gic_wedgeb2bok == 0
-       unsigned long flags;
-#endif
        pr_debug("CPU%d: %s status %08x\n", smp_processor_id(), __func__,
                 read_c0_status());
-       if (!gic_wedgeb2bok)
-               spin_lock_irqsave(&gic_wedgeb2b_lock, flags);
        GICWRITE(GIC_REG(SHARED, GIC_SH_WEDGE), 0x80000000 | intr);
-       if (!gic_wedgeb2bok) {
-               (void) GIC_REG(SHARED, GIC_SH_CONFIG);
-               spin_unlock_irqrestore(&gic_wedgeb2b_lock, flags);
-       }
 }
 
 /* This is Malta specific and needs to be exported */
-static void vpe_local_setup(unsigned int numvpes)
+static void __init vpe_local_setup(unsigned int numvpes)
 {
        int i;
        unsigned long timer_interrupt = 5, perf_interrupt = 5;
@@ -105,44 +90,34 @@ unsigned int gic_get_int(void)
 
 static unsigned int gic_irq_startup(unsigned int irq)
 {
-       pr_debug("CPU%d: %s: irq%d\n", smp_processor_id(), __func__, irq);
        irq -= _irqbase;
-       GIC_SET_INTR_MASK(irq, 1);
+       pr_debug("CPU%d: %s: irq%d\n", smp_processor_id(), __func__, irq);
+       GIC_SET_INTR_MASK(irq);
        return 0;
 }
 
 static void gic_irq_ack(unsigned int irq)
 {
-#if gic_wedgeb2bok == 0
-       unsigned long flags;
-#endif
-       pr_debug("CPU%d: %s: irq%d\n", smp_processor_id(), __func__, irq);
        irq -= _irqbase;
-       GIC_CLR_INTR_MASK(irq, 1);
+       pr_debug("CPU%d: %s: irq%d\n", smp_processor_id(), __func__, irq);
+       GIC_CLR_INTR_MASK(irq);
 
-       if (_intrmap[irq].trigtype == GIC_TRIG_EDGE) {
-               if (!gic_wedgeb2bok)
-                       spin_lock_irqsave(&gic_wedgeb2b_lock, flags);
+       if (gic_irq_flags[irq] & GIC_IRQ_FLAG_EDGE)
                GICWRITE(GIC_REG(SHARED, GIC_SH_WEDGE), irq);
-               if (!gic_wedgeb2bok) {
-                       (void) GIC_REG(SHARED, GIC_SH_CONFIG);
-                       spin_unlock_irqrestore(&gic_wedgeb2b_lock, flags);
-               }
-       }
 }
 
 static void gic_mask_irq(unsigned int irq)
 {
-       pr_debug("CPU%d: %s: irq%d\n", smp_processor_id(), __func__, irq);
        irq -= _irqbase;
-       GIC_CLR_INTR_MASK(irq, 1);
+       pr_debug("CPU%d: %s: irq%d\n", smp_processor_id(), __func__, irq);
+       GIC_CLR_INTR_MASK(irq);
 }
 
 static void gic_unmask_irq(unsigned int irq)
 {
-       pr_debug("CPU%d: %s: irq%d\n", smp_processor_id(), __func__, irq);
        irq -= _irqbase;
-       GIC_SET_INTR_MASK(irq, 1);
+       pr_debug("CPU%d: %s: irq%d\n", smp_processor_id(), __func__, irq);
+       GIC_SET_INTR_MASK(irq);
 }
 
 #ifdef CONFIG_SMP
@@ -155,9 +130,8 @@ static int gic_set_affinity(unsigned int irq, const struct cpumask *cpumask)
        unsigned long   flags;
        int             i;
 
-       pr_debug(KERN_DEBUG "%s called\n", __func__);
        irq -= _irqbase;
-
+       pr_debug(KERN_DEBUG "%s(%d) called\n", __func__, irq);
        cpumask_and(&tmp, cpumask, cpu_online_mask);
        if (cpus_empty(tmp))
                return -1;
@@ -168,13 +142,6 @@ static int gic_set_affinity(unsigned int irq, const struct cpumask *cpumask)
                /* Re-route this IRQ */
                GIC_SH_MAP_TO_VPE_SMASK(irq, first_cpu(tmp));
 
-               /*
-                * FIXME: assumption that _intrmap is ordered and has no holes
-                */
-
-               /* Update the intr_map */
-               _intrmap[irq].cpunum = first_cpu(tmp);
-
                /* Update the pcpu_masks */
                for (i = 0; i < NR_CPUS; i++)
                        clear_bit(irq, pcpu_masks[i].pcpu_mask);
@@ -201,8 +168,9 @@ static struct irq_chip gic_irq_controller = {
 #endif
 };
 
-static void __init setup_intr(unsigned int intr, unsigned int cpu,
-       unsigned int pin, unsigned int polarity, unsigned int trigtype)
+static void __init gic_setup_intr(unsigned int intr, unsigned int cpu,
+       unsigned int pin, unsigned int polarity, unsigned int trigtype,
+       unsigned int flags)
 {
        /* Setup Intr to Pin mapping */
        if (pin & GIC_MAP_TO_NMI_MSK) {
@@ -227,38 +195,43 @@ static void __init setup_intr(unsigned int intr, unsigned int cpu,
        GIC_SET_TRIGGER(intr, trigtype);
 
        /* Init Intr Masks */
-       GIC_SET_INTR_MASK(intr, 0);
+       GIC_CLR_INTR_MASK(intr);
+       /* Initialise per-cpu Interrupt software masks */
+       if (flags & GIC_FLAG_IPI)
+               set_bit(intr, pcpu_masks[cpu].pcpu_mask);
+       if (flags & GIC_FLAG_TRANSPARENT)
+               GIC_SET_INTR_MASK(intr);
+       if (trigtype == GIC_TRIG_EDGE)
+               gic_irq_flags[intr] |= GIC_IRQ_FLAG_EDGE;
 }
 
-static void __init gic_basic_init(void)
+static void __init gic_basic_init(int numintrs, int numvpes,
+                       struct gic_intr_map *intrmap, int mapsize)
 {
        unsigned int i, cpu;
 
        /* Setup defaults */
-       for (i = 0; i < GIC_NUM_INTRS; i++) {
+       for (i = 0; i < numintrs; i++) {
                GIC_SET_POLARITY(i, GIC_POL_POS);
                GIC_SET_TRIGGER(i, GIC_TRIG_LEVEL);
-               GIC_SET_INTR_MASK(i, 0);
+               GIC_CLR_INTR_MASK(i);
+               if (i < GIC_NUM_INTRS)
+                       gic_irq_flags[i] = 0;
        }
 
        /* Setup specifics */
-       for (i = 0; i < _mapsize; i++) {
-               cpu = _intrmap[i].cpunum;
+       for (i = 0; i < mapsize; i++) {
+               cpu = intrmap[i].cpunum;
                if (cpu == X)
                        continue;
-
-               if (cpu == 0 && i != 0 && _intrmap[i].intrnum == 0 &&
-                                       _intrmap[i].ipiflag == 0)
+               if (cpu == 0 && i != 0 && intrmap[i].flags == 0)
                        continue;
-
-               setup_intr(_intrmap[i].intrnum,
-                               _intrmap[i].cpunum,
-                               _intrmap[i].pin,
-                               _intrmap[i].polarity,
-                               _intrmap[i].trigtype);
-               /* Initialise per-cpu Interrupt software masks */
-               if (_intrmap[i].ipiflag)
-                       set_bit(_intrmap[i].intrnum, pcpu_masks[cpu].pcpu_mask);
+               gic_setup_intr(i,
+                       intrmap[i].cpunum,
+                       intrmap[i].pin,
+                       intrmap[i].polarity,
+                       intrmap[i].trigtype,
+                       intrmap[i].flags);
        }
 
        vpe_local_setup(numvpes);
@@ -273,12 +246,11 @@ void __init gic_init(unsigned long gic_base_addr,
                     unsigned int irqbase)
 {
        unsigned int gicconfig;
+       int numvpes, numintrs;
 
        _gic_base = (unsigned long) ioremap_nocache(gic_base_addr,
                                                    gic_addrspace_size);
        _irqbase = irqbase;
-       _intrmap = intr_map;
-       _mapsize = intr_map_size;
 
        GICREAD(GIC_REG(SHARED, GIC_SH_CONFIG), gicconfig);
        numintrs = (gicconfig & GIC_SH_CONFIG_NUMINTRS_MSK) >>
@@ -290,5 +262,5 @@ void __init gic_init(unsigned long gic_base_addr,
 
        pr_debug("%s called\n", __func__);
 
-       gic_basic_init();
+       gic_basic_init(numintrs, numvpes, intr_map, intr_map_size);
 }
index 6242bc6..b77fefa 100644 (file)
@@ -428,3 +428,9 @@ _sys32_clone(nabi_no_regargs struct pt_regs regs)
        return do_fork(clone_flags, newsp, &regs, 0,
                       parent_tidptr, child_tidptr);
 }
+
+asmlinkage long sys32_lookup_dcookie(u32 a0, u32 a1, char __user *buf,
+       size_t len)
+{
+       return sys_lookup_dcookie(merge_64(a0, a1), buf, len);
+}
index 9bbf977..14dde4c 100644 (file)
@@ -450,7 +450,7 @@ sys_call_table:
        PTR     sys_io_submit
        PTR     sys_io_cancel                   /* 4245 */
        PTR     sys_exit_group
-       PTR     sys_lookup_dcookie
+       PTR     sys32_lookup_dcookie
        PTR     sys_epoll_create
        PTR     sys_epoll_ctl
        PTR     sys_epoll_wait                  /* 4250 */
@@ -505,7 +505,7 @@ sys_call_table:
        PTR     sys_fchmodat
        PTR     sys_faccessat                   /* 4300 */
        PTR     compat_sys_pselect6
-       PTR     sys_ppoll
+       PTR     compat_sys_ppoll
        PTR     sys_unshare
        PTR     sys_splice
        PTR     sys32_sync_file_range           /* 4305 */
index 4d181df..24630fd 100644 (file)
@@ -75,7 +75,6 @@ unsigned long irq_hwmask[NR_IRQS];
 
 asiduse smtc_live_asid[MAX_SMTC_TLBS][MAX_SMTC_ASIDS];
 
-
 /*
  * Number of InterProcessor Interrupt (IPI) message buffers to allocate
  */
@@ -388,6 +387,7 @@ void smtc_prepare_cpus(int cpus)
                IPIQ[i].head = IPIQ[i].tail = NULL;
                spin_lock_init(&IPIQ[i].lock);
                IPIQ[i].depth = 0;
+               IPIQ[i].resched_flag = 0; /* No reschedules queued initially */
        }
 
        /* cpu_data index starts at zero */
@@ -741,11 +741,24 @@ void smtc_forward_irq(unsigned int irq)
 static void smtc_ipi_qdump(void)
 {
        int i;
+       struct smtc_ipi *temp;
 
        for (i = 0; i < NR_CPUS ;i++) {
-               printk("IPIQ[%d]: head = 0x%x, tail = 0x%x, depth = %d\n",
+               pr_info("IPIQ[%d]: head = 0x%x, tail = 0x%x, depth = %d\n",
                        i, (unsigned)IPIQ[i].head, (unsigned)IPIQ[i].tail,
                        IPIQ[i].depth);
+               temp = IPIQ[i].head;
+
+               while (temp != IPIQ[i].tail) {
+                       pr_debug("%d %d %d: ", temp->type, temp->dest,
+                              (int)temp->arg);
+#ifdef SMTC_IPI_DEBUG
+                   pr_debug("%u %lu\n", temp->sender, temp->stamp);
+#else
+                   pr_debug("\n");
+#endif
+                   temp = temp->flink;
+               }
        }
 }
 
@@ -784,11 +797,16 @@ void smtc_send_ipi(int cpu, int type, unsigned int action)
        int mtflags;
        unsigned long tcrestart;
        extern void r4k_wait_irqoff(void), __pastwait(void);
+       int set_resched_flag = (type == LINUX_SMP_IPI &&
+                               action == SMP_RESCHEDULE_YOURSELF);
 
        if (cpu == smp_processor_id()) {
                printk("Cannot Send IPI to self!\n");
                return;
        }
+       if (set_resched_flag && IPIQ[cpu].resched_flag != 0)
+               return; /* There is a reschedule queued already */
+
        /* Set up a descriptor, to be delivered either promptly or queued */
        pipi = smtc_ipi_dq(&freeIPIq);
        if (pipi == NULL) {
@@ -801,6 +819,7 @@ void smtc_send_ipi(int cpu, int type, unsigned int action)
        pipi->dest = cpu;
        if (cpu_data[cpu].vpe_id != cpu_data[smp_processor_id()].vpe_id) {
                /* If not on same VPE, enqueue and send cross-VPE interrupt */
+               IPIQ[cpu].resched_flag |= set_resched_flag;
                smtc_ipi_nq(&IPIQ[cpu], pipi);
                LOCK_CORE_PRA();
                settc(cpu_data[cpu].tc_id);
@@ -847,6 +866,7 @@ void smtc_send_ipi(int cpu, int type, unsigned int action)
                         */
                        write_tc_c0_tchalt(0);
                        UNLOCK_CORE_PRA();
+                       IPIQ[cpu].resched_flag |= set_resched_flag;
                        smtc_ipi_nq(&IPIQ[cpu], pipi);
                } else {
 postdirect:
@@ -996,12 +1016,15 @@ void deferred_smtc_ipi(void)
                 * already enabled.
                 */
                local_irq_save(flags);
-
                spin_lock(&q->lock);
                pipi = __smtc_ipi_dq(q);
                spin_unlock(&q->lock);
-               if (pipi != NULL)
+               if (pipi != NULL) {
+                       if (pipi->type == LINUX_SMP_IPI &&
+                           (int)pipi->arg == SMP_RESCHEDULE_YOURSELF)
+                               IPIQ[cpu].resched_flag = 0;
                        ipi_decode(pipi);
+               }
                /*
                 * The use of the __raw_local restore isn't
                 * as obviously necessary here as in smtc_ipi_replay(),
@@ -1082,6 +1105,9 @@ static irqreturn_t ipi_interrupt(int irq, void *dev_idm)
                                 * with interrupts off
                                 */
                                local_irq_save(flags);
+                               if (pipi->type == LINUX_SMP_IPI &&
+                                   (int)pipi->arg == SMP_RESCHEDULE_YOURSELF)
+                                       IPIQ[cpu].resched_flag = 0;
                                ipi_decode(pipi);
                                local_irq_restore(flags);
                        }
index 6ddb507..1821d12 100644 (file)
@@ -13,7 +13,6 @@
 #include <linux/ptrace.h>
 #include <linux/stddef.h>
 
-#include <asm/cpu.h>
 #include <asm/fpu.h>
 #include <asm/mipsregs.h>
 #include <asm/system.h>
@@ -198,8 +197,7 @@ static __cpuinit void probe_spram(char *type,
                offset += 2 * SPRAM_TAG_STRIDE;
        }
 }
-
-__cpuinit void spram_config(void)
+void __cpuinit spram_config(void)
 {
        struct cpuinfo_mips *c = &current_cpu_data;
        unsigned int config0;
@@ -208,6 +206,7 @@ __cpuinit void spram_config(void)
        case CPU_24K:
        case CPU_34K:
        case CPU_74K:
+       case CPU_1004K:
                config0 = read_c0_config();
                /* FIXME: addresses are Malta specific */
                if (config0 & (1<<24)) {
index 03092ab..6047752 100644 (file)
@@ -1116,8 +1116,6 @@ static int vpe_open(struct inode *inode, struct file *filp)
        v->shared_ptr = NULL;
        v->__start = 0;
 
-       unlock_kernel();
-
        return 0;
 }
 
index f368c73..b32b4a3 100644 (file)
@@ -55,7 +55,6 @@ void __init arch_init_irq(void)
         * int-handler is not on bootstrap
         */
        clear_c0_status(ST0_IM | ST0_BEV);
-       local_irq_disable();
 
        /* setting irq trigger mode */
        set_irq_trigger_mode();
index 1c555e6..d9ae1db 100644 (file)
@@ -62,8 +62,6 @@ ieee754dp ieee754dp_neg(ieee754dp x)
                return ieee754dp_nanxcpt(y, "neg");
        }
 
-       if (ieee754dp_isnan(x)) /* but not infinity */
-               return ieee754dp_nanxcpt(x, "neg", x);
        return x;
 }
 
@@ -76,15 +74,12 @@ ieee754dp ieee754dp_abs(ieee754dp x)
        CLEARCX;
        FLUSHXDP;
 
+       /* Clear sign ALWAYS, irrespective of NaN */
+       DPSIGN(x) = 0;
+
        if (xc == IEEE754_CLASS_SNAN) {
-               SETCX(IEEE754_INVALID_OPERATION);
-               return ieee754dp_nanxcpt(ieee754dp_indef(), "neg");
+               return ieee754dp_nanxcpt(ieee754dp_indef(), "abs");
        }
 
-       if (ieee754dp_isnan(x)) /* but not infinity */
-               return ieee754dp_nanxcpt(x, "abs", x);
-
-       /* quick fix up */
-       DPSIGN(x) = 0;
        return x;
 }
index 770f0f4..3175477 100644 (file)
@@ -62,8 +62,6 @@ ieee754sp ieee754sp_neg(ieee754sp x)
                return ieee754sp_nanxcpt(y, "neg");
        }
 
-       if (ieee754sp_isnan(x)) /* but not infinity */
-               return ieee754sp_nanxcpt(x, "neg", x);
        return x;
 }
 
@@ -76,15 +74,12 @@ ieee754sp ieee754sp_abs(ieee754sp x)
        CLEARCX;
        FLUSHXSP;
 
+       /* Clear sign ALWAYS, irrespective of NaN */
+       SPSIGN(x) = 0;
+
        if (xc == IEEE754_CLASS_SNAN) {
-               SETCX(IEEE754_INVALID_OPERATION);
                return ieee754sp_nanxcpt(ieee754sp_indef(), "abs");
        }
 
-       if (ieee754sp_isnan(x)) /* but not infinity */
-               return ieee754sp_nanxcpt(x, "abs", x);
-
-       /* quick fix up */
-       SPSIGN(x) = 0;
        return x;
 }
index 15aa190..8d1f4f3 100644 (file)
@@ -27,6 +27,7 @@
 #include <linux/swap.h>
 #include <linux/proc_fs.h>
 #include <linux/pfn.h>
+#include <linux/hardirq.h>
 
 #include <asm/asm-offsets.h>
 #include <asm/bootinfo.h>
@@ -132,7 +133,10 @@ void *kmap_coherent(struct page *page, unsigned long addr)
        inc_preempt_count();
        idx = (addr >> PAGE_SHIFT) & (FIX_N_COLOURS - 1);
 #ifdef CONFIG_MIPS_MT_SMTC
-       idx += FIX_N_COLOURS * smp_processor_id();
+       idx += FIX_N_COLOURS * smp_processor_id() +
+               (in_interrupt() ? (FIX_N_COLOURS * NR_CPUS) : 0);
+#else
+       idx += in_interrupt() ? FIX_N_COLOURS : 0;
 #endif
        vaddr = __fix_to_virt(FIX_CMAP_END - idx);
        pte = mk_pte(page, PAGE_KERNEL);
index df9e526..469d9b0 100644 (file)
@@ -70,11 +70,12 @@ void amon_cpu_start(int cpu,
        launch->sp = sp;
        launch->a0 = a0;
 
-       /* Make sure target sees parameters before the go bit */
-       smp_mb();
-
+       smp_wmb();              /* Target must see parameters before go */
        launch->flags |= LAUNCH_FGO;
+       smp_wmb();              /* Target must see go before we poll  */
+
        while ((launch->flags & LAUNCH_FGONE) == 0)
                ;
+       smp_rmb();      /* Target will be updating flags soon */
        pr_debug("launch: cpu%d gone!\n", cpu);
 }
index 3e0a9b3..4c3fca1 100644 (file)
@@ -87,7 +87,7 @@ static inline int mips_pcibios_iack(void)
                dummy = BONITO_PCIMAP_CFG;
                iob();    /* sync */
 
-               irq = readl((u32 *)_pcictrl_bonito_pcicfg);
+               irq = __raw_readl((u32 *)_pcictrl_bonito_pcicfg);
                iob();    /* sync */
                irq &= 0xff;
                BONITO_PCIMAP_CFG = 0;
@@ -379,38 +379,43 @@ static msc_irqmap_t __initdata msc_eicirqmap[] = {
 
 static int __initdata msc_nr_eicirqs = ARRAY_SIZE(msc_eicirqmap);
 
-#if defined(CONFIG_MIPS_MT_SMP)
 /*
  * This GIC specific tabular array defines the association between External
  * Interrupts and CPUs/Core Interrupts. The nature of the External
  * Interrupts is also defined here - polarity/trigger.
  */
+
+#define GIC_CPU_NMI GIC_MAP_TO_NMI_MSK
 static struct gic_intr_map gic_intr_map[GIC_NUM_INTRS] = {
-       { GIC_EXT_INTR(0),      X,      X,              X,              X,              0 },
-       { GIC_EXT_INTR(1),      X,      X,              X,              X,              0 },
-       { GIC_EXT_INTR(2),      X,      X,              X,              X,              0 },
-       { GIC_EXT_INTR(3),      0,      GIC_CPU_INT0,   GIC_POL_POS,    GIC_TRIG_LEVEL, 0 },
-       { GIC_EXT_INTR(4),      0,      GIC_CPU_INT1,   GIC_POL_POS,    GIC_TRIG_LEVEL, 0 },
-       { GIC_EXT_INTR(5),      0,      GIC_CPU_INT2,   GIC_POL_POS,    GIC_TRIG_LEVEL, 0 },
-       { GIC_EXT_INTR(6),      0,      GIC_CPU_INT3,   GIC_POL_POS,    GIC_TRIG_LEVEL, 0 },
-       { GIC_EXT_INTR(7),      0,      GIC_CPU_INT4,   GIC_POL_POS,    GIC_TRIG_LEVEL, 0 },
-       { GIC_EXT_INTR(8),      0,      GIC_CPU_INT3,   GIC_POL_POS,    GIC_TRIG_LEVEL, 0 },
-       { GIC_EXT_INTR(9),      0,      GIC_CPU_INT3,   GIC_POL_POS,    GIC_TRIG_LEVEL, 0 },
-       { GIC_EXT_INTR(10),     X,      X,              X,              X,              0 },
-       { GIC_EXT_INTR(11),     X,      X,              X,              X,              0 },
-       { GIC_EXT_INTR(12),     0,      GIC_CPU_INT3,   GIC_POL_POS,    GIC_TRIG_LEVEL, 0 },
-       { GIC_EXT_INTR(13),     0,      GIC_MAP_TO_NMI_MSK,     GIC_POL_POS, GIC_TRIG_LEVEL,    0 },
-       { GIC_EXT_INTR(14),     0,      GIC_MAP_TO_NMI_MSK,     GIC_POL_POS, GIC_TRIG_LEVEL,    0 },
-       { GIC_EXT_INTR(15),     X,      X,              X,              X,              0 },
-/* This is the end of the general interrupts now we do IPI ones */
+       { X, X,            X,           X,              0 },
+       { X, X,            X,           X,              0 },
+       { X, X,            X,           X,              0 },
+       { 0, GIC_CPU_INT0, GIC_POL_POS, GIC_TRIG_LEVEL, GIC_FLAG_TRANSPARENT },
+       { 0, GIC_CPU_INT1, GIC_POL_POS, GIC_TRIG_LEVEL, GIC_FLAG_TRANSPARENT },
+       { 0, GIC_CPU_INT2, GIC_POL_POS, GIC_TRIG_LEVEL, GIC_FLAG_TRANSPARENT },
+       { 0, GIC_CPU_INT3, GIC_POL_POS, GIC_TRIG_LEVEL, GIC_FLAG_TRANSPARENT },
+       { 0, GIC_CPU_INT4, GIC_POL_POS, GIC_TRIG_LEVEL, GIC_FLAG_TRANSPARENT },
+       { 0, GIC_CPU_INT3, GIC_POL_POS, GIC_TRIG_LEVEL, GIC_FLAG_TRANSPARENT },
+       { 0, GIC_CPU_INT3, GIC_POL_POS, GIC_TRIG_LEVEL, GIC_FLAG_TRANSPARENT },
+       { X, X,            X,           X,              0 },
+       { X, X,            X,           X,              0 },
+       { 0, GIC_CPU_INT3, GIC_POL_POS, GIC_TRIG_LEVEL, GIC_FLAG_TRANSPARENT },
+       { 0, GIC_CPU_NMI,  GIC_POL_POS, GIC_TRIG_LEVEL, GIC_FLAG_TRANSPARENT },
+       { 0, GIC_CPU_NMI,  GIC_POL_POS, GIC_TRIG_LEVEL, GIC_FLAG_TRANSPARENT },
+       { X, X,            X,           X,              0 },
+       /* The remainder of this table is initialised by fill_ipi_map */
 };
-#endif
 
 /*
  * GCMP needs to be detected before any SMP initialisation
  */
 int __init gcmp_probe(unsigned long addr, unsigned long size)
 {
+       if (mips_revision_sconid != MIPS_REVISION_SCON_ROCIT) {
+               gcmp_present = 0;
+               return gcmp_present;
+       }
+
        if (gcmp_present >= 0)
                return gcmp_present;
 
@@ -419,20 +424,35 @@ int __init gcmp_probe(unsigned long addr, unsigned long size)
        gcmp_present = (GCMPGCB(GCMPB) & GCMP_GCB_GCMPB_GCMPBASE_MSK) == GCMP_BASE_ADDR;
 
        if (gcmp_present)
-               printk(KERN_DEBUG "GCMP present\n");
+               pr_debug("GCMP present\n");
        return gcmp_present;
 }
 
+/* Return the number of IOCU's present */
+int __init gcmp_niocu(void)
+{
+  return gcmp_present ?
+    (GCMPGCB(GC) & GCMP_GCB_GC_NUMIOCU_MSK) >> GCMP_GCB_GC_NUMIOCU_SHF :
+    0;
+}
+
+/* Set GCMP region attributes */
+void __init gcmp_setregion(int region, unsigned long base,
+                          unsigned long mask, int type)
+{
+       GCMPGCBn(CMxBASE, region) = base;
+       GCMPGCBn(CMxMASK, region) = mask | type;
+}
+
 #if defined(CONFIG_MIPS_MT_SMP)
 static void __init fill_ipi_map1(int baseintr, int cpu, int cpupin)
 {
        int intr = baseintr + cpu;
-       gic_intr_map[intr].intrnum = GIC_EXT_INTR(intr);
        gic_intr_map[intr].cpunum = cpu;
        gic_intr_map[intr].pin = cpupin;
        gic_intr_map[intr].polarity = GIC_POL_POS;
        gic_intr_map[intr].trigtype = GIC_TRIG_EDGE;
-       gic_intr_map[intr].ipiflag = 1;
+       gic_intr_map[intr].flags = GIC_FLAG_IPI;
        ipi_map[cpu] |= (1 << (cpupin + 2));
 }
 
@@ -447,6 +467,12 @@ static void __init fill_ipi_map(void)
 }
 #endif
 
+void __init arch_init_ipiirq(int irq, struct irqaction *action)
+{
+       setup_irq(irq, action);
+       set_irq_handler(irq, handle_percpu_irq);
+}
+
 void __init arch_init_irq(void)
 {
        init_i8259_irqs();
@@ -458,12 +484,17 @@ void __init arch_init_irq(void)
                GCMPGCB(GICBA) = GIC_BASE_ADDR | GCMP_GCB_GICBA_EN_MSK;
                gic_present = 1;
        } else {
-               _msc01_biu_base = (unsigned long) ioremap_nocache(MSC01_BIU_REG_BASE, MSC01_BIU_ADDRSPACE_SZ);
-               gic_present = (REG(_msc01_biu_base, MSC01_SC_CFG) &
-               MSC01_SC_CFG_GICPRES_MSK) >> MSC01_SC_CFG_GICPRES_SHF;
+               if (mips_revision_sconid == MIPS_REVISION_SCON_ROCIT) {
+                       _msc01_biu_base = (unsigned long)
+                                       ioremap_nocache(MSC01_BIU_REG_BASE,
+                                               MSC01_BIU_ADDRSPACE_SZ);
+                       gic_present = (REG(_msc01_biu_base, MSC01_SC_CFG) &
+                                       MSC01_SC_CFG_GICPRES_MSK) >>
+                                       MSC01_SC_CFG_GICPRES_SHF;
+               }
        }
        if (gic_present)
-               printk(KERN_DEBUG "GIC present\n");
+               pr_debug("GIC present\n");
 
        switch (mips_revision_sconid) {
        case MIPS_REVISION_SCON_SOCIT:
@@ -526,16 +557,16 @@ void __init arch_init_irq(void)
                                                &corehi_irqaction);
        }
 
-#if defined(CONFIG_MIPS_MT_SMP)
        if (gic_present) {
                /* FIXME */
                int i;
-
+#if defined(CONFIG_MIPS_MT_SMP)
                gic_call_int_base = GIC_NUM_INTRS - NR_CPUS;
                gic_resched_int_base = gic_call_int_base - NR_CPUS;
-
                fill_ipi_map();
-               gic_init(GIC_BASE_ADDR, GIC_ADDRSPACE_SZ, gic_intr_map, ARRAY_SIZE(gic_intr_map), MIPS_GIC_IRQ_BASE);
+#endif
+               gic_init(GIC_BASE_ADDR, GIC_ADDRSPACE_SZ, gic_intr_map,
+                               ARRAY_SIZE(gic_intr_map), MIPS_GIC_IRQ_BASE);
                if (!gcmp_present) {
                        /* Enable the GIC */
                        i = REG(_msc01_biu_base, MSC01_SC_CFG);
@@ -543,7 +574,7 @@ void __init arch_init_irq(void)
                                (i | (0x1 << MSC01_SC_CFG_GICENA_SHF));
                        pr_debug("GIC Enabled\n");
                }
-
+#if defined(CONFIG_MIPS_MT_SMP)
                /* set up ipi interrupts */
                if (cpu_has_vint) {
                        set_vi_handler(MIPSCPU_INT_IPI0, malta_ipi_irqdispatch);
@@ -556,16 +587,14 @@ void __init arch_init_irq(void)
                write_c0_status(0x1100dc00);
                printk("CPU%d: status register frc %08x\n", smp_processor_id(), read_c0_status());
                for (i = 0; i < NR_CPUS; i++) {
-                       setup_irq(MIPS_GIC_IRQ_BASE +
-                                       GIC_RESCHED_INT(i), &irq_resched);
-                       setup_irq(MIPS_GIC_IRQ_BASE +
-                                       GIC_CALL_INT(i), &irq_call);
-                       set_irq_handler(MIPS_GIC_IRQ_BASE +
-                                       GIC_RESCHED_INT(i), handle_percpu_irq);
-                       set_irq_handler(MIPS_GIC_IRQ_BASE +
-                                       GIC_CALL_INT(i), handle_percpu_irq);
+                       arch_init_ipiirq(MIPS_GIC_IRQ_BASE +
+                                        GIC_RESCHED_INT(i), &irq_resched);
+                       arch_init_ipiirq(MIPS_GIC_IRQ_BASE +
+                                        GIC_CALL_INT(i), &irq_call);
                }
+#endif
        } else {
+#if defined(CONFIG_MIPS_MT_SMP)
                /* set up ipi interrupts */
                if (cpu_has_veic) {
                        set_vi_handler (MSC01E_INT_SW0, ipi_resched_dispatch);
@@ -580,14 +609,10 @@ void __init arch_init_irq(void)
                        cpu_ipi_resched_irq = MIPS_CPU_IRQ_BASE + MIPS_CPU_IPI_RESCHED_IRQ;
                        cpu_ipi_call_irq = MIPS_CPU_IRQ_BASE + MIPS_CPU_IPI_CALL_IRQ;
                }
-
-               setup_irq(cpu_ipi_resched_irq, &irq_resched);
-               setup_irq(cpu_ipi_call_irq, &irq_call);
-
-               set_irq_handler(cpu_ipi_resched_irq, handle_percpu_irq);
-               set_irq_handler(cpu_ipi_call_irq, handle_percpu_irq);
-       }
+               arch_init_ipiirq(cpu_ipi_resched_irq, &irq_resched);
+               arch_init_ipiirq(cpu_ipi_call_irq, &irq_call);
 #endif
+       }
 }
 
 void malta_be_init(void)
index b974319..2fbfa1a 100644 (file)
@@ -27,7 +27,7 @@
 #include <linux/init.h>
 
 #include <asm/gt64120.h>
-
+#include <asm/gcmpregs.h>
 #include <asm/mips-boards/generic.h>
 #include <asm/mips-boards/bonito64.h>
 #include <asm/mips-boards/msc01_pci.h>
@@ -201,7 +201,11 @@ void __init mips_pcibios_init(void)
                msc_mem_resource.start = start & mask;
                msc_mem_resource.end = (start & mask) | ~mask;
                msc_controller.mem_offset = (start & mask) - (map & mask);
-
+#ifdef CONFIG_MIPS_CMP
+               if (gcmp_niocu())
+                       gcmp_setregion(0, start, mask,
+                               GCMP_GCB_GCMPB_CMDEFTGT_IOCU1);
+#endif
                MSC_READ(MSC01_PCI_SC2PIOBASL, start);
                MSC_READ(MSC01_PCI_SC2PIOMSKL, mask);
                MSC_READ(MSC01_PCI_SC2PIOMAPL, map);
@@ -209,7 +213,11 @@ void __init mips_pcibios_init(void)
                msc_io_resource.end = (map & mask) | ~mask;
                msc_controller.io_offset = 0;
                ioport_resource.end = ~mask;
-
+#ifdef CONFIG_MIPS_CMP
+               if (gcmp_niocu())
+                       gcmp_setregion(1, start, mask,
+                               GCMP_GCB_GCMPB_CMDEFTGT_IOCU1);
+#endif
                /* If ranges overlap I/O takes precedence.  */
                start = start & mask;
                end = start | ~mask;
@@ -241,3 +249,16 @@ void __init mips_pcibios_init(void)
 
        register_pci_controller(controller);
 }
+
+/* Enable PCI 2.1 compatibility in PIIX4 */
+static void __init quirk_dlcsetup(struct pci_dev *dev)
+{
+       u8 odlc, ndlc;
+       (void) pci_read_config_byte(dev, 0x82, &odlc);
+       /* Enable passive releases and delayed transaction */
+       ndlc = odlc | 7;
+       (void) pci_write_config_byte(dev, 0x82, ndlc);
+}
+
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB_0,
+       quirk_dlcsetup);
index f080f11..7aca7d5 100644 (file)
@@ -172,7 +172,7 @@ static struct irqaction gic_action = {
 
 static struct irqaction timer_action = {
        .handler =      no_action,
-       .flags =        IRQF_DISABLED,
+       .flags =        IRQF_DISABLED | IRQF_TIMER,
        .name =         "Timer",
 };
 
index 18b1927..8836c62 100644 (file)
@@ -59,7 +59,7 @@ static irqreturn_t pnx8xxx_timer_interrupt(int irq, void *dev_id)
 
 static struct irqaction pnx8xxx_timer_irq = {
        .handler        = pnx8xxx_timer_interrupt,
-       .flags          = IRQF_DISABLED | IRQF_PERCPU,
+       .flags          = IRQF_DISABLED | IRQF_PERCPU | IRQF_TIMER,
        .name           = "pnx8xxx_timer",
 };
 
@@ -72,7 +72,7 @@ static irqreturn_t monotonic_interrupt(int irq, void *dev_id)
 
 static struct irqaction monotonic_irqaction = {
        .handler = monotonic_interrupt,
-       .flags = IRQF_DISABLED,
+       .flags = IRQF_DISABLED | IRQF_TIMER,
        .name = "Monotonic timer",
 };
 
index deed1d5..575cd14 100644 (file)
@@ -22,7 +22,7 @@
  * otherwise, the oprofile tool will not recognize this and complain about
  * "cpu_type 'unset' is not valid".
  */
-#define LOONGSON2_CPU_TYPE     "mips/godson2"
+#define LOONGSON2_CPU_TYPE     "mips/loongson2"
 
 #define LOONGSON2_COUNTER1_EVENT(event)        ((event & 0x0f) << 5)
 #define LOONGSON2_COUNTER2_EVENT(event)        ((event & 0x0f) << 9)
index 6d0e59f..d6802d6 100644 (file)
@@ -105,7 +105,7 @@ static irqreturn_t hub_rt_counter_handler(int irq, void *dev_id)
 
 struct irqaction hub_rt_irqaction = {
        .handler        = hub_rt_counter_handler,
-       .flags          = IRQF_DISABLED | IRQF_PERCPU,
+       .flags          = IRQF_DISABLED | IRQF_PERCPU | IRQF_TIMER,
        .name           = "hub-rt",
 };
 
index 62df6a5..f3b60e6 100644 (file)
@@ -67,7 +67,7 @@ static irqreturn_t a20r_interrupt(int irq, void *dev_id)
 
 static struct irqaction a20r_irqaction = {
        .handler        = a20r_interrupt,
-       .flags          = IRQF_DISABLED | IRQF_PERCPU,
+       .flags          = IRQF_DISABLED | IRQF_PERCPU | IRQF_TIMER,
        .name           = "a20r-timer",
 };
 
index c860810..e10184c 100644 (file)
@@ -85,7 +85,7 @@ int txx9_ccfg_toeon __initdata = 1;
 struct clk *clk_get(struct device *dev, const char *id)
 {
        if (!strcmp(id, "spi-baseclk"))
-               return (struct clk *)((unsigned long)txx9_gbus_clock / 2 / 4);
+               return (struct clk *)((unsigned long)txx9_gbus_clock / 2 / 2);
        if (!strcmp(id, "imbus_clk"))
                return (struct clk *)((unsigned long)txx9_gbus_clock / 2);
        return ERR_PTR(-ENOENT);
@@ -817,7 +817,8 @@ void __init txx9_iocled_init(unsigned long baseaddr,
 out_pdev:
        platform_device_put(pdev);
 out_gpio:
-       gpio_remove(&iocled->chip);
+       if (gpiochip_remove(&iocled->chip))
+               return;
 out_unmap:
        iounmap(iocled->mmioaddr);
 out_free:
index f388dc6..524d935 100644 (file)
@@ -18,6 +18,7 @@ config PARISC
        select BUG
        select HAVE_PERF_EVENTS
        select GENERIC_ATOMIC64 if !64BIT
+       select HAVE_ARCH_TRACEHOOK
        help
          The PA-RISC microprocessor is designed by Hewlett-Packard and used
          in many of their workstations & servers (HP9000 700 and 800 series,
index de3fe3a..6fec4d4 100644 (file)
@@ -21,9 +21,9 @@
 #define KERNEL_MAP_END         (TMPALIAS_MAP_START)
 
 #ifndef __ASSEMBLY__
-extern void *vmalloc_start;
+extern void *parisc_vmalloc_start;
 #define PCXL_DMA_MAP_SIZE      (8*1024*1024)
-#define VMALLOC_START          ((unsigned long)vmalloc_start)
+#define VMALLOC_START          ((unsigned long)parisc_vmalloc_start)
 #define VMALLOC_END            (KERNEL_MAP_END)
 #endif /*__ASSEMBLY__*/
 
index ce93133..0d68184 100644 (file)
@@ -1,29 +1,11 @@
 /* hardirq.h: PA-RISC hard IRQ support.
  *
  * Copyright (C) 2001 Matthew Wilcox <matthew@wil.cx>
- *
- * The locking is really quite interesting.  There's a cpu-local
- * count of how many interrupts are being handled, and a global
- * lock.  An interrupt can only be serviced if the global lock
- * is free.  You can't be sure no more interrupts are being
- * serviced until you've acquired the lock and then checked
- * all the per-cpu interrupt counts are all zero.  It's a specialised
- * br_lock, and that's exactly how Sparc does it.  We don't because
- * it's more locking for us.  This way is lock-free in the interrupt path.
  */
 
 #ifndef _PARISC_HARDIRQ_H
 #define _PARISC_HARDIRQ_H
 
-#include <linux/threads.h>
-#include <linux/irq.h>
-
-typedef struct {
-       unsigned long __softirq_pending; /* set_bit is used on this */
-} ____cacheline_aligned irq_cpustat_t;
-
-#include <linux/irq_cpustat.h> /* Standard mappings for irq_cpustat_t above */
-
-void ack_bad_irq(unsigned int irq);
+#include <asm-generic/hardirq.h>
 
 #endif /* _PARISC_HARDIRQ_H */
index 302f68d..aead40b 100644 (file)
@@ -59,8 +59,11 @@ void user_enable_block_step(struct task_struct *task);
 #define user_mode(regs)                        (((regs)->iaoq[0] & 3) ? 1 : 0)
 #define user_space(regs)               (((regs)->iasq[1] != 0) ? 1 : 0)
 #define instruction_pointer(regs)      ((regs)->iaoq[0] & ~3)
+#define user_stack_pointer(regs)       ((regs)->gr[30])
 unsigned long profile_pc(struct pt_regs *);
 extern void show_regs(struct pt_regs *);
-#endif
+
+
+#endif /* __KERNEL__ */
 
 #endif
diff --git a/arch/parisc/include/asm/syscall.h b/arch/parisc/include/asm/syscall.h
new file mode 100644 (file)
index 0000000..8bdfd2c
--- /dev/null
@@ -0,0 +1,40 @@
+/* syscall.h */
+
+#ifndef _ASM_PARISC_SYSCALL_H_
+#define _ASM_PARISC_SYSCALL_H_
+
+#include <linux/err.h>
+#include <asm/ptrace.h>
+
+static inline long syscall_get_nr(struct task_struct *tsk,
+                                 struct pt_regs *regs)
+{
+       return regs->gr[20];
+}
+
+static inline void syscall_get_arguments(struct task_struct *tsk,
+                                        struct pt_regs *regs, unsigned int i,
+                                        unsigned int n, unsigned long *args)
+{
+       BUG_ON(i);
+
+       switch (n) {
+       case 6:
+               args[5] = regs->gr[21];
+       case 5:
+               args[4] = regs->gr[22];
+       case 4:
+               args[3] = regs->gr[23];
+       case 3:
+               args[2] = regs->gr[24];
+       case 2:
+               args[1] = regs->gr[25];
+       case 1:
+               args[0] = regs->gr[26];
+               break;
+       default:
+               BUG();
+       }
+}
+
+#endif /*_ASM_PARISC_SYSCALL_H_*/
index ac775a7..7ecc103 100644 (file)
@@ -32,6 +32,11 @@ struct thread_info {
 #define init_thread_info        (init_thread_union.thread_info)
 #define init_stack              (init_thread_union.stack)
 
+/* how to get the thread information struct from C */
+#define current_thread_info()  ((struct thread_info *)mfctl(30))
+
+#endif /* !__ASSEMBLY */
+
 /* thread information allocation */
 
 #define THREAD_SIZE_ORDER            2
@@ -40,11 +45,6 @@ struct thread_info {
 #define THREAD_SIZE             (PAGE_SIZE << THREAD_SIZE_ORDER)
 #define THREAD_SHIFT            (PAGE_SHIFT + THREAD_SIZE_ORDER)
 
-/* how to get the thread information struct from C */
-#define current_thread_info()  ((struct thread_info *)mfctl(30))
-
-#endif /* !__ASSEMBLY */
-
 #define PREEMPT_ACTIVE_BIT     28
 #define PREEMPT_ACTIVE         (1 << PREEMPT_ACTIVE_BIT)
 
@@ -60,6 +60,8 @@ struct thread_info {
 #define TIF_RESTORE_SIGMASK    6       /* restore saved signal mask */
 #define TIF_FREEZE             7       /* is freezing for suspend */
 #define TIF_NOTIFY_RESUME      8       /* callback before returning to user */
+#define TIF_SINGLESTEP         9       /* single stepping? */
+#define TIF_BLOCKSTEP          10      /* branch stepping? */
 
 #define _TIF_SYSCALL_TRACE     (1 << TIF_SYSCALL_TRACE)
 #define _TIF_SIGPENDING                (1 << TIF_SIGPENDING)
@@ -69,6 +71,8 @@ struct thread_info {
 #define _TIF_RESTORE_SIGMASK   (1 << TIF_RESTORE_SIGMASK)
 #define _TIF_FREEZE            (1 << TIF_FREEZE)
 #define _TIF_NOTIFY_RESUME     (1 << TIF_NOTIFY_RESUME)
+#define _TIF_SINGLESTEP                (1 << TIF_SINGLESTEP)
+#define _TIF_BLOCKSTEP         (1 << TIF_BLOCKSTEP)
 
 #define _TIF_USER_WORK_MASK     (_TIF_SIGPENDING | _TIF_NOTIFY_RESUME | \
                                  _TIF_NEED_RESCHED | _TIF_RESTORE_SIGMASK)
index 699cf8e..fcd3c70 100644 (file)
@@ -270,8 +270,8 @@ int main(void)
        DEFINE(DTLB_OFF_COUNT, offsetof(struct pdc_cache_info, dt_off_count));
        DEFINE(DTLB_LOOP, offsetof(struct pdc_cache_info, dt_loop));
        BLANK();
-       DEFINE(PA_BLOCKSTEP_BIT, 31-PT_BLOCKSTEP_BIT);
-       DEFINE(PA_SINGLESTEP_BIT, 31-PT_SINGLESTEP_BIT);
+       DEFINE(TIF_BLOCKSTEP_PA_BIT, 31-TIF_BLOCKSTEP);
+       DEFINE(TIF_SINGLESTEP_PA_BIT, 31-TIF_SINGLESTEP);
        BLANK();
        DEFINE(ASM_PMD_SHIFT, PMD_SHIFT);
        DEFINE(ASM_PGDIR_SHIFT, PGDIR_SHIFT);
index 8c4712b..3a44f7f 100644 (file)
@@ -2047,12 +2047,13 @@ syscall_do_signal:
        b,n     syscall_check_sig
 
 syscall_restore:
-       /* Are we being ptraced? */
        LDREG   TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r1
 
-       ldw     TASK_PTRACE(%r1), %r19
-       bb,<    %r19,31,syscall_restore_rfi
-       nop
+       /* Are we being ptraced? */
+       ldw     TASK_FLAGS(%r1),%r19
+       ldi     (_TIF_SINGLESTEP|_TIF_BLOCKSTEP),%r2
+       and,COND(=)     %r19,%r2,%r0
+       b,n     syscall_restore_rfi
 
        ldo     TASK_PT_FR31(%r1),%r19             /* reload fpregs */
        rest_fp %r19
@@ -2113,16 +2114,16 @@ syscall_restore_rfi:
        ldi     0x0b,%r20                          /* Create new PSW */
        depi    -1,13,1,%r20                       /* C, Q, D, and I bits */
 
-       /* The values of PA_SINGLESTEP_BIT and PA_BLOCKSTEP_BIT are
-        * set in include/linux/ptrace.h and converted to PA bitmap
+       /* The values of SINGLESTEP_BIT and BLOCKSTEP_BIT are
+        * set in thread_info.h and converted to PA bitmap
         * numbers in asm-offsets.c */
 
-       /* if ((%r19.PA_SINGLESTEP_BIT)) { %r20.27=1} */
-       extru,= %r19,PA_SINGLESTEP_BIT,1,%r0
+       /* if ((%r19.SINGLESTEP_BIT)) { %r20.27=1} */
+       extru,= %r19,TIF_SINGLESTEP_PA_BIT,1,%r0
        depi    -1,27,1,%r20                       /* R bit */
 
-       /* if ((%r19.PA_BLOCKSTEP_BIT)) { %r20.7=1} */
-       extru,= %r19,PA_BLOCKSTEP_BIT,1,%r0
+       /* if ((%r19.BLOCKSTEP_BIT)) { %r20.7=1} */
+       extru,= %r19,TIF_BLOCKSTEP_PA_BIT,1,%r0
        depi    -1,7,1,%r20                        /* T bit */
 
        STREG   %r20,TASK_PT_PSW(%r1)
index 330f536..2e7610c 100644 (file)
@@ -423,8 +423,3 @@ void __init init_IRQ(void)
         set_eiem(cpu_eiem);    /* EIEM : enable all external intr */
 
 }
-
-void ack_bad_irq(unsigned int irq)
-{
-       printk(KERN_WARNING "unexpected IRQ %d\n", irq);
-}
index 61ee0ee..2120746 100644 (file)
@@ -893,7 +893,7 @@ int module_finalize(const Elf_Ehdr *hdr,
         * ourselves */
        for (i = 1; i < hdr->e_shnum; i++) {
                if(sechdrs[i].sh_type == SHT_SYMTAB
-                  && (sechdrs[i].sh_type & SHF_ALLOC)) {
+                  && (sechdrs[i].sh_flags & SHF_ALLOC)) {
                        int strindex = sechdrs[i].sh_link;
                        /* FIXME: AWFUL HACK
                         * The cast is to drop the const from
index 927db36..c4f49e4 100644 (file)
@@ -13,6 +13,7 @@
 #include <linux/smp.h>
 #include <linux/errno.h>
 #include <linux/ptrace.h>
+#include <linux/tracehook.h>
 #include <linux/user.h>
 #include <linux/personality.h>
 #include <linux/security.h>
@@ -35,7 +36,8 @@
  */
 void ptrace_disable(struct task_struct *task)
 {
-       task->ptrace &= ~(PT_SINGLESTEP|PT_BLOCKSTEP);
+       clear_tsk_thread_flag(task, TIF_SINGLESTEP);
+       clear_tsk_thread_flag(task, TIF_BLOCKSTEP);
 
        /* make sure the trap bits are not set */
        pa_psw(task)->r = 0;
@@ -55,8 +57,8 @@ void user_disable_single_step(struct task_struct *task)
 
 void user_enable_single_step(struct task_struct *task)
 {
-       task->ptrace &= ~PT_BLOCKSTEP;
-       task->ptrace |= PT_SINGLESTEP;
+       clear_tsk_thread_flag(task, TIF_BLOCKSTEP);
+       set_tsk_thread_flag(task, TIF_SINGLESTEP);
 
        if (pa_psw(task)->n) {
                struct siginfo si;
@@ -98,8 +100,8 @@ void user_enable_single_step(struct task_struct *task)
 
 void user_enable_block_step(struct task_struct *task)
 {
-       task->ptrace &= ~PT_SINGLESTEP;
-       task->ptrace |= PT_BLOCKSTEP;
+       clear_tsk_thread_flag(task, TIF_SINGLESTEP);
+       set_tsk_thread_flag(task, TIF_BLOCKSTEP);
 
        /* Enable taken branch trap. */
        pa_psw(task)->r = 0;
@@ -263,22 +265,20 @@ long compat_arch_ptrace(struct task_struct *child, compat_long_t request,
 }
 #endif
 
+long do_syscall_trace_enter(struct pt_regs *regs)
+{
+       if (test_thread_flag(TIF_SYSCALL_TRACE) &&
+           tracehook_report_syscall_entry(regs))
+               return -1L;
+
+       return regs->gr[20];
+}
 
-void syscall_trace(void)
+void do_syscall_trace_exit(struct pt_regs *regs)
 {
-       if (!test_thread_flag(TIF_SYSCALL_TRACE))
-               return;
-       if (!(current->ptrace & PT_PTRACED))
-               return;
-       ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD)
-                                ? 0x80 : 0));
-       /*
-        * this isn't the same as continuing with a signal, but it will do
-        * for normal use.  strace only continues with a signal if the
-        * stopping signal is not SIGTRAP.  -brl
-        */
-       if (current->exit_code) {
-               send_sig(current->exit_code, current, 1);
-               current->exit_code = 0;
-       }
+       int stepping = test_thread_flag(TIF_SINGLESTEP) ||
+               test_thread_flag(TIF_BLOCKSTEP);
+
+       if (stepping || test_thread_flag(TIF_SYSCALL_TRACE))
+               tracehook_report_syscall_exit(regs, stepping);
 }
index 8eb3c63..e8467e4 100644 (file)
@@ -21,6 +21,7 @@
 #include <linux/errno.h>
 #include <linux/wait.h>
 #include <linux/ptrace.h>
+#include <linux/tracehook.h>
 #include <linux/unistd.h>
 #include <linux/stddef.h>
 #include <linux/compat.h>
@@ -34,7 +35,6 @@
 #include <asm/asm-offsets.h>
 
 #ifdef CONFIG_COMPAT
-#include <linux/compat.h>
 #include "signal32.h"
 #endif
 
@@ -468,6 +468,9 @@ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka,
                sigaddset(&current->blocked,sig);
        recalc_sigpending();
        spin_unlock_irq(&current->sighand->siglock);
+
+       tracehook_signal_handler(sig, info, ka, regs, 0);
+
        return 1;
 }
 
index 59fc1a4..f5f9602 100644 (file)
@@ -288,18 +288,23 @@ tracesys:
        STREG   %r18,PT_GR18(%r2)
        /* Finished saving things for the debugger */
 
-       ldil    L%syscall_trace,%r1
+       copy    %r2,%r26
+       ldil    L%do_syscall_trace_enter,%r1
        ldil    L%tracesys_next,%r2
-       be      R%syscall_trace(%sr7,%r1)
+       be      R%do_syscall_trace_enter(%sr7,%r1)
        ldo     R%tracesys_next(%r2),%r2
        
-tracesys_next: 
+tracesys_next:
+       /* do_syscall_trace_enter either returned the syscallno, or -1L,
+        *  so we skip restoring the PT_GR20 below, since we pulled it from
+        *  task->thread.regs.gr[20] above.
+        */
+       copy    %ret0,%r20
        ldil    L%sys_call_table,%r1
        ldo     R%sys_call_table(%r1), %r19
 
        ldo     -THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r1      /* get task ptr */
        LDREG   TI_TASK(%r1), %r1
-       LDREG   TASK_PT_GR20(%r1), %r20
        LDREG   TASK_PT_GR26(%r1), %r26         /* Restore the users args */
        LDREG   TASK_PT_GR25(%r1), %r25
        LDREG   TASK_PT_GR24(%r1), %r24
@@ -336,7 +341,8 @@ tracesys_exit:
 #ifdef CONFIG_64BIT
        ldo     -16(%r30),%r29                  /* Reference param save area */
 #endif
-       bl      syscall_trace, %r2
+       ldo     TASK_REGS(%r1),%r26
+       bl      do_syscall_trace_exit,%r2
        STREG   %r28,TASK_PT_GR28(%r1)          /* save return value now */
        ldo     -THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r1      /* get task ptr */
        LDREG   TI_TASK(%r1), %r1
@@ -353,12 +359,12 @@ tracesys_exit:
 
 tracesys_sigexit:
        ldo     -THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r1      /* get task ptr */
-       LDREG   0(%r1), %r1
+       LDREG   TI_TASK(%r1), %r1
 #ifdef CONFIG_64BIT
        ldo     -16(%r30),%r29                  /* Reference param save area */
 #endif
-       bl      syscall_trace, %r2
-       nop
+       bl      do_syscall_trace_exit,%r2
+       ldo     TASK_REGS(%r1),%r26
 
        ldil    L%syscall_exit_rfi,%r1
        be,n    R%syscall_exit_rfi(%sr7,%r1)
index 775be27..fda4baa 100644 (file)
@@ -28,6 +28,7 @@
 #include <asm/cache.h>
 #include <asm/page.h>
 #include <asm/asm-offsets.h>
+#include <asm/thread_info.h>
        
 /* ld script to make hppa Linux kernel */
 #ifndef CONFIG_64BIT
@@ -134,6 +135,15 @@ SECTIONS
        __init_begin = .;
        INIT_TEXT_SECTION(16384)
        INIT_DATA_SECTION(16)
+       /* we have to discard exit text and such at runtime, not link time */
+       .exit.text :
+       {
+               EXIT_TEXT
+       }
+       .exit.data :
+       {
+               EXIT_DATA
+       }
 
        PERCPU(PAGE_SIZE)
        . = ALIGN(PAGE_SIZE);
index d5aca31..13b6e3e 100644 (file)
@@ -434,8 +434,8 @@ void mark_rodata_ro(void)
 #define SET_MAP_OFFSET(x) ((void *)(((unsigned long)(x) + VM_MAP_OFFSET) \
                                     & ~(VM_MAP_OFFSET-1)))
 
-void *vmalloc_start __read_mostly;
-EXPORT_SYMBOL(vmalloc_start);
+void *parisc_vmalloc_start __read_mostly;
+EXPORT_SYMBOL(parisc_vmalloc_start);
 
 #ifdef CONFIG_PA11
 unsigned long pcxl_dma_start __read_mostly;
@@ -496,13 +496,14 @@ void __init mem_init(void)
 #ifdef CONFIG_PA11
        if (hppa_dma_ops == &pcxl_dma_ops) {
                pcxl_dma_start = (unsigned long)SET_MAP_OFFSET(MAP_START);
-               vmalloc_start = SET_MAP_OFFSET(pcxl_dma_start + PCXL_DMA_MAP_SIZE);
+               parisc_vmalloc_start = SET_MAP_OFFSET(pcxl_dma_start
+                                               + PCXL_DMA_MAP_SIZE);
        } else {
                pcxl_dma_start = 0;
-               vmalloc_start = SET_MAP_OFFSET(MAP_START);
+               parisc_vmalloc_start = SET_MAP_OFFSET(MAP_START);
        }
 #else
-       vmalloc_start = SET_MAP_OFFSET(MAP_START);
+       parisc_vmalloc_start = SET_MAP_OFFSET(MAP_START);
 #endif
 
        printk(KERN_INFO "Memory: %luk/%luk available (%dk kernel code, %dk reserved, %dk data, %dk init)\n",
index cee8080..dd38608 100644 (file)
                        compatible = "fsl,mpc5200b-i2c","fsl,mpc5200-i2c","fsl-i2c";
                        reg = <0x3d40 0x40>;
                        interrupts = <2 16 0>;
-                       fsl5200-clocking;
                };
 
                sram@8000 {
index 4c36186..8e9be6b 100644 (file)
                        compatible = "fsl,mpc5200b-i2c","fsl,mpc5200-i2c","fsl-i2c";
                        reg = <0x3d00 0x40>;
                        interrupts = <2 15 0>;
-                       fsl5200-clocking;
 
                        rtc@50 {
                                compatible = "at,24c08";
index de30b3f..82ff2b1 100644 (file)
                        compatible = "fsl,mpc5200-i2c","fsl-i2c";
                        reg = <0x3d00 0x40>;
                        interrupts = <2 15 0>;
-                       fsl5200-clocking;
                };
 
                i2c@3d40 {
                        compatible = "fsl,mpc5200-i2c","fsl-i2c";
                        reg = <0x3d40 0x40>;
                        interrupts = <2 16 0>;
-                       fsl5200-clocking;
                };
                sram@8000 {
                        compatible = "fsl,mpc5200-sram";
index d13cb11..e45a63b 100644 (file)
                        compatible = "fsl,mpc5200b-i2c","fsl,mpc5200-i2c","fsl-i2c";
                        reg = <0x3d00 0x40>;
                        interrupts = <2 15 0>;
-                       fsl5200-clocking;
                };
 
                i2c@3d40 {
                        compatible = "fsl,mpc5200b-i2c","fsl,mpc5200-i2c","fsl-i2c";
                        reg = <0x3d40 0x40>;
                        interrupts = <2 16 0>;
-                       fsl5200-clocking;
                };
 
                sram@8000 {
index e297d8b..0c3902b 100644 (file)
                        compatible = "fsl,mpc5200b-i2c","fsl,mpc5200-i2c","fsl-i2c";
                        reg = <0x3d00 0x40>;
                        interrupts = <2 15 0>;
-                       fsl5200-clocking;
                };
 
                i2c@3d40 {
                        compatible = "fsl,mpc5200b-i2c","fsl,mpc5200-i2c","fsl-i2c";
                        reg = <0x3d40 0x40>;
                        interrupts = <2 16 0>;
-                       fsl5200-clocking;
                };
 
                sram@8000 {
index 7be8ca0..6ca4fc1 100644 (file)
                        compatible = "fsl,mpc5200b-i2c","fsl,mpc5200-i2c","fsl-i2c";
                        reg = <0x3d40 0x40>;
                        interrupts = <2 16 0>;
-                       fsl5200-clocking;
 
                        rtc@68 {
                                compatible = "dallas,ds1339";
index c2b8dbf..c353dac 100644 (file)
                        reg = <0x1700 0x20>;
                        interrupts = <9 0x8>;
                        interrupt-parent = < &ipic >;
-                       fsl5200-clocking;
                };
 
                i2c@1720 {
                        reg = <0x1720 0x20>;
                        interrupts = <10 0x8>;
                        interrupt-parent = < &ipic >;
-                       fsl5200-clocking;
                };
 
                i2c@1740 {
                        reg = <0x1740 0x20>;
                        interrupts = <11 0x8>;
                        interrupt-parent = < &ipic >;
-                       fsl5200-clocking;
                };
 
                i2ccontrol@1760 {
diff --git a/arch/powerpc/boot/dts/mucmc52.dts b/arch/powerpc/boot/dts/mucmc52.dts
new file mode 100644 (file)
index 0000000..b72a758
--- /dev/null
@@ -0,0 +1,332 @@
+/*
+ * Manroland mucmc52 board Device Tree Source
+ *
+ * Copyright (C) 2009 DENX Software Engineering GmbH
+ * Heiko Schocher <hs@denx.de>
+ * Copyright 2006-2007 Secret Lab Technologies Ltd.
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+/dts-v1/;
+
+/ {
+       model = "manroland,mucmc52";
+       compatible = "manroland,mucmc52";
+       #address-cells = <1>;
+       #size-cells = <1>;
+       interrupt-parent = <&mpc5200_pic>;
+
+       cpus {
+               #address-cells = <1>;
+               #size-cells = <0>;
+
+               PowerPC,5200@0 {
+                       device_type = "cpu";
+                       reg = <0>;
+                       d-cache-line-size = <32>;
+                       i-cache-line-size = <32>;
+                       d-cache-size = <0x4000>;        // L1, 16K
+                       i-cache-size = <0x4000>;        // L1, 16K
+                       timebase-frequency = <0>;       // from bootloader
+                       bus-frequency = <0>;            // from bootloader
+                       clock-frequency = <0>;          // from bootloader
+               };
+       };
+
+       memory {
+               device_type = "memory";
+               reg = <0x00000000 0x04000000>;  // 64MB
+       };
+
+       soc5200@f0000000 {
+               #address-cells = <1>;
+               #size-cells = <1>;
+               compatible = "fsl,mpc5200b-immr";
+               ranges = <0 0xf0000000 0x0000c000>;
+               reg = <0xf0000000 0x00000100>;
+               bus-frequency = <0>;            // from bootloader
+               system-frequency = <0>;         // from bootloader
+
+               cdm@200 {
+                       compatible = "fsl,mpc5200b-cdm","fsl,mpc5200-cdm";
+                       reg = <0x200 0x38>;
+               };
+
+               mpc5200_pic: interrupt-controller@500 {
+                       // 5200 interrupts are encoded into two levels;
+                       interrupt-controller;
+                       #interrupt-cells = <3>;
+                       compatible = "fsl,mpc5200b-pic","fsl,mpc5200-pic";
+                       reg = <0x500 0x80>;
+               };
+
+               gpt0: timer@600 {       // GPT 0 in GPIO mode
+                       compatible = "fsl,mpc5200b-gpt","fsl,mpc5200-gpt";
+                       reg = <0x600 0x10>;
+                       interrupts = <1 9 0>;
+                       gpio-controller;
+                       #gpio-cells = <2>;
+               };
+
+               gpt1: timer@610 {       // General Purpose Timer in GPIO mode
+                       compatible = "fsl,mpc5200b-gpt","fsl,mpc5200-gpt";
+                       reg = <0x610 0x10>;
+                       interrupts = <1 10 0>;
+                       gpio-controller;
+                       #gpio-cells = <2>;
+               };
+
+               gpt2: timer@620 {       // General Purpose Timer in GPIO mode
+                       compatible = "fsl,mpc5200b-gpt","fsl,mpc5200-gpt";
+                       reg = <0x620 0x10>;
+                       interrupts = <1 11 0>;
+                       gpio-controller;
+                       #gpio-cells = <2>;
+               };
+
+               gpt3: timer@630 {       // General Purpose Timer in GPIO mode
+                       compatible = "fsl,mpc5200b-gpt","fsl,mpc5200-gpt";
+                       reg = <0x630 0x10>;
+                       interrupts = <1 12 0>;
+                       gpio-controller;
+                       #gpio-cells = <2>;
+               };
+
+               gpio_simple: gpio@b00 {
+                       compatible = "fsl,mpc5200b-gpio","fsl,mpc5200-gpio";
+                       reg = <0xb00 0x40>;
+                       interrupts = <1 7 0>;
+                       gpio-controller;
+                       #gpio-cells = <2>;
+               };
+
+               gpio_wkup: gpio@c00 {
+                       compatible = "fsl,mpc5200b-gpio-wkup","fsl,mpc5200-gpio-wkup";
+                       reg = <0xc00 0x40>;
+                       interrupts = <1 8 0 0 3 0>;
+                       gpio-controller;
+                       #gpio-cells = <2>;
+               };
+
+               dma-controller@1200 {
+                       compatible = "fsl,mpc5200b-bestcomm","fsl,mpc5200-bestcomm";
+                       reg = <0x1200 0x80>;
+                       interrupts = <3 0 0  3 1 0  3 2 0  3 3 0
+                                     3 4 0  3 5 0  3 6 0  3 7 0
+                                     3 8 0  3 9 0  3 10 0  3 11 0
+                                     3 12 0  3 13 0  3 14 0  3 15 0>;
+               };
+
+               xlb@1f00 {
+                       compatible = "fsl,mpc5200b-xlb","fsl,mpc5200-xlb";
+                       reg = <0x1f00 0x100>;
+               };
+
+               serial@2000 { /* PSC1 in UART mode */
+                       compatible = "fsl,mpc5200b-psc-uart","fsl,mpc5200-psc-uart";
+                       reg = <0x2000 0x100>;
+                       interrupts = <2 1 0>;
+               };
+
+               serial@2200 { /* PSC2 in UART mode */
+                       compatible = "fsl,mpc5200b-psc-uart","fsl,mpc5200-psc-uart";
+                       reg = <0x2200 0x100>;
+                       interrupts = <2 2 0>;
+               };
+
+               serial@2c00 { /* PSC6 in UART mode */
+                       compatible = "fsl,mpc5200b-psc-uart","fsl,mpc5200-psc-uart";
+                       reg = <0x2c00 0x100>;
+                       interrupts = <2 4 0>;
+               };
+
+               ethernet@3000 {
+                       compatible = "fsl,mpc5200b-fec","fsl,mpc5200-fec";
+                       reg = <0x3000 0x400>;
+                       local-mac-address = [ 00 00 00 00 00 00 ];
+                       interrupts = <2 5 0>;
+                       phy-handle = <&phy0>;
+               };
+
+               mdio@3000 {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       compatible = "fsl,mpc5200b-mdio","fsl,mpc5200-mdio";
+                       reg = <0x3000 0x400>;   // fec range, since we need to setup fec interrupts
+                       interrupts = <2 5 0>;   // these are for "mii command finished", not link changes & co.
+
+                       phy0: ethernet-phy@0 {
+                               compatible = "intel,lxt971";
+                               reg = <0>;
+                       };
+               };
+
+               ata@3a00 {
+                       compatible = "fsl,mpc5200b-ata","fsl,mpc5200-ata";
+                       reg = <0x3a00 0x100>;
+                       interrupts = <2 7 0>;
+               };
+
+               i2c@3d40 {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       compatible = "fsl,mpc5200b-i2c","fsl,mpc5200-i2c","fsl-i2c";
+                       reg = <0x3d40 0x40>;
+                       interrupts = <2 16 0>;
+                       hwmon@2c {
+                               compatible = "ad,adm9240";
+                               reg = <0x2c>;
+                       };
+                       rtc@51 {
+                               compatible = "nxp,pcf8563";
+                               reg = <0x51>;
+                       };
+               };
+
+               sram@8000 {
+                       compatible = "fsl,mpc5200b-sram","fsl,mpc5200-sram";
+                       reg = <0x8000 0x4000>;
+               };
+       };
+
+       pci@f0000d00 {
+               #interrupt-cells = <1>;
+               #size-cells = <2>;
+               #address-cells = <3>;
+               device_type = "pci";
+               compatible = "fsl,mpc5200b-pci","fsl,mpc5200-pci";
+               reg = <0xf0000d00 0x100>;
+               interrupt-map-mask = <0xf800 0 0 7>;
+               interrupt-map = <
+                               /* IDSEL 0x10 */
+                               0x8000 0 0 1 &mpc5200_pic 0 3 3
+                               0x8000 0 0 2 &mpc5200_pic 0 3 3
+                               0x8000 0 0 3 &mpc5200_pic 0 2 3
+                               0x8000 0 0 4 &mpc5200_pic 0 1 3
+                               >;
+               clock-frequency = <0>; // From boot loader
+               interrupts = <2 8 0 2 9 0 2 10 0>;
+               bus-range = <0 0>;
+               ranges = <0x42000000 0 0x60000000 0x60000000 0 0x10000000
+                         0x02000000 0 0x90000000 0x90000000 0 0x10000000
+                         0x01000000 0 0x00000000 0xa0000000 0 0x01000000>;
+       };
+
+       localbus {
+               compatible = "fsl,mpc5200b-lpb","fsl,mpc5200-lpb","simple-bus";
+
+               #address-cells = <2>;
+               #size-cells = <1>;
+
+               ranges = <0 0 0xff800000 0x00800000
+                         1 0 0x80000000 0x00800000
+                         3 0 0x80000000 0x00800000>;
+
+               flash@0,0 {
+                       compatible = "cfi-flash";
+                       reg = <0 0 0x00800000>;
+                       bank-width = <4>;
+                       device-width = <2>;
+                       #size-cells = <1>;
+                       #address-cells = <1>;
+                       partition@0 {
+                               label = "DTS";
+                               reg = <0x0 0x00100000>;
+                       };
+                       partition@100000 {
+                               label = "Kernel";
+                               reg = <0x100000 0x00200000>;
+                       };
+                       partition@300000 {
+                               label = "RootFS";
+                               reg = <0x00300000 0x00200000>;
+                       };
+                       partition@500000 {
+                               label = "user";
+                               reg = <0x00500000 0x00200000>;
+                       };
+                       partition@700000 {
+                               label = "U-Boot";
+                               reg = <0x00700000 0x00040000>;
+                       };
+                       partition@740000 {
+                               label = "Env";
+                               reg = <0x00740000 0x00020000>;
+                       };
+                       partition@760000 {
+                               label = "red. Env";
+                               reg = <0x00760000 0x00020000>;
+                       };
+                       partition@780000 {
+                               label = "reserve";
+                               reg = <0x00780000 0x00080000>;
+                       };
+               };
+
+               simple100: gpio-controller-100@3,600100 {
+                       compatible = "manroland,mucmc52-aux-gpio";
+                       reg = <3 0x00600100 0x1>;
+                       gpio-controller;
+                       #gpio-cells = <2>;
+               };
+               simple104: gpio-controller-104@3,600104 {
+                       compatible = "manroland,mucmc52-aux-gpio";
+                       reg = <3 0x00600104 0x1>;
+                       gpio-controller;
+                       #gpio-cells = <2>;
+               };
+               simple200: gpio-controller-200@3,600200 {
+                       compatible = "manroland,mucmc52-aux-gpio";
+                       reg = <3 0x00600200 0x1>;
+                       gpio-controller;
+                       #gpio-cells = <2>;
+               };
+               simple201: gpio-controller-201@3,600201 {
+                       compatible = "manroland,mucmc52-aux-gpio";
+                       reg = <3 0x00600201 0x1>;
+                       gpio-controller;
+                       #gpio-cells = <2>;
+               };
+               simple202: gpio-controller-202@3,600202 {
+                       compatible = "manroland,mucmc52-aux-gpio";
+                       reg = <3 0x00600202 0x1>;
+                       gpio-controller;
+                       #gpio-cells = <2>;
+               };
+               simple203: gpio-controller-203@3,600203 {
+                       compatible = "manroland,mucmc52-aux-gpio";
+                       reg = <3 0x00600203 0x1>;
+                       gpio-controller;
+                       #gpio-cells = <2>;
+               };
+               simple204: gpio-controller-204@3,600204 {
+                       compatible = "manroland,mucmc52-aux-gpio";
+                       reg = <3 0x00600204 0x1>;
+                       gpio-controller;
+                       #gpio-cells = <2>;
+               };
+               simple206: gpio-controller-206@3,600206 {
+                       compatible = "manroland,mucmc52-aux-gpio";
+                       reg = <3 0x00600206 0x1>;
+                       gpio-controller;
+                       #gpio-cells = <2>;
+               };
+               simple207: gpio-controller-207@3,600207 {
+                       compatible = "manroland,mucmc52-aux-gpio";
+                       reg = <3 0x00600207 0x1>;
+                       gpio-controller;
+                       #gpio-cells = <2>;
+               };
+               simple20f: gpio-controller-20f@3,60020f {
+                       compatible = "manroland,mucmc52-aux-gpio";
+                       reg = <3 0x0060020f 0x1>;
+                       gpio-controller;
+                       #gpio-cells = <2>;
+               };
+
+       };
+};
index 30bfdc0..8a4ec30 100644 (file)
                        compatible = "fsl,mpc5200b-i2c","fsl,mpc5200-i2c","fsl-i2c";
                        reg = <0x3d00 0x40>;
                        interrupts = <2 15 0>;
-                       fsl5200-clocking;
                };
 
                i2c@3d40 {
                        compatible = "fsl,mpc5200b-i2c","fsl,mpc5200-i2c","fsl-i2c";
                        reg = <0x3d40 0x40>;
                        interrupts = <2 16 0>;
-                       fsl5200-clocking;
                        rtc@51 {
                                compatible = "nxp,pcf8563";
                                reg = <0x51>;
index 0300426..85d857a 100644 (file)
                        compatible = "fsl,mpc5200b-i2c","fsl,mpc5200-i2c","fsl-i2c";
                        reg = <0x3d00 0x40>;
                        interrupts = <2 15 0>;
-                       fsl5200-clocking;
                };
 
                i2c@3d40 {
                        compatible = "fsl,mpc5200b-i2c","fsl,mpc5200-i2c","fsl-i2c";
                        reg = <0x3d40 0x40>;
                        interrupts = <2 16 0>;
-                       fsl5200-clocking;
                        rtc@51 {
                                compatible = "nxp,pcf8563";
                                reg = <0x51>;
index c9590b5..1db07f6 100644 (file)
                        compatible = "fsl,mpc5200-i2c","fsl-i2c";
                        reg = <0x3d40 0x40>;
                        interrupts = <2 16 0>;
-                       fsl5200-clocking;
 
                         rtc@68 {
                                compatible = "dallas,ds1307";
diff --git a/arch/powerpc/boot/dts/uc101.dts b/arch/powerpc/boot/dts/uc101.dts
new file mode 100644 (file)
index 0000000..019264c
--- /dev/null
@@ -0,0 +1,284 @@
+/*
+ * Manroland uc101 board Device Tree Source
+ *
+ * Copyright (C) 2009 DENX Software Engineering GmbH
+ * Heiko Schocher <hs@denx.de>
+ * Copyright 2006-2007 Secret Lab Technologies Ltd.
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+/dts-v1/;
+
+/ {
+       model = "manroland,uc101";
+       compatible = "manroland,uc101";
+       #address-cells = <1>;
+       #size-cells = <1>;
+       interrupt-parent = <&mpc5200_pic>;
+
+       cpus {
+               #address-cells = <1>;
+               #size-cells = <0>;
+
+               PowerPC,5200@0 {
+                       device_type = "cpu";
+                       reg = <0>;
+                       d-cache-line-size = <32>;
+                       i-cache-line-size = <32>;
+                       d-cache-size = <0x4000>;        // L1, 16K
+                       i-cache-size = <0x4000>;        // L1, 16K
+                       timebase-frequency = <0>;       // from bootloader
+                       bus-frequency = <0>;            // from bootloader
+                       clock-frequency = <0>;          // from bootloader
+               };
+       };
+
+       memory {
+               device_type = "memory";
+               reg = <0x00000000 0x04000000>;  // 64MB
+       };
+
+       soc5200@f0000000 {
+               #address-cells = <1>;
+               #size-cells = <1>;
+               compatible = "fsl,mpc5200b-immr";
+               ranges = <0 0xf0000000 0x0000c000>;
+               reg = <0xf0000000 0x00000100>;
+               bus-frequency = <0>;            // from bootloader
+               system-frequency = <0>;         // from bootloader
+
+               cdm@200 {
+                       compatible = "fsl,mpc5200b-cdm","fsl,mpc5200-cdm";
+                       reg = <0x200 0x38>;
+               };
+
+               mpc5200_pic: interrupt-controller@500 {
+                       // 5200 interrupts are encoded into two levels;
+                       interrupt-controller;
+                       #interrupt-cells = <3>;
+                       compatible = "fsl,mpc5200b-pic","fsl,mpc5200-pic";
+                       reg = <0x500 0x80>;
+               };
+
+               gpt0: timer@600 {       // General Purpose Timer in GPIO mode
+                       compatible = "fsl,mpc5200b-gpt","fsl,mpc5200-gpt";
+                       reg = <0x600 0x10>;
+                       interrupts = <1 9 0>;
+                       gpio-controller;
+                       #gpio-cells = <2>;
+               };
+
+               gpt1: timer@610 {       // General Purpose Timer in GPIO mode
+                       compatible = "fsl,mpc5200b-gpt","fsl,mpc5200-gpt";
+                       reg = <0x610 0x10>;
+                       interrupts = <1 10 0>;
+                       gpio-controller;
+                       #gpio-cells = <2>;
+               };
+
+               gpt2: timer@620 {       // General Purpose Timer in GPIO mode
+                       compatible = "fsl,mpc5200b-gpt","fsl,mpc5200-gpt";
+                       reg = <0x620 0x10>;
+                       interrupts = <1 11 0>;
+                       gpio-controller;
+                       #gpio-cells = <2>;
+               };
+
+               gpt3: timer@630 {       // General Purpose Timer in GPIO mode
+                       compatible = "fsl,mpc5200b-gpt","fsl,mpc5200-gpt";
+                       reg = <0x630 0x10>;
+                       interrupts = <1 12 0>;
+                       gpio-controller;
+                       #gpio-cells = <2>;
+               };
+
+               gpt4: timer@640 {       // General Purpose Timer in GPIO mode
+                       compatible = "fsl,mpc5200b-gpt","fsl,mpc5200-gpt";
+                       reg = <0x640 0x10>;
+                       interrupts = <1 13 0>;
+                       gpio-controller;
+                       #gpio-cells = <2>;
+               };
+
+               gpt5: timer@650 {       // General Purpose Timer in GPIO mode
+                       compatible = "fsl,mpc5200b-gpt","fsl,mpc5200-gpt";
+                       reg = <0x650 0x10>;
+                       interrupts = <1 14 0>;
+                       gpio-controller;
+                       #gpio-cells = <2>;
+               };
+
+               gpt6: timer@660 {       // General Purpose Timer in GPIO mode
+                       compatible = "fsl,mpc5200b-gpt","fsl,mpc5200-gpt";
+                       reg = <0x660 0x10>;
+                       interrupts = <1 15 0>;
+                       gpio-controller;
+                       #gpio-cells = <2>;
+               };
+
+               gpt7: timer@670 {       // General Purpose Timer in GPIO mode
+                       compatible = "fsl,mpc5200b-gpt","fsl,mpc5200-gpt";
+                       reg = <0x670 0x10>;
+                       interrupts = <1 16 0>;
+                       gpio-controller;
+                       #gpio-cells = <2>;
+               };
+
+               gpio_simple: gpio@b00 {
+                       compatible = "fsl,mpc5200b-gpio","fsl,mpc5200-gpio";
+                       reg = <0xb00 0x40>;
+                       interrupts = <1 7 0>;
+                       gpio-controller;
+                       #gpio-cells = <2>;
+               };
+
+               gpio_wkup: gpio@c00 {
+                       compatible = "fsl,mpc5200b-gpio-wkup","fsl,mpc5200-gpio-wkup";
+                       reg = <0xc00 0x40>;
+                       interrupts = <1 8 0 0 3 0>;
+                       gpio-controller;
+                       #gpio-cells = <2>;
+               };
+
+               dma-controller@1200 {
+                       compatible = "fsl,mpc5200b-bestcomm","fsl,mpc5200-bestcomm";
+                       reg = <0x1200 0x80>;
+                       interrupts = <3 0 0  3 1 0  3 2 0  3 3 0
+                                     3 4 0  3 5 0  3 6 0  3 7 0
+                                     3 8 0  3 9 0  3 10 0  3 11 0
+                                     3 12 0  3 13 0  3 14 0  3 15 0>;
+               };
+
+               xlb@1f00 {
+                       compatible = "fsl,mpc5200b-xlb","fsl,mpc5200-xlb";
+                       reg = <0x1f00 0x100>;
+               };
+
+               serial@2000 { /* PSC1 in UART mode */
+                       compatible = "fsl,mpc5200b-psc-uart","fsl,mpc5200-psc-uart";
+                       reg = <0x2000 0x100>;
+                       interrupts = <2 1 0>;
+               };
+
+               serial@2200 { /* PSC2 in UART mode */
+                       compatible = "fsl,mpc5200b-psc-uart","fsl,mpc5200-psc-uart";
+                       reg = <0x2200 0x100>;
+                       interrupts = <2 2 0>;
+               };
+
+               serial@2c00 {           /* PSC6 in UART mode */
+                       compatible = "fsl,mpc5200b-psc-uart","fsl,mpc5200-psc-uart";
+                       reg = <0x2c00 0x100>;
+                       interrupts = <2 4 0>;
+               };
+
+               ethernet@3000 {
+                       compatible = "fsl,mpc5200b-fec","fsl,mpc5200-fec";
+                       reg = <0x3000 0x400>;
+                       local-mac-address = [ 00 00 00 00 00 00 ];
+                       interrupts = <2 5 0>;
+                       phy-handle = <&phy0>;
+               };
+
+               mdio@3000 {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       compatible = "fsl,mpc5200b-mdio","fsl,mpc5200-mdio";
+                       reg = <0x3000 0x400>;   // fec range, since we need to setup fec interrupts
+                       interrupts = <2 5 0>;   // these are for "mii command finished", not link changes & co.
+
+                       phy0: ethernet-phy@0 {
+                               compatible = "intel,lxt971";
+                               reg = <0>;
+                       };
+               };
+
+               ata@3a00 {
+                       compatible = "fsl,mpc5200b-ata","fsl,mpc5200-ata";
+                       reg = <0x3a00 0x100>;
+                       interrupts = <2 7 0>;
+               };
+
+               i2c@3d40 {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       compatible = "fsl,mpc5200b-i2c","fsl,mpc5200-i2c","fsl-i2c";
+                       reg = <0x3d40 0x40>;
+                       interrupts = <2 16 0>;
+                       fsl,preserve-clocking;
+                       clock-frequency = <400000>;
+
+                       hwmon@2c {
+                               compatible = "ad,adm9240";
+                               reg = <0x2c>;
+                       };
+                       rtc@51 {
+                               compatible = "nxp,pcf8563";
+                               reg = <0x51>;
+                       };
+               };
+
+               sram@8000 {
+                       compatible = "fsl,mpc5200b-sram","fsl,mpc5200-sram";
+                       reg = <0x8000 0x4000>;
+               };
+       };
+
+       localbus {
+               compatible = "fsl,mpc5200b-lpb","fsl,mpc5200-lpb","simple-bus";
+
+               #address-cells = <2>;
+               #size-cells = <1>;
+
+               ranges = <0 0 0xff800000 0x00800000
+                         1 0 0x80000000 0x00800000
+                         3 0 0x80000000 0x00800000>;
+
+               flash@0,0 {
+                       compatible = "cfi-flash";
+                       reg = <0 0 0x00800000>;
+                       bank-width = <2>;
+                       device-width = <2>;
+                       #size-cells = <1>;
+                       #address-cells = <1>;
+
+                       partition@0 {
+                               label = "DTS";
+                               reg = <0x0 0x00100000>;
+                       };
+                       partition@100000 {
+                               label = "Kernel";
+                               reg = <0x100000 0x00200000>;
+                       };
+                       partition@300000 {
+                               label = "RootFS";
+                               reg = <0x00300000 0x00200000>;
+                       };
+                       partition@500000 {
+                               label = "user";
+                               reg = <0x00500000 0x00200000>;
+                       };
+                       partition@700000 {
+                               label = "U-Boot";
+                               reg = <0x00700000 0x00040000>;
+                       };
+                       partition@740000 {
+                               label = "Env";
+                               reg = <0x00740000 0x00010000>;
+                       };
+                       partition@750000 {
+                               label = "red. Env";
+                               reg = <0x00750000 0x00010000>;
+                       };
+                       partition@760000 {
+                               label = "reserve";
+                               reg = <0x00760000 0x000a0000>;
+                       };
+               };
+
+       };
+};
index 3838b77..0396ce7 100644 (file)
@@ -1,25 +1,27 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.30-rc2
-# Sat Apr 18 00:47:44 2009
+# Linux kernel version: 2.6.32-rc4
+# Thu Oct 15 10:33:22 2009
 #
 # CONFIG_PPC64 is not set
 
 #
 # Processor support
 #
-CONFIG_6xx=y
+CONFIG_PPC_BOOK3S_32=y
 # CONFIG_PPC_85xx is not set
 # CONFIG_PPC_8xx is not set
 # CONFIG_40x is not set
 # CONFIG_44x is not set
 # CONFIG_E200 is not set
 CONFIG_PPC_BOOK3S=y
+CONFIG_6xx=y
 CONFIG_PPC_FPU=y
 # CONFIG_ALTIVEC is not set
 CONFIG_PPC_STD_MMU=y
 CONFIG_PPC_STD_MMU_32=y
 # CONFIG_PPC_MM_SLICES is not set
+CONFIG_PPC_HAVE_PMU_SUPPORT=y
 # CONFIG_SMP is not set
 CONFIG_PPC32=y
 CONFIG_WORD_SIZE=32
@@ -30,15 +32,17 @@ CONFIG_GENERIC_TIME=y
 CONFIG_GENERIC_TIME_VSYSCALL=y
 CONFIG_GENERIC_CLOCKEVENTS=y
 CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
 # CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
+# CONFIG_NEED_PER_CPU_EMBED_FIRST_CHUNK is not set
 CONFIG_IRQ_PER_CPU=y
 CONFIG_STACKTRACE_SUPPORT=y
 CONFIG_HAVE_LATENCYTOP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
 CONFIG_LOCKDEP_SUPPORT=y
 CONFIG_RWSEM_XCHGADD_ALGORITHM=y
 CONFIG_ARCH_HAS_ILOG2_U32=y
 CONFIG_GENERIC_HWEIGHT=y
-CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_GENERIC_FIND_NEXT_BIT=y
 # CONFIG_ARCH_NO_VIRT_TO_BUS is not set
 CONFIG_PPC=y
@@ -52,11 +56,13 @@ CONFIG_OF=y
 # CONFIG_GENERIC_TBSYNC is not set
 CONFIG_AUDIT_ARCH=y
 CONFIG_GENERIC_BUG=y
+CONFIG_DTC=y
 CONFIG_DEFAULT_UIMAGE=y
 # CONFIG_PPC_DCR_NATIVE is not set
 # CONFIG_PPC_DCR_MMIO is not set
 CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_CONSTRUCTORS=y
 
 #
 # General setup
@@ -77,11 +83,12 @@ CONFIG_SYSVIPC_SYSCTL=y
 #
 # RCU Subsystem
 #
-CONFIG_CLASSIC_RCU=y
-# CONFIG_TREE_RCU is not set
-# CONFIG_PREEMPT_RCU is not set
+CONFIG_TREE_RCU=y
+# CONFIG_TREE_PREEMPT_RCU is not set
+# CONFIG_RCU_TRACE is not set
+CONFIG_RCU_FANOUT=32
+# CONFIG_RCU_FANOUT_EXACT is not set
 # CONFIG_TREE_RCU_TRACE is not set
-# CONFIG_PREEMPT_RCU_TRACE is not set
 # CONFIG_IKCONFIG is not set
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_GROUP_SCHED=y
@@ -105,7 +112,6 @@ CONFIG_ANON_INODES=y
 CONFIG_EMBEDDED=y
 # CONFIG_SYSCTL_SYSCALL is not set
 # CONFIG_KALLSYMS is not set
-# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_HOTPLUG=y
 CONFIG_PRINTK=y
 CONFIG_BUG=y
@@ -118,6 +124,13 @@ CONFIG_TIMERFD=y
 CONFIG_EVENTFD=y
 CONFIG_SHMEM=y
 CONFIG_AIO=y
+CONFIG_HAVE_PERF_EVENTS=y
+
+#
+# Kernel Performance Events And Counters
+#
+# CONFIG_PERF_EVENTS is not set
+# CONFIG_PERF_COUNTERS is not set
 CONFIG_VM_EVENT_COUNTERS=y
 CONFIG_SLUB_DEBUG=y
 CONFIG_COMPAT_BRK=y
@@ -125,14 +138,19 @@ CONFIG_COMPAT_BRK=y
 CONFIG_SLUB=y
 # CONFIG_SLOB is not set
 # CONFIG_PROFILING is not set
-# CONFIG_MARKERS is not set
 CONFIG_HAVE_OPROFILE=y
 CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y
 CONFIG_HAVE_IOREMAP_PROT=y
 CONFIG_HAVE_KPROBES=y
 CONFIG_HAVE_KRETPROBES=y
 CONFIG_HAVE_ARCH_TRACEHOOK=y
+CONFIG_HAVE_DMA_ATTRS=y
 CONFIG_HAVE_CLK=y
+CONFIG_HAVE_DMA_API_DEBUG=y
+
+#
+# GCOV-based kernel profiling
+#
 # CONFIG_SLOW_WORK is not set
 # CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
 CONFIG_SLABINFO=y
@@ -140,7 +158,7 @@ CONFIG_RT_MUTEXES=y
 CONFIG_BASE_SMALL=0
 # CONFIG_MODULES is not set
 CONFIG_BLOCK=y
-# CONFIG_LBD is not set
+CONFIG_LBDAF=y
 # CONFIG_BLK_DEV_BSG is not set
 # CONFIG_BLK_DEV_INTEGRITY is not set
 
@@ -219,11 +237,13 @@ CONFIG_BINFMT_ELF=y
 # CONFIG_HAVE_AOUT is not set
 # CONFIG_BINFMT_MISC is not set
 # CONFIG_IOMMU_HELPER is not set
+# CONFIG_SWIOTLB is not set
 CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
 CONFIG_ARCH_HAS_WALK_MEMORY=y
 CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
 # CONFIG_KEXEC is not set
 # CONFIG_CRASH_DUMP is not set
+CONFIG_MAX_ACTIVE_REGIONS=32
 CONFIG_ARCH_FLATMEM_ENABLE=y
 CONFIG_ARCH_POPULATES_NODE_MAP=y
 CONFIG_SELECT_MEMORY_MODEL=y
@@ -239,9 +259,10 @@ CONFIG_MIGRATION=y
 CONFIG_ZONE_DMA_FLAG=1
 CONFIG_BOUNCE=y
 CONFIG_VIRT_TO_BUS=y
-CONFIG_UNEVICTABLE_LRU=y
 CONFIG_HAVE_MLOCK=y
 CONFIG_HAVE_MLOCKED_PAGE_BIT=y
+# CONFIG_KSM is not set
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
 CONFIG_PPC_4K_PAGES=y
 # CONFIG_PPC_16K_PAGES is not set
 # CONFIG_PPC_64K_PAGES is not set
@@ -252,6 +273,7 @@ CONFIG_PROC_DEVICETREE=y
 CONFIG_EXTRA_TARGETS=""
 CONFIG_PM=y
 # CONFIG_PM_DEBUG is not set
+# CONFIG_PM_RUNTIME is not set
 CONFIG_SECCOMP=y
 CONFIG_ISA_DMA_API=y
 
@@ -328,6 +350,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
 # CONFIG_NETFILTER is not set
 # CONFIG_IP_DCCP is not set
 # CONFIG_IP_SCTP is not set
+# CONFIG_RDS is not set
 # CONFIG_TIPC is not set
 # CONFIG_ATM is not set
 # CONFIG_BRIDGE is not set
@@ -342,6 +365,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
 # CONFIG_PHONET is not set
+# CONFIG_IEEE802154 is not set
 # CONFIG_NET_SCHED is not set
 # CONFIG_DCB is not set
 
@@ -367,6 +391,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
 # Generic Driver Options
 #
 CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+# CONFIG_DEVTMPFS is not set
 CONFIG_STANDALONE=y
 CONFIG_PREVENT_FIRMWARE_BUILD=y
 # CONFIG_FW_LOADER is not set
@@ -457,6 +482,7 @@ CONFIG_MTD_PHYSMAP_OF=y
 # CONFIG_MTD_UBI is not set
 CONFIG_OF_DEVICE=y
 CONFIG_OF_I2C=y
+CONFIG_OF_MDIO=y
 # CONFIG_PARPORT is not set
 CONFIG_BLK_DEV=y
 # CONFIG_BLK_DEV_FD is not set
@@ -495,10 +521,6 @@ CONFIG_BLK_DEV_SD=y
 # CONFIG_BLK_DEV_SR is not set
 CONFIG_CHR_DEV_SG=y
 # CONFIG_CHR_DEV_SCH is not set
-
-#
-# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
-#
 # CONFIG_SCSI_MULTI_LUN is not set
 # CONFIG_SCSI_CONSTANTS is not set
 # CONFIG_SCSI_LOGGING is not set
@@ -519,7 +541,6 @@ CONFIG_CHR_DEV_SG=y
 # CONFIG_MD is not set
 # CONFIG_MACINTOSH_DRIVERS is not set
 CONFIG_NETDEVICES=y
-CONFIG_COMPAT_NET_DEV_OPS=y
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
 # CONFIG_MACVLAN is not set
@@ -558,14 +579,14 @@ CONFIG_NET_ETHERNET=y
 # CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
 # CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
 # CONFIG_B44 is not set
+# CONFIG_KS8842 is not set
+# CONFIG_KS8851_MLL is not set
 CONFIG_FEC_MPC52xx=y
 CONFIG_FEC_MPC52xx_MDIO=y
+# CONFIG_XILINX_EMACLITE is not set
 # CONFIG_NETDEV_1000 is not set
 # CONFIG_NETDEV_10000 is not set
-
-#
-# Wireless LAN
-#
+CONFIG_WLAN=y
 # CONFIG_WLAN_PRE80211 is not set
 # CONFIG_WLAN_80211 is not set
 
@@ -636,6 +657,7 @@ CONFIG_LEGACY_PTY_COUNT=256
 # CONFIG_TCG_TPM is not set
 CONFIG_I2C=y
 CONFIG_I2C_BOARDINFO=y
+CONFIG_I2C_COMPAT=y
 CONFIG_I2C_CHARDEV=y
 CONFIG_I2C_HELPER_AUTO=y
 
@@ -646,6 +668,7 @@ CONFIG_I2C_HELPER_AUTO=y
 #
 # I2C system bus drivers (mostly embedded / system-on-chip)
 #
+# CONFIG_I2C_DESIGNWARE is not set
 CONFIG_I2C_MPC=y
 # CONFIG_I2C_OCORES is not set
 # CONFIG_I2C_SIMTEC is not set
@@ -666,23 +689,23 @@ CONFIG_I2C_MPC=y
 # Miscellaneous I2C Chip support
 #
 # CONFIG_DS1682 is not set
-# CONFIG_SENSORS_PCF8574 is not set
-# CONFIG_PCF8575 is not set
-# CONFIG_SENSORS_PCA9539 is not set
-# CONFIG_SENSORS_MAX6875 is not set
 # CONFIG_SENSORS_TSL2550 is not set
 # CONFIG_I2C_DEBUG_CORE is not set
 # CONFIG_I2C_DEBUG_ALGO is not set
 # CONFIG_I2C_DEBUG_BUS is not set
 # CONFIG_I2C_DEBUG_CHIP is not set
 # CONFIG_SPI is not set
+
+#
+# PPS support
+#
+# CONFIG_PPS is not set
 CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
 # CONFIG_GPIOLIB is not set
 # CONFIG_W1 is not set
 # CONFIG_POWER_SUPPLY is not set
 # CONFIG_HWMON is not set
 # CONFIG_THERMAL is not set
-# CONFIG_THERMAL_HWMON is not set
 CONFIG_WATCHDOG=y
 # CONFIG_WATCHDOG_NOWAYOUT is not set
 
@@ -713,25 +736,12 @@ CONFIG_SSB_POSSIBLE=y
 # CONFIG_MFD_TMIO is not set
 # CONFIG_PMIC_DA903X is not set
 # CONFIG_MFD_WM8400 is not set
+# CONFIG_MFD_WM831X is not set
 # CONFIG_MFD_WM8350_I2C is not set
 # CONFIG_MFD_PCF50633 is not set
+# CONFIG_AB3100_CORE is not set
 # CONFIG_REGULATOR is not set
-
-#
-# Multimedia devices
-#
-
-#
-# Multimedia core support
-#
-# CONFIG_VIDEO_DEV is not set
-# CONFIG_DVB_CORE is not set
-# CONFIG_VIDEO_MEDIA is not set
-
-#
-# Multimedia drivers
-#
-# CONFIG_DAB is not set
+# CONFIG_MEDIA_SUPPORT is not set
 
 #
 # Graphics support
@@ -775,11 +785,12 @@ CONFIG_USB_DEVICEFS=y
 # CONFIG_USB_OXU210HP_HCD is not set
 # CONFIG_USB_ISP116X_HCD is not set
 # CONFIG_USB_ISP1760_HCD is not set
+# CONFIG_USB_ISP1362_HCD is not set
 CONFIG_USB_OHCI_HCD=y
 CONFIG_USB_OHCI_HCD_PPC_SOC=y
-CONFIG_USB_OHCI_HCD_PPC_OF=y
 CONFIG_USB_OHCI_HCD_PPC_OF_BE=y
 # CONFIG_USB_OHCI_HCD_PPC_OF_LE is not set
+CONFIG_USB_OHCI_HCD_PPC_OF=y
 CONFIG_USB_OHCI_BIG_ENDIAN_DESC=y
 CONFIG_USB_OHCI_BIG_ENDIAN_MMIO=y
 # CONFIG_USB_OHCI_LITTLE_ENDIAN is not set
@@ -866,6 +877,10 @@ CONFIG_USB_STORAGE=y
 # CONFIG_DMADEVICES is not set
 # CONFIG_AUXDISPLAY is not set
 # CONFIG_UIO is not set
+
+#
+# TI VLYNQ
+#
 # CONFIG_STAGING is not set
 
 #
@@ -885,10 +900,13 @@ CONFIG_FS_MBCACHE=y
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
 # CONFIG_FS_POSIX_ACL is not set
-CONFIG_FILE_LOCKING=y
 # CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
 # CONFIG_OCFS2_FS is not set
 # CONFIG_BTRFS_FS is not set
+# CONFIG_NILFS2_FS is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
 CONFIG_DNOTIFY=y
 CONFIG_INOTIFY=y
 CONFIG_INOTIFY_USER=y
@@ -959,12 +977,12 @@ CONFIG_CRAMFS=y
 # CONFIG_ROMFS_FS is not set
 # CONFIG_SYSV_FS is not set
 # CONFIG_UFS_FS is not set
-# CONFIG_NILFS2_FS is not set
 CONFIG_NETWORK_FILESYSTEMS=y
 CONFIG_NFS_FS=y
 CONFIG_NFS_V3=y
 # CONFIG_NFS_V3_ACL is not set
 CONFIG_NFS_V4=y
+# CONFIG_NFS_V4_1 is not set
 CONFIG_ROOT_NFS=y
 # CONFIG_NFSD is not set
 CONFIG_LOCKD=y
@@ -1064,6 +1082,7 @@ CONFIG_HAS_IOPORT=y
 CONFIG_HAS_DMA=y
 CONFIG_HAVE_LMB=y
 CONFIG_NLATTR=y
+CONFIG_GENERIC_ATOMIC64=y
 
 #
 # Kernel hacking
@@ -1073,6 +1092,7 @@ CONFIG_ENABLE_WARN_DEPRECATED=y
 CONFIG_ENABLE_MUST_CHECK=y
 CONFIG_FRAME_WARN=1024
 # CONFIG_MAGIC_SYSRQ is not set
+# CONFIG_STRIP_ASM_SYMS is not set
 # CONFIG_UNUSED_SYMBOLS is not set
 # CONFIG_DEBUG_FS is not set
 # CONFIG_HEADERS_CHECK is not set
@@ -1090,10 +1110,14 @@ CONFIG_SCHED_DEBUG=y
 # CONFIG_DEBUG_OBJECTS is not set
 # CONFIG_SLUB_DEBUG_ON is not set
 # CONFIG_SLUB_STATS is not set
+# CONFIG_DEBUG_KMEMLEAK is not set
 # CONFIG_DEBUG_RT_MUTEXES is not set
 # CONFIG_RT_MUTEX_TESTER is not set
 # CONFIG_DEBUG_SPINLOCK is not set
 # CONFIG_DEBUG_MUTEXES is not set
+# CONFIG_DEBUG_LOCK_ALLOC is not set
+# CONFIG_PROVE_LOCKING is not set
+# CONFIG_LOCK_STAT is not set
 # CONFIG_DEBUG_SPINLOCK_SLEEP is not set
 # CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
 # CONFIG_DEBUG_KOBJECT is not set
@@ -1105,11 +1129,12 @@ CONFIG_SCHED_DEBUG=y
 # CONFIG_DEBUG_LIST is not set
 # CONFIG_DEBUG_SG is not set
 # CONFIG_DEBUG_NOTIFIERS is not set
-# CONFIG_BOOT_PRINTK_DELAY is not set
+# CONFIG_DEBUG_CREDENTIALS is not set
 # CONFIG_RCU_TORTURE_TEST is not set
 # CONFIG_RCU_CPU_STALL_DETECTOR is not set
 # CONFIG_BACKTRACE_SELF_TEST is not set
 # CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
+# CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set
 # CONFIG_FAULT_INJECTION is not set
 # CONFIG_LATENCYTOP is not set
 # CONFIG_DEBUG_PAGEALLOC is not set
@@ -1118,23 +1143,25 @@ CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y
 CONFIG_HAVE_DYNAMIC_FTRACE=y
 CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
 CONFIG_TRACING_SUPPORT=y
-
-#
-# Tracers
-#
+CONFIG_FTRACE=y
 # CONFIG_FUNCTION_TRACER is not set
+# CONFIG_IRQSOFF_TRACER is not set
 # CONFIG_SCHED_TRACER is not set
-# CONFIG_CONTEXT_SWITCH_TRACER is not set
-# CONFIG_EVENT_TRACER is not set
+# CONFIG_ENABLE_DEFAULT_TRACERS is not set
 # CONFIG_BOOT_TRACER is not set
-# CONFIG_TRACE_BRANCH_PROFILING is not set
+CONFIG_BRANCH_PROFILE_NONE=y
+# CONFIG_PROFILE_ANNOTATED_BRANCHES is not set
+# CONFIG_PROFILE_ALL_BRANCHES is not set
 # CONFIG_STACK_TRACER is not set
 # CONFIG_KMEMTRACE is not set
 # CONFIG_WORKQUEUE_TRACER is not set
 # CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_DMA_API_DEBUG is not set
 # CONFIG_SAMPLES is not set
 CONFIG_HAVE_ARCH_KGDB=y
 # CONFIG_KGDB is not set
+# CONFIG_PPC_DISABLE_WERROR is not set
+CONFIG_PPC_WERROR=y
 CONFIG_PRINT_STACK_DEPTH=64
 # CONFIG_DEBUG_STACKOVERFLOW is not set
 # CONFIG_DEBUG_STACK_USAGE is not set
@@ -1159,7 +1186,6 @@ CONFIG_CRYPTO=y
 #
 # Crypto core or helper
 #
-# CONFIG_CRYPTO_FIPS is not set
 CONFIG_CRYPTO_ALGAPI=y
 CONFIG_CRYPTO_ALGAPI2=y
 CONFIG_CRYPTO_AEAD2=y
@@ -1200,11 +1226,13 @@ CONFIG_CRYPTO_PCBC=y
 #
 # CONFIG_CRYPTO_HMAC is not set
 # CONFIG_CRYPTO_XCBC is not set
+# CONFIG_CRYPTO_VMAC is not set
 
 #
 # Digest
 #
 # CONFIG_CRYPTO_CRC32C is not set
+# CONFIG_CRYPTO_GHASH is not set
 # CONFIG_CRYPTO_MD4 is not set
 CONFIG_CRYPTO_MD5=y
 # CONFIG_CRYPTO_MICHAEL_MIC is not set
index 29b0f34..f5c07fd 100644 (file)
@@ -1,25 +1,27 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.30-rc2
-# Sat Apr 18 00:48:04 2009
+# Linux kernel version: 2.6.32-rc4
+# Thu Oct 15 10:33:24 2009
 #
 # CONFIG_PPC64 is not set
 
 #
 # Processor support
 #
-CONFIG_6xx=y
+CONFIG_PPC_BOOK3S_32=y
 # CONFIG_PPC_85xx is not set
 # CONFIG_PPC_8xx is not set
 # CONFIG_40x is not set
 # CONFIG_44x is not set
 # CONFIG_E200 is not set
 CONFIG_PPC_BOOK3S=y
+CONFIG_6xx=y
 CONFIG_PPC_FPU=y
 # CONFIG_ALTIVEC is not set
 CONFIG_PPC_STD_MMU=y
 CONFIG_PPC_STD_MMU_32=y
 # CONFIG_PPC_MM_SLICES is not set
+CONFIG_PPC_HAVE_PMU_SUPPORT=y
 # CONFIG_SMP is not set
 CONFIG_PPC32=y
 CONFIG_WORD_SIZE=32
@@ -30,15 +32,17 @@ CONFIG_GENERIC_TIME=y
 CONFIG_GENERIC_TIME_VSYSCALL=y
 CONFIG_GENERIC_CLOCKEVENTS=y
 CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
 # CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
+# CONFIG_NEED_PER_CPU_EMBED_FIRST_CHUNK is not set
 CONFIG_IRQ_PER_CPU=y
 CONFIG_STACKTRACE_SUPPORT=y
 CONFIG_HAVE_LATENCYTOP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
 CONFIG_LOCKDEP_SUPPORT=y
 CONFIG_RWSEM_XCHGADD_ALGORITHM=y
 CONFIG_ARCH_HAS_ILOG2_U32=y
 CONFIG_GENERIC_HWEIGHT=y
-CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_GENERIC_FIND_NEXT_BIT=y
 # CONFIG_ARCH_NO_VIRT_TO_BUS is not set
 CONFIG_PPC=y
@@ -52,12 +56,14 @@ CONFIG_OF=y
 # CONFIG_GENERIC_TBSYNC is not set
 CONFIG_AUDIT_ARCH=y
 CONFIG_GENERIC_BUG=y
+CONFIG_DTC=y
 CONFIG_DEFAULT_UIMAGE=y
 CONFIG_ARCH_SUSPEND_POSSIBLE=y
 # CONFIG_PPC_DCR_NATIVE is not set
 # CONFIG_PPC_DCR_MMIO is not set
 CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_CONSTRUCTORS=y
 
 #
 # General setup
@@ -78,11 +84,12 @@ CONFIG_SYSVIPC_SYSCTL=y
 #
 # RCU Subsystem
 #
-CONFIG_CLASSIC_RCU=y
-# CONFIG_TREE_RCU is not set
-# CONFIG_PREEMPT_RCU is not set
+CONFIG_TREE_RCU=y
+# CONFIG_TREE_PREEMPT_RCU is not set
+# CONFIG_RCU_TRACE is not set
+CONFIG_RCU_FANOUT=32
+# CONFIG_RCU_FANOUT_EXACT is not set
 # CONFIG_TREE_RCU_TRACE is not set
-# CONFIG_PREEMPT_RCU_TRACE is not set
 # CONFIG_IKCONFIG is not set
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_GROUP_SCHED=y
@@ -106,7 +113,6 @@ CONFIG_ANON_INODES=y
 CONFIG_EMBEDDED=y
 # CONFIG_SYSCTL_SYSCALL is not set
 # CONFIG_KALLSYMS is not set
-# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_HOTPLUG=y
 CONFIG_PRINTK=y
 CONFIG_BUG=y
@@ -119,6 +125,13 @@ CONFIG_TIMERFD=y
 CONFIG_EVENTFD=y
 CONFIG_SHMEM=y
 CONFIG_AIO=y
+CONFIG_HAVE_PERF_EVENTS=y
+
+#
+# Kernel Performance Events And Counters
+#
+# CONFIG_PERF_EVENTS is not set
+# CONFIG_PERF_COUNTERS is not set
 CONFIG_VM_EVENT_COUNTERS=y
 CONFIG_PCI_QUIRKS=y
 CONFIG_SLUB_DEBUG=y
@@ -127,14 +140,19 @@ CONFIG_COMPAT_BRK=y
 CONFIG_SLUB=y
 # CONFIG_SLOB is not set
 # CONFIG_PROFILING is not set
-# CONFIG_MARKERS is not set
 CONFIG_HAVE_OPROFILE=y
 CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y
 CONFIG_HAVE_IOREMAP_PROT=y
 CONFIG_HAVE_KPROBES=y
 CONFIG_HAVE_KRETPROBES=y
 CONFIG_HAVE_ARCH_TRACEHOOK=y
+CONFIG_HAVE_DMA_ATTRS=y
 CONFIG_HAVE_CLK=y
+CONFIG_HAVE_DMA_API_DEBUG=y
+
+#
+# GCOV-based kernel profiling
+#
 # CONFIG_SLOW_WORK is not set
 # CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
 CONFIG_SLABINFO=y
@@ -147,7 +165,7 @@ CONFIG_MODULE_UNLOAD=y
 # CONFIG_MODVERSIONS is not set
 # CONFIG_MODULE_SRCVERSION_ALL is not set
 CONFIG_BLOCK=y
-# CONFIG_LBD is not set
+CONFIG_LBDAF=y
 # CONFIG_BLK_DEV_BSG is not set
 # CONFIG_BLK_DEV_INTEGRITY is not set
 
@@ -228,11 +246,13 @@ CONFIG_BINFMT_ELF=y
 # CONFIG_HAVE_AOUT is not set
 # CONFIG_BINFMT_MISC is not set
 # CONFIG_IOMMU_HELPER is not set
+# CONFIG_SWIOTLB is not set
 CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
 CONFIG_ARCH_HAS_WALK_MEMORY=y
 CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
 # CONFIG_KEXEC is not set
 # CONFIG_CRASH_DUMP is not set
+CONFIG_MAX_ACTIVE_REGIONS=32
 CONFIG_ARCH_FLATMEM_ENABLE=y
 CONFIG_ARCH_POPULATES_NODE_MAP=y
 CONFIG_SELECT_MEMORY_MODEL=y
@@ -248,9 +268,10 @@ CONFIG_MIGRATION=y
 CONFIG_ZONE_DMA_FLAG=1
 CONFIG_BOUNCE=y
 CONFIG_VIRT_TO_BUS=y
-CONFIG_UNEVICTABLE_LRU=y
 CONFIG_HAVE_MLOCK=y
 CONFIG_HAVE_MLOCKED_PAGE_BIT=y
+# CONFIG_KSM is not set
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
 CONFIG_PPC_4K_PAGES=y
 # CONFIG_PPC_16K_PAGES is not set
 # CONFIG_PPC_64K_PAGES is not set
@@ -264,6 +285,7 @@ CONFIG_PM=y
 CONFIG_PM_SLEEP=y
 CONFIG_SUSPEND=y
 CONFIG_SUSPEND_FREEZER=y
+# CONFIG_PM_RUNTIME is not set
 CONFIG_SECCOMP=y
 CONFIG_ISA_DMA_API=y
 
@@ -348,6 +370,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
 # CONFIG_NETFILTER is not set
 # CONFIG_IP_DCCP is not set
 # CONFIG_IP_SCTP is not set
+# CONFIG_RDS is not set
 # CONFIG_TIPC is not set
 # CONFIG_ATM is not set
 # CONFIG_BRIDGE is not set
@@ -362,6 +385,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
 # CONFIG_PHONET is not set
+# CONFIG_IEEE802154 is not set
 # CONFIG_NET_SCHED is not set
 # CONFIG_DCB is not set
 
@@ -387,6 +411,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
 # Generic Driver Options
 #
 CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+# CONFIG_DEVTMPFS is not set
 CONFIG_STANDALONE=y
 CONFIG_PREVENT_FIRMWARE_BUILD=y
 # CONFIG_FW_LOADER is not set
@@ -397,6 +422,7 @@ CONFIG_PREVENT_FIRMWARE_BUILD=y
 # CONFIG_MTD is not set
 CONFIG_OF_DEVICE=y
 CONFIG_OF_I2C=y
+CONFIG_OF_MDIO=y
 # CONFIG_PARPORT is not set
 CONFIG_BLK_DEV=y
 # CONFIG_BLK_DEV_FD is not set
@@ -431,7 +457,9 @@ CONFIG_MISC_DEVICES=y
 #
 # CONFIG_EEPROM_AT24 is not set
 # CONFIG_EEPROM_LEGACY is not set
+# CONFIG_EEPROM_MAX6875 is not set
 # CONFIG_EEPROM_93CX6 is not set
+# CONFIG_CB710_CORE is not set
 CONFIG_HAVE_IDE=y
 # CONFIG_IDE is not set
 
@@ -454,10 +482,6 @@ CONFIG_BLK_DEV_SD=y
 # CONFIG_BLK_DEV_SR is not set
 # CONFIG_CHR_DEV_SG is not set
 # CONFIG_CHR_DEV_SCH is not set
-
-#
-# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
-#
 # CONFIG_SCSI_MULTI_LUN is not set
 # CONFIG_SCSI_CONSTANTS is not set
 # CONFIG_SCSI_LOGGING is not set
@@ -475,6 +499,8 @@ CONFIG_SCSI_WAIT_SCAN=m
 CONFIG_SCSI_LOWLEVEL=y
 # CONFIG_ISCSI_TCP is not set
 # CONFIG_SCSI_CXGB3_ISCSI is not set
+# CONFIG_SCSI_BNX2_ISCSI is not set
+# CONFIG_BE2ISCSI is not set
 # CONFIG_BLK_DEV_3W_XXXX_RAID is not set
 # CONFIG_SCSI_3W_9XXX is not set
 # CONFIG_SCSI_ACARD is not set
@@ -483,6 +509,7 @@ CONFIG_SCSI_LOWLEVEL=y
 # CONFIG_SCSI_AIC7XXX_OLD is not set
 # CONFIG_SCSI_AIC79XX is not set
 # CONFIG_SCSI_AIC94XX is not set
+# CONFIG_SCSI_MVSAS is not set
 # CONFIG_SCSI_DPT_I2O is not set
 # CONFIG_SCSI_ADVANSYS is not set
 # CONFIG_SCSI_ARCMSR is not set
@@ -502,7 +529,6 @@ CONFIG_SCSI_LOWLEVEL=y
 # CONFIG_SCSI_IPS is not set
 # CONFIG_SCSI_INITIO is not set
 # CONFIG_SCSI_INIA100 is not set
-# CONFIG_SCSI_MVSAS is not set
 # CONFIG_SCSI_STEX is not set
 # CONFIG_SCSI_SYM53C8XX_2 is not set
 # CONFIG_SCSI_IPR is not set
@@ -514,11 +540,14 @@ CONFIG_SCSI_LOWLEVEL=y
 # CONFIG_SCSI_DC390T is not set
 # CONFIG_SCSI_NSP32 is not set
 # CONFIG_SCSI_DEBUG is not set
+# CONFIG_SCSI_PMCRAID is not set
 # CONFIG_SCSI_SRP is not set
+# CONFIG_SCSI_BFA_FC is not set
 # CONFIG_SCSI_DH is not set
 # CONFIG_SCSI_OSD_INITIATOR is not set
 CONFIG_ATA=y
 # CONFIG_ATA_NONSTANDARD is not set
+CONFIG_ATA_VERBOSE_ERROR=y
 CONFIG_SATA_PMP=y
 # CONFIG_SATA_AHCI is not set
 # CONFIG_SATA_SIL24 is not set
@@ -540,6 +569,7 @@ CONFIG_ATA_SFF=y
 # CONFIG_PATA_ALI is not set
 # CONFIG_PATA_AMD is not set
 # CONFIG_PATA_ARTOP is not set
+# CONFIG_PATA_ATP867X is not set
 # CONFIG_PATA_ATIIXP is not set
 # CONFIG_PATA_CMD640_PCI is not set
 # CONFIG_PATA_CMD64X is not set
@@ -568,6 +598,7 @@ CONFIG_PATA_MPC52xx=y
 # CONFIG_PATA_OPTIDMA is not set
 # CONFIG_PATA_PDC_OLD is not set
 # CONFIG_PATA_RADISYS is not set
+# CONFIG_PATA_RDC is not set
 # CONFIG_PATA_RZ1000 is not set
 # CONFIG_PATA_SC1200 is not set
 # CONFIG_PATA_SERVERWORKS is not set
@@ -586,14 +617,17 @@ CONFIG_PATA_MPC52xx=y
 #
 
 #
-# Enable only one of the two stacks, unless you know what you are doing
+# You can enable one or both FireWire driver stacks.
+#
+
+#
+# See the help texts for more information.
 #
 # CONFIG_FIREWIRE is not set
 # CONFIG_IEEE1394 is not set
 # CONFIG_I2O is not set
 # CONFIG_MACINTOSH_DRIVERS is not set
 CONFIG_NETDEVICES=y
-CONFIG_COMPAT_NET_DEV_OPS=y
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
 # CONFIG_MACVLAN is not set
@@ -640,9 +674,12 @@ CONFIG_NET_ETHERNET=y
 # CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
 # CONFIG_NET_PCI is not set
 # CONFIG_B44 is not set
+# CONFIG_KS8842 is not set
+# CONFIG_KS8851_MLL is not set
 CONFIG_FEC_MPC52xx=y
 CONFIG_FEC_MPC52xx_MDIO=y
 # CONFIG_ATL2 is not set
+# CONFIG_XILINX_EMACLITE is not set
 CONFIG_NETDEV_1000=y
 # CONFIG_ACENIC is not set
 # CONFIG_DL2K is not set
@@ -661,6 +698,8 @@ CONFIG_NETDEV_1000=y
 # CONFIG_VIA_VELOCITY is not set
 # CONFIG_TIGON3 is not set
 # CONFIG_BNX2 is not set
+# CONFIG_CNIC is not set
+# CONFIG_MV643XX_ETH is not set
 # CONFIG_QLA3XXX is not set
 # CONFIG_ATL1 is not set
 # CONFIG_ATL1E is not set
@@ -686,10 +725,7 @@ CONFIG_CHELSIO_T3_DEPENDS=y
 # CONFIG_SFC is not set
 # CONFIG_BE2NET is not set
 # CONFIG_TR is not set
-
-#
-# Wireless LAN
-#
+CONFIG_WLAN=y
 # CONFIG_WLAN_PRE80211 is not set
 # CONFIG_WLAN_80211 is not set
 
@@ -759,6 +795,7 @@ CONFIG_GEN_RTC=y
 CONFIG_DEVPORT=y
 CONFIG_I2C=y
 CONFIG_I2C_BOARDINFO=y
+CONFIG_I2C_COMPAT=y
 CONFIG_I2C_CHARDEV=y
 CONFIG_I2C_HELPER_AUTO=y
 
@@ -787,6 +824,7 @@ CONFIG_I2C_HELPER_AUTO=y
 #
 # I2C system bus drivers (mostly embedded / system-on-chip)
 #
+# CONFIG_I2C_DESIGNWARE is not set
 CONFIG_I2C_MPC=y
 # CONFIG_I2C_OCORES is not set
 # CONFIG_I2C_SIMTEC is not set
@@ -812,23 +850,23 @@ CONFIG_I2C_MPC=y
 # Miscellaneous I2C Chip support
 #
 # CONFIG_DS1682 is not set
-# CONFIG_SENSORS_PCF8574 is not set
-# CONFIG_PCF8575 is not set
-# CONFIG_SENSORS_PCA9539 is not set
-# CONFIG_SENSORS_MAX6875 is not set
 # CONFIG_SENSORS_TSL2550 is not set
 # CONFIG_I2C_DEBUG_CORE is not set
 # CONFIG_I2C_DEBUG_ALGO is not set
 # CONFIG_I2C_DEBUG_BUS is not set
 # CONFIG_I2C_DEBUG_CHIP is not set
 # CONFIG_SPI is not set
+
+#
+# PPS support
+#
+# CONFIG_PPS is not set
 CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
 # CONFIG_GPIOLIB is not set
 # CONFIG_W1 is not set
 # CONFIG_POWER_SUPPLY is not set
 # CONFIG_HWMON is not set
 # CONFIG_THERMAL is not set
-# CONFIG_THERMAL_HWMON is not set
 # CONFIG_WATCHDOG is not set
 CONFIG_SSB_POSSIBLE=y
 
@@ -847,30 +885,18 @@ CONFIG_SSB_POSSIBLE=y
 # CONFIG_MFD_TMIO is not set
 # CONFIG_PMIC_DA903X is not set
 # CONFIG_MFD_WM8400 is not set
+# CONFIG_MFD_WM831X is not set
 # CONFIG_MFD_WM8350_I2C is not set
 # CONFIG_MFD_PCF50633 is not set
+# CONFIG_AB3100_CORE is not set
 # CONFIG_REGULATOR is not set
-
-#
-# Multimedia devices
-#
-
-#
-# Multimedia core support
-#
-# CONFIG_VIDEO_DEV is not set
-# CONFIG_DVB_CORE is not set
-# CONFIG_VIDEO_MEDIA is not set
-
-#
-# Multimedia drivers
-#
-# CONFIG_DAB is not set
+# CONFIG_MEDIA_SUPPORT is not set
 
 #
 # Graphics support
 #
 # CONFIG_AGP is not set
+CONFIG_VGA_ARB=y
 # CONFIG_DRM is not set
 # CONFIG_VGASTATE is not set
 CONFIG_VIDEO_OUTPUT_CONTROL=m
@@ -913,6 +939,10 @@ CONFIG_USB_ARCH_HAS_EHCI=y
 # CONFIG_DMADEVICES is not set
 # CONFIG_AUXDISPLAY is not set
 # CONFIG_UIO is not set
+
+#
+# TI VLYNQ
+#
 # CONFIG_STAGING is not set
 
 #
@@ -932,10 +962,13 @@ CONFIG_FS_MBCACHE=y
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
 # CONFIG_FS_POSIX_ACL is not set
-CONFIG_FILE_LOCKING=y
 # CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
 # CONFIG_OCFS2_FS is not set
 # CONFIG_BTRFS_FS is not set
+# CONFIG_NILFS2_FS is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
 CONFIG_DNOTIFY=y
 CONFIG_INOTIFY=y
 CONFIG_INOTIFY_USER=y
@@ -992,12 +1025,12 @@ CONFIG_MISC_FILESYSTEMS=y
 # CONFIG_ROMFS_FS is not set
 # CONFIG_SYSV_FS is not set
 # CONFIG_UFS_FS is not set
-# CONFIG_NILFS2_FS is not set
 CONFIG_NETWORK_FILESYSTEMS=y
 CONFIG_NFS_FS=y
 CONFIG_NFS_V3=y
 # CONFIG_NFS_V3_ACL is not set
 CONFIG_NFS_V4=y
+# CONFIG_NFS_V4_1 is not set
 CONFIG_ROOT_NFS=y
 # CONFIG_NFSD is not set
 CONFIG_LOCKD=y
@@ -1041,6 +1074,7 @@ CONFIG_HAS_IOPORT=y
 CONFIG_HAS_DMA=y
 CONFIG_HAVE_LMB=y
 CONFIG_NLATTR=y
+CONFIG_GENERIC_ATOMIC64=y
 
 #
 # Kernel hacking
@@ -1050,6 +1084,7 @@ CONFIG_ENABLE_WARN_DEPRECATED=y
 CONFIG_ENABLE_MUST_CHECK=y
 CONFIG_FRAME_WARN=1024
 # CONFIG_MAGIC_SYSRQ is not set
+# CONFIG_STRIP_ASM_SYMS is not set
 # CONFIG_UNUSED_SYMBOLS is not set
 # CONFIG_DEBUG_FS is not set
 # CONFIG_HEADERS_CHECK is not set
@@ -1067,10 +1102,14 @@ CONFIG_SCHED_DEBUG=y
 # CONFIG_DEBUG_OBJECTS is not set
 # CONFIG_SLUB_DEBUG_ON is not set
 # CONFIG_SLUB_STATS is not set
+# CONFIG_DEBUG_KMEMLEAK is not set
 # CONFIG_DEBUG_RT_MUTEXES is not set
 # CONFIG_RT_MUTEX_TESTER is not set
 # CONFIG_DEBUG_SPINLOCK is not set
 # CONFIG_DEBUG_MUTEXES is not set
+# CONFIG_DEBUG_LOCK_ALLOC is not set
+# CONFIG_PROVE_LOCKING is not set
+# CONFIG_LOCK_STAT is not set
 # CONFIG_DEBUG_SPINLOCK_SLEEP is not set
 # CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
 # CONFIG_DEBUG_KOBJECT is not set
@@ -1082,11 +1121,12 @@ CONFIG_DEBUG_INFO=y
 # CONFIG_DEBUG_LIST is not set
 # CONFIG_DEBUG_SG is not set
 # CONFIG_DEBUG_NOTIFIERS is not set
-# CONFIG_BOOT_PRINTK_DELAY is not set
+# CONFIG_DEBUG_CREDENTIALS is not set
 # CONFIG_RCU_TORTURE_TEST is not set
 # CONFIG_RCU_CPU_STALL_DETECTOR is not set
 # CONFIG_BACKTRACE_SELF_TEST is not set
 # CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
+# CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set
 # CONFIG_FAULT_INJECTION is not set
 # CONFIG_LATENCYTOP is not set
 # CONFIG_DEBUG_PAGEALLOC is not set
@@ -1095,23 +1135,25 @@ CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y
 CONFIG_HAVE_DYNAMIC_FTRACE=y
 CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
 CONFIG_TRACING_SUPPORT=y
-
-#
-# Tracers
-#
+CONFIG_FTRACE=y
 # CONFIG_FUNCTION_TRACER is not set
+# CONFIG_IRQSOFF_TRACER is not set
 # CONFIG_SCHED_TRACER is not set
-# CONFIG_CONTEXT_SWITCH_TRACER is not set
-# CONFIG_EVENT_TRACER is not set
+# CONFIG_ENABLE_DEFAULT_TRACERS is not set
 # CONFIG_BOOT_TRACER is not set
-# CONFIG_TRACE_BRANCH_PROFILING is not set
+CONFIG_BRANCH_PROFILE_NONE=y
+# CONFIG_PROFILE_ANNOTATED_BRANCHES is not set
+# CONFIG_PROFILE_ALL_BRANCHES is not set
 # CONFIG_STACK_TRACER is not set
 # CONFIG_KMEMTRACE is not set
 # CONFIG_WORKQUEUE_TRACER is not set
 # CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_DMA_API_DEBUG is not set
 # CONFIG_SAMPLES is not set
 CONFIG_HAVE_ARCH_KGDB=y
 # CONFIG_KGDB is not set
+# CONFIG_PPC_DISABLE_WERROR is not set
+CONFIG_PPC_WERROR=y
 CONFIG_PRINT_STACK_DEPTH=64
 # CONFIG_DEBUG_STACKOVERFLOW is not set
 # CONFIG_DEBUG_STACK_USAGE is not set
@@ -1136,7 +1178,6 @@ CONFIG_CRYPTO=y
 #
 # Crypto core or helper
 #
-# CONFIG_CRYPTO_FIPS is not set
 CONFIG_CRYPTO_ALGAPI=y
 CONFIG_CRYPTO_ALGAPI2=y
 CONFIG_CRYPTO_AEAD2=y
@@ -1178,11 +1219,13 @@ CONFIG_CRYPTO_CBC=y
 #
 # CONFIG_CRYPTO_HMAC is not set
 # CONFIG_CRYPTO_XCBC is not set
+# CONFIG_CRYPTO_VMAC is not set
 
 #
 # Digest
 #
 # CONFIG_CRYPTO_CRC32C is not set
+# CONFIG_CRYPTO_GHASH is not set
 # CONFIG_CRYPTO_MD4 is not set
 CONFIG_CRYPTO_MD5=y
 # CONFIG_CRYPTO_MICHAEL_MIC is not set
index 07b6b26..4f77a1b 100644 (file)
@@ -1,25 +1,27 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.30-rc2
-# Sat Apr 18 00:48:22 2009
+# Linux kernel version: 2.6.32-rc4
+# Thu Oct 15 10:33:22 2009
 #
 # CONFIG_PPC64 is not set
 
 #
 # Processor support
 #
-CONFIG_6xx=y
+CONFIG_PPC_BOOK3S_32=y
 # CONFIG_PPC_85xx is not set
 # CONFIG_PPC_8xx is not set
 # CONFIG_40x is not set
 # CONFIG_44x is not set
 # CONFIG_E200 is not set
 CONFIG_PPC_BOOK3S=y
+CONFIG_6xx=y
 CONFIG_PPC_FPU=y
 # CONFIG_ALTIVEC is not set
 CONFIG_PPC_STD_MMU=y
 CONFIG_PPC_STD_MMU_32=y
 # CONFIG_PPC_MM_SLICES is not set
+CONFIG_PPC_HAVE_PMU_SUPPORT=y
 # CONFIG_SMP is not set
 CONFIG_PPC32=y
 CONFIG_WORD_SIZE=32
@@ -30,15 +32,17 @@ CONFIG_GENERIC_TIME=y
 CONFIG_GENERIC_TIME_VSYSCALL=y
 CONFIG_GENERIC_CLOCKEVENTS=y
 CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
 # CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
+# CONFIG_NEED_PER_CPU_EMBED_FIRST_CHUNK is not set
 CONFIG_IRQ_PER_CPU=y
 CONFIG_STACKTRACE_SUPPORT=y
 CONFIG_HAVE_LATENCYTOP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
 CONFIG_LOCKDEP_SUPPORT=y
 CONFIG_RWSEM_XCHGADD_ALGORITHM=y
 CONFIG_ARCH_HAS_ILOG2_U32=y
 CONFIG_GENERIC_HWEIGHT=y
-CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_GENERIC_FIND_NEXT_BIT=y
 # CONFIG_ARCH_NO_VIRT_TO_BUS is not set
 CONFIG_PPC=y
@@ -52,11 +56,13 @@ CONFIG_OF=y
 # CONFIG_GENERIC_TBSYNC is not set
 CONFIG_AUDIT_ARCH=y
 CONFIG_GENERIC_BUG=y
+CONFIG_DTC=y
 CONFIG_DEFAULT_UIMAGE=y
 # CONFIG_PPC_DCR_NATIVE is not set
 # CONFIG_PPC_DCR_MMIO is not set
 CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_CONSTRUCTORS=y
 
 #
 # General setup
@@ -77,11 +83,12 @@ CONFIG_SYSVIPC_SYSCTL=y
 #
 # RCU Subsystem
 #
-CONFIG_CLASSIC_RCU=y
-# CONFIG_TREE_RCU is not set
-# CONFIG_PREEMPT_RCU is not set
+CONFIG_TREE_RCU=y
+# CONFIG_TREE_PREEMPT_RCU is not set
+# CONFIG_RCU_TRACE is not set
+CONFIG_RCU_FANOUT=32
+# CONFIG_RCU_FANOUT_EXACT is not set
 # CONFIG_TREE_RCU_TRACE is not set
-# CONFIG_PREEMPT_RCU_TRACE is not set
 # CONFIG_IKCONFIG is not set
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_GROUP_SCHED=y
@@ -105,7 +112,6 @@ CONFIG_ANON_INODES=y
 CONFIG_EMBEDDED=y
 # CONFIG_SYSCTL_SYSCALL is not set
 # CONFIG_KALLSYMS is not set
-# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_HOTPLUG=y
 CONFIG_PRINTK=y
 CONFIG_BUG=y
@@ -118,6 +124,13 @@ CONFIG_TIMERFD=y
 CONFIG_EVENTFD=y
 CONFIG_SHMEM=y
 CONFIG_AIO=y
+CONFIG_HAVE_PERF_EVENTS=y
+
+#
+# Kernel Performance Events And Counters
+#
+# CONFIG_PERF_EVENTS is not set
+# CONFIG_PERF_COUNTERS is not set
 CONFIG_VM_EVENT_COUNTERS=y
 CONFIG_SLUB_DEBUG=y
 CONFIG_COMPAT_BRK=y
@@ -125,14 +138,19 @@ CONFIG_COMPAT_BRK=y
 CONFIG_SLUB=y
 # CONFIG_SLOB is not set
 # CONFIG_PROFILING is not set
-# CONFIG_MARKERS is not set
 CONFIG_HAVE_OPROFILE=y
 CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y
 CONFIG_HAVE_IOREMAP_PROT=y
 CONFIG_HAVE_KPROBES=y
 CONFIG_HAVE_KRETPROBES=y
 CONFIG_HAVE_ARCH_TRACEHOOK=y
+CONFIG_HAVE_DMA_ATTRS=y
 CONFIG_HAVE_CLK=y
+CONFIG_HAVE_DMA_API_DEBUG=y
+
+#
+# GCOV-based kernel profiling
+#
 # CONFIG_SLOW_WORK is not set
 # CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
 CONFIG_SLABINFO=y
@@ -140,7 +158,7 @@ CONFIG_RT_MUTEXES=y
 CONFIG_BASE_SMALL=0
 # CONFIG_MODULES is not set
 CONFIG_BLOCK=y
-# CONFIG_LBD is not set
+CONFIG_LBDAF=y
 # CONFIG_BLK_DEV_BSG is not set
 # CONFIG_BLK_DEV_INTEGRITY is not set
 
@@ -220,11 +238,13 @@ CONFIG_BINFMT_ELF=y
 # CONFIG_HAVE_AOUT is not set
 # CONFIG_BINFMT_MISC is not set
 # CONFIG_IOMMU_HELPER is not set
+# CONFIG_SWIOTLB is not set
 CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
 CONFIG_ARCH_HAS_WALK_MEMORY=y
 CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
 # CONFIG_KEXEC is not set
 # CONFIG_CRASH_DUMP is not set
+CONFIG_MAX_ACTIVE_REGIONS=32
 CONFIG_ARCH_FLATMEM_ENABLE=y
 CONFIG_ARCH_POPULATES_NODE_MAP=y
 CONFIG_SELECT_MEMORY_MODEL=y
@@ -240,9 +260,10 @@ CONFIG_MIGRATION=y
 CONFIG_ZONE_DMA_FLAG=1
 CONFIG_BOUNCE=y
 CONFIG_VIRT_TO_BUS=y
-CONFIG_UNEVICTABLE_LRU=y
 CONFIG_HAVE_MLOCK=y
 CONFIG_HAVE_MLOCKED_PAGE_BIT=y
+# CONFIG_KSM is not set
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
 CONFIG_PPC_4K_PAGES=y
 # CONFIG_PPC_16K_PAGES is not set
 # CONFIG_PPC_64K_PAGES is not set
@@ -253,6 +274,7 @@ CONFIG_PROC_DEVICETREE=y
 CONFIG_EXTRA_TARGETS=""
 CONFIG_PM=y
 # CONFIG_PM_DEBUG is not set
+# CONFIG_PM_RUNTIME is not set
 CONFIG_SECCOMP=y
 CONFIG_ISA_DMA_API=y
 
@@ -329,6 +351,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
 # CONFIG_NETFILTER is not set
 # CONFIG_IP_DCCP is not set
 # CONFIG_IP_SCTP is not set
+# CONFIG_RDS is not set
 # CONFIG_TIPC is not set
 # CONFIG_ATM is not set
 # CONFIG_BRIDGE is not set
@@ -343,6 +366,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
 # CONFIG_PHONET is not set
+# CONFIG_IEEE802154 is not set
 # CONFIG_NET_SCHED is not set
 # CONFIG_DCB is not set
 
@@ -368,6 +392,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
 # Generic Driver Options
 #
 CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+# CONFIG_DEVTMPFS is not set
 CONFIG_STANDALONE=y
 CONFIG_PREVENT_FIRMWARE_BUILD=y
 # CONFIG_FW_LOADER is not set
@@ -458,6 +483,7 @@ CONFIG_MTD_ROM=y
 # CONFIG_MTD_UBI is not set
 CONFIG_OF_DEVICE=y
 CONFIG_OF_I2C=y
+CONFIG_OF_MDIO=y
 # CONFIG_PARPORT is not set
 CONFIG_BLK_DEV=y
 # CONFIG_BLK_DEV_FD is not set
@@ -483,6 +509,7 @@ CONFIG_MISC_DEVICES=y
 #
 # CONFIG_EEPROM_AT24 is not set
 CONFIG_EEPROM_LEGACY=y
+# CONFIG_EEPROM_MAX6875 is not set
 # CONFIG_EEPROM_93CX6 is not set
 CONFIG_HAVE_IDE=y
 # CONFIG_IDE is not set
@@ -506,10 +533,6 @@ CONFIG_BLK_DEV_SD=y
 # CONFIG_BLK_DEV_SR is not set
 CONFIG_CHR_DEV_SG=y
 # CONFIG_CHR_DEV_SCH is not set
-
-#
-# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
-#
 # CONFIG_SCSI_MULTI_LUN is not set
 # CONFIG_SCSI_CONSTANTS is not set
 # CONFIG_SCSI_LOGGING is not set
@@ -532,6 +555,7 @@ CONFIG_SCSI_LOWLEVEL=y
 # CONFIG_SCSI_OSD_INITIATOR is not set
 CONFIG_ATA=y
 # CONFIG_ATA_NONSTANDARD is not set
+CONFIG_ATA_VERBOSE_ERROR=y
 CONFIG_SATA_PMP=y
 CONFIG_ATA_SFF=y
 # CONFIG_SATA_MV is not set
@@ -540,7 +564,6 @@ CONFIG_PATA_MPC52xx=y
 # CONFIG_MD is not set
 # CONFIG_MACINTOSH_DRIVERS is not set
 CONFIG_NETDEVICES=y
-CONFIG_COMPAT_NET_DEV_OPS=y
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
 # CONFIG_MACVLAN is not set
@@ -579,14 +602,14 @@ CONFIG_MII=y
 # CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
 # CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
 # CONFIG_B44 is not set
+# CONFIG_KS8842 is not set
+# CONFIG_KS8851_MLL is not set
 CONFIG_FEC_MPC52xx=y
 CONFIG_FEC_MPC52xx_MDIO=y
+# CONFIG_XILINX_EMACLITE is not set
 # CONFIG_NETDEV_1000 is not set
 # CONFIG_NETDEV_10000 is not set
-
-#
-# Wireless LAN
-#
+CONFIG_WLAN=y
 # CONFIG_WLAN_PRE80211 is not set
 # CONFIG_WLAN_80211 is not set
 
@@ -647,6 +670,7 @@ CONFIG_LEGACY_PTY_COUNT=256
 # CONFIG_TCG_TPM is not set
 CONFIG_I2C=y
 CONFIG_I2C_BOARDINFO=y
+CONFIG_I2C_COMPAT=y
 CONFIG_I2C_CHARDEV=y
 CONFIG_I2C_HELPER_AUTO=y
 
@@ -657,6 +681,7 @@ CONFIG_I2C_HELPER_AUTO=y
 #
 # I2C system bus drivers (mostly embedded / system-on-chip)
 #
+# CONFIG_I2C_DESIGNWARE is not set
 CONFIG_I2C_MPC=y
 # CONFIG_I2C_OCORES is not set
 # CONFIG_I2C_SIMTEC is not set
@@ -676,22 +701,28 @@ CONFIG_I2C_MPC=y
 # Miscellaneous I2C Chip support
 #
 # CONFIG_DS1682 is not set
-# CONFIG_SENSORS_PCF8574 is not set
-# CONFIG_PCF8575 is not set
-# CONFIG_SENSORS_PCA9539 is not set
-# CONFIG_SENSORS_MAX6875 is not set
 # CONFIG_SENSORS_TSL2550 is not set
 # CONFIG_I2C_DEBUG_CORE is not set
 # CONFIG_I2C_DEBUG_ALGO is not set
 # CONFIG_I2C_DEBUG_BUS is not set
 # CONFIG_I2C_DEBUG_CHIP is not set
 # CONFIG_SPI is not set
+
+#
+# PPS support
+#
+# CONFIG_PPS is not set
 CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
 # CONFIG_GPIOLIB is not set
 # CONFIG_W1 is not set
 # CONFIG_POWER_SUPPLY is not set
 CONFIG_HWMON=y
 # CONFIG_HWMON_VID is not set
+# CONFIG_HWMON_DEBUG_CHIP is not set
+
+#
+# Native drivers
+#
 # CONFIG_SENSORS_AD7414 is not set
 # CONFIG_SENSORS_AD7418 is not set
 # CONFIG_SENSORS_ADM1021 is not set
@@ -738,6 +769,8 @@ CONFIG_HWMON=y
 # CONFIG_SENSORS_SMSC47B397 is not set
 # CONFIG_SENSORS_ADS7828 is not set
 # CONFIG_SENSORS_THMC50 is not set
+# CONFIG_SENSORS_TMP401 is not set
+# CONFIG_SENSORS_TMP421 is not set
 # CONFIG_SENSORS_VT1211 is not set
 # CONFIG_SENSORS_W83781D is not set
 # CONFIG_SENSORS_W83791D is not set
@@ -747,9 +780,7 @@ CONFIG_HWMON=y
 # CONFIG_SENSORS_W83L786NG is not set
 # CONFIG_SENSORS_W83627HF is not set
 # CONFIG_SENSORS_W83627EHF is not set
-# CONFIG_HWMON_DEBUG_CHIP is not set
 # CONFIG_THERMAL is not set
-# CONFIG_THERMAL_HWMON is not set
 CONFIG_WATCHDOG=y
 # CONFIG_WATCHDOG_NOWAYOUT is not set
 
@@ -775,25 +806,12 @@ CONFIG_SSB_POSSIBLE=y
 # CONFIG_MFD_TMIO is not set
 # CONFIG_PMIC_DA903X is not set
 # CONFIG_MFD_WM8400 is not set
+# CONFIG_MFD_WM831X is not set
 # CONFIG_MFD_WM8350_I2C is not set
 # CONFIG_MFD_PCF50633 is not set
+# CONFIG_AB3100_CORE is not set
 # CONFIG_REGULATOR is not set
-
-#
-# Multimedia devices
-#
-
-#
-# Multimedia core support
-#
-# CONFIG_VIDEO_DEV is not set
-# CONFIG_DVB_CORE is not set
-# CONFIG_VIDEO_MEDIA is not set
-
-#
-# Multimedia drivers
-#
-CONFIG_DAB=y
+# CONFIG_MEDIA_SUPPORT is not set
 
 #
 # Graphics support
@@ -817,7 +835,7 @@ CONFIG_LEDS_CLASS=y
 #
 # LED drivers
 #
-# CONFIG_LEDS_LP5521 is not set
+# CONFIG_LEDS_LP3944 is not set
 # CONFIG_LEDS_PCA955X is not set
 # CONFIG_LEDS_BD2802 is not set
 
@@ -866,6 +884,7 @@ CONFIG_RTC_DRV_DS1307=y
 # CONFIG_RTC_DRV_S35390A is not set
 # CONFIG_RTC_DRV_FM3130 is not set
 # CONFIG_RTC_DRV_RX8581 is not set
+# CONFIG_RTC_DRV_RX8025 is not set
 
 #
 # SPI RTC drivers
@@ -893,6 +912,10 @@ CONFIG_RTC_DRV_DS1307=y
 # CONFIG_DMADEVICES is not set
 # CONFIG_AUXDISPLAY is not set
 # CONFIG_UIO is not set
+
+#
+# TI VLYNQ
+#
 # CONFIG_STAGING is not set
 
 #
@@ -912,10 +935,13 @@ CONFIG_FS_MBCACHE=y
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
 # CONFIG_FS_POSIX_ACL is not set
-CONFIG_FILE_LOCKING=y
 # CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
 # CONFIG_OCFS2_FS is not set
 # CONFIG_BTRFS_FS is not set
+# CONFIG_NILFS2_FS is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
 CONFIG_DNOTIFY=y
 CONFIG_INOTIFY=y
 CONFIG_INOTIFY_USER=y
@@ -986,12 +1012,12 @@ CONFIG_CRAMFS=y
 # CONFIG_ROMFS_FS is not set
 # CONFIG_SYSV_FS is not set
 # CONFIG_UFS_FS is not set
-# CONFIG_NILFS2_FS is not set
 CONFIG_NETWORK_FILESYSTEMS=y
 CONFIG_NFS_FS=y
 CONFIG_NFS_V3=y
 # CONFIG_NFS_V3_ACL is not set
 CONFIG_NFS_V4=y
+# CONFIG_NFS_V4_1 is not set
 CONFIG_ROOT_NFS=y
 # CONFIG_NFSD is not set
 CONFIG_LOCKD=y
@@ -1091,6 +1117,7 @@ CONFIG_HAS_IOPORT=y
 CONFIG_HAS_DMA=y
 CONFIG_HAVE_LMB=y
 CONFIG_NLATTR=y
+CONFIG_GENERIC_ATOMIC64=y
 
 #
 # Kernel hacking
@@ -1100,6 +1127,7 @@ CONFIG_ENABLE_WARN_DEPRECATED=y
 CONFIG_ENABLE_MUST_CHECK=y
 CONFIG_FRAME_WARN=1024
 # CONFIG_MAGIC_SYSRQ is not set
+# CONFIG_STRIP_ASM_SYMS is not set
 # CONFIG_UNUSED_SYMBOLS is not set
 # CONFIG_DEBUG_FS is not set
 # CONFIG_HEADERS_CHECK is not set
@@ -1117,10 +1145,14 @@ CONFIG_SCHED_DEBUG=y
 # CONFIG_DEBUG_OBJECTS is not set
 # CONFIG_SLUB_DEBUG_ON is not set
 # CONFIG_SLUB_STATS is not set
+# CONFIG_DEBUG_KMEMLEAK is not set
 # CONFIG_DEBUG_RT_MUTEXES is not set
 # CONFIG_RT_MUTEX_TESTER is not set
 # CONFIG_DEBUG_SPINLOCK is not set
 # CONFIG_DEBUG_MUTEXES is not set
+# CONFIG_DEBUG_LOCK_ALLOC is not set
+# CONFIG_PROVE_LOCKING is not set
+# CONFIG_LOCK_STAT is not set
 # CONFIG_DEBUG_SPINLOCK_SLEEP is not set
 # CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
 # CONFIG_DEBUG_KOBJECT is not set
@@ -1132,11 +1164,12 @@ CONFIG_DEBUG_INFO=y
 # CONFIG_DEBUG_LIST is not set
 # CONFIG_DEBUG_SG is not set
 # CONFIG_DEBUG_NOTIFIERS is not set
-# CONFIG_BOOT_PRINTK_DELAY is not set
+# CONFIG_DEBUG_CREDENTIALS is not set
 # CONFIG_RCU_TORTURE_TEST is not set
 # CONFIG_RCU_CPU_STALL_DETECTOR is not set
 # CONFIG_BACKTRACE_SELF_TEST is not set
 # CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
+# CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set
 # CONFIG_FAULT_INJECTION is not set
 # CONFIG_LATENCYTOP is not set
 # CONFIG_DEBUG_PAGEALLOC is not set
@@ -1145,23 +1178,25 @@ CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y
 CONFIG_HAVE_DYNAMIC_FTRACE=y
 CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
 CONFIG_TRACING_SUPPORT=y
-
-#
-# Tracers
-#
+CONFIG_FTRACE=y
 # CONFIG_FUNCTION_TRACER is not set
+# CONFIG_IRQSOFF_TRACER is not set
 # CONFIG_SCHED_TRACER is not set
-# CONFIG_CONTEXT_SWITCH_TRACER is not set
-# CONFIG_EVENT_TRACER is not set
+# CONFIG_ENABLE_DEFAULT_TRACERS is not set
 # CONFIG_BOOT_TRACER is not set
-# CONFIG_TRACE_BRANCH_PROFILING is not set
+CONFIG_BRANCH_PROFILE_NONE=y
+# CONFIG_PROFILE_ANNOTATED_BRANCHES is not set
+# CONFIG_PROFILE_ALL_BRANCHES is not set
 # CONFIG_STACK_TRACER is not set
 # CONFIG_KMEMTRACE is not set
 # CONFIG_WORKQUEUE_TRACER is not set
 # CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_DMA_API_DEBUG is not set
 # CONFIG_SAMPLES is not set
 CONFIG_HAVE_ARCH_KGDB=y
 # CONFIG_KGDB is not set
+# CONFIG_PPC_DISABLE_WERROR is not set
+CONFIG_PPC_WERROR=y
 CONFIG_PRINT_STACK_DEPTH=64
 # CONFIG_DEBUG_STACKOVERFLOW is not set
 # CONFIG_DEBUG_STACK_USAGE is not set
@@ -1186,7 +1221,6 @@ CONFIG_CRYPTO=y
 #
 # Crypto core or helper
 #
-# CONFIG_CRYPTO_FIPS is not set
 CONFIG_CRYPTO_ALGAPI=y
 CONFIG_CRYPTO_ALGAPI2=y
 CONFIG_CRYPTO_AEAD2=y
@@ -1227,11 +1261,13 @@ CONFIG_CRYPTO_PCBC=y
 #
 # CONFIG_CRYPTO_HMAC is not set
 # CONFIG_CRYPTO_XCBC is not set
+# CONFIG_CRYPTO_VMAC is not set
 
 #
 # Digest
 #
 # CONFIG_CRYPTO_CRC32C is not set
+# CONFIG_CRYPTO_GHASH is not set
 # CONFIG_CRYPTO_MD4 is not set
 CONFIG_CRYPTO_MD5=y
 # CONFIG_CRYPTO_MICHAEL_MIC is not set
index afb1a3d..f9168c1 100644 (file)
@@ -1,25 +1,27 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.30-rc2
-# Sat Apr 18 00:48:42 2009
+# Linux kernel version: 2.6.32-rc4
+# Thu Oct 15 10:33:25 2009
 #
 # CONFIG_PPC64 is not set
 
 #
 # Processor support
 #
-CONFIG_6xx=y
+CONFIG_PPC_BOOK3S_32=y
 # CONFIG_PPC_85xx is not set
 # CONFIG_PPC_8xx is not set
 # CONFIG_40x is not set
 # CONFIG_44x is not set
 # CONFIG_E200 is not set
 CONFIG_PPC_BOOK3S=y
+CONFIG_6xx=y
 CONFIG_PPC_FPU=y
 # CONFIG_ALTIVEC is not set
 CONFIG_PPC_STD_MMU=y
 CONFIG_PPC_STD_MMU_32=y
 # CONFIG_PPC_MM_SLICES is not set
+CONFIG_PPC_HAVE_PMU_SUPPORT=y
 # CONFIG_SMP is not set
 CONFIG_PPC32=y
 CONFIG_WORD_SIZE=32
@@ -30,15 +32,17 @@ CONFIG_GENERIC_TIME=y
 CONFIG_GENERIC_TIME_VSYSCALL=y
 CONFIG_GENERIC_CLOCKEVENTS=y
 CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
 # CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
+# CONFIG_NEED_PER_CPU_EMBED_FIRST_CHUNK is not set
 CONFIG_IRQ_PER_CPU=y
 CONFIG_STACKTRACE_SUPPORT=y
 CONFIG_HAVE_LATENCYTOP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
 CONFIG_LOCKDEP_SUPPORT=y
 CONFIG_RWSEM_XCHGADD_ALGORITHM=y
 CONFIG_ARCH_HAS_ILOG2_U32=y
 CONFIG_GENERIC_HWEIGHT=y
-CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_GENERIC_FIND_NEXT_BIT=y
 # CONFIG_ARCH_NO_VIRT_TO_BUS is not set
 CONFIG_PPC=y
@@ -52,11 +56,13 @@ CONFIG_OF=y
 # CONFIG_GENERIC_TBSYNC is not set
 CONFIG_AUDIT_ARCH=y
 CONFIG_GENERIC_BUG=y
+CONFIG_DTC=y
 CONFIG_DEFAULT_UIMAGE=y
 # CONFIG_PPC_DCR_NATIVE is not set
 # CONFIG_PPC_DCR_MMIO is not set
 CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_CONSTRUCTORS=y
 
 #
 # General setup
@@ -79,11 +85,12 @@ CONFIG_POSIX_MQUEUE_SYSCTL=y
 #
 # RCU Subsystem
 #
-CONFIG_CLASSIC_RCU=y
-# CONFIG_TREE_RCU is not set
-# CONFIG_PREEMPT_RCU is not set
+CONFIG_TREE_RCU=y
+# CONFIG_TREE_PREEMPT_RCU is not set
+# CONFIG_RCU_TRACE is not set
+CONFIG_RCU_FANOUT=32
+# CONFIG_RCU_FANOUT_EXACT is not set
 # CONFIG_TREE_RCU_TRACE is not set
-# CONFIG_PREEMPT_RCU_TRACE is not set
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=14
@@ -105,7 +112,6 @@ CONFIG_EMBEDDED=y
 # CONFIG_SYSCTL_SYSCALL is not set
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
-# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_HOTPLUG=y
 CONFIG_PRINTK=y
 CONFIG_BUG=y
@@ -118,6 +124,13 @@ CONFIG_TIMERFD=y
 CONFIG_EVENTFD=y
 CONFIG_SHMEM=y
 CONFIG_AIO=y
+CONFIG_HAVE_PERF_EVENTS=y
+
+#
+# Kernel Performance Events And Counters
+#
+# CONFIG_PERF_EVENTS is not set
+# CONFIG_PERF_COUNTERS is not set
 # CONFIG_VM_EVENT_COUNTERS is not set
 CONFIG_PCI_QUIRKS=y
 CONFIG_COMPAT_BRK=y
@@ -125,7 +138,6 @@ CONFIG_SLAB=y
 # CONFIG_SLUB is not set
 # CONFIG_SLOB is not set
 # CONFIG_PROFILING is not set
-# CONFIG_MARKERS is not set
 CONFIG_HAVE_OPROFILE=y
 # CONFIG_KPROBES is not set
 CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y
@@ -133,7 +145,13 @@ CONFIG_HAVE_IOREMAP_PROT=y
 CONFIG_HAVE_KPROBES=y
 CONFIG_HAVE_KRETPROBES=y
 CONFIG_HAVE_ARCH_TRACEHOOK=y
+CONFIG_HAVE_DMA_ATTRS=y
 CONFIG_HAVE_CLK=y
+CONFIG_HAVE_DMA_API_DEBUG=y
+
+#
+# GCOV-based kernel profiling
+#
 # CONFIG_SLOW_WORK is not set
 # CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
 CONFIG_SLABINFO=y
@@ -146,7 +164,7 @@ CONFIG_MODULE_UNLOAD=y
 # CONFIG_MODVERSIONS is not set
 # CONFIG_MODULE_SRCVERSION_ALL is not set
 CONFIG_BLOCK=y
-# CONFIG_LBD is not set
+CONFIG_LBDAF=y
 # CONFIG_BLK_DEV_BSG is not set
 # CONFIG_BLK_DEV_INTEGRITY is not set
 
@@ -227,11 +245,13 @@ CONFIG_BINFMT_ELF=y
 # CONFIG_HAVE_AOUT is not set
 # CONFIG_BINFMT_MISC is not set
 # CONFIG_IOMMU_HELPER is not set
+# CONFIG_SWIOTLB is not set
 CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
 CONFIG_ARCH_HAS_WALK_MEMORY=y
 CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
 # CONFIG_KEXEC is not set
 # CONFIG_CRASH_DUMP is not set
+CONFIG_MAX_ACTIVE_REGIONS=32
 CONFIG_ARCH_FLATMEM_ENABLE=y
 CONFIG_ARCH_POPULATES_NODE_MAP=y
 CONFIG_SELECT_MEMORY_MODEL=y
@@ -247,9 +267,10 @@ CONFIG_MIGRATION=y
 CONFIG_ZONE_DMA_FLAG=1
 CONFIG_BOUNCE=y
 CONFIG_VIRT_TO_BUS=y
-CONFIG_UNEVICTABLE_LRU=y
 CONFIG_HAVE_MLOCK=y
 CONFIG_HAVE_MLOCKED_PAGE_BIT=y
+# CONFIG_KSM is not set
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
 CONFIG_PPC_4K_PAGES=y
 # CONFIG_PPC_16K_PAGES is not set
 # CONFIG_PPC_64K_PAGES is not set
@@ -336,6 +357,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
 # CONFIG_NETFILTER is not set
 # CONFIG_IP_DCCP is not set
 # CONFIG_IP_SCTP is not set
+# CONFIG_RDS is not set
 # CONFIG_TIPC is not set
 # CONFIG_ATM is not set
 # CONFIG_BRIDGE is not set
@@ -350,6 +372,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
 # CONFIG_PHONET is not set
+# CONFIG_IEEE802154 is not set
 # CONFIG_NET_SCHED is not set
 # CONFIG_DCB is not set
 
@@ -375,6 +398,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
 # Generic Driver Options
 #
 CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+# CONFIG_DEVTMPFS is not set
 CONFIG_STANDALONE=y
 CONFIG_PREVENT_FIRMWARE_BUILD=y
 # CONFIG_FW_LOADER is not set
@@ -382,9 +406,9 @@ CONFIG_PREVENT_FIRMWARE_BUILD=y
 # CONFIG_CONNECTOR is not set
 CONFIG_MTD=y
 # CONFIG_MTD_DEBUG is not set
+# CONFIG_MTD_TESTS is not set
 # CONFIG_MTD_CONCAT is not set
 CONFIG_MTD_PARTITIONS=y
-# CONFIG_MTD_TESTS is not set
 # CONFIG_MTD_REDBOOT_PARTS is not set
 CONFIG_MTD_CMDLINE_PARTS=y
 # CONFIG_MTD_OF_PARTS is not set
@@ -467,6 +491,7 @@ CONFIG_MTD_PHYSMAP=y
 # CONFIG_MTD_UBI is not set
 CONFIG_OF_DEVICE=y
 CONFIG_OF_I2C=y
+CONFIG_OF_MDIO=y
 # CONFIG_PARPORT is not set
 # CONFIG_BLK_DEV is not set
 # CONFIG_MISC_DEVICES is not set
@@ -492,10 +517,6 @@ CONFIG_BLK_DEV_SD=m
 # CONFIG_BLK_DEV_SR is not set
 # CONFIG_CHR_DEV_SG is not set
 # CONFIG_CHR_DEV_SCH is not set
-
-#
-# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
-#
 # CONFIG_SCSI_MULTI_LUN is not set
 # CONFIG_SCSI_CONSTANTS is not set
 # CONFIG_SCSI_LOGGING is not set
@@ -515,6 +536,7 @@ CONFIG_SCSI_WAIT_SCAN=m
 # CONFIG_SCSI_OSD_INITIATOR is not set
 CONFIG_ATA=m
 # CONFIG_ATA_NONSTANDARD is not set
+CONFIG_ATA_VERBOSE_ERROR=y
 CONFIG_SATA_PMP=y
 # CONFIG_SATA_AHCI is not set
 # CONFIG_SATA_SIL24 is not set
@@ -536,6 +558,7 @@ CONFIG_ATA_SFF=y
 # CONFIG_PATA_ALI is not set
 # CONFIG_PATA_AMD is not set
 # CONFIG_PATA_ARTOP is not set
+# CONFIG_PATA_ATP867X is not set
 # CONFIG_PATA_ATIIXP is not set
 # CONFIG_PATA_CMD640_PCI is not set
 # CONFIG_PATA_CMD64X is not set
@@ -564,6 +587,7 @@ CONFIG_PATA_MPC52xx=m
 # CONFIG_PATA_OPTIDMA is not set
 # CONFIG_PATA_PDC_OLD is not set
 # CONFIG_PATA_RADISYS is not set
+# CONFIG_PATA_RDC is not set
 # CONFIG_PATA_RZ1000 is not set
 # CONFIG_PATA_SC1200 is not set
 # CONFIG_PATA_SERVERWORKS is not set
@@ -582,14 +606,17 @@ CONFIG_PATA_MPC52xx=m
 #
 
 #
-# Enable only one of the two stacks, unless you know what you are doing
+# You can enable one or both FireWire driver stacks.
+#
+
+#
+# See the help texts for more information.
 #
 # CONFIG_FIREWIRE is not set
 # CONFIG_IEEE1394 is not set
 # CONFIG_I2O is not set
 # CONFIG_MACINTOSH_DRIVERS is not set
 CONFIG_NETDEVICES=y
-CONFIG_COMPAT_NET_DEV_OPS=y
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
 # CONFIG_MACVLAN is not set
@@ -636,16 +663,16 @@ CONFIG_MII=y
 # CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
 # CONFIG_NET_PCI is not set
 # CONFIG_B44 is not set
+# CONFIG_KS8842 is not set
+# CONFIG_KS8851_MLL is not set
 CONFIG_FEC_MPC52xx=y
 CONFIG_FEC_MPC52xx_MDIO=y
 # CONFIG_ATL2 is not set
+# CONFIG_XILINX_EMACLITE is not set
 # CONFIG_NETDEV_1000 is not set
 # CONFIG_NETDEV_10000 is not set
 # CONFIG_TR is not set
-
-#
-# Wireless LAN
-#
+CONFIG_WLAN=y
 # CONFIG_WLAN_PRE80211 is not set
 # CONFIG_WLAN_80211 is not set
 
@@ -722,6 +749,7 @@ CONFIG_HW_RANDOM=y
 CONFIG_DEVPORT=y
 CONFIG_I2C=y
 CONFIG_I2C_BOARDINFO=y
+CONFIG_I2C_COMPAT=y
 CONFIG_I2C_CHARDEV=y
 CONFIG_I2C_HELPER_AUTO=y
 
@@ -750,6 +778,7 @@ CONFIG_I2C_HELPER_AUTO=y
 #
 # I2C system bus drivers (mostly embedded / system-on-chip)
 #
+# CONFIG_I2C_DESIGNWARE is not set
 CONFIG_I2C_MPC=y
 # CONFIG_I2C_OCORES is not set
 # CONFIG_I2C_SIMTEC is not set
@@ -776,23 +805,23 @@ CONFIG_I2C_MPC=y
 # Miscellaneous I2C Chip support
 #
 # CONFIG_DS1682 is not set
-# CONFIG_SENSORS_PCF8574 is not set
-# CONFIG_PCF8575 is not set
-# CONFIG_SENSORS_PCA9539 is not set
-# CONFIG_SENSORS_MAX6875 is not set
 # CONFIG_SENSORS_TSL2550 is not set
 # CONFIG_I2C_DEBUG_CORE is not set
 # CONFIG_I2C_DEBUG_ALGO is not set
 # CONFIG_I2C_DEBUG_BUS is not set
 # CONFIG_I2C_DEBUG_CHIP is not set
 # CONFIG_SPI is not set
+
+#
+# PPS support
+#
+# CONFIG_PPS is not set
 CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
 # CONFIG_GPIOLIB is not set
 # CONFIG_W1 is not set
 # CONFIG_POWER_SUPPLY is not set
 # CONFIG_HWMON is not set
 # CONFIG_THERMAL is not set
-# CONFIG_THERMAL_HWMON is not set
 # CONFIG_WATCHDOG is not set
 CONFIG_SSB_POSSIBLE=y
 
@@ -811,30 +840,18 @@ CONFIG_SSB_POSSIBLE=y
 # CONFIG_MFD_TMIO is not set
 # CONFIG_PMIC_DA903X is not set
 # CONFIG_MFD_WM8400 is not set
+# CONFIG_MFD_WM831X is not set
 # CONFIG_MFD_WM8350_I2C is not set
 # CONFIG_MFD_PCF50633 is not set
+# CONFIG_AB3100_CORE is not set
 # CONFIG_REGULATOR is not set
-
-#
-# Multimedia devices
-#
-
-#
-# Multimedia core support
-#
-# CONFIG_VIDEO_DEV is not set
-# CONFIG_DVB_CORE is not set
-# CONFIG_VIDEO_MEDIA is not set
-
-#
-# Multimedia drivers
-#
-# CONFIG_DAB is not set
+# CONFIG_MEDIA_SUPPORT is not set
 
 #
 # Graphics support
 #
 # CONFIG_AGP is not set
+CONFIG_VGA_ARB=y
 # CONFIG_DRM is not set
 # CONFIG_VGASTATE is not set
 # CONFIG_VIDEO_OUTPUT_CONTROL is not set
@@ -871,15 +888,17 @@ CONFIG_USB_DEVICEFS=y
 # USB Host Controller Drivers
 #
 # CONFIG_USB_C67X00_HCD is not set
+# CONFIG_USB_XHCI_HCD is not set
 # CONFIG_USB_EHCI_HCD is not set
 # CONFIG_USB_OXU210HP_HCD is not set
 # CONFIG_USB_ISP116X_HCD is not set
 # CONFIG_USB_ISP1760_HCD is not set
+# CONFIG_USB_ISP1362_HCD is not set
 CONFIG_USB_OHCI_HCD=m
 # CONFIG_USB_OHCI_HCD_PPC_SOC is not set
-CONFIG_USB_OHCI_HCD_PPC_OF=y
 CONFIG_USB_OHCI_HCD_PPC_OF_BE=y
 # CONFIG_USB_OHCI_HCD_PPC_OF_LE is not set
+CONFIG_USB_OHCI_HCD_PPC_OF=y
 # CONFIG_USB_OHCI_HCD_PCI is not set
 CONFIG_USB_OHCI_BIG_ENDIAN_DESC=y
 CONFIG_USB_OHCI_BIG_ENDIAN_MMIO=y
@@ -995,6 +1014,7 @@ CONFIG_RTC_DRV_PCF8563=m
 # CONFIG_RTC_DRV_S35390A is not set
 # CONFIG_RTC_DRV_FM3130 is not set
 # CONFIG_RTC_DRV_RX8581 is not set
+# CONFIG_RTC_DRV_RX8025 is not set
 
 #
 # SPI RTC drivers
@@ -1022,6 +1042,10 @@ CONFIG_RTC_DRV_PCF8563=m
 # CONFIG_DMADEVICES is not set
 # CONFIG_AUXDISPLAY is not set
 # CONFIG_UIO is not set
+
+#
+# TI VLYNQ
+#
 # CONFIG_STAGING is not set
 
 #
@@ -1041,12 +1065,16 @@ CONFIG_FS_MBCACHE=m
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
 # CONFIG_FS_POSIX_ACL is not set
-CONFIG_FILE_LOCKING=y
 # CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
 # CONFIG_OCFS2_FS is not set
 # CONFIG_BTRFS_FS is not set
+# CONFIG_NILFS2_FS is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
 # CONFIG_DNOTIFY is not set
 # CONFIG_INOTIFY is not set
+CONFIG_INOTIFY_USER=y
 # CONFIG_QUOTA is not set
 # CONFIG_AUTOFS_FS is not set
 # CONFIG_AUTOFS4_FS is not set
@@ -1114,7 +1142,6 @@ CONFIG_JFFS2_RTIME=y
 # CONFIG_ROMFS_FS is not set
 # CONFIG_SYSV_FS is not set
 # CONFIG_UFS_FS is not set
-# CONFIG_NILFS2_FS is not set
 CONFIG_NETWORK_FILESYSTEMS=y
 CONFIG_NFS_FS=y
 CONFIG_NFS_V3=y
@@ -1201,6 +1228,7 @@ CONFIG_HAS_IOPORT=y
 CONFIG_HAS_DMA=y
 CONFIG_HAVE_LMB=y
 CONFIG_NLATTR=y
+CONFIG_GENERIC_ATOMIC64=y
 
 #
 # Kernel hacking
@@ -1210,6 +1238,7 @@ CONFIG_ENABLE_WARN_DEPRECATED=y
 CONFIG_ENABLE_MUST_CHECK=y
 CONFIG_FRAME_WARN=1024
 # CONFIG_MAGIC_SYSRQ is not set
+# CONFIG_STRIP_ASM_SYMS is not set
 # CONFIG_UNUSED_SYMBOLS is not set
 # CONFIG_DEBUG_FS is not set
 # CONFIG_HEADERS_CHECK is not set
@@ -1223,23 +1252,12 @@ CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y
 CONFIG_HAVE_DYNAMIC_FTRACE=y
 CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
 CONFIG_TRACING_SUPPORT=y
-
-#
-# Tracers
-#
-# CONFIG_FUNCTION_TRACER is not set
-# CONFIG_PREEMPT_TRACER is not set
-# CONFIG_SCHED_TRACER is not set
-# CONFIG_CONTEXT_SWITCH_TRACER is not set
-# CONFIG_EVENT_TRACER is not set
-# CONFIG_BOOT_TRACER is not set
-# CONFIG_TRACE_BRANCH_PROFILING is not set
-# CONFIG_STACK_TRACER is not set
-# CONFIG_KMEMTRACE is not set
-# CONFIG_WORKQUEUE_TRACER is not set
-# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_FTRACE is not set
+# CONFIG_DMA_API_DEBUG is not set
 # CONFIG_SAMPLES is not set
 CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_PPC_DISABLE_WERROR is not set
+CONFIG_PPC_WERROR=y
 CONFIG_PRINT_STACK_DEPTH=64
 # CONFIG_IRQSTACKS is not set
 # CONFIG_BOOTX_TEXT is not set
index 8585c7c..75c835c 100644 (file)
@@ -1,25 +1,27 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.30-rc2
-# Sat Apr 18 00:48:57 2009
+# Linux kernel version: 2.6.32-rc4
+# Thu Oct 15 10:33:23 2009
 #
 # CONFIG_PPC64 is not set
 
 #
 # Processor support
 #
-CONFIG_6xx=y
+CONFIG_PPC_BOOK3S_32=y
 # CONFIG_PPC_85xx is not set
 # CONFIG_PPC_8xx is not set
 # CONFIG_40x is not set
 # CONFIG_44x is not set
 # CONFIG_E200 is not set
 CONFIG_PPC_BOOK3S=y
+CONFIG_6xx=y
 CONFIG_PPC_FPU=y
 # CONFIG_ALTIVEC is not set
 CONFIG_PPC_STD_MMU=y
 CONFIG_PPC_STD_MMU_32=y
 # CONFIG_PPC_MM_SLICES is not set
+CONFIG_PPC_HAVE_PMU_SUPPORT=y
 # CONFIG_SMP is not set
 CONFIG_PPC32=y
 CONFIG_WORD_SIZE=32
@@ -30,15 +32,17 @@ CONFIG_GENERIC_TIME=y
 CONFIG_GENERIC_TIME_VSYSCALL=y
 CONFIG_GENERIC_CLOCKEVENTS=y
 CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
 # CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
+# CONFIG_NEED_PER_CPU_EMBED_FIRST_CHUNK is not set
 CONFIG_IRQ_PER_CPU=y
 CONFIG_STACKTRACE_SUPPORT=y
 CONFIG_HAVE_LATENCYTOP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
 CONFIG_LOCKDEP_SUPPORT=y
 CONFIG_RWSEM_XCHGADD_ALGORITHM=y
 CONFIG_ARCH_HAS_ILOG2_U32=y
 CONFIG_GENERIC_HWEIGHT=y
-CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_GENERIC_FIND_NEXT_BIT=y
 # CONFIG_ARCH_NO_VIRT_TO_BUS is not set
 CONFIG_PPC=y
@@ -52,11 +56,13 @@ CONFIG_OF=y
 # CONFIG_GENERIC_TBSYNC is not set
 CONFIG_AUDIT_ARCH=y
 CONFIG_GENERIC_BUG=y
+CONFIG_DTC=y
 CONFIG_DEFAULT_UIMAGE=y
 # CONFIG_PPC_DCR_NATIVE is not set
 # CONFIG_PPC_DCR_MMIO is not set
 CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_CONSTRUCTORS=y
 
 #
 # General setup
@@ -77,11 +83,12 @@ CONFIG_SYSVIPC_SYSCTL=y
 #
 # RCU Subsystem
 #
-CONFIG_CLASSIC_RCU=y
-# CONFIG_TREE_RCU is not set
-# CONFIG_PREEMPT_RCU is not set
+CONFIG_TREE_RCU=y
+# CONFIG_TREE_PREEMPT_RCU is not set
+# CONFIG_RCU_TRACE is not set
+CONFIG_RCU_FANOUT=32
+# CONFIG_RCU_FANOUT_EXACT is not set
 # CONFIG_TREE_RCU_TRACE is not set
-# CONFIG_PREEMPT_RCU_TRACE is not set
 # CONFIG_IKCONFIG is not set
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_GROUP_SCHED=y
@@ -105,7 +112,6 @@ CONFIG_ANON_INODES=y
 CONFIG_EMBEDDED=y
 # CONFIG_SYSCTL_SYSCALL is not set
 # CONFIG_KALLSYMS is not set
-# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_HOTPLUG=y
 CONFIG_PRINTK=y
 CONFIG_BUG=y
@@ -118,6 +124,13 @@ CONFIG_TIMERFD=y
 CONFIG_EVENTFD=y
 CONFIG_SHMEM=y
 CONFIG_AIO=y
+CONFIG_HAVE_PERF_EVENTS=y
+
+#
+# Kernel Performance Events And Counters
+#
+# CONFIG_PERF_EVENTS is not set
+# CONFIG_PERF_COUNTERS is not set
 CONFIG_VM_EVENT_COUNTERS=y
 CONFIG_SLUB_DEBUG=y
 CONFIG_COMPAT_BRK=y
@@ -125,14 +138,19 @@ CONFIG_COMPAT_BRK=y
 CONFIG_SLUB=y
 # CONFIG_SLOB is not set
 # CONFIG_PROFILING is not set
-# CONFIG_MARKERS is not set
 CONFIG_HAVE_OPROFILE=y
 CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y
 CONFIG_HAVE_IOREMAP_PROT=y
 CONFIG_HAVE_KPROBES=y
 CONFIG_HAVE_KRETPROBES=y
 CONFIG_HAVE_ARCH_TRACEHOOK=y
+CONFIG_HAVE_DMA_ATTRS=y
 CONFIG_HAVE_CLK=y
+CONFIG_HAVE_DMA_API_DEBUG=y
+
+#
+# GCOV-based kernel profiling
+#
 # CONFIG_SLOW_WORK is not set
 # CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
 CONFIG_SLABINFO=y
@@ -145,7 +163,7 @@ CONFIG_MODULE_UNLOAD=y
 CONFIG_MODVERSIONS=y
 # CONFIG_MODULE_SRCVERSION_ALL is not set
 CONFIG_BLOCK=y
-# CONFIG_LBD is not set
+CONFIG_LBDAF=y
 # CONFIG_BLK_DEV_BSG is not set
 # CONFIG_BLK_DEV_INTEGRITY is not set
 
@@ -225,11 +243,13 @@ CONFIG_BINFMT_ELF=y
 # CONFIG_HAVE_AOUT is not set
 # CONFIG_BINFMT_MISC is not set
 # CONFIG_IOMMU_HELPER is not set
+# CONFIG_SWIOTLB is not set
 CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
 CONFIG_ARCH_HAS_WALK_MEMORY=y
 CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
 # CONFIG_KEXEC is not set
 # CONFIG_CRASH_DUMP is not set
+CONFIG_MAX_ACTIVE_REGIONS=32
 CONFIG_ARCH_FLATMEM_ENABLE=y
 CONFIG_ARCH_POPULATES_NODE_MAP=y
 CONFIG_SELECT_MEMORY_MODEL=y
@@ -245,9 +265,10 @@ CONFIG_MIGRATION=y
 CONFIG_ZONE_DMA_FLAG=1
 CONFIG_BOUNCE=y
 CONFIG_VIRT_TO_BUS=y
-CONFIG_UNEVICTABLE_LRU=y
 CONFIG_HAVE_MLOCK=y
 CONFIG_HAVE_MLOCKED_PAGE_BIT=y
+# CONFIG_KSM is not set
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
 CONFIG_PPC_4K_PAGES=y
 # CONFIG_PPC_16K_PAGES is not set
 # CONFIG_PPC_64K_PAGES is not set
@@ -258,6 +279,7 @@ CONFIG_PROC_DEVICETREE=y
 CONFIG_EXTRA_TARGETS=""
 CONFIG_PM=y
 # CONFIG_PM_DEBUG is not set
+# CONFIG_PM_RUNTIME is not set
 CONFIG_SECCOMP=y
 CONFIG_ISA_DMA_API=y
 
@@ -334,6 +356,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
 # CONFIG_NETFILTER is not set
 # CONFIG_IP_DCCP is not set
 # CONFIG_IP_SCTP is not set
+# CONFIG_RDS is not set
 # CONFIG_TIPC is not set
 # CONFIG_ATM is not set
 # CONFIG_BRIDGE is not set
@@ -348,6 +371,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
 # CONFIG_PHONET is not set
+# CONFIG_IEEE802154 is not set
 # CONFIG_NET_SCHED is not set
 # CONFIG_DCB is not set
 
@@ -373,6 +397,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
 # Generic Driver Options
 #
 CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+# CONFIG_DEVTMPFS is not set
 CONFIG_STANDALONE=y
 CONFIG_PREVENT_FIRMWARE_BUILD=y
 # CONFIG_FW_LOADER is not set
@@ -382,9 +407,9 @@ CONFIG_PREVENT_FIRMWARE_BUILD=y
 # CONFIG_CONNECTOR is not set
 CONFIG_MTD=y
 # CONFIG_MTD_DEBUG is not set
+# CONFIG_MTD_TESTS is not set
 CONFIG_MTD_CONCAT=y
 CONFIG_MTD_PARTITIONS=y
-# CONFIG_MTD_TESTS is not set
 # CONFIG_MTD_REDBOOT_PARTS is not set
 CONFIG_MTD_CMDLINE_PARTS=y
 # CONFIG_MTD_OF_PARTS is not set
@@ -464,6 +489,7 @@ CONFIG_MTD_PHYSMAP_OF=y
 # CONFIG_MTD_UBI is not set
 CONFIG_OF_DEVICE=y
 CONFIG_OF_I2C=y
+CONFIG_OF_MDIO=y
 # CONFIG_PARPORT is not set
 CONFIG_BLK_DEV=y
 # CONFIG_BLK_DEV_FD is not set
@@ -502,10 +528,6 @@ CONFIG_BLK_DEV_SD=y
 # CONFIG_BLK_DEV_SR is not set
 CONFIG_CHR_DEV_SG=y
 # CONFIG_CHR_DEV_SCH is not set
-
-#
-# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
-#
 # CONFIG_SCSI_MULTI_LUN is not set
 # CONFIG_SCSI_CONSTANTS is not set
 # CONFIG_SCSI_LOGGING is not set
@@ -529,6 +551,7 @@ CONFIG_SCSI_LOWLEVEL=y
 # CONFIG_SCSI_OSD_INITIATOR is not set
 CONFIG_ATA=y
 # CONFIG_ATA_NONSTANDARD is not set
+CONFIG_ATA_VERBOSE_ERROR=y
 CONFIG_SATA_PMP=y
 CONFIG_ATA_SFF=y
 # CONFIG_SATA_MV is not set
@@ -538,7 +561,6 @@ CONFIG_PATA_PLATFORM=y
 # CONFIG_MD is not set
 # CONFIG_MACINTOSH_DRIVERS is not set
 CONFIG_NETDEVICES=y
-CONFIG_COMPAT_NET_DEV_OPS=y
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
 # CONFIG_MACVLAN is not set
@@ -577,14 +599,14 @@ CONFIG_NET_ETHERNET=y
 # CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
 # CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
 # CONFIG_B44 is not set
+# CONFIG_KS8842 is not set
+# CONFIG_KS8851_MLL is not set
 CONFIG_FEC_MPC52xx=y
 CONFIG_FEC_MPC52xx_MDIO=y
+# CONFIG_XILINX_EMACLITE is not set
 # CONFIG_NETDEV_1000 is not set
 # CONFIG_NETDEV_10000 is not set
-
-#
-# Wireless LAN
-#
+CONFIG_WLAN=y
 # CONFIG_WLAN_PRE80211 is not set
 # CONFIG_WLAN_80211 is not set
 
@@ -654,6 +676,7 @@ CONFIG_LEGACY_PTY_COUNT=256
 # CONFIG_TCG_TPM is not set
 CONFIG_I2C=y
 CONFIG_I2C_BOARDINFO=y
+CONFIG_I2C_COMPAT=y
 CONFIG_I2C_CHARDEV=y
 CONFIG_I2C_HELPER_AUTO=y
 
@@ -664,6 +687,7 @@ CONFIG_I2C_HELPER_AUTO=y
 #
 # I2C system bus drivers (mostly embedded / system-on-chip)
 #
+# CONFIG_I2C_DESIGNWARE is not set
 CONFIG_I2C_MPC=y
 # CONFIG_I2C_OCORES is not set
 # CONFIG_I2C_SIMTEC is not set
@@ -685,22 +709,28 @@ CONFIG_I2C_MPC=y
 # Miscellaneous I2C Chip support
 #
 # CONFIG_DS1682 is not set
-# CONFIG_SENSORS_PCF8574 is not set
-# CONFIG_PCF8575 is not set
-# CONFIG_SENSORS_PCA9539 is not set
-# CONFIG_SENSORS_MAX6875 is not set
 # CONFIG_SENSORS_TSL2550 is not set
 # CONFIG_I2C_DEBUG_CORE is not set
 # CONFIG_I2C_DEBUG_ALGO is not set
 # CONFIG_I2C_DEBUG_BUS is not set
 # CONFIG_I2C_DEBUG_CHIP is not set
 # CONFIG_SPI is not set
+
+#
+# PPS support
+#
+# CONFIG_PPS is not set
 CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
 # CONFIG_GPIOLIB is not set
 # CONFIG_W1 is not set
 # CONFIG_POWER_SUPPLY is not set
 CONFIG_HWMON=y
 # CONFIG_HWMON_VID is not set
+# CONFIG_HWMON_DEBUG_CHIP is not set
+
+#
+# Native drivers
+#
 # CONFIG_SENSORS_AD7414 is not set
 # CONFIG_SENSORS_AD7418 is not set
 # CONFIG_SENSORS_ADM1021 is not set
@@ -747,6 +777,8 @@ CONFIG_HWMON=y
 # CONFIG_SENSORS_SMSC47B397 is not set
 # CONFIG_SENSORS_ADS7828 is not set
 # CONFIG_SENSORS_THMC50 is not set
+# CONFIG_SENSORS_TMP401 is not set
+# CONFIG_SENSORS_TMP421 is not set
 # CONFIG_SENSORS_VT1211 is not set
 # CONFIG_SENSORS_W83781D is not set
 # CONFIG_SENSORS_W83791D is not set
@@ -756,9 +788,7 @@ CONFIG_HWMON=y
 # CONFIG_SENSORS_W83L786NG is not set
 # CONFIG_SENSORS_W83627HF is not set
 # CONFIG_SENSORS_W83627EHF is not set
-# CONFIG_HWMON_DEBUG_CHIP is not set
 # CONFIG_THERMAL is not set
-# CONFIG_THERMAL_HWMON is not set
 CONFIG_WATCHDOG=y
 # CONFIG_WATCHDOG_NOWAYOUT is not set
 
@@ -789,25 +819,12 @@ CONFIG_SSB_POSSIBLE=y
 # CONFIG_MFD_TMIO is not set
 # CONFIG_PMIC_DA903X is not set
 # CONFIG_MFD_WM8400 is not set
+# CONFIG_MFD_WM831X is not set
 # CONFIG_MFD_WM8350_I2C is not set
 # CONFIG_MFD_PCF50633 is not set
+# CONFIG_AB3100_CORE is not set
 # CONFIG_REGULATOR is not set
-
-#
-# Multimedia devices
-#
-
-#
-# Multimedia core support
-#
-# CONFIG_VIDEO_DEV is not set
-# CONFIG_DVB_CORE is not set
-# CONFIG_VIDEO_MEDIA is not set
-
-#
-# Multimedia drivers
-#
-# CONFIG_DAB is not set
+# CONFIG_MEDIA_SUPPORT is not set
 
 #
 # Graphics support
@@ -851,11 +868,12 @@ CONFIG_USB_MON=y
 # CONFIG_USB_OXU210HP_HCD is not set
 # CONFIG_USB_ISP116X_HCD is not set
 # CONFIG_USB_ISP1760_HCD is not set
+# CONFIG_USB_ISP1362_HCD is not set
 CONFIG_USB_OHCI_HCD=y
 CONFIG_USB_OHCI_HCD_PPC_SOC=y
-CONFIG_USB_OHCI_HCD_PPC_OF=y
 CONFIG_USB_OHCI_HCD_PPC_OF_BE=y
 # CONFIG_USB_OHCI_HCD_PPC_OF_LE is not set
+CONFIG_USB_OHCI_HCD_PPC_OF=y
 CONFIG_USB_OHCI_BIG_ENDIAN_DESC=y
 CONFIG_USB_OHCI_BIG_ENDIAN_MMIO=y
 # CONFIG_USB_OHCI_LITTLE_ENDIAN is not set
@@ -969,6 +987,7 @@ CONFIG_RTC_DRV_DS1307=y
 # CONFIG_RTC_DRV_S35390A is not set
 # CONFIG_RTC_DRV_FM3130 is not set
 # CONFIG_RTC_DRV_RX8581 is not set
+# CONFIG_RTC_DRV_RX8025 is not set
 
 #
 # SPI RTC drivers
@@ -996,6 +1015,10 @@ CONFIG_RTC_DRV_DS1307=y
 # CONFIG_DMADEVICES is not set
 # CONFIG_AUXDISPLAY is not set
 # CONFIG_UIO is not set
+
+#
+# TI VLYNQ
+#
 # CONFIG_STAGING is not set
 
 #
@@ -1015,10 +1038,13 @@ CONFIG_FS_MBCACHE=y
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
 # CONFIG_FS_POSIX_ACL is not set
-CONFIG_FILE_LOCKING=y
 # CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
 # CONFIG_OCFS2_FS is not set
 # CONFIG_BTRFS_FS is not set
+# CONFIG_NILFS2_FS is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
 CONFIG_DNOTIFY=y
 CONFIG_INOTIFY=y
 CONFIG_INOTIFY_USER=y
@@ -1089,12 +1115,12 @@ CONFIG_CRAMFS=y
 # CONFIG_ROMFS_FS is not set
 # CONFIG_SYSV_FS is not set
 # CONFIG_UFS_FS is not set
-# CONFIG_NILFS2_FS is not set
 CONFIG_NETWORK_FILESYSTEMS=y
 CONFIG_NFS_FS=y
 CONFIG_NFS_V3=y
 # CONFIG_NFS_V3_ACL is not set
 CONFIG_NFS_V4=y
+# CONFIG_NFS_V4_1 is not set
 CONFIG_ROOT_NFS=y
 # CONFIG_NFSD is not set
 CONFIG_LOCKD=y
@@ -1194,6 +1220,7 @@ CONFIG_HAS_IOPORT=y
 CONFIG_HAS_DMA=y
 CONFIG_HAVE_LMB=y
 CONFIG_NLATTR=y
+CONFIG_GENERIC_ATOMIC64=y
 
 #
 # Kernel hacking
@@ -1203,6 +1230,7 @@ CONFIG_ENABLE_WARN_DEPRECATED=y
 CONFIG_ENABLE_MUST_CHECK=y
 CONFIG_FRAME_WARN=1024
 # CONFIG_MAGIC_SYSRQ is not set
+# CONFIG_STRIP_ASM_SYMS is not set
 # CONFIG_UNUSED_SYMBOLS is not set
 # CONFIG_DEBUG_FS is not set
 # CONFIG_HEADERS_CHECK is not set
@@ -1220,10 +1248,14 @@ CONFIG_SCHED_DEBUG=y
 # CONFIG_DEBUG_OBJECTS is not set
 # CONFIG_SLUB_DEBUG_ON is not set
 # CONFIG_SLUB_STATS is not set
+# CONFIG_DEBUG_KMEMLEAK is not set
 # CONFIG_DEBUG_RT_MUTEXES is not set
 # CONFIG_RT_MUTEX_TESTER is not set
 # CONFIG_DEBUG_SPINLOCK is not set
 # CONFIG_DEBUG_MUTEXES is not set
+# CONFIG_DEBUG_LOCK_ALLOC is not set
+# CONFIG_PROVE_LOCKING is not set
+# CONFIG_LOCK_STAT is not set
 # CONFIG_DEBUG_SPINLOCK_SLEEP is not set
 # CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
 # CONFIG_DEBUG_KOBJECT is not set
@@ -1235,11 +1267,12 @@ CONFIG_DEBUG_INFO=y
 # CONFIG_DEBUG_LIST is not set
 # CONFIG_DEBUG_SG is not set
 # CONFIG_DEBUG_NOTIFIERS is not set
-# CONFIG_BOOT_PRINTK_DELAY is not set
+# CONFIG_DEBUG_CREDENTIALS is not set
 # CONFIG_RCU_TORTURE_TEST is not set
 # CONFIG_RCU_CPU_STALL_DETECTOR is not set
 # CONFIG_BACKTRACE_SELF_TEST is not set
 # CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
+# CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set
 # CONFIG_FAULT_INJECTION is not set
 # CONFIG_LATENCYTOP is not set
 # CONFIG_DEBUG_PAGEALLOC is not set
@@ -1248,23 +1281,25 @@ CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y
 CONFIG_HAVE_DYNAMIC_FTRACE=y
 CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
 CONFIG_TRACING_SUPPORT=y
-
-#
-# Tracers
-#
+CONFIG_FTRACE=y
 # CONFIG_FUNCTION_TRACER is not set
+# CONFIG_IRQSOFF_TRACER is not set
 # CONFIG_SCHED_TRACER is not set
-# CONFIG_CONTEXT_SWITCH_TRACER is not set
-# CONFIG_EVENT_TRACER is not set
+# CONFIG_ENABLE_DEFAULT_TRACERS is not set
 # CONFIG_BOOT_TRACER is not set
-# CONFIG_TRACE_BRANCH_PROFILING is not set
+CONFIG_BRANCH_PROFILE_NONE=y
+# CONFIG_PROFILE_ANNOTATED_BRANCHES is not set
+# CONFIG_PROFILE_ALL_BRANCHES is not set
 # CONFIG_STACK_TRACER is not set
 # CONFIG_KMEMTRACE is not set
 # CONFIG_WORKQUEUE_TRACER is not set
 # CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_DMA_API_DEBUG is not set
 # CONFIG_SAMPLES is not set
 CONFIG_HAVE_ARCH_KGDB=y
 # CONFIG_KGDB is not set
+# CONFIG_PPC_DISABLE_WERROR is not set
+CONFIG_PPC_WERROR=y
 CONFIG_PRINT_STACK_DEPTH=64
 # CONFIG_DEBUG_STACKOVERFLOW is not set
 # CONFIG_DEBUG_STACK_USAGE is not set
@@ -1289,7 +1324,6 @@ CONFIG_CRYPTO=y
 #
 # Crypto core or helper
 #
-# CONFIG_CRYPTO_FIPS is not set
 CONFIG_CRYPTO_ALGAPI=y
 CONFIG_CRYPTO_ALGAPI2=y
 CONFIG_CRYPTO_AEAD2=y
@@ -1331,11 +1365,13 @@ CONFIG_CRYPTO_PCBC=y
 #
 # CONFIG_CRYPTO_HMAC is not set
 # CONFIG_CRYPTO_XCBC is not set
+# CONFIG_CRYPTO_VMAC is not set
 
 #
 # Digest
 #
 # CONFIG_CRYPTO_CRC32C is not set
+# CONFIG_CRYPTO_GHASH is not set
 # CONFIG_CRYPTO_MD4 is not set
 CONFIG_CRYPTO_MD5=y
 # CONFIG_CRYPTO_MICHAEL_MIC is not set
index aaa4416..523d5fe 100644 (file)
@@ -1,25 +1,27 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.30-rc2
-# Mon Apr 20 11:06:25 2009
+# Linux kernel version: 2.6.32-rc4
+# Thu Oct 15 10:33:21 2009
 #
 # CONFIG_PPC64 is not set
 
 #
 # Processor support
 #
-CONFIG_6xx=y
+CONFIG_PPC_BOOK3S_32=y
 # CONFIG_PPC_85xx is not set
 # CONFIG_PPC_8xx is not set
 # CONFIG_40x is not set
 # CONFIG_44x is not set
 # CONFIG_E200 is not set
 CONFIG_PPC_BOOK3S=y
+CONFIG_6xx=y
 CONFIG_PPC_FPU=y
 # CONFIG_ALTIVEC is not set
 CONFIG_PPC_STD_MMU=y
 CONFIG_PPC_STD_MMU_32=y
 # CONFIG_PPC_MM_SLICES is not set
+CONFIG_PPC_HAVE_PMU_SUPPORT=y
 # CONFIG_SMP is not set
 CONFIG_PPC32=y
 CONFIG_WORD_SIZE=32
@@ -30,15 +32,17 @@ CONFIG_GENERIC_TIME=y
 CONFIG_GENERIC_TIME_VSYSCALL=y
 CONFIG_GENERIC_CLOCKEVENTS=y
 CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
 # CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
+# CONFIG_NEED_PER_CPU_EMBED_FIRST_CHUNK is not set
 CONFIG_IRQ_PER_CPU=y
 CONFIG_STACKTRACE_SUPPORT=y
 CONFIG_HAVE_LATENCYTOP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
 CONFIG_LOCKDEP_SUPPORT=y
 CONFIG_RWSEM_XCHGADD_ALGORITHM=y
 CONFIG_ARCH_HAS_ILOG2_U32=y
 CONFIG_GENERIC_HWEIGHT=y
-CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_GENERIC_FIND_NEXT_BIT=y
 CONFIG_GENERIC_GPIO=y
 # CONFIG_ARCH_NO_VIRT_TO_BUS is not set
@@ -53,12 +57,14 @@ CONFIG_OF=y
 # CONFIG_GENERIC_TBSYNC is not set
 CONFIG_AUDIT_ARCH=y
 CONFIG_GENERIC_BUG=y
+CONFIG_DTC=y
 CONFIG_DEFAULT_UIMAGE=y
 CONFIG_ARCH_SUSPEND_POSSIBLE=y
 # CONFIG_PPC_DCR_NATIVE is not set
 # CONFIG_PPC_DCR_MMIO is not set
 CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_CONSTRUCTORS=y
 
 #
 # General setup
@@ -79,11 +85,12 @@ CONFIG_SYSVIPC_SYSCTL=y
 #
 # RCU Subsystem
 #
-CONFIG_CLASSIC_RCU=y
-# CONFIG_TREE_RCU is not set
-# CONFIG_PREEMPT_RCU is not set
+CONFIG_TREE_RCU=y
+# CONFIG_TREE_PREEMPT_RCU is not set
+# CONFIG_RCU_TRACE is not set
+CONFIG_RCU_FANOUT=32
+# CONFIG_RCU_FANOUT_EXACT is not set
 # CONFIG_TREE_RCU_TRACE is not set
-# CONFIG_PREEMPT_RCU_TRACE is not set
 # CONFIG_IKCONFIG is not set
 CONFIG_LOG_BUF_SHIFT=14
 # CONFIG_GROUP_SCHED is not set
@@ -103,7 +110,6 @@ CONFIG_ANON_INODES=y
 CONFIG_EMBEDDED=y
 # CONFIG_SYSCTL_SYSCALL is not set
 # CONFIG_KALLSYMS is not set
-# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_HOTPLUG=y
 CONFIG_PRINTK=y
 CONFIG_BUG=y
@@ -116,6 +122,13 @@ CONFIG_TIMERFD=y
 CONFIG_EVENTFD=y
 CONFIG_SHMEM=y
 CONFIG_AIO=y
+CONFIG_HAVE_PERF_EVENTS=y
+
+#
+# Kernel Performance Events And Counters
+#
+# CONFIG_PERF_EVENTS is not set
+# CONFIG_PERF_COUNTERS is not set
 CONFIG_VM_EVENT_COUNTERS=y
 CONFIG_PCI_QUIRKS=y
 CONFIG_SLUB_DEBUG=y
@@ -124,14 +137,19 @@ CONFIG_COMPAT_BRK=y
 CONFIG_SLUB=y
 # CONFIG_SLOB is not set
 # CONFIG_PROFILING is not set
-# CONFIG_MARKERS is not set
 CONFIG_HAVE_OPROFILE=y
 CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y
 CONFIG_HAVE_IOREMAP_PROT=y
 CONFIG_HAVE_KPROBES=y
 CONFIG_HAVE_KRETPROBES=y
 CONFIG_HAVE_ARCH_TRACEHOOK=y
+CONFIG_HAVE_DMA_ATTRS=y
 CONFIG_HAVE_CLK=y
+CONFIG_HAVE_DMA_API_DEBUG=y
+
+#
+# GCOV-based kernel profiling
+#
 # CONFIG_SLOW_WORK is not set
 # CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
 CONFIG_SLABINFO=y
@@ -144,7 +162,7 @@ CONFIG_MODULE_UNLOAD=y
 # CONFIG_MODVERSIONS is not set
 # CONFIG_MODULE_SRCVERSION_ALL is not set
 CONFIG_BLOCK=y
-# CONFIG_LBD is not set
+CONFIG_LBDAF=y
 # CONFIG_BLK_DEV_BSG is not set
 # CONFIG_BLK_DEV_INTEGRITY is not set
 
@@ -205,7 +223,7 @@ CONFIG_RTAS_PROC=y
 CONFIG_PPC_BESTCOMM=y
 CONFIG_PPC_BESTCOMM_ATA=y
 CONFIG_PPC_BESTCOMM_FEC=y
-# CONFIG_SIMPLE_GPIO is not set
+CONFIG_SIMPLE_GPIO=y
 
 #
 # Kernel options
@@ -229,11 +247,13 @@ CONFIG_BINFMT_ELF=y
 # CONFIG_HAVE_AOUT is not set
 # CONFIG_BINFMT_MISC is not set
 # CONFIG_IOMMU_HELPER is not set
+# CONFIG_SWIOTLB is not set
 CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
 CONFIG_ARCH_HAS_WALK_MEMORY=y
 CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
 # CONFIG_KEXEC is not set
 # CONFIG_CRASH_DUMP is not set
+CONFIG_MAX_ACTIVE_REGIONS=32
 CONFIG_ARCH_FLATMEM_ENABLE=y
 CONFIG_ARCH_POPULATES_NODE_MAP=y
 CONFIG_SELECT_MEMORY_MODEL=y
@@ -249,9 +269,10 @@ CONFIG_MIGRATION=y
 CONFIG_ZONE_DMA_FLAG=1
 CONFIG_BOUNCE=y
 CONFIG_VIRT_TO_BUS=y
-CONFIG_UNEVICTABLE_LRU=y
 CONFIG_HAVE_MLOCK=y
 CONFIG_HAVE_MLOCKED_PAGE_BIT=y
+# CONFIG_KSM is not set
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
 CONFIG_PPC_4K_PAGES=y
 # CONFIG_PPC_16K_PAGES is not set
 # CONFIG_PPC_64K_PAGES is not set
@@ -265,6 +286,7 @@ CONFIG_PM=y
 CONFIG_PM_SLEEP=y
 CONFIG_SUSPEND=y
 CONFIG_SUSPEND_FREEZER=y
+# CONFIG_PM_RUNTIME is not set
 CONFIG_SECCOMP=y
 CONFIG_ISA_DMA_API=y
 
@@ -349,6 +371,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
 # CONFIG_NETFILTER is not set
 # CONFIG_IP_DCCP is not set
 # CONFIG_IP_SCTP is not set
+# CONFIG_RDS is not set
 # CONFIG_TIPC is not set
 # CONFIG_ATM is not set
 # CONFIG_BRIDGE is not set
@@ -363,6 +386,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
 # CONFIG_PHONET is not set
+# CONFIG_IEEE802154 is not set
 # CONFIG_NET_SCHED is not set
 # CONFIG_DCB is not set
 
@@ -388,6 +412,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
 # Generic Driver Options
 #
 CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+# CONFIG_DEVTMPFS is not set
 CONFIG_STANDALONE=y
 CONFIG_PREVENT_FIRMWARE_BUILD=y
 # CONFIG_FW_LOADER is not set
@@ -397,9 +422,9 @@ CONFIG_PREVENT_FIRMWARE_BUILD=y
 # CONFIG_CONNECTOR is not set
 CONFIG_MTD=y
 # CONFIG_MTD_DEBUG is not set
+# CONFIG_MTD_TESTS is not set
 CONFIG_MTD_CONCAT=y
 CONFIG_MTD_PARTITIONS=y
-# CONFIG_MTD_TESTS is not set
 # CONFIG_MTD_REDBOOT_PARTS is not set
 CONFIG_MTD_CMDLINE_PARTS=y
 CONFIG_MTD_OF_PARTS=y
@@ -458,6 +483,7 @@ CONFIG_MTD_PHYSMAP_OF=y
 # CONFIG_MTD_PMC551 is not set
 # CONFIG_MTD_DATAFLASH is not set
 # CONFIG_MTD_M25P80 is not set
+# CONFIG_MTD_SST25L is not set
 # CONFIG_MTD_SLRAM is not set
 # CONFIG_MTD_PHRAM is not set
 # CONFIG_MTD_MTDRAM is not set
@@ -493,6 +519,7 @@ CONFIG_OF_DEVICE=y
 CONFIG_OF_GPIO=y
 CONFIG_OF_I2C=y
 CONFIG_OF_SPI=y
+CONFIG_OF_MDIO=y
 # CONFIG_PARPORT is not set
 CONFIG_BLK_DEV=y
 # CONFIG_BLK_DEV_FD is not set
@@ -529,7 +556,9 @@ CONFIG_MISC_DEVICES=y
 CONFIG_EEPROM_AT24=y
 # CONFIG_EEPROM_AT25 is not set
 # CONFIG_EEPROM_LEGACY is not set
+# CONFIG_EEPROM_MAX6875 is not set
 # CONFIG_EEPROM_93CX6 is not set
+# CONFIG_CB710_CORE is not set
 CONFIG_HAVE_IDE=y
 # CONFIG_IDE is not set
 
@@ -552,10 +581,6 @@ CONFIG_BLK_DEV_SD=y
 # CONFIG_BLK_DEV_SR is not set
 CONFIG_CHR_DEV_SG=y
 # CONFIG_CHR_DEV_SCH is not set
-
-#
-# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
-#
 # CONFIG_SCSI_MULTI_LUN is not set
 # CONFIG_SCSI_CONSTANTS is not set
 # CONFIG_SCSI_LOGGING is not set
@@ -572,6 +597,8 @@ CONFIG_SCSI_WAIT_SCAN=m
 # CONFIG_SCSI_SRP_ATTRS is not set
 CONFIG_SCSI_LOWLEVEL=y
 # CONFIG_ISCSI_TCP is not set
+# CONFIG_SCSI_BNX2_ISCSI is not set
+# CONFIG_BE2ISCSI is not set
 # CONFIG_BLK_DEV_3W_XXXX_RAID is not set
 # CONFIG_SCSI_3W_9XXX is not set
 # CONFIG_SCSI_ACARD is not set
@@ -580,6 +607,7 @@ CONFIG_SCSI_LOWLEVEL=y
 # CONFIG_SCSI_AIC7XXX_OLD is not set
 # CONFIG_SCSI_AIC79XX is not set
 # CONFIG_SCSI_AIC94XX is not set
+# CONFIG_SCSI_MVSAS is not set
 # CONFIG_SCSI_DPT_I2O is not set
 # CONFIG_SCSI_ADVANSYS is not set
 # CONFIG_SCSI_ARCMSR is not set
@@ -599,7 +627,6 @@ CONFIG_SCSI_LOWLEVEL=y
 # CONFIG_SCSI_IPS is not set
 # CONFIG_SCSI_INITIO is not set
 # CONFIG_SCSI_INIA100 is not set
-# CONFIG_SCSI_MVSAS is not set
 # CONFIG_SCSI_STEX is not set
 # CONFIG_SCSI_SYM53C8XX_2 is not set
 # CONFIG_SCSI_IPR is not set
@@ -611,11 +638,14 @@ CONFIG_SCSI_LOWLEVEL=y
 # CONFIG_SCSI_DC390T is not set
 # CONFIG_SCSI_NSP32 is not set
 # CONFIG_SCSI_DEBUG is not set
+# CONFIG_SCSI_PMCRAID is not set
 # CONFIG_SCSI_SRP is not set
+# CONFIG_SCSI_BFA_FC is not set
 # CONFIG_SCSI_DH is not set
 # CONFIG_SCSI_OSD_INITIATOR is not set
 CONFIG_ATA=y
 # CONFIG_ATA_NONSTANDARD is not set
+CONFIG_ATA_VERBOSE_ERROR=y
 CONFIG_SATA_PMP=y
 # CONFIG_SATA_AHCI is not set
 # CONFIG_SATA_SIL24 is not set
@@ -637,6 +667,7 @@ CONFIG_ATA_SFF=y
 # CONFIG_PATA_ALI is not set
 # CONFIG_PATA_AMD is not set
 # CONFIG_PATA_ARTOP is not set
+# CONFIG_PATA_ATP867X is not set
 # CONFIG_PATA_ATIIXP is not set
 # CONFIG_PATA_CMD640_PCI is not set
 # CONFIG_PATA_CMD64X is not set
@@ -665,6 +696,7 @@ CONFIG_PATA_MPC52xx=y
 # CONFIG_PATA_OPTIDMA is not set
 # CONFIG_PATA_PDC_OLD is not set
 # CONFIG_PATA_RADISYS is not set
+# CONFIG_PATA_RDC is not set
 # CONFIG_PATA_RZ1000 is not set
 # CONFIG_PATA_SC1200 is not set
 # CONFIG_PATA_SERVERWORKS is not set
@@ -684,14 +716,17 @@ CONFIG_PATA_PLATFORM=y
 #
 
 #
-# Enable only one of the two stacks, unless you know what you are doing
+# You can enable one or both FireWire driver stacks.
+#
+
+#
+# See the help texts for more information.
 #
 # CONFIG_FIREWIRE is not set
 # CONFIG_IEEE1394 is not set
 # CONFIG_I2O is not set
 # CONFIG_MACINTOSH_DRIVERS is not set
 CONFIG_NETDEVICES=y
-CONFIG_COMPAT_NET_DEV_OPS=y
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
 # CONFIG_MACVLAN is not set
@@ -739,16 +774,17 @@ CONFIG_NET_ETHERNET=y
 # CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
 # CONFIG_NET_PCI is not set
 # CONFIG_B44 is not set
+# CONFIG_KS8842 is not set
+# CONFIG_KS8851 is not set
+# CONFIG_KS8851_MLL is not set
 CONFIG_FEC_MPC52xx=y
 CONFIG_FEC_MPC52xx_MDIO=y
 # CONFIG_ATL2 is not set
+# CONFIG_XILINX_EMACLITE is not set
 # CONFIG_NETDEV_1000 is not set
 # CONFIG_NETDEV_10000 is not set
 # CONFIG_TR is not set
-
-#
-# Wireless LAN
-#
+CONFIG_WLAN=y
 # CONFIG_WLAN_PRE80211 is not set
 # CONFIG_WLAN_80211 is not set
 
@@ -854,6 +890,7 @@ CONFIG_LEGACY_PTY_COUNT=256
 CONFIG_DEVPORT=y
 CONFIG_I2C=y
 CONFIG_I2C_BOARDINFO=y
+CONFIG_I2C_COMPAT=y
 CONFIG_I2C_CHARDEV=y
 CONFIG_I2C_HELPER_AUTO=y
 CONFIG_I2C_ALGOBIT=y
@@ -883,6 +920,7 @@ CONFIG_I2C_ALGOBIT=y
 #
 # I2C system bus drivers (mostly embedded / system-on-chip)
 #
+# CONFIG_I2C_DESIGNWARE is not set
 # CONFIG_I2C_GPIO is not set
 CONFIG_I2C_MPC=y
 # CONFIG_I2C_OCORES is not set
@@ -910,10 +948,6 @@ CONFIG_I2C_MPC=y
 # Miscellaneous I2C Chip support
 #
 # CONFIG_DS1682 is not set
-# CONFIG_SENSORS_PCF8574 is not set
-# CONFIG_PCF8575 is not set
-# CONFIG_SENSORS_PCA9539 is not set
-# CONFIG_SENSORS_MAX6875 is not set
 # CONFIG_SENSORS_TSL2550 is not set
 # CONFIG_I2C_DEBUG_CORE is not set
 # CONFIG_I2C_DEBUG_ALGO is not set
@@ -935,6 +969,11 @@ CONFIG_SPI_MPC52xx_PSC=m
 #
 CONFIG_SPI_SPIDEV=m
 # CONFIG_SPI_TLE62X0 is not set
+
+#
+# PPS support
+#
+# CONFIG_PPS is not set
 CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
 CONFIG_ARCH_REQUIRE_GPIOLIB=y
 CONFIG_GPIOLIB=y
@@ -957,16 +996,27 @@ CONFIG_GPIOLIB=y
 # PCI GPIO expanders:
 #
 # CONFIG_GPIO_BT8XX is not set
+# CONFIG_GPIO_LANGWELL is not set
 
 #
 # SPI GPIO expanders:
 #
 # CONFIG_GPIO_MAX7301 is not set
 # CONFIG_GPIO_MCP23S08 is not set
+# CONFIG_GPIO_MC33880 is not set
+
+#
+# AC97 GPIO expanders:
+#
 # CONFIG_W1 is not set
 # CONFIG_POWER_SUPPLY is not set
 CONFIG_HWMON=y
 # CONFIG_HWMON_VID is not set
+# CONFIG_HWMON_DEBUG_CHIP is not set
+
+#
+# Native drivers
+#
 # CONFIG_SENSORS_AD7414 is not set
 # CONFIG_SENSORS_AD7418 is not set
 # CONFIG_SENSORS_ADCXX is not set
@@ -1019,6 +1069,8 @@ CONFIG_HWMON=y
 # CONFIG_SENSORS_SMSC47B397 is not set
 # CONFIG_SENSORS_ADS7828 is not set
 # CONFIG_SENSORS_THMC50 is not set
+# CONFIG_SENSORS_TMP401 is not set
+# CONFIG_SENSORS_TMP421 is not set
 # CONFIG_SENSORS_VIA686A is not set
 # CONFIG_SENSORS_VT1211 is not set
 # CONFIG_SENSORS_VT8231 is not set
@@ -1031,9 +1083,7 @@ CONFIG_HWMON=y
 # CONFIG_SENSORS_W83627HF is not set
 # CONFIG_SENSORS_W83627EHF is not set
 # CONFIG_SENSORS_LIS3_SPI is not set
-# CONFIG_HWMON_DEBUG_CHIP is not set
 # CONFIG_THERMAL is not set
-# CONFIG_THERMAL_HWMON is not set
 CONFIG_WATCHDOG=y
 # CONFIG_WATCHDOG_NOWAYOUT is not set
 
@@ -1073,31 +1123,20 @@ CONFIG_SSB_POSSIBLE=y
 # CONFIG_MFD_TMIO is not set
 # CONFIG_PMIC_DA903X is not set
 # CONFIG_MFD_WM8400 is not set
+# CONFIG_MFD_WM831X is not set
 # CONFIG_MFD_WM8350_I2C is not set
 # CONFIG_MFD_PCF50633 is not set
+# CONFIG_MFD_MC13783 is not set
+# CONFIG_AB3100_CORE is not set
+# CONFIG_EZX_PCAP is not set
 # CONFIG_REGULATOR is not set
-
-#
-# Multimedia devices
-#
-
-#
-# Multimedia core support
-#
-# CONFIG_VIDEO_DEV is not set
-# CONFIG_DVB_CORE is not set
-# CONFIG_VIDEO_MEDIA is not set
-
-#
-# Multimedia drivers
-#
-CONFIG_DAB=y
-# CONFIG_USB_DABUSB is not set
+# CONFIG_MEDIA_SUPPORT is not set
 
 #
 # Graphics support
 #
 # CONFIG_AGP is not set
+CONFIG_VGA_ARB=y
 CONFIG_DRM=y
 # CONFIG_DRM_TDFX is not set
 # CONFIG_DRM_R128 is not set
@@ -1167,6 +1206,7 @@ CONFIG_FB_RADEON_BACKLIGHT=y
 # CONFIG_FB_BROADSHEET is not set
 CONFIG_BACKLIGHT_LCD_SUPPORT=y
 CONFIG_LCD_CLASS_DEVICE=m
+# CONFIG_LCD_LMS283GF05 is not set
 # CONFIG_LCD_LTV350QV is not set
 # CONFIG_LCD_ILI9320 is not set
 # CONFIG_LCD_TDO24M is not set
@@ -1198,7 +1238,6 @@ CONFIG_LOGO_LINUX_CLUT224=y
 # CONFIG_SOUND is not set
 CONFIG_HID_SUPPORT=y
 CONFIG_HID=y
-# CONFIG_HID_DEBUG is not set
 # CONFIG_HIDRAW is not set
 
 #
@@ -1217,10 +1256,11 @@ CONFIG_HID_BELKIN=y
 CONFIG_HID_CHERRY=y
 # CONFIG_HID_CHICONY is not set
 CONFIG_HID_CYPRESS=y
-# CONFIG_DRAGONRISE_FF is not set
+# CONFIG_HID_DRAGONRISE is not set
 CONFIG_HID_EZKEY=y
 # CONFIG_HID_KYE is not set
 # CONFIG_HID_GYRATION is not set
+# CONFIG_HID_TWINHAN is not set
 # CONFIG_HID_KENSINGTON is not set
 # CONFIG_HID_LOGITECH is not set
 # CONFIG_HID_MICROSOFT is not set
@@ -1231,10 +1271,11 @@ CONFIG_HID_EZKEY=y
 # CONFIG_HID_SAMSUNG is not set
 # CONFIG_HID_SONY is not set
 # CONFIG_HID_SUNPLUS is not set
-# CONFIG_GREENASIA_FF is not set
+# CONFIG_HID_GREENASIA is not set
+# CONFIG_HID_SMARTJOYPLUS is not set
 # CONFIG_HID_TOPSEED is not set
-# CONFIG_THRUSTMASTER_FF is not set
-# CONFIG_ZEROPLUS_FF is not set
+# CONFIG_HID_THRUSTMASTER is not set
+# CONFIG_HID_ZEROPLUS is not set
 CONFIG_USB_SUPPORT=y
 CONFIG_USB_ARCH_HAS_HCD=y
 CONFIG_USB_ARCH_HAS_OHCI=y
@@ -1261,15 +1302,17 @@ CONFIG_USB_MON=y
 # USB Host Controller Drivers
 #
 # CONFIG_USB_C67X00_HCD is not set
+# CONFIG_USB_XHCI_HCD is not set
 # CONFIG_USB_EHCI_HCD is not set
 # CONFIG_USB_OXU210HP_HCD is not set
 # CONFIG_USB_ISP116X_HCD is not set
 # CONFIG_USB_ISP1760_HCD is not set
+# CONFIG_USB_ISP1362_HCD is not set
 CONFIG_USB_OHCI_HCD=y
 CONFIG_USB_OHCI_HCD_PPC_SOC=y
-CONFIG_USB_OHCI_HCD_PPC_OF=y
 CONFIG_USB_OHCI_HCD_PPC_OF_BE=y
 # CONFIG_USB_OHCI_HCD_PPC_OF_LE is not set
+CONFIG_USB_OHCI_HCD_PPC_OF=y
 CONFIG_USB_OHCI_HCD_PCI=y
 CONFIG_USB_OHCI_BIG_ENDIAN_DESC=y
 CONFIG_USB_OHCI_BIG_ENDIAN_MMIO=y
@@ -1400,6 +1443,7 @@ CONFIG_RTC_DRV_DS1307=y
 # CONFIG_RTC_DRV_S35390A is not set
 # CONFIG_RTC_DRV_FM3130 is not set
 # CONFIG_RTC_DRV_RX8581 is not set
+# CONFIG_RTC_DRV_RX8025 is not set
 
 #
 # SPI RTC drivers
@@ -1411,6 +1455,7 @@ CONFIG_RTC_DRV_DS1307=y
 # CONFIG_RTC_DRV_R9701 is not set
 # CONFIG_RTC_DRV_RS5C348 is not set
 # CONFIG_RTC_DRV_DS3234 is not set
+# CONFIG_RTC_DRV_PCF2123 is not set
 
 #
 # Platform RTC drivers
@@ -1434,6 +1479,10 @@ CONFIG_RTC_DRV_DS1307=y
 # CONFIG_DMADEVICES is not set
 # CONFIG_AUXDISPLAY is not set
 # CONFIG_UIO is not set
+
+#
+# TI VLYNQ
+#
 # CONFIG_STAGING is not set
 
 #
@@ -1453,10 +1502,13 @@ CONFIG_FS_MBCACHE=y
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
 # CONFIG_FS_POSIX_ACL is not set
-CONFIG_FILE_LOCKING=y
 # CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
 # CONFIG_OCFS2_FS is not set
 # CONFIG_BTRFS_FS is not set
+# CONFIG_NILFS2_FS is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
 CONFIG_DNOTIFY=y
 CONFIG_INOTIFY=y
 CONFIG_INOTIFY_USER=y
@@ -1533,12 +1585,12 @@ CONFIG_CRAMFS=y
 # CONFIG_ROMFS_FS is not set
 # CONFIG_SYSV_FS is not set
 # CONFIG_UFS_FS is not set
-# CONFIG_NILFS2_FS is not set
 CONFIG_NETWORK_FILESYSTEMS=y
 CONFIG_NFS_FS=y
 CONFIG_NFS_V3=y
 # CONFIG_NFS_V3_ACL is not set
 CONFIG_NFS_V4=y
+# CONFIG_NFS_V4_1 is not set
 CONFIG_ROOT_NFS=y
 # CONFIG_NFSD is not set
 CONFIG_LOCKD=y
@@ -1624,6 +1676,7 @@ CONFIG_HAS_IOPORT=y
 CONFIG_HAS_DMA=y
 CONFIG_HAVE_LMB=y
 CONFIG_NLATTR=y
+CONFIG_GENERIC_ATOMIC64=y
 
 #
 # Kernel hacking
@@ -1633,6 +1686,7 @@ CONFIG_ENABLE_WARN_DEPRECATED=y
 CONFIG_ENABLE_MUST_CHECK=y
 CONFIG_FRAME_WARN=1024
 # CONFIG_MAGIC_SYSRQ is not set
+# CONFIG_STRIP_ASM_SYMS is not set
 # CONFIG_UNUSED_SYMBOLS is not set
 # CONFIG_DEBUG_FS is not set
 # CONFIG_HEADERS_CHECK is not set
@@ -1650,10 +1704,14 @@ CONFIG_SCHED_DEBUG=y
 # CONFIG_DEBUG_OBJECTS is not set
 # CONFIG_SLUB_DEBUG_ON is not set
 # CONFIG_SLUB_STATS is not set
+# CONFIG_DEBUG_KMEMLEAK is not set
 # CONFIG_DEBUG_RT_MUTEXES is not set
 # CONFIG_RT_MUTEX_TESTER is not set
 # CONFIG_DEBUG_SPINLOCK is not set
 # CONFIG_DEBUG_MUTEXES is not set
+# CONFIG_DEBUG_LOCK_ALLOC is not set
+# CONFIG_PROVE_LOCKING is not set
+# CONFIG_LOCK_STAT is not set
 # CONFIG_DEBUG_SPINLOCK_SLEEP is not set
 # CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
 # CONFIG_DEBUG_KOBJECT is not set
@@ -1665,11 +1723,12 @@ CONFIG_DEBUG_INFO=y
 # CONFIG_DEBUG_LIST is not set
 # CONFIG_DEBUG_SG is not set
 # CONFIG_DEBUG_NOTIFIERS is not set
-# CONFIG_BOOT_PRINTK_DELAY is not set
+# CONFIG_DEBUG_CREDENTIALS is not set
 # CONFIG_RCU_TORTURE_TEST is not set
 # CONFIG_RCU_CPU_STALL_DETECTOR is not set
 # CONFIG_BACKTRACE_SELF_TEST is not set
 # CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
+# CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set
 # CONFIG_FAULT_INJECTION is not set
 # CONFIG_LATENCYTOP is not set
 # CONFIG_DEBUG_PAGEALLOC is not set
@@ -1678,23 +1737,25 @@ CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y
 CONFIG_HAVE_DYNAMIC_FTRACE=y
 CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
 CONFIG_TRACING_SUPPORT=y
-
-#
-# Tracers
-#
+CONFIG_FTRACE=y
 # CONFIG_FUNCTION_TRACER is not set
+# CONFIG_IRQSOFF_TRACER is not set
 # CONFIG_SCHED_TRACER is not set
-# CONFIG_CONTEXT_SWITCH_TRACER is not set
-# CONFIG_EVENT_TRACER is not set
+# CONFIG_ENABLE_DEFAULT_TRACERS is not set
 # CONFIG_BOOT_TRACER is not set
-# CONFIG_TRACE_BRANCH_PROFILING is not set
+CONFIG_BRANCH_PROFILE_NONE=y
+# CONFIG_PROFILE_ANNOTATED_BRANCHES is not set
+# CONFIG_PROFILE_ALL_BRANCHES is not set
 # CONFIG_STACK_TRACER is not set
 # CONFIG_KMEMTRACE is not set
 # CONFIG_WORKQUEUE_TRACER is not set
 # CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_DMA_API_DEBUG is not set
 # CONFIG_SAMPLES is not set
 CONFIG_HAVE_ARCH_KGDB=y
 # CONFIG_KGDB is not set
+# CONFIG_PPC_DISABLE_WERROR is not set
+CONFIG_PPC_WERROR=y
 CONFIG_PRINT_STACK_DEPTH=64
 # CONFIG_DEBUG_STACKOVERFLOW is not set
 # CONFIG_DEBUG_STACK_USAGE is not set
@@ -1719,7 +1780,6 @@ CONFIG_CRYPTO=y
 #
 # Crypto core or helper
 #
-# CONFIG_CRYPTO_FIPS is not set
 CONFIG_CRYPTO_ALGAPI=y
 CONFIG_CRYPTO_ALGAPI2=y
 CONFIG_CRYPTO_AEAD2=y
@@ -1761,11 +1821,13 @@ CONFIG_CRYPTO_CBC=y
 #
 # CONFIG_CRYPTO_HMAC is not set
 # CONFIG_CRYPTO_XCBC is not set
+# CONFIG_CRYPTO_VMAC is not set
 
 #
 # Digest
 #
 # CONFIG_CRYPTO_CRC32C is not set
+# CONFIG_CRYPTO_GHASH is not set
 # CONFIG_CRYPTO_MD4 is not set
 CONFIG_CRYPTO_MD5=y
 # CONFIG_CRYPTO_MICHAEL_MIC is not set
diff --git a/arch/powerpc/configs/ppc64e_defconfig b/arch/powerpc/configs/ppc64e_defconfig
new file mode 100644 (file)
index 0000000..18af460
--- /dev/null
@@ -0,0 +1,2199 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.32-rc5
+# Fri Oct 16 11:37:15 2009
+#
+CONFIG_PPC64=y
+
+#
+# Processor support
+#
+# CONFIG_PPC_BOOK3S_64 is not set
+CONFIG_PPC_BOOK3E_64=y
+CONFIG_PPC_BOOK3E=y
+CONFIG_PPC_FPU=y
+CONFIG_BOOKE=y
+CONFIG_PPC_MMU_NOHASH=y
+CONFIG_PPC_MMU_NOHASH_64=y
+CONFIG_PPC_BOOK3E_MMU=y
+# CONFIG_PPC_MM_SLICES is not set
+CONFIG_VIRT_CPU_ACCOUNTING=y
+CONFIG_PPC_HAVE_PMU_SUPPORT=y
+CONFIG_PPC_PERF_CTRS=y
+CONFIG_SMP=y
+CONFIG_NR_CPUS=32
+CONFIG_64BIT=y
+CONFIG_WORD_SIZE=64
+CONFIG_ARCH_PHYS_ADDR_T_64BIT=y
+CONFIG_MMU=y
+CONFIG_GENERIC_CMOS_UPDATE=y
+CONFIG_GENERIC_TIME=y
+CONFIG_GENERIC_TIME_VSYSCALL=y
+CONFIG_GENERIC_CLOCKEVENTS=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
+CONFIG_HAVE_SETUP_PER_CPU_AREA=y
+CONFIG_NEED_PER_CPU_EMBED_FIRST_CHUNK=y
+CONFIG_IRQ_PER_CPU=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_HAVE_LATENCYTOP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_ARCH_HAS_ILOG2_U32=y
+CONFIG_ARCH_HAS_ILOG2_U64=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_ARCH_NO_VIRT_TO_BUS=y
+CONFIG_PPC=y
+CONFIG_EARLY_PRINTK=y
+CONFIG_COMPAT=y
+CONFIG_SYSVIPC_COMPAT=y
+CONFIG_SCHED_OMIT_FRAME_POINTER=y
+CONFIG_ARCH_MAY_HAVE_PC_FDC=y
+CONFIG_PPC_OF=y
+CONFIG_OF=y
+# CONFIG_PPC_UDBG_16550 is not set
+# CONFIG_GENERIC_TBSYNC is not set
+CONFIG_AUDIT_ARCH=y
+CONFIG_GENERIC_BUG=y
+CONFIG_DTC=y
+# CONFIG_DEFAULT_UIMAGE is not set
+# CONFIG_PPC_DCR_NATIVE is not set
+# CONFIG_PPC_DCR_MMIO is not set
+# CONFIG_PPC_OF_PLATFORM_PCI is not set
+CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_CONSTRUCTORS=y
+
+#
+# General setup
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_LOCK_KERNEL=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_SYSVIPC_SYSCTL=y
+CONFIG_POSIX_MQUEUE=y
+CONFIG_POSIX_MQUEUE_SYSCTL=y
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_TASKSTATS=y
+CONFIG_TASK_DELAY_ACCT=y
+# CONFIG_TASK_XACCT is not set
+# CONFIG_AUDIT is not set
+
+#
+# RCU Subsystem
+#
+CONFIG_TREE_RCU=y
+# CONFIG_TREE_PREEMPT_RCU is not set
+# CONFIG_RCU_TRACE is not set
+CONFIG_RCU_FANOUT=64
+# CONFIG_RCU_FANOUT_EXACT is not set
+# CONFIG_TREE_RCU_TRACE is not set
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=17
+# CONFIG_GROUP_SCHED is not set
+CONFIG_CGROUPS=y
+# CONFIG_CGROUP_DEBUG is not set
+# CONFIG_CGROUP_NS is not set
+# CONFIG_CGROUP_FREEZER is not set
+# CONFIG_CGROUP_DEVICE is not set
+CONFIG_CPUSETS=y
+CONFIG_PROC_PID_CPUSET=y
+# CONFIG_CGROUP_CPUACCT is not set
+# CONFIG_RESOURCE_COUNTERS is not set
+CONFIG_SYSFS_DEPRECATED=y
+CONFIG_SYSFS_DEPRECATED_V2=y
+CONFIG_RELAY=y
+CONFIG_NAMESPACES=y
+# CONFIG_UTS_NS is not set
+# CONFIG_IPC_NS is not set
+# CONFIG_USER_NS is not set
+# CONFIG_PID_NS is not set
+# CONFIG_NET_NS is not set
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_RD_GZIP=y
+CONFIG_RD_BZIP2=y
+CONFIG_RD_LZMA=y
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SYSCTL=y
+CONFIG_ANON_INODES=y
+# CONFIG_EMBEDDED is not set
+CONFIG_SYSCTL_SYSCALL=y
+CONFIG_KALLSYMS=y
+CONFIG_KALLSYMS_ALL=y
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
+CONFIG_SHMEM=y
+CONFIG_AIO=y
+CONFIG_HAVE_PERF_EVENTS=y
+
+#
+# Kernel Performance Events And Counters
+#
+CONFIG_PERF_EVENTS=y
+CONFIG_EVENT_PROFILE=y
+# CONFIG_PERF_COUNTERS is not set
+# CONFIG_DEBUG_PERF_USE_VMALLOC is not set
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_PCI_QUIRKS=y
+CONFIG_SLUB_DEBUG=y
+# CONFIG_COMPAT_BRK is not set
+# CONFIG_SLAB is not set
+CONFIG_SLUB=y
+# CONFIG_SLOB is not set
+CONFIG_PROFILING=y
+CONFIG_TRACEPOINTS=y
+CONFIG_OPROFILE=y
+CONFIG_HAVE_OPROFILE=y
+# CONFIG_KPROBES is not set
+CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y
+CONFIG_HAVE_SYSCALL_WRAPPERS=y
+CONFIG_HAVE_IOREMAP_PROT=y
+CONFIG_HAVE_KPROBES=y
+CONFIG_HAVE_KRETPROBES=y
+CONFIG_HAVE_ARCH_TRACEHOOK=y
+CONFIG_HAVE_DMA_ATTRS=y
+CONFIG_USE_GENERIC_SMP_HELPERS=y
+CONFIG_HAVE_DMA_API_DEBUG=y
+
+#
+# GCOV-based kernel profiling
+#
+# CONFIG_GCOV_KERNEL is not set
+CONFIG_SLOW_WORK=y
+# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
+CONFIG_SLABINFO=y
+CONFIG_RT_MUTEXES=y
+CONFIG_BASE_SMALL=0
+CONFIG_MODULES=y
+# CONFIG_MODULE_FORCE_LOAD is not set
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_MODVERSIONS=y
+CONFIG_MODULE_SRCVERSION_ALL=y
+CONFIG_STOP_MACHINE=y
+CONFIG_BLOCK=y
+CONFIG_BLK_DEV_BSG=y
+# CONFIG_BLK_DEV_INTEGRITY is not set
+CONFIG_BLOCK_COMPAT=y
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+CONFIG_DEFAULT_AS=y
+# CONFIG_DEFAULT_DEADLINE is not set
+# CONFIG_DEFAULT_CFQ is not set
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="anticipatory"
+# CONFIG_FREEZER is not set
+
+#
+# Platform support
+#
+# CONFIG_PPC_CELL is not set
+# CONFIG_PPC_CELL_NATIVE is not set
+# CONFIG_PQ2ADS is not set
+CONFIG_PPC_OF_BOOT_TRAMPOLINE=y
+# CONFIG_IPIC is not set
+# CONFIG_MPIC is not set
+# CONFIG_MPIC_WEIRD is not set
+# CONFIG_PPC_I8259 is not set
+# CONFIG_U3_DART is not set
+# CONFIG_PPC_RTAS is not set
+# CONFIG_MMIO_NVRAM is not set
+# CONFIG_PPC_MPC106 is not set
+# CONFIG_PPC_970_NAP is not set
+# CONFIG_PPC_INDIRECT_IO is not set
+# CONFIG_GENERIC_IOMAP is not set
+CONFIG_CPU_FREQ=y
+CONFIG_CPU_FREQ_TABLE=y
+# CONFIG_CPU_FREQ_DEBUG is not set
+CONFIG_CPU_FREQ_STAT=y
+# CONFIG_CPU_FREQ_STAT_DETAILS is not set
+CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE=y
+# CONFIG_CPU_FREQ_DEFAULT_GOV_POWERSAVE is not set
+# CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set
+# CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND is not set
+# CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE is not set
+CONFIG_CPU_FREQ_GOV_PERFORMANCE=y
+CONFIG_CPU_FREQ_GOV_POWERSAVE=y
+CONFIG_CPU_FREQ_GOV_USERSPACE=y
+# CONFIG_CPU_FREQ_GOV_ONDEMAND is not set
+# CONFIG_CPU_FREQ_GOV_CONSERVATIVE is not set
+
+#
+# CPU Frequency drivers
+#
+# CONFIG_FSL_ULI1575 is not set
+# CONFIG_SIMPLE_GPIO is not set
+
+#
+# Kernel options
+#
+CONFIG_TICK_ONESHOT=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+# CONFIG_HZ_100 is not set
+CONFIG_HZ_250=y
+# CONFIG_HZ_300 is not set
+# CONFIG_HZ_1000 is not set
+CONFIG_HZ=250
+CONFIG_SCHED_HRTICK=y
+CONFIG_PREEMPT_NONE=y
+# CONFIG_PREEMPT_VOLUNTARY is not set
+# CONFIG_PREEMPT is not set
+CONFIG_BINFMT_ELF=y
+CONFIG_COMPAT_BINFMT_ELF=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+# CONFIG_HAVE_AOUT is not set
+CONFIG_BINFMT_MISC=m
+CONFIG_IOMMU_VMERGE=y
+CONFIG_IOMMU_HELPER=y
+# CONFIG_SWIOTLB is not set
+CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
+CONFIG_ARCH_HAS_WALK_MEMORY=y
+CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
+# CONFIG_CRASH_DUMP is not set
+CONFIG_IRQ_ALL_CPUS=y
+# CONFIG_NUMA is not set
+CONFIG_MAX_ACTIVE_REGIONS=256
+CONFIG_ARCH_SELECT_MEMORY_MODEL=y
+CONFIG_ARCH_FLATMEM_ENABLE=y
+CONFIG_ARCH_SPARSEMEM_ENABLE=y
+CONFIG_ARCH_POPULATES_NODE_MAP=y
+CONFIG_SELECT_MEMORY_MODEL=y
+# CONFIG_FLATMEM_MANUAL is not set
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+CONFIG_SPARSEMEM_MANUAL=y
+CONFIG_SPARSEMEM=y
+CONFIG_HAVE_MEMORY_PRESENT=y
+CONFIG_SPARSEMEM_EXTREME=y
+CONFIG_SPARSEMEM_VMEMMAP_ENABLE=y
+CONFIG_SPARSEMEM_VMEMMAP=y
+# CONFIG_MEMORY_HOTPLUG is not set
+CONFIG_PAGEFLAGS_EXTENDED=y
+CONFIG_SPLIT_PTLOCK_CPUS=4
+CONFIG_MIGRATION=y
+CONFIG_PHYS_ADDR_T_64BIT=y
+CONFIG_ZONE_DMA_FLAG=1
+CONFIG_BOUNCE=y
+CONFIG_HAVE_MLOCK=y
+CONFIG_HAVE_MLOCKED_PAGE_BIT=y
+# CONFIG_KSM is not set
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
+# CONFIG_PPC_HAS_HASH_64K is not set
+CONFIG_PPC_4K_PAGES=y
+# CONFIG_PPC_16K_PAGES is not set
+# CONFIG_PPC_64K_PAGES is not set
+# CONFIG_PPC_256K_PAGES is not set
+CONFIG_FORCE_MAX_ZONEORDER=13
+# CONFIG_SCHED_SMT is not set
+CONFIG_PROC_DEVICETREE=y
+# CONFIG_CMDLINE_BOOL is not set
+CONFIG_EXTRA_TARGETS=""
+# CONFIG_PM is not set
+CONFIG_SECCOMP=y
+CONFIG_ISA_DMA_API=y
+
+#
+# Bus options
+#
+CONFIG_ZONE_DMA=y
+CONFIG_GENERIC_ISA_DMA=y
+# CONFIG_PPC_INDIRECT_PCI is not set
+CONFIG_PCI=y
+CONFIG_PCI_DOMAINS=y
+CONFIG_PCI_SYSCALL=y
+# CONFIG_PCIEPORTBUS is not set
+CONFIG_ARCH_SUPPORTS_MSI=y
+CONFIG_PCI_MSI=y
+# CONFIG_PCI_LEGACY is not set
+# CONFIG_PCI_DEBUG is not set
+# CONFIG_PCI_STUB is not set
+# CONFIG_PCI_IOV is not set
+CONFIG_PCCARD=y
+# CONFIG_PCMCIA_DEBUG is not set
+CONFIG_PCMCIA=y
+CONFIG_PCMCIA_LOAD_CIS=y
+CONFIG_PCMCIA_IOCTL=y
+CONFIG_CARDBUS=y
+
+#
+# PC-card bridges
+#
+# CONFIG_YENTA is not set
+# CONFIG_PD6729 is not set
+# CONFIG_I82092 is not set
+CONFIG_HOTPLUG_PCI=m
+# CONFIG_HOTPLUG_PCI_FAKE is not set
+# CONFIG_HOTPLUG_PCI_CPCI is not set
+# CONFIG_HOTPLUG_PCI_SHPC is not set
+# CONFIG_HAS_RAPIDIO is not set
+# CONFIG_RELOCATABLE is not set
+CONFIG_PAGE_OFFSET=0xc000000000000000
+CONFIG_KERNEL_START=0xc000000000000000
+CONFIG_PHYSICAL_START=0x00000000
+CONFIG_NET=y
+CONFIG_COMPAT_NETLINK_MESSAGES=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+CONFIG_XFRM_USER=m
+# CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_XFRM_MIGRATE is not set
+# CONFIG_XFRM_STATISTICS is not set
+CONFIG_XFRM_IPCOMP=m
+CONFIG_NET_KEY=m
+# CONFIG_NET_KEY_MIGRATE is not set
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+# CONFIG_IP_PNP_RARP is not set
+CONFIG_NET_IPIP=y
+# CONFIG_NET_IPGRE is not set
+# CONFIG_IP_MROUTE is not set
+# CONFIG_ARPD is not set
+CONFIG_SYN_COOKIES=y
+CONFIG_INET_AH=m
+CONFIG_INET_ESP=m
+CONFIG_INET_IPCOMP=m
+CONFIG_INET_XFRM_TUNNEL=m
+CONFIG_INET_TUNNEL=y
+CONFIG_INET_XFRM_MODE_TRANSPORT=y
+CONFIG_INET_XFRM_MODE_TUNNEL=y
+CONFIG_INET_XFRM_MODE_BEET=y
+CONFIG_INET_LRO=y
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
+# CONFIG_IPV6 is not set
+# CONFIG_NETWORK_SECMARK is not set
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+CONFIG_NETFILTER_ADVANCED=y
+
+#
+# Core Netfilter Configuration
+#
+CONFIG_NETFILTER_NETLINK=m
+CONFIG_NETFILTER_NETLINK_QUEUE=m
+CONFIG_NETFILTER_NETLINK_LOG=m
+CONFIG_NF_CONNTRACK=m
+CONFIG_NF_CT_ACCT=y
+CONFIG_NF_CONNTRACK_MARK=y
+CONFIG_NF_CONNTRACK_EVENTS=y
+# CONFIG_NF_CT_PROTO_DCCP is not set
+CONFIG_NF_CT_PROTO_GRE=m
+CONFIG_NF_CT_PROTO_SCTP=m
+# CONFIG_NF_CT_PROTO_UDPLITE is not set
+CONFIG_NF_CONNTRACK_AMANDA=m
+CONFIG_NF_CONNTRACK_FTP=m
+CONFIG_NF_CONNTRACK_H323=m
+CONFIG_NF_CONNTRACK_IRC=m
+CONFIG_NF_CONNTRACK_NETBIOS_NS=m
+CONFIG_NF_CONNTRACK_PPTP=m
+# CONFIG_NF_CONNTRACK_SANE is not set
+CONFIG_NF_CONNTRACK_SIP=m
+CONFIG_NF_CONNTRACK_TFTP=m
+CONFIG_NF_CT_NETLINK=m
+CONFIG_NETFILTER_TPROXY=m
+CONFIG_NETFILTER_XTABLES=m
+CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
+CONFIG_NETFILTER_XT_TARGET_CONNMARK=m
+CONFIG_NETFILTER_XT_TARGET_DSCP=m
+CONFIG_NETFILTER_XT_TARGET_HL=m
+CONFIG_NETFILTER_XT_TARGET_MARK=m
+CONFIG_NETFILTER_XT_TARGET_NFLOG=m
+CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
+CONFIG_NETFILTER_XT_TARGET_NOTRACK=m
+CONFIG_NETFILTER_XT_TARGET_RATEEST=m
+CONFIG_NETFILTER_XT_TARGET_TPROXY=m
+CONFIG_NETFILTER_XT_TARGET_TRACE=m
+CONFIG_NETFILTER_XT_TARGET_TCPMSS=m
+CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP=m
+# CONFIG_NETFILTER_XT_MATCH_CLUSTER is not set
+CONFIG_NETFILTER_XT_MATCH_COMMENT=m
+CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m
+CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=m
+CONFIG_NETFILTER_XT_MATCH_CONNMARK=m
+CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m
+CONFIG_NETFILTER_XT_MATCH_DCCP=m
+CONFIG_NETFILTER_XT_MATCH_DSCP=m
+CONFIG_NETFILTER_XT_MATCH_ESP=m
+CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m
+CONFIG_NETFILTER_XT_MATCH_HELPER=m
+CONFIG_NETFILTER_XT_MATCH_HL=m
+CONFIG_NETFILTER_XT_MATCH_IPRANGE=m
+CONFIG_NETFILTER_XT_MATCH_LENGTH=m
+CONFIG_NETFILTER_XT_MATCH_LIMIT=m
+CONFIG_NETFILTER_XT_MATCH_MAC=m
+CONFIG_NETFILTER_XT_MATCH_MARK=m
+CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m
+CONFIG_NETFILTER_XT_MATCH_OWNER=m
+CONFIG_NETFILTER_XT_MATCH_POLICY=m
+CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m
+CONFIG_NETFILTER_XT_MATCH_QUOTA=m
+CONFIG_NETFILTER_XT_MATCH_RATEEST=m
+CONFIG_NETFILTER_XT_MATCH_REALM=m
+CONFIG_NETFILTER_XT_MATCH_RECENT=m
+# CONFIG_NETFILTER_XT_MATCH_RECENT_PROC_COMPAT is not set
+CONFIG_NETFILTER_XT_MATCH_SCTP=m
+CONFIG_NETFILTER_XT_MATCH_SOCKET=m
+CONFIG_NETFILTER_XT_MATCH_STATE=m
+CONFIG_NETFILTER_XT_MATCH_STATISTIC=m
+CONFIG_NETFILTER_XT_MATCH_STRING=m
+CONFIG_NETFILTER_XT_MATCH_TCPMSS=m
+# CONFIG_NETFILTER_XT_MATCH_TIME is not set
+CONFIG_NETFILTER_XT_MATCH_U32=m
+# CONFIG_NETFILTER_XT_MATCH_OSF is not set
+# CONFIG_IP_VS is not set
+
+#
+# IP: Netfilter Configuration
+#
+CONFIG_NF_DEFRAG_IPV4=m
+CONFIG_NF_CONNTRACK_IPV4=m
+CONFIG_NF_CONNTRACK_PROC_COMPAT=y
+CONFIG_IP_NF_QUEUE=m
+CONFIG_IP_NF_IPTABLES=m
+CONFIG_IP_NF_MATCH_ADDRTYPE=m
+CONFIG_IP_NF_MATCH_AH=m
+CONFIG_IP_NF_MATCH_ECN=m
+CONFIG_IP_NF_MATCH_TTL=m
+CONFIG_IP_NF_FILTER=m
+CONFIG_IP_NF_TARGET_REJECT=m
+CONFIG_IP_NF_TARGET_LOG=m
+CONFIG_IP_NF_TARGET_ULOG=m
+CONFIG_NF_NAT=m
+CONFIG_NF_NAT_NEEDED=y
+CONFIG_IP_NF_TARGET_MASQUERADE=m
+CONFIG_IP_NF_TARGET_NETMAP=m
+CONFIG_IP_NF_TARGET_REDIRECT=m
+CONFIG_NF_NAT_SNMP_BASIC=m
+CONFIG_NF_NAT_PROTO_GRE=m
+CONFIG_NF_NAT_PROTO_SCTP=m
+CONFIG_NF_NAT_FTP=m
+CONFIG_NF_NAT_IRC=m
+CONFIG_NF_NAT_TFTP=m
+CONFIG_NF_NAT_AMANDA=m
+CONFIG_NF_NAT_PPTP=m
+CONFIG_NF_NAT_H323=m
+CONFIG_NF_NAT_SIP=m
+CONFIG_IP_NF_MANGLE=m
+CONFIG_IP_NF_TARGET_CLUSTERIP=m
+CONFIG_IP_NF_TARGET_ECN=m
+CONFIG_IP_NF_TARGET_TTL=m
+CONFIG_IP_NF_RAW=m
+CONFIG_IP_NF_ARPTABLES=m
+CONFIG_IP_NF_ARPFILTER=m
+CONFIG_IP_NF_ARP_MANGLE=m
+# CONFIG_IP_DCCP is not set
+# CONFIG_IP_SCTP is not set
+# CONFIG_RDS is not set
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_NET_DSA is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+CONFIG_LLC=y
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_PHONET is not set
+# CONFIG_IEEE802154 is not set
+# CONFIG_NET_SCHED is not set
+CONFIG_NET_CLS_ROUTE=y
+# CONFIG_DCB is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_NET_DROP_MONITOR is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_CAN is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+CONFIG_WIRELESS=y
+# CONFIG_CFG80211 is not set
+CONFIG_CFG80211_DEFAULT_PS_VALUE=0
+CONFIG_WIRELESS_OLD_REGULATORY=y
+CONFIG_WIRELESS_EXT=y
+CONFIG_WIRELESS_EXT_SYSFS=y
+# CONFIG_LIB80211 is not set
+
+#
+# CFG80211 needs to be enabled for MAC80211
+#
+# CONFIG_WIMAX is not set
+# CONFIG_RFKILL is not set
+# CONFIG_NET_9P is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+# CONFIG_DEVTMPFS is not set
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=y
+CONFIG_FIRMWARE_IN_KERNEL=y
+CONFIG_EXTRA_FIRMWARE=""
+# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_DEBUG_DEVRES is not set
+# CONFIG_SYS_HYPERVISOR is not set
+# CONFIG_CONNECTOR is not set
+# CONFIG_MTD is not set
+CONFIG_OF_DEVICE=y
+CONFIG_OF_I2C=y
+CONFIG_OF_MDIO=y
+# CONFIG_PARPORT is not set
+CONFIG_BLK_DEV=y
+CONFIG_BLK_DEV_FD=y
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_UMEM is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=y
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+CONFIG_BLK_DEV_NBD=m
+# CONFIG_BLK_DEV_SX8 is not set
+# CONFIG_BLK_DEV_UB is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=65536
+# CONFIG_BLK_DEV_XIP is not set
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+# CONFIG_BLK_DEV_HD is not set
+CONFIG_MISC_DEVICES=y
+# CONFIG_PHANTOM is not set
+# CONFIG_SGI_IOC4 is not set
+# CONFIG_TIFM_CORE is not set
+# CONFIG_ICS932S401 is not set
+# CONFIG_ENCLOSURE_SERVICES is not set
+# CONFIG_HP_ILO is not set
+# CONFIG_ISL29003 is not set
+# CONFIG_C2PORT is not set
+
+#
+# EEPROM support
+#
+# CONFIG_EEPROM_AT24 is not set
+# CONFIG_EEPROM_LEGACY is not set
+# CONFIG_EEPROM_MAX6875 is not set
+# CONFIG_EEPROM_93CX6 is not set
+# CONFIG_CB710_CORE is not set
+CONFIG_HAVE_IDE=y
+CONFIG_IDE=y
+
+#
+# Please see Documentation/ide/ide.txt for help/info on IDE drives
+#
+CONFIG_IDE_XFER_MODE=y
+CONFIG_IDE_TIMINGS=y
+CONFIG_IDE_ATAPI=y
+# CONFIG_BLK_DEV_IDE_SATA is not set
+CONFIG_IDE_GD=y
+CONFIG_IDE_GD_ATA=y
+# CONFIG_IDE_GD_ATAPI is not set
+# CONFIG_BLK_DEV_IDECS is not set
+# CONFIG_BLK_DEV_DELKIN is not set
+CONFIG_BLK_DEV_IDECD=y
+CONFIG_BLK_DEV_IDECD_VERBOSE_ERRORS=y
+# CONFIG_BLK_DEV_IDETAPE is not set
+# CONFIG_IDE_TASK_IOCTL is not set
+CONFIG_IDE_PROC_FS=y
+
+#
+# IDE chipset support/bugfixes
+#
+# CONFIG_BLK_DEV_PLATFORM is not set
+CONFIG_BLK_DEV_IDEDMA_SFF=y
+
+#
+# PCI IDE chipsets support
+#
+CONFIG_BLK_DEV_IDEPCI=y
+CONFIG_IDEPCI_PCIBUS_ORDER=y
+# CONFIG_BLK_DEV_OFFBOARD is not set
+CONFIG_BLK_DEV_GENERIC=y
+# CONFIG_BLK_DEV_OPTI621 is not set
+CONFIG_BLK_DEV_IDEDMA_PCI=y
+# CONFIG_BLK_DEV_AEC62XX is not set
+# CONFIG_BLK_DEV_ALI15X3 is not set
+CONFIG_BLK_DEV_AMD74XX=y
+# CONFIG_BLK_DEV_CMD64X is not set
+# CONFIG_BLK_DEV_TRIFLEX is not set
+# CONFIG_BLK_DEV_CS5520 is not set
+# CONFIG_BLK_DEV_CS5530 is not set
+# CONFIG_BLK_DEV_HPT366 is not set
+# CONFIG_BLK_DEV_JMICRON is not set
+# CONFIG_BLK_DEV_SC1200 is not set
+# CONFIG_BLK_DEV_PIIX is not set
+# CONFIG_BLK_DEV_IT8172 is not set
+# CONFIG_BLK_DEV_IT8213 is not set
+# CONFIG_BLK_DEV_IT821X is not set
+# CONFIG_BLK_DEV_NS87415 is not set
+# CONFIG_BLK_DEV_PDC202XX_OLD is not set
+# CONFIG_BLK_DEV_PDC202XX_NEW is not set
+# CONFIG_BLK_DEV_SVWKS is not set
+# CONFIG_BLK_DEV_SIIMAGE is not set
+# CONFIG_BLK_DEV_SL82C105 is not set
+# CONFIG_BLK_DEV_SLC90E66 is not set
+# CONFIG_BLK_DEV_TRM290 is not set
+# CONFIG_BLK_DEV_VIA82CXXX is not set
+# CONFIG_BLK_DEV_TC86C001 is not set
+CONFIG_BLK_DEV_IDEDMA=y
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+CONFIG_SCSI=y
+CONFIG_SCSI_DMA=y
+# CONFIG_SCSI_TGT is not set
+CONFIG_SCSI_NETLINK=y
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=y
+CONFIG_CHR_DEV_ST=y
+# CONFIG_CHR_DEV_OSST is not set
+CONFIG_BLK_DEV_SR=y
+CONFIG_BLK_DEV_SR_VENDOR=y
+CONFIG_CHR_DEV_SG=y
+# CONFIG_CHR_DEV_SCH is not set
+CONFIG_SCSI_MULTI_LUN=y
+CONFIG_SCSI_CONSTANTS=y
+# CONFIG_SCSI_LOGGING is not set
+# CONFIG_SCSI_SCAN_ASYNC is not set
+CONFIG_SCSI_WAIT_SCAN=m
+
+#
+# SCSI Transports
+#
+CONFIG_SCSI_SPI_ATTRS=y
+CONFIG_SCSI_FC_ATTRS=y
+CONFIG_SCSI_ISCSI_ATTRS=m
+# CONFIG_SCSI_SAS_ATTRS is not set
+# CONFIG_SCSI_SAS_LIBSAS is not set
+CONFIG_SCSI_SRP_ATTRS=y
+CONFIG_SCSI_LOWLEVEL=y
+# CONFIG_ISCSI_TCP is not set
+# CONFIG_SCSI_CXGB3_ISCSI is not set
+# CONFIG_SCSI_BNX2_ISCSI is not set
+# CONFIG_BE2ISCSI is not set
+# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
+# CONFIG_SCSI_3W_9XXX is not set
+# CONFIG_SCSI_ACARD is not set
+# CONFIG_SCSI_AACRAID is not set
+# CONFIG_SCSI_AIC7XXX is not set
+# CONFIG_SCSI_AIC7XXX_OLD is not set
+# CONFIG_SCSI_AIC79XX is not set
+# CONFIG_SCSI_AIC94XX is not set
+# CONFIG_SCSI_MVSAS is not set
+# CONFIG_SCSI_ARCMSR is not set
+# CONFIG_MEGARAID_NEWGEN is not set
+# CONFIG_MEGARAID_LEGACY is not set
+# CONFIG_MEGARAID_SAS is not set
+# CONFIG_SCSI_MPT2SAS is not set
+# CONFIG_SCSI_HPTIOP is not set
+# CONFIG_LIBFC is not set
+# CONFIG_LIBFCOE is not set
+# CONFIG_FCOE is not set
+# CONFIG_SCSI_DMX3191D is not set
+# CONFIG_SCSI_EATA is not set
+# CONFIG_SCSI_FUTURE_DOMAIN is not set
+# CONFIG_SCSI_GDTH is not set
+# CONFIG_SCSI_IPS is not set
+# CONFIG_SCSI_INITIO is not set
+# CONFIG_SCSI_INIA100 is not set
+# CONFIG_SCSI_STEX is not set
+CONFIG_SCSI_SYM53C8XX_2=y
+CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=0
+CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16
+CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64
+CONFIG_SCSI_SYM53C8XX_MMIO=y
+CONFIG_SCSI_IPR=y
+CONFIG_SCSI_IPR_TRACE=y
+CONFIG_SCSI_IPR_DUMP=y
+# CONFIG_SCSI_QLOGIC_1280 is not set
+# CONFIG_SCSI_QLA_FC is not set
+# CONFIG_SCSI_QLA_ISCSI is not set
+CONFIG_SCSI_LPFC=m
+# CONFIG_SCSI_LPFC_DEBUG_FS is not set
+# CONFIG_SCSI_DC395x is not set
+# CONFIG_SCSI_DC390T is not set
+CONFIG_SCSI_DEBUG=m
+# CONFIG_SCSI_PMCRAID is not set
+# CONFIG_SCSI_SRP is not set
+# CONFIG_SCSI_BFA_FC is not set
+# CONFIG_SCSI_LOWLEVEL_PCMCIA is not set
+# CONFIG_SCSI_DH is not set
+# CONFIG_SCSI_OSD_INITIATOR is not set
+CONFIG_ATA=y
+# CONFIG_ATA_NONSTANDARD is not set
+CONFIG_ATA_VERBOSE_ERROR=y
+CONFIG_SATA_PMP=y
+# CONFIG_SATA_AHCI is not set
+CONFIG_SATA_SIL24=y
+CONFIG_ATA_SFF=y
+CONFIG_SATA_SVW=y
+# CONFIG_ATA_PIIX is not set
+# CONFIG_SATA_MV is not set
+# CONFIG_SATA_NV is not set
+# CONFIG_PDC_ADMA is not set
+# CONFIG_SATA_QSTOR is not set
+# CONFIG_SATA_PROMISE is not set
+# CONFIG_SATA_SX4 is not set
+# CONFIG_SATA_SIL is not set
+# CONFIG_SATA_SIS is not set
+# CONFIG_SATA_ULI is not set
+# CONFIG_SATA_VIA is not set
+# CONFIG_SATA_VITESSE is not set
+# CONFIG_SATA_INIC162X is not set
+# CONFIG_PATA_ALI is not set
+# CONFIG_PATA_AMD is not set
+# CONFIG_PATA_ARTOP is not set
+# CONFIG_PATA_ATP867X is not set
+# CONFIG_PATA_ATIIXP is not set
+# CONFIG_PATA_CMD640_PCI is not set
+# CONFIG_PATA_CMD64X is not set
+# CONFIG_PATA_CS5520 is not set
+# CONFIG_PATA_CS5530 is not set
+# CONFIG_PATA_CYPRESS is not set
+# CONFIG_PATA_EFAR is not set
+# CONFIG_ATA_GENERIC is not set
+# CONFIG_PATA_HPT366 is not set
+# CONFIG_PATA_HPT37X is not set
+# CONFIG_PATA_HPT3X2N is not set
+# CONFIG_PATA_HPT3X3 is not set
+# CONFIG_PATA_IT821X is not set
+# CONFIG_PATA_IT8213 is not set
+# CONFIG_PATA_JMICRON is not set
+# CONFIG_PATA_TRIFLEX is not set
+# CONFIG_PATA_MARVELL is not set
+# CONFIG_PATA_MPIIX is not set
+# CONFIG_PATA_OLDPIIX is not set
+# CONFIG_PATA_NETCELL is not set
+# CONFIG_PATA_NINJA32 is not set
+# CONFIG_PATA_NS87410 is not set
+# CONFIG_PATA_NS87415 is not set
+# CONFIG_PATA_OPTI is not set
+# CONFIG_PATA_OPTIDMA is not set
+# CONFIG_PATA_PCMCIA is not set
+# CONFIG_PATA_PDC_OLD is not set
+# CONFIG_PATA_RADISYS is not set
+# CONFIG_PATA_RDC is not set
+# CONFIG_PATA_RZ1000 is not set
+# CONFIG_PATA_SC1200 is not set
+# CONFIG_PATA_SERVERWORKS is not set
+# CONFIG_PATA_PDC2027X is not set
+# CONFIG_PATA_SIL680 is not set
+# CONFIG_PATA_SIS is not set
+# CONFIG_PATA_VIA is not set
+# CONFIG_PATA_WINBOND is not set
+# CONFIG_PATA_PLATFORM is not set
+# CONFIG_PATA_SCH is not set
+CONFIG_MD=y
+CONFIG_BLK_DEV_MD=y
+CONFIG_MD_AUTODETECT=y
+CONFIG_MD_LINEAR=y
+CONFIG_MD_RAID0=y
+CONFIG_MD_RAID1=y
+CONFIG_MD_RAID10=y
+CONFIG_MD_RAID456=y
+# CONFIG_MULTICORE_RAID456 is not set
+CONFIG_MD_RAID6_PQ=y
+# CONFIG_ASYNC_RAID6_TEST is not set
+CONFIG_MD_MULTIPATH=m
+CONFIG_MD_FAULTY=m
+CONFIG_BLK_DEV_DM=y
+# CONFIG_DM_DEBUG is not set
+CONFIG_DM_CRYPT=m
+CONFIG_DM_SNAPSHOT=m
+CONFIG_DM_MIRROR=m
+# CONFIG_DM_LOG_USERSPACE is not set
+CONFIG_DM_ZERO=m
+CONFIG_DM_MULTIPATH=m
+# CONFIG_DM_MULTIPATH_QL is not set
+# CONFIG_DM_MULTIPATH_ST is not set
+# CONFIG_DM_DELAY is not set
+# CONFIG_DM_UEVENT is not set
+# CONFIG_FUSION is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+
+#
+# You can enable one or both FireWire driver stacks.
+#
+
+#
+# See the help texts for more information.
+#
+# CONFIG_FIREWIRE is not set
+CONFIG_IEEE1394=y
+CONFIG_IEEE1394_OHCI1394=y
+# CONFIG_IEEE1394_PCILYNX is not set
+CONFIG_IEEE1394_SBP2=m
+CONFIG_IEEE1394_ETH1394_ROM_ENTRY=y
+CONFIG_IEEE1394_ETH1394=m
+CONFIG_IEEE1394_RAWIO=y
+CONFIG_IEEE1394_VIDEO1394=m
+CONFIG_IEEE1394_DV1394=m
+# CONFIG_IEEE1394_VERBOSEDEBUG is not set
+# CONFIG_I2O is not set
+CONFIG_MACINTOSH_DRIVERS=y
+# CONFIG_MAC_EMUMOUSEBTN is not set
+CONFIG_WINDFARM=y
+CONFIG_NETDEVICES=y
+CONFIG_DUMMY=m
+CONFIG_BONDING=m
+# CONFIG_MACVLAN is not set
+# CONFIG_EQUALIZER is not set
+CONFIG_TUN=m
+# CONFIG_VETH is not set
+# CONFIG_ARCNET is not set
+CONFIG_PHYLIB=y
+
+#
+# MII PHY device drivers
+#
+CONFIG_MARVELL_PHY=y
+# CONFIG_DAVICOM_PHY is not set
+# CONFIG_QSEMI_PHY is not set
+# CONFIG_LXT_PHY is not set
+# CONFIG_CICADA_PHY is not set
+# CONFIG_VITESSE_PHY is not set
+# CONFIG_SMSC_PHY is not set
+CONFIG_BROADCOM_PHY=m
+# CONFIG_ICPLUS_PHY is not set
+# CONFIG_REALTEK_PHY is not set
+# CONFIG_NATIONAL_PHY is not set
+# CONFIG_STE10XP is not set
+# CONFIG_LSI_ET1011C_PHY is not set
+# CONFIG_FIXED_PHY is not set
+# CONFIG_MDIO_BITBANG is not set
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_HAPPYMEAL is not set
+CONFIG_SUNGEM=y
+# CONFIG_CASSINI is not set
+CONFIG_NET_VENDOR_3COM=y
+CONFIG_VORTEX=y
+# CONFIG_TYPHOON is not set
+# CONFIG_ETHOC is not set
+# CONFIG_DNET is not set
+# CONFIG_NET_TULIP is not set
+# CONFIG_HP100 is not set
+# CONFIG_IBM_NEW_EMAC_ZMII is not set
+# CONFIG_IBM_NEW_EMAC_RGMII is not set
+# CONFIG_IBM_NEW_EMAC_TAH is not set
+# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+# CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set
+# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
+# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
+CONFIG_NET_PCI=y
+CONFIG_PCNET32=y
+# CONFIG_AMD8111_ETH is not set
+# CONFIG_ADAPTEC_STARFIRE is not set
+# CONFIG_B44 is not set
+# CONFIG_FORCEDETH is not set
+CONFIG_E100=y
+# CONFIG_FEALNX is not set
+# CONFIG_NATSEMI is not set
+# CONFIG_NE2K_PCI is not set
+# CONFIG_8139CP is not set
+# CONFIG_8139TOO is not set
+# CONFIG_R6040 is not set
+# CONFIG_SIS900 is not set
+# CONFIG_EPIC100 is not set
+# CONFIG_SMSC9420 is not set
+# CONFIG_SUNDANCE is not set
+# CONFIG_TLAN is not set
+# CONFIG_KS8842 is not set
+# CONFIG_KS8851_MLL is not set
+# CONFIG_VIA_RHINE is not set
+# CONFIG_SC92031 is not set
+# CONFIG_ATL2 is not set
+CONFIG_NETDEV_1000=y
+CONFIG_ACENIC=y
+CONFIG_ACENIC_OMIT_TIGON_I=y
+# CONFIG_DL2K is not set
+CONFIG_E1000=y
+# CONFIG_E1000E is not set
+# CONFIG_IP1000 is not set
+# CONFIG_IGB is not set
+# CONFIG_IGBVF is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_R8169 is not set
+# CONFIG_SIS190 is not set
+# CONFIG_SKGE is not set
+# CONFIG_SKY2 is not set
+# CONFIG_VIA_VELOCITY is not set
+CONFIG_TIGON3=y
+# CONFIG_BNX2 is not set
+# CONFIG_CNIC is not set
+# CONFIG_QLA3XXX is not set
+# CONFIG_ATL1 is not set
+# CONFIG_ATL1E is not set
+# CONFIG_ATL1C is not set
+# CONFIG_JME is not set
+CONFIG_NETDEV_10000=y
+# CONFIG_CHELSIO_T1 is not set
+CONFIG_CHELSIO_T3_DEPENDS=y
+# CONFIG_CHELSIO_T3 is not set
+# CONFIG_ENIC is not set
+# CONFIG_IXGBE is not set
+CONFIG_IXGB=m
+# CONFIG_S2IO is not set
+# CONFIG_VXGE is not set
+# CONFIG_MYRI10GE is not set
+# CONFIG_NETXEN_NIC is not set
+# CONFIG_NIU is not set
+# CONFIG_MLX4_EN is not set
+# CONFIG_MLX4_CORE is not set
+# CONFIG_TEHUTI is not set
+# CONFIG_BNX2X is not set
+# CONFIG_QLGE is not set
+# CONFIG_SFC is not set
+# CONFIG_BE2NET is not set
+CONFIG_TR=y
+CONFIG_IBMOL=y
+# CONFIG_3C359 is not set
+# CONFIG_TMS380TR is not set
+CONFIG_WLAN=y
+# CONFIG_WLAN_PRE80211 is not set
+# CONFIG_WLAN_80211 is not set
+
+#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
+
+#
+# USB Network Adapters
+#
+# CONFIG_USB_CATC is not set
+# CONFIG_USB_KAWETH is not set
+# CONFIG_USB_PEGASUS is not set
+# CONFIG_USB_RTL8150 is not set
+# CONFIG_USB_USBNET is not set
+# CONFIG_NET_PCMCIA is not set
+# CONFIG_WAN is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+CONFIG_PPP=m
+# CONFIG_PPP_MULTILINK is not set
+# CONFIG_PPP_FILTER is not set
+CONFIG_PPP_ASYNC=m
+CONFIG_PPP_SYNC_TTY=m
+CONFIG_PPP_DEFLATE=m
+CONFIG_PPP_BSDCOMP=m
+# CONFIG_PPP_MPPE is not set
+CONFIG_PPPOE=m
+# CONFIG_PPPOL2TP is not set
+# CONFIG_SLIP is not set
+CONFIG_SLHC=m
+# CONFIG_NET_FC is not set
+CONFIG_NETCONSOLE=y
+# CONFIG_NETCONSOLE_DYNAMIC is not set
+CONFIG_NETPOLL=y
+CONFIG_NETPOLL_TRAP=y
+CONFIG_NET_POLL_CONTROLLER=y
+# CONFIG_ISDN is not set
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
+# CONFIG_INPUT_POLLDEV is not set
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
+CONFIG_INPUT_EVDEV=m
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+# CONFIG_KEYBOARD_ADP5588 is not set
+CONFIG_KEYBOARD_ATKBD=y
+# CONFIG_QT2160 is not set
+# CONFIG_KEYBOARD_LKKBD is not set
+# CONFIG_KEYBOARD_MAX7359 is not set
+# CONFIG_KEYBOARD_NEWTON is not set
+# CONFIG_KEYBOARD_OPENCORES is not set
+# CONFIG_KEYBOARD_STOWAWAY is not set
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_XTKBD is not set
+CONFIG_INPUT_MOUSE=y
+CONFIG_MOUSE_PS2=y
+CONFIG_MOUSE_PS2_ALPS=y
+CONFIG_MOUSE_PS2_LOGIPS2PP=y
+CONFIG_MOUSE_PS2_SYNAPTICS=y
+CONFIG_MOUSE_PS2_TRACKPOINT=y
+# CONFIG_MOUSE_PS2_ELANTECH is not set
+# CONFIG_MOUSE_PS2_SENTELIC is not set
+# CONFIG_MOUSE_PS2_TOUCHKIT is not set
+# CONFIG_MOUSE_SERIAL is not set
+# CONFIG_MOUSE_APPLETOUCH is not set
+# CONFIG_MOUSE_BCM5974 is not set
+# CONFIG_MOUSE_VSXXXAA is not set
+# CONFIG_MOUSE_SYNAPTICS_I2C is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+CONFIG_INPUT_MISC=y
+# CONFIG_INPUT_ATI_REMOTE is not set
+# CONFIG_INPUT_ATI_REMOTE2 is not set
+# CONFIG_INPUT_KEYSPAN_REMOTE is not set
+# CONFIG_INPUT_POWERMATE is not set
+# CONFIG_INPUT_YEALINK is not set
+# CONFIG_INPUT_CM109 is not set
+# CONFIG_INPUT_UINPUT is not set
+
+#
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+CONFIG_SERIO_I8042=y
+# CONFIG_SERIO_SERPORT is not set
+# CONFIG_SERIO_PCIPS2 is not set
+CONFIG_SERIO_LIBPS2=y
+# CONFIG_SERIO_RAW is not set
+# CONFIG_SERIO_XILINX_XPS_PS2 is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_CONSOLE_TRANSLATIONS=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+CONFIG_VT_HW_CONSOLE_BINDING=y
+CONFIG_DEVKMEM=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+# CONFIG_NOZOMI is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_PCI=y
+# CONFIG_SERIAL_8250_CS is not set
+CONFIG_SERIAL_8250_NR_UARTS=4
+CONFIG_SERIAL_8250_RUNTIME_UARTS=4
+# CONFIG_SERIAL_8250_EXTENDED is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_JSM is not set
+# CONFIG_SERIAL_OF_PLATFORM is not set
+CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+# CONFIG_HVC_UDBG is not set
+# CONFIG_IPMI_HANDLER is not set
+# CONFIG_HW_RANDOM is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# PCMCIA character devices
+#
+# CONFIG_SYNCLINK_CS is not set
+# CONFIG_CARDMAN_4000 is not set
+# CONFIG_CARDMAN_4040 is not set
+# CONFIG_IPWIRELESS is not set
+CONFIG_RAW_DRIVER=y
+CONFIG_MAX_RAW_DEVS=256
+# CONFIG_HANGCHECK_TIMER is not set
+# CONFIG_TCG_TPM is not set
+CONFIG_DEVPORT=y
+CONFIG_I2C=y
+CONFIG_I2C_BOARDINFO=y
+CONFIG_I2C_COMPAT=y
+CONFIG_I2C_CHARDEV=y
+CONFIG_I2C_HELPER_AUTO=y
+CONFIG_I2C_ALGOBIT=y
+
+#
+# I2C Hardware Bus support
+#
+
+#
+# PC SMBus host controller drivers
+#
+# CONFIG_I2C_ALI1535 is not set
+# CONFIG_I2C_ALI1563 is not set
+# CONFIG_I2C_ALI15X3 is not set
+# CONFIG_I2C_AMD756 is not set
+CONFIG_I2C_AMD8111=y
+# CONFIG_I2C_I801 is not set
+# CONFIG_I2C_ISCH is not set
+# CONFIG_I2C_PIIX4 is not set
+# CONFIG_I2C_NFORCE2 is not set
+# CONFIG_I2C_SIS5595 is not set
+# CONFIG_I2C_SIS630 is not set
+# CONFIG_I2C_SIS96X is not set
+# CONFIG_I2C_VIA is not set
+# CONFIG_I2C_VIAPRO is not set
+
+#
+# I2C system bus drivers (mostly embedded / system-on-chip)
+#
+# CONFIG_I2C_OCORES is not set
+# CONFIG_I2C_SIMTEC is not set
+
+#
+# External I2C/SMBus adapter drivers
+#
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_TAOS_EVM is not set
+# CONFIG_I2C_TINY_USB is not set
+
+#
+# Graphics adapter I2C/DDC channel drivers
+#
+# CONFIG_I2C_VOODOO3 is not set
+
+#
+# Other I2C/SMBus bus drivers
+#
+# CONFIG_I2C_PCA_PLATFORM is not set
+# CONFIG_I2C_STUB is not set
+
+#
+# Miscellaneous I2C Chip support
+#
+# CONFIG_DS1682 is not set
+# CONFIG_SENSORS_TSL2550 is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+# CONFIG_SPI is not set
+
+#
+# PPS support
+#
+# CONFIG_PPS is not set
+CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
+# CONFIG_GPIOLIB is not set
+# CONFIG_W1 is not set
+# CONFIG_POWER_SUPPLY is not set
+# CONFIG_HWMON is not set
+# CONFIG_THERMAL is not set
+# CONFIG_WATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
+
+#
+# Sonics Silicon Backplane
+#
+# CONFIG_SSB is not set
+
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_CORE is not set
+# CONFIG_MFD_SM501 is not set
+# CONFIG_HTC_PASIC3 is not set
+# CONFIG_TWL4030_CORE is not set
+# CONFIG_MFD_TMIO is not set
+# CONFIG_PMIC_DA903X is not set
+# CONFIG_MFD_WM8400 is not set
+# CONFIG_MFD_WM831X is not set
+# CONFIG_MFD_WM8350_I2C is not set
+# CONFIG_MFD_PCF50633 is not set
+# CONFIG_AB3100_CORE is not set
+# CONFIG_REGULATOR is not set
+# CONFIG_MEDIA_SUPPORT is not set
+
+#
+# Graphics support
+#
+# CONFIG_AGP is not set
+CONFIG_VGA_ARB=y
+# CONFIG_DRM is not set
+# CONFIG_VGASTATE is not set
+CONFIG_VIDEO_OUTPUT_CONTROL=m
+CONFIG_FB=y
+CONFIG_FIRMWARE_EDID=y
+CONFIG_FB_DDC=y
+# CONFIG_FB_BOOT_VESA_SUPPORT is not set
+CONFIG_FB_CFB_FILLRECT=y
+CONFIG_FB_CFB_COPYAREA=y
+CONFIG_FB_CFB_IMAGEBLIT=y
+# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set
+# CONFIG_FB_SYS_FILLRECT is not set
+# CONFIG_FB_SYS_COPYAREA is not set
+# CONFIG_FB_SYS_IMAGEBLIT is not set
+# CONFIG_FB_FOREIGN_ENDIAN is not set
+# CONFIG_FB_SYS_FOPS is not set
+# CONFIG_FB_SVGALIB is not set
+CONFIG_FB_MACMODES=y
+CONFIG_FB_BACKLIGHT=y
+CONFIG_FB_MODE_HELPERS=y
+CONFIG_FB_TILEBLITTING=y
+
+#
+# Frame buffer hardware drivers
+#
+# CONFIG_FB_CIRRUS is not set
+# CONFIG_FB_PM2 is not set
+# CONFIG_FB_CYBER2000 is not set
+CONFIG_FB_OF=y
+# CONFIG_FB_ASILIANT is not set
+# CONFIG_FB_IMSTT is not set
+# CONFIG_FB_VGA16 is not set
+# CONFIG_FB_S1D13XXX is not set
+# CONFIG_FB_NVIDIA is not set
+# CONFIG_FB_RIVA is not set
+CONFIG_FB_MATROX=y
+CONFIG_FB_MATROX_MILLENIUM=y
+CONFIG_FB_MATROX_MYSTIQUE=y
+CONFIG_FB_MATROX_G=y
+CONFIG_FB_MATROX_I2C=m
+CONFIG_FB_MATROX_MAVEN=m
+CONFIG_FB_RADEON=y
+CONFIG_FB_RADEON_I2C=y
+CONFIG_FB_RADEON_BACKLIGHT=y
+# CONFIG_FB_RADEON_DEBUG is not set
+# CONFIG_FB_ATY128 is not set
+# CONFIG_FB_ATY is not set
+# CONFIG_FB_S3 is not set
+# CONFIG_FB_SAVAGE is not set
+# CONFIG_FB_SIS is not set
+# CONFIG_FB_VIA is not set
+# CONFIG_FB_NEOMAGIC is not set
+# CONFIG_FB_KYRO is not set
+# CONFIG_FB_3DFX is not set
+# CONFIG_FB_VOODOO1 is not set
+# CONFIG_FB_VT8623 is not set
+# CONFIG_FB_TRIDENT is not set
+# CONFIG_FB_ARK is not set
+# CONFIG_FB_PM3 is not set
+# CONFIG_FB_CARMINE is not set
+CONFIG_FB_IBM_GXT4500=y
+# CONFIG_FB_VIRTUAL is not set
+# CONFIG_FB_METRONOME is not set
+# CONFIG_FB_MB862XX is not set
+# CONFIG_FB_BROADSHEET is not set
+CONFIG_BACKLIGHT_LCD_SUPPORT=y
+CONFIG_LCD_CLASS_DEVICE=y
+# CONFIG_LCD_ILI9320 is not set
+# CONFIG_LCD_PLATFORM is not set
+CONFIG_BACKLIGHT_CLASS_DEVICE=y
+CONFIG_BACKLIGHT_GENERIC=y
+
+#
+# Display device support
+#
+CONFIG_DISPLAY_SUPPORT=y
+
+#
+# Display hardware drivers
+#
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+# CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY is not set
+# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set
+# CONFIG_FONTS is not set
+CONFIG_FONT_8x8=y
+CONFIG_FONT_8x16=y
+CONFIG_LOGO=y
+CONFIG_LOGO_LINUX_MONO=y
+CONFIG_LOGO_LINUX_VGA16=y
+CONFIG_LOGO_LINUX_CLUT224=y
+CONFIG_SOUND=m
+CONFIG_SOUND_OSS_CORE=y
+CONFIG_SOUND_OSS_CORE_PRECLAIM=y
+CONFIG_SND=m
+CONFIG_SND_TIMER=m
+CONFIG_SND_PCM=m
+CONFIG_SND_SEQUENCER=m
+CONFIG_SND_SEQ_DUMMY=m
+CONFIG_SND_OSSEMUL=y
+CONFIG_SND_MIXER_OSS=m
+CONFIG_SND_PCM_OSS=m
+CONFIG_SND_PCM_OSS_PLUGINS=y
+CONFIG_SND_SEQUENCER_OSS=y
+# CONFIG_SND_HRTIMER is not set
+# CONFIG_SND_DYNAMIC_MINORS is not set
+CONFIG_SND_SUPPORT_OLD_API=y
+CONFIG_SND_VERBOSE_PROCFS=y
+# CONFIG_SND_VERBOSE_PRINTK is not set
+# CONFIG_SND_DEBUG is not set
+# CONFIG_SND_RAWMIDI_SEQ is not set
+# CONFIG_SND_OPL3_LIB_SEQ is not set
+# CONFIG_SND_OPL4_LIB_SEQ is not set
+# CONFIG_SND_SBAWE_SEQ is not set
+# CONFIG_SND_EMU10K1_SEQ is not set
+CONFIG_SND_DRIVERS=y
+# CONFIG_SND_DUMMY is not set
+# CONFIG_SND_VIRMIDI is not set
+# CONFIG_SND_MTPAV is not set
+# CONFIG_SND_SERIAL_U16550 is not set
+# CONFIG_SND_MPU401 is not set
+CONFIG_SND_PCI=y
+# CONFIG_SND_AD1889 is not set
+# CONFIG_SND_ALS300 is not set
+# CONFIG_SND_ALS4000 is not set
+# CONFIG_SND_ALI5451 is not set
+# CONFIG_SND_ATIIXP is not set
+# CONFIG_SND_ATIIXP_MODEM is not set
+# CONFIG_SND_AU8810 is not set
+# CONFIG_SND_AU8820 is not set
+# CONFIG_SND_AU8830 is not set
+# CONFIG_SND_AW2 is not set
+# CONFIG_SND_AZT3328 is not set
+# CONFIG_SND_BT87X is not set
+# CONFIG_SND_CA0106 is not set
+# CONFIG_SND_CMIPCI is not set
+# CONFIG_SND_OXYGEN is not set
+# CONFIG_SND_CS4281 is not set
+# CONFIG_SND_CS46XX is not set
+# CONFIG_SND_CS5530 is not set
+# CONFIG_SND_CTXFI is not set
+# CONFIG_SND_DARLA20 is not set
+# CONFIG_SND_GINA20 is not set
+# CONFIG_SND_LAYLA20 is not set
+# CONFIG_SND_DARLA24 is not set
+# CONFIG_SND_GINA24 is not set
+# CONFIG_SND_LAYLA24 is not set
+# CONFIG_SND_MONA is not set
+# CONFIG_SND_MIA is not set
+# CONFIG_SND_ECHO3G is not set
+# CONFIG_SND_INDIGO is not set
+# CONFIG_SND_INDIGOIO is not set
+# CONFIG_SND_INDIGODJ is not set
+# CONFIG_SND_INDIGOIOX is not set
+# CONFIG_SND_INDIGODJX is not set
+# CONFIG_SND_EMU10K1 is not set
+# CONFIG_SND_EMU10K1X is not set
+# CONFIG_SND_ENS1370 is not set
+# CONFIG_SND_ENS1371 is not set
+# CONFIG_SND_ES1938 is not set
+# CONFIG_SND_ES1968 is not set
+# CONFIG_SND_FM801 is not set
+# CONFIG_SND_HDA_INTEL is not set
+# CONFIG_SND_HDSP is not set
+# CONFIG_SND_HDSPM is not set
+# CONFIG_SND_HIFIER is not set
+# CONFIG_SND_ICE1712 is not set
+# CONFIG_SND_ICE1724 is not set
+# CONFIG_SND_INTEL8X0 is not set
+# CONFIG_SND_INTEL8X0M is not set
+# CONFIG_SND_KORG1212 is not set
+# CONFIG_SND_LX6464ES is not set
+# CONFIG_SND_MAESTRO3 is not set
+# CONFIG_SND_MIXART is not set
+# CONFIG_SND_NM256 is not set
+# CONFIG_SND_PCXHR is not set
+# CONFIG_SND_RIPTIDE is not set
+# CONFIG_SND_RME32 is not set
+# CONFIG_SND_RME96 is not set
+# CONFIG_SND_RME9652 is not set
+# CONFIG_SND_SONICVIBES is not set
+# CONFIG_SND_TRIDENT is not set
+# CONFIG_SND_VIA82XX is not set
+# CONFIG_SND_VIA82XX_MODEM is not set
+# CONFIG_SND_VIRTUOSO is not set
+# CONFIG_SND_VX222 is not set
+# CONFIG_SND_YMFPCI is not set
+CONFIG_SND_PPC=y
+CONFIG_SND_USB=y
+# CONFIG_SND_USB_AUDIO is not set
+# CONFIG_SND_USB_USX2Y is not set
+# CONFIG_SND_USB_CAIAQ is not set
+CONFIG_SND_PCMCIA=y
+# CONFIG_SND_VXPOCKET is not set
+# CONFIG_SND_PDAUDIOCF is not set
+# CONFIG_SND_SOC is not set
+# CONFIG_SOUND_PRIME is not set
+CONFIG_HID_SUPPORT=y
+CONFIG_HID=y
+# CONFIG_HIDRAW is not set
+
+#
+# USB Input Devices
+#
+CONFIG_USB_HID=y
+# CONFIG_HID_PID is not set
+CONFIG_USB_HIDDEV=y
+
+#
+# Special HID drivers
+#
+CONFIG_HID_A4TECH=y
+CONFIG_HID_APPLE=y
+CONFIG_HID_BELKIN=y
+CONFIG_HID_CHERRY=y
+CONFIG_HID_CHICONY=y
+CONFIG_HID_CYPRESS=y
+CONFIG_HID_DRAGONRISE=y
+# CONFIG_DRAGONRISE_FF is not set
+CONFIG_HID_EZKEY=y
+CONFIG_HID_KYE=y
+CONFIG_HID_GYRATION=y
+CONFIG_HID_TWINHAN=y
+CONFIG_HID_KENSINGTON=y
+CONFIG_HID_LOGITECH=y
+# CONFIG_LOGITECH_FF is not set
+# CONFIG_LOGIRUMBLEPAD2_FF is not set
+CONFIG_HID_MICROSOFT=y
+CONFIG_HID_MONTEREY=y
+CONFIG_HID_NTRIG=y
+CONFIG_HID_PANTHERLORD=y
+# CONFIG_PANTHERLORD_FF is not set
+CONFIG_HID_PETALYNX=y
+CONFIG_HID_SAMSUNG=y
+CONFIG_HID_SONY=y
+CONFIG_HID_SUNPLUS=y
+CONFIG_HID_GREENASIA=y
+# CONFIG_GREENASIA_FF is not set
+CONFIG_HID_SMARTJOYPLUS=y
+# CONFIG_SMARTJOYPLUS_FF is not set
+CONFIG_HID_TOPSEED=y
+CONFIG_HID_THRUSTMASTER=y
+# CONFIG_THRUSTMASTER_FF is not set
+CONFIG_HID_ZEROPLUS=y
+# CONFIG_ZEROPLUS_FF is not set
+CONFIG_USB_SUPPORT=y
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
+CONFIG_USB=y
+# CONFIG_USB_DEBUG is not set
+# CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set
+
+#
+# Miscellaneous USB options
+#
+CONFIG_USB_DEVICEFS=y
+CONFIG_USB_DEVICE_CLASS=y
+# CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_OTG is not set
+# CONFIG_USB_MON is not set
+# CONFIG_USB_WUSB is not set
+# CONFIG_USB_WUSB_CBAF is not set
+
+#
+# USB Host Controller Drivers
+#
+# CONFIG_USB_C67X00_HCD is not set
+# CONFIG_USB_XHCI_HCD is not set
+CONFIG_USB_EHCI_HCD=y
+# CONFIG_USB_EHCI_ROOT_HUB_TT is not set
+CONFIG_USB_EHCI_TT_NEWSCHED=y
+# CONFIG_USB_EHCI_HCD_PPC_OF is not set
+# CONFIG_USB_OXU210HP_HCD is not set
+# CONFIG_USB_ISP116X_HCD is not set
+# CONFIG_USB_ISP1760_HCD is not set
+# CONFIG_USB_ISP1362_HCD is not set
+CONFIG_USB_OHCI_HCD=y
+# CONFIG_USB_OHCI_HCD_PPC_OF_BE is not set
+# CONFIG_USB_OHCI_HCD_PPC_OF_LE is not set
+# CONFIG_USB_OHCI_HCD_PPC_OF is not set
+# CONFIG_USB_OHCI_BIG_ENDIAN_DESC is not set
+# CONFIG_USB_OHCI_BIG_ENDIAN_MMIO is not set
+CONFIG_USB_OHCI_LITTLE_ENDIAN=y
+# CONFIG_USB_UHCI_HCD is not set
+# CONFIG_USB_SL811_HCD is not set
+# CONFIG_USB_R8A66597_HCD is not set
+# CONFIG_USB_WHCI_HCD is not set
+# CONFIG_USB_HWA_HCD is not set
+
+#
+# USB Device Class drivers
+#
+# CONFIG_USB_ACM is not set
+# CONFIG_USB_PRINTER is not set
+# CONFIG_USB_WDM is not set
+# CONFIG_USB_TMC is not set
+
+#
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may
+#
+
+#
+# also be needed; see USB_STORAGE Help for more info
+#
+CONFIG_USB_STORAGE=m
+# CONFIG_USB_STORAGE_DEBUG is not set
+# CONFIG_USB_STORAGE_DATAFAB is not set
+# CONFIG_USB_STORAGE_FREECOM is not set
+# CONFIG_USB_STORAGE_ISD200 is not set
+# CONFIG_USB_STORAGE_USBAT is not set
+# CONFIG_USB_STORAGE_SDDR09 is not set
+# CONFIG_USB_STORAGE_SDDR55 is not set
+# CONFIG_USB_STORAGE_JUMPSHOT is not set
+# CONFIG_USB_STORAGE_ALAUDA is not set
+# CONFIG_USB_STORAGE_ONETOUCH is not set
+# CONFIG_USB_STORAGE_KARMA is not set
+# CONFIG_USB_STORAGE_CYPRESS_ATACB is not set
+# CONFIG_USB_LIBUSUAL is not set
+
+#
+# USB Imaging devices
+#
+# CONFIG_USB_MDC800 is not set
+# CONFIG_USB_MICROTEK is not set
+
+#
+# USB port drivers
+#
+# CONFIG_USB_SERIAL is not set
+
+#
+# USB Miscellaneous drivers
+#
+# CONFIG_USB_EMI62 is not set
+# CONFIG_USB_EMI26 is not set
+# CONFIG_USB_ADUTUX is not set
+# CONFIG_USB_SEVSEG is not set
+# CONFIG_USB_RIO500 is not set
+# CONFIG_USB_LEGOTOWER is not set
+# CONFIG_USB_LCD is not set
+# CONFIG_USB_BERRY_CHARGE is not set
+# CONFIG_USB_LED is not set
+# CONFIG_USB_CYPRESS_CY7C63 is not set
+# CONFIG_USB_CYTHERM is not set
+# CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_FTDI_ELAN is not set
+CONFIG_USB_APPLEDISPLAY=m
+# CONFIG_USB_SISUSBVGA is not set
+# CONFIG_USB_LD is not set
+# CONFIG_USB_TRANCEVIBRATOR is not set
+# CONFIG_USB_IOWARRIOR is not set
+# CONFIG_USB_TEST is not set
+# CONFIG_USB_ISIGHTFW is not set
+# CONFIG_USB_VST is not set
+# CONFIG_USB_GADGET is not set
+
+#
+# OTG and related infrastructure
+#
+# CONFIG_NOP_USB_XCEIV is not set
+# CONFIG_UWB is not set
+# CONFIG_MMC is not set
+# CONFIG_MEMSTICK is not set
+# CONFIG_NEW_LEDS is not set
+# CONFIG_ACCESSIBILITY is not set
+CONFIG_INFINIBAND=m
+# CONFIG_INFINIBAND_USER_MAD is not set
+# CONFIG_INFINIBAND_USER_ACCESS is not set
+CONFIG_INFINIBAND_ADDR_TRANS=y
+CONFIG_INFINIBAND_MTHCA=m
+CONFIG_INFINIBAND_MTHCA_DEBUG=y
+# CONFIG_INFINIBAND_IPATH is not set
+# CONFIG_INFINIBAND_AMSO1100 is not set
+# CONFIG_MLX4_INFINIBAND is not set
+# CONFIG_INFINIBAND_NES is not set
+CONFIG_INFINIBAND_IPOIB=m
+# CONFIG_INFINIBAND_IPOIB_CM is not set
+CONFIG_INFINIBAND_IPOIB_DEBUG=y
+# CONFIG_INFINIBAND_IPOIB_DEBUG_DATA is not set
+# CONFIG_INFINIBAND_SRP is not set
+CONFIG_INFINIBAND_ISER=m
+CONFIG_EDAC=y
+
+#
+# Reporting subsystems
+#
+# CONFIG_EDAC_DEBUG is not set
+CONFIG_EDAC_MM_EDAC=y
+# CONFIG_EDAC_CPC925 is not set
+CONFIG_RTC_LIB=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_HCTOSYS=y
+CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
+# CONFIG_RTC_DEBUG is not set
+
+#
+# RTC interfaces
+#
+CONFIG_RTC_INTF_SYSFS=y
+CONFIG_RTC_INTF_PROC=y
+CONFIG_RTC_INTF_DEV=y
+# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
+# CONFIG_RTC_DRV_TEST is not set
+
+#
+# I2C RTC drivers
+#
+CONFIG_RTC_DRV_DS1307=y
+# CONFIG_RTC_DRV_DS1374 is not set
+# CONFIG_RTC_DRV_DS1672 is not set
+# CONFIG_RTC_DRV_MAX6900 is not set
+# CONFIG_RTC_DRV_RS5C372 is not set
+# CONFIG_RTC_DRV_ISL1208 is not set
+# CONFIG_RTC_DRV_X1205 is not set
+# CONFIG_RTC_DRV_PCF8563 is not set
+# CONFIG_RTC_DRV_PCF8583 is not set
+# CONFIG_RTC_DRV_M41T80 is not set
+# CONFIG_RTC_DRV_S35390A is not set
+# CONFIG_RTC_DRV_FM3130 is not set
+# CONFIG_RTC_DRV_RX8581 is not set
+# CONFIG_RTC_DRV_RX8025 is not set
+
+#
+# SPI RTC drivers
+#
+
+#
+# Platform RTC drivers
+#
+# CONFIG_RTC_DRV_CMOS is not set
+# CONFIG_RTC_DRV_DS1286 is not set
+# CONFIG_RTC_DRV_DS1511 is not set
+# CONFIG_RTC_DRV_DS1553 is not set
+# CONFIG_RTC_DRV_DS1742 is not set
+# CONFIG_RTC_DRV_STK17TA8 is not set
+# CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_M48T35 is not set
+# CONFIG_RTC_DRV_M48T59 is not set
+# CONFIG_RTC_DRV_BQ4802 is not set
+# CONFIG_RTC_DRV_V3020 is not set
+
+#
+# on-CPU RTC drivers
+#
+# CONFIG_RTC_DRV_GENERIC is not set
+# CONFIG_DMADEVICES is not set
+# CONFIG_AUXDISPLAY is not set
+# CONFIG_UIO is not set
+
+#
+# TI VLYNQ
+#
+# CONFIG_STAGING is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+CONFIG_EXT2_FS_XATTR=y
+CONFIG_EXT2_FS_POSIX_ACL=y
+CONFIG_EXT2_FS_SECURITY=y
+CONFIG_EXT2_FS_XIP=y
+CONFIG_EXT3_FS=y
+# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
+CONFIG_EXT3_FS_XATTR=y
+CONFIG_EXT3_FS_POSIX_ACL=y
+CONFIG_EXT3_FS_SECURITY=y
+CONFIG_EXT4_FS=y
+CONFIG_EXT4_FS_XATTR=y
+CONFIG_EXT4_FS_POSIX_ACL=y
+CONFIG_EXT4_FS_SECURITY=y
+# CONFIG_EXT4_DEBUG is not set
+CONFIG_FS_XIP=y
+CONFIG_JBD=y
+# CONFIG_JBD_DEBUG is not set
+CONFIG_JBD2=y
+# CONFIG_JBD2_DEBUG is not set
+CONFIG_FS_MBCACHE=y
+CONFIG_REISERFS_FS=y
+# CONFIG_REISERFS_CHECK is not set
+# CONFIG_REISERFS_PROC_INFO is not set
+CONFIG_REISERFS_FS_XATTR=y
+CONFIG_REISERFS_FS_POSIX_ACL=y
+CONFIG_REISERFS_FS_SECURITY=y
+CONFIG_JFS_FS=y
+CONFIG_JFS_POSIX_ACL=y
+CONFIG_JFS_SECURITY=y
+# CONFIG_JFS_DEBUG is not set
+# CONFIG_JFS_STATISTICS is not set
+CONFIG_FS_POSIX_ACL=y
+CONFIG_XFS_FS=m
+# CONFIG_XFS_QUOTA is not set
+CONFIG_XFS_POSIX_ACL=y
+# CONFIG_XFS_RT is not set
+# CONFIG_XFS_DEBUG is not set
+# CONFIG_GFS2_FS is not set
+# CONFIG_OCFS2_FS is not set
+# CONFIG_BTRFS_FS is not set
+# CONFIG_NILFS2_FS is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
+CONFIG_DNOTIFY=y
+CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+CONFIG_AUTOFS4_FS=m
+# CONFIG_FUSE_FS is not set
+
+#
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+CONFIG_ISO9660_FS=y
+# CONFIG_JOLIET is not set
+# CONFIG_ZISOFS is not set
+CONFIG_UDF_FS=m
+CONFIG_UDF_NLS=y
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=y
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_PROC_SYSCTL=y
+CONFIG_PROC_PAGE_MONITOR=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
+# CONFIG_HUGETLBFS is not set
+# CONFIG_HUGETLB_PAGE is not set
+# CONFIG_CONFIGFS_FS is not set
+CONFIG_MISC_FILESYSTEMS=y
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+CONFIG_HFS_FS=m
+CONFIG_HFSPLUS_FS=m
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+CONFIG_CRAMFS=y
+# CONFIG_SQUASHFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_OMFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+CONFIG_NETWORK_FILESYSTEMS=y
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+CONFIG_NFS_V3_ACL=y
+CONFIG_NFS_V4=y
+# CONFIG_NFS_V4_1 is not set
+CONFIG_ROOT_NFS=y
+CONFIG_NFSD=m
+CONFIG_NFSD_V2_ACL=y
+CONFIG_NFSD_V3=y
+CONFIG_NFSD_V3_ACL=y
+CONFIG_NFSD_V4=y
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_EXPORTFS=m
+CONFIG_NFS_ACL_SUPPORT=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=y
+CONFIG_SUNRPC_GSS=y
+CONFIG_SUNRPC_XPRT_RDMA=m
+CONFIG_RPCSEC_GSS_KRB5=y
+CONFIG_RPCSEC_GSS_SPKM3=m
+# CONFIG_SMB_FS is not set
+CONFIG_CIFS=m
+# CONFIG_CIFS_STATS is not set
+# CONFIG_CIFS_WEAK_PW_HASH is not set
+CONFIG_CIFS_XATTR=y
+CONFIG_CIFS_POSIX=y
+# CONFIG_CIFS_DEBUG2 is not set
+# CONFIG_CIFS_EXPERIMENTAL is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+CONFIG_MAC_PARTITION=y
+CONFIG_MSDOS_PARTITION=y
+# CONFIG_BSD_DISKLABEL is not set
+# CONFIG_MINIX_SUBPARTITION is not set
+# CONFIG_SOLARIS_X86_PARTITION is not set
+# CONFIG_UNIXWARE_DISKLABEL is not set
+# CONFIG_LDM_PARTITION is not set
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_KARMA_PARTITION is not set
+# CONFIG_EFI_PARTITION is not set
+# CONFIG_SYSV68_PARTITION is not set
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="iso8859-1"
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_CODEPAGE_737=m
+CONFIG_NLS_CODEPAGE_775=m
+CONFIG_NLS_CODEPAGE_850=m
+CONFIG_NLS_CODEPAGE_852=m
+CONFIG_NLS_CODEPAGE_855=m
+CONFIG_NLS_CODEPAGE_857=m
+CONFIG_NLS_CODEPAGE_860=m
+CONFIG_NLS_CODEPAGE_861=m
+CONFIG_NLS_CODEPAGE_862=m
+CONFIG_NLS_CODEPAGE_863=m
+CONFIG_NLS_CODEPAGE_864=m
+CONFIG_NLS_CODEPAGE_865=m
+CONFIG_NLS_CODEPAGE_866=m
+CONFIG_NLS_CODEPAGE_869=m
+CONFIG_NLS_CODEPAGE_936=m
+CONFIG_NLS_CODEPAGE_950=m
+CONFIG_NLS_CODEPAGE_932=m
+CONFIG_NLS_CODEPAGE_949=m
+CONFIG_NLS_CODEPAGE_874=m
+CONFIG_NLS_ISO8859_8=m
+CONFIG_NLS_CODEPAGE_1250=m
+CONFIG_NLS_CODEPAGE_1251=m
+CONFIG_NLS_ASCII=m
+CONFIG_NLS_ISO8859_1=y
+CONFIG_NLS_ISO8859_2=m
+CONFIG_NLS_ISO8859_3=m
+CONFIG_NLS_ISO8859_4=m
+CONFIG_NLS_ISO8859_5=m
+CONFIG_NLS_ISO8859_6=m
+CONFIG_NLS_ISO8859_7=m
+CONFIG_NLS_ISO8859_9=m
+CONFIG_NLS_ISO8859_13=m
+CONFIG_NLS_ISO8859_14=m
+CONFIG_NLS_ISO8859_15=m
+CONFIG_NLS_KOI8_R=m
+CONFIG_NLS_KOI8_U=m
+CONFIG_NLS_UTF8=m
+# CONFIG_DLM is not set
+CONFIG_BINARY_PRINTF=y
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
+CONFIG_CRC_CCITT=m
+CONFIG_CRC16=y
+CONFIG_CRC_T10DIF=y
+CONFIG_CRC_ITU_T=m
+CONFIG_CRC32=y
+# CONFIG_CRC7 is not set
+CONFIG_LIBCRC32C=m
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=m
+CONFIG_LZO_COMPRESS=m
+CONFIG_LZO_DECOMPRESS=m
+CONFIG_DECOMPRESS_GZIP=y
+CONFIG_DECOMPRESS_BZIP2=y
+CONFIG_DECOMPRESS_LZMA=y
+CONFIG_TEXTSEARCH=y
+CONFIG_TEXTSEARCH_KMP=m
+CONFIG_TEXTSEARCH_BM=m
+CONFIG_TEXTSEARCH_FSM=m
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
+CONFIG_HAVE_LMB=y
+CONFIG_NLATTR=y
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_WARN_DEPRECATED=y
+CONFIG_ENABLE_MUST_CHECK=y
+CONFIG_FRAME_WARN=2048
+CONFIG_MAGIC_SYSRQ=y
+# CONFIG_STRIP_ASM_SYMS is not set
+# CONFIG_UNUSED_SYMBOLS is not set
+CONFIG_DEBUG_FS=y
+# CONFIG_HEADERS_CHECK is not set
+CONFIG_DEBUG_KERNEL=y
+# CONFIG_DEBUG_SHIRQ is not set
+CONFIG_DETECT_SOFTLOCKUP=y
+# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set
+CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0
+CONFIG_DETECT_HUNG_TASK=y
+# CONFIG_BOOTPARAM_HUNG_TASK_PANIC is not set
+CONFIG_BOOTPARAM_HUNG_TASK_PANIC_VALUE=0
+CONFIG_SCHED_DEBUG=y
+CONFIG_SCHEDSTATS=y
+# CONFIG_TIMER_STATS is not set
+# CONFIG_DEBUG_OBJECTS is not set
+# CONFIG_SLUB_DEBUG_ON is not set
+# CONFIG_SLUB_STATS is not set
+# CONFIG_DEBUG_KMEMLEAK is not set
+# CONFIG_DEBUG_RT_MUTEXES is not set
+# CONFIG_RT_MUTEX_TESTER is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+CONFIG_DEBUG_MUTEXES=y
+# CONFIG_DEBUG_LOCK_ALLOC is not set
+# CONFIG_PROVE_LOCKING is not set
+# CONFIG_LOCK_STAT is not set
+CONFIG_TRACE_IRQFLAGS=y
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+CONFIG_STACKTRACE=y
+# CONFIG_DEBUG_KOBJECT is not set
+CONFIG_DEBUG_BUGVERBOSE=y
+# CONFIG_DEBUG_INFO is not set
+# CONFIG_DEBUG_VM is not set
+# CONFIG_DEBUG_WRITECOUNT is not set
+CONFIG_DEBUG_MEMORY_INIT=y
+# CONFIG_DEBUG_LIST is not set
+# CONFIG_DEBUG_SG is not set
+# CONFIG_DEBUG_NOTIFIERS is not set
+# CONFIG_DEBUG_CREDENTIALS is not set
+# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
+# CONFIG_BACKTRACE_SELF_TEST is not set
+# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
+# CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set
+# CONFIG_FAULT_INJECTION is not set
+CONFIG_LATENCYTOP=y
+CONFIG_SYSCTL_SYSCALL_CHECK=y
+# CONFIG_DEBUG_PAGEALLOC is not set
+CONFIG_NOP_TRACER=y
+CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y
+CONFIG_HAVE_DYNAMIC_FTRACE=y
+CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
+CONFIG_TRACER_MAX_TRACE=y
+CONFIG_RING_BUFFER=y
+CONFIG_EVENT_TRACING=y
+CONFIG_CONTEXT_SWITCH_TRACER=y
+CONFIG_RING_BUFFER_ALLOW_SWAP=y
+CONFIG_TRACING=y
+CONFIG_GENERIC_TRACER=y
+CONFIG_TRACING_SUPPORT=y
+CONFIG_FTRACE=y
+# CONFIG_FUNCTION_TRACER is not set
+CONFIG_IRQSOFF_TRACER=y
+CONFIG_SCHED_TRACER=y
+# CONFIG_BOOT_TRACER is not set
+CONFIG_BRANCH_PROFILE_NONE=y
+# CONFIG_PROFILE_ANNOTATED_BRANCHES is not set
+# CONFIG_PROFILE_ALL_BRANCHES is not set
+# CONFIG_STACK_TRACER is not set
+# CONFIG_KMEMTRACE is not set
+# CONFIG_WORKQUEUE_TRACER is not set
+CONFIG_BLK_DEV_IO_TRACE=y
+# CONFIG_FTRACE_STARTUP_TEST is not set
+# CONFIG_RING_BUFFER_BENCHMARK is not set
+# CONFIG_DYNAMIC_DEBUG is not set
+# CONFIG_DMA_API_DEBUG is not set
+# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_KGDB is not set
+# CONFIG_PPC_DISABLE_WERROR is not set
+CONFIG_PPC_WERROR=y
+CONFIG_PRINT_STACK_DEPTH=64
+CONFIG_DEBUG_STACKOVERFLOW=y
+CONFIG_DEBUG_STACK_USAGE=y
+# CONFIG_PPC_EMULATED_STATS is not set
+CONFIG_CODE_PATCHING_SELFTEST=y
+CONFIG_FTR_FIXUP_SELFTEST=y
+CONFIG_MSI_BITMAP_SELFTEST=y
+CONFIG_XMON=y
+# CONFIG_XMON_DEFAULT is not set
+CONFIG_XMON_DISASSEMBLY=y
+CONFIG_DEBUGGER=y
+CONFIG_IRQSTACKS=y
+# CONFIG_VIRQ_DEBUG is not set
+# CONFIG_PPC_EARLY_DEBUG is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+# CONFIG_SECURITYFS is not set
+# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+CONFIG_XOR_BLOCKS=y
+CONFIG_ASYNC_CORE=y
+CONFIG_ASYNC_MEMCPY=y
+CONFIG_ASYNC_XOR=y
+CONFIG_ASYNC_PQ=y
+CONFIG_ASYNC_RAID6_RECOV=y
+CONFIG_CRYPTO=y
+
+#
+# Crypto core or helper
+#
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_ALGAPI2=y
+CONFIG_CRYPTO_AEAD=m
+CONFIG_CRYPTO_AEAD2=y
+CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_BLKCIPHER2=y
+CONFIG_CRYPTO_HASH=y
+CONFIG_CRYPTO_HASH2=y
+CONFIG_CRYPTO_RNG=m
+CONFIG_CRYPTO_RNG2=y
+CONFIG_CRYPTO_PCOMP=y
+CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_MANAGER2=y
+CONFIG_CRYPTO_GF128MUL=m
+CONFIG_CRYPTO_NULL=m
+CONFIG_CRYPTO_WORKQUEUE=y
+# CONFIG_CRYPTO_CRYPTD is not set
+CONFIG_CRYPTO_AUTHENC=m
+CONFIG_CRYPTO_TEST=m
+
+#
+# Authenticated Encryption with Associated Data
+#
+CONFIG_CRYPTO_CCM=m
+CONFIG_CRYPTO_GCM=m
+CONFIG_CRYPTO_SEQIV=m
+
+#
+# Block modes
+#
+CONFIG_CRYPTO_CBC=y
+CONFIG_CRYPTO_CTR=m
+# CONFIG_CRYPTO_CTS is not set
+CONFIG_CRYPTO_ECB=m
+# CONFIG_CRYPTO_LRW is not set
+CONFIG_CRYPTO_PCBC=m
+# CONFIG_CRYPTO_XTS is not set
+
+#
+# Hash modes
+#
+CONFIG_CRYPTO_HMAC=y
+# CONFIG_CRYPTO_XCBC is not set
+# CONFIG_CRYPTO_VMAC is not set
+
+#
+# Digest
+#
+CONFIG_CRYPTO_CRC32C=m
+CONFIG_CRYPTO_GHASH=m
+CONFIG_CRYPTO_MD4=m
+CONFIG_CRYPTO_MD5=y
+CONFIG_CRYPTO_MICHAEL_MIC=m
+# CONFIG_CRYPTO_RMD128 is not set
+# CONFIG_CRYPTO_RMD160 is not set
+# CONFIG_CRYPTO_RMD256 is not set
+# CONFIG_CRYPTO_RMD320 is not set
+CONFIG_CRYPTO_SHA1=m
+CONFIG_CRYPTO_SHA256=m
+CONFIG_CRYPTO_SHA512=m
+CONFIG_CRYPTO_TGR192=m
+CONFIG_CRYPTO_WP512=m
+
+#
+# Ciphers
+#
+CONFIG_CRYPTO_AES=m
+CONFIG_CRYPTO_ANUBIS=m
+CONFIG_CRYPTO_ARC4=m
+CONFIG_CRYPTO_BLOWFISH=m
+# CONFIG_CRYPTO_CAMELLIA is not set
+CONFIG_CRYPTO_CAST5=m
+CONFIG_CRYPTO_CAST6=m
+CONFIG_CRYPTO_DES=y
+# CONFIG_CRYPTO_FCRYPT is not set
+CONFIG_CRYPTO_KHAZAD=m
+CONFIG_CRYPTO_SALSA20=m
+# CONFIG_CRYPTO_SEED is not set
+CONFIG_CRYPTO_SERPENT=m
+CONFIG_CRYPTO_TEA=m
+CONFIG_CRYPTO_TWOFISH=m
+CONFIG_CRYPTO_TWOFISH_COMMON=m
+
+#
+# Compression
+#
+CONFIG_CRYPTO_DEFLATE=m
+# CONFIG_CRYPTO_ZLIB is not set
+CONFIG_CRYPTO_LZO=m
+
+#
+# Random Number Generation
+#
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
+# CONFIG_CRYPTO_HW is not set
+# CONFIG_PPC_CLOCK is not set
+# CONFIG_VIRTUALIZATION is not set
index 3a17982..20778a4 100644 (file)
@@ -37,7 +37,7 @@
 #define FW_FEATURE_VIO         ASM_CONST(0x0000000000004000)
 #define FW_FEATURE_RDMA                ASM_CONST(0x0000000000008000)
 #define FW_FEATURE_LLAN                ASM_CONST(0x0000000000010000)
-#define FW_FEATURE_BULK                ASM_CONST(0x0000000000020000)
+#define FW_FEATURE_BULK_REMOVE ASM_CONST(0x0000000000020000)
 #define FW_FEATURE_XDABR       ASM_CONST(0x0000000000040000)
 #define FW_FEATURE_MULTITCE    ASM_CONST(0x0000000000080000)
 #define FW_FEATURE_SPLPAR      ASM_CONST(0x0000000000100000)
@@ -45,8 +45,7 @@
 #define FW_FEATURE_LPAR                ASM_CONST(0x0000000000400000)
 #define FW_FEATURE_PS3_LV1     ASM_CONST(0x0000000000800000)
 #define FW_FEATURE_BEAT                ASM_CONST(0x0000000001000000)
-#define FW_FEATURE_BULK_REMOVE ASM_CONST(0x0000000002000000)
-#define FW_FEATURE_CMO         ASM_CONST(0x0000000004000000)
+#define FW_FEATURE_CMO         ASM_CONST(0x0000000002000000)
 
 #ifndef __ASSEMBLY__
 
@@ -58,8 +57,9 @@ enum {
                FW_FEATURE_PERF | FW_FEATURE_DUMP | FW_FEATURE_INTERRUPT |
                FW_FEATURE_MIGRATE | FW_FEATURE_PERFMON | FW_FEATURE_CRQ |
                FW_FEATURE_VIO | FW_FEATURE_RDMA | FW_FEATURE_LLAN |
-               FW_FEATURE_BULK | FW_FEATURE_XDABR | FW_FEATURE_MULTITCE |
-               FW_FEATURE_SPLPAR | FW_FEATURE_LPAR | FW_FEATURE_CMO,
+               FW_FEATURE_BULK_REMOVE | FW_FEATURE_XDABR |
+               FW_FEATURE_MULTITCE | FW_FEATURE_SPLPAR | FW_FEATURE_LPAR |
+               FW_FEATURE_CMO,
        FW_FEATURE_PSERIES_ALWAYS = 0,
        FW_FEATURE_ISERIES_POSSIBLE = FW_FEATURE_ISERIES | FW_FEATURE_LPAR,
        FW_FEATURE_ISERIES_ALWAYS = FW_FEATURE_ISERIES | FW_FEATURE_LPAR,
index 0b9c913..03c862b 100644 (file)
@@ -711,6 +711,8 @@ static struct cpu_spec __initdata cpu_specs[] = {
                .cpu_setup              = __setup_cpu_750,
                .machine_check          = machine_check_generic,
                .platform               = "ppc750",
+               .oprofile_cpu_type      = "ppc/750",
+               .oprofile_type          = PPC_OPROFILE_G4,
        },
        {       /* 745/755 */
                .pvr_mask               = 0xfffff000,
index 900e0ee..9763267 100644 (file)
@@ -658,42 +658,43 @@ do_work:
        cmpdi   r0,0
        crandc  eq,cr1*4+eq,eq
        bne     restore
-       /* here we are preempting the current task */
-1:
-#ifdef CONFIG_TRACE_IRQFLAGS
-       bl      .trace_hardirqs_on
-       /* Note: we just clobbered r10 which used to contain the previous
-        * MSR before the hard-disabling done by the caller of do_work.
-        * We don't have that value anymore, but it doesn't matter as
-        * we will hard-enable unconditionally, we can just reload the
-        * current MSR into r10
+
+       /* Here we are preempting the current task.
+        *
+        * Ensure interrupts are soft-disabled. We also properly mark
+        * the PACA to reflect the fact that they are hard-disabled
+        * and trace the change
         */
-       mfmsr   r10
-#endif /* CONFIG_TRACE_IRQFLAGS */
-       li      r0,1
+       li      r0,0
        stb     r0,PACASOFTIRQEN(r13)
        stb     r0,PACAHARDIRQEN(r13)
+       TRACE_DISABLE_INTS
+
+       /* Call the scheduler with soft IRQs off */
+1:     bl      .preempt_schedule_irq
+
+       /* Hard-disable interrupts again (and update PACA) */
 #ifdef CONFIG_PPC_BOOK3E
-       wrteei  1
-       bl      .preempt_schedule
        wrteei  0
 #else
-       ori     r10,r10,MSR_EE
-       mtmsrd  r10,1           /* reenable interrupts */
-       bl      .preempt_schedule
        mfmsr   r10
-       clrrdi  r9,r1,THREAD_SHIFT
-       rldicl  r10,r10,48,1    /* disable interrupts again */
+       rldicl  r10,r10,48,1
        rotldi  r10,r10,16
        mtmsrd  r10,1
 #endif /* CONFIG_PPC_BOOK3E */
+       li      r0,0
+       stb     r0,PACAHARDIRQEN(r13)
+
+       /* Re-test flags and eventually loop */
+       clrrdi  r9,r1,THREAD_SHIFT
        ld      r4,TI_FLAGS(r9)
        andi.   r0,r4,_TIF_NEED_RESCHED
        bne     1b
        b       restore
 
 user_work:
-#endif
+#endif /* CONFIG_PREEMPT */
+
        /* Enable interrupts */
 #ifdef CONFIG_PPC_BOOK3E
        wrteei  1
@@ -1038,8 +1039,7 @@ _GLOBAL(mod_return_to_handler)
         * We are in a module using the module's TOC.
         * Switch to our TOC to run inside the core kernel.
         */
-       LOAD_REG_IMMEDIATE(r4,ftrace_return_to_handler)
-       ld      r2, 8(r4)
+       ld      r2, PACATOC(r13)
 
        bl      .ftrace_return_to_handler
        nop
index fe8f71d..641c74b 100644 (file)
@@ -282,12 +282,6 @@ void gdb_regs_to_pt_regs(unsigned long *gdb_regs, struct pt_regs *regs)
 {
        unsigned long *ptr = gdb_regs;
        int reg;
-#ifdef CONFIG_SPE
-       union {
-               u32 v32[2];
-               u64 v64;
-       } acc;
-#endif
 
        for (reg = 0; reg < 32; reg++)
                UNPACK64(regs->gpr[reg], ptr);
index bb8209e..e8dfdbd 100644 (file)
@@ -1190,7 +1190,7 @@ EXPORT_SYMBOL(pcibios_align_resource);
  * Reparent resource children of pr that conflict with res
  * under res, and make res replace those children.
  */
-static int __init reparent_resources(struct resource *parent,
+static int reparent_resources(struct resource *parent,
                                     struct resource *res)
 {
        struct resource *p, **pp;
index ba949a2..ccf56ac 100644 (file)
@@ -97,7 +97,9 @@ int pcibios_unmap_io_space(struct pci_bus *bus)
         * to do an appropriate TLB flush here too
         */
        if (bus->self) {
+#ifdef CONFIG_PPC_STD_MMU_64
                struct resource *res = bus->resource[0];
+#endif
 
                pr_debug("IO unmapping for PCI-PCI bridge %s\n",
                         pci_name(bus->self));
index bbcbae1..87f1663 100644 (file)
@@ -116,20 +116,23 @@ static inline void perf_get_data_addr(struct pt_regs *regs, u64 *addrp)
 static inline u32 perf_get_misc_flags(struct pt_regs *regs)
 {
        unsigned long mmcra = regs->dsisr;
+       unsigned long sihv = MMCRA_SIHV;
+       unsigned long sipr = MMCRA_SIPR;
 
        if (TRAP(regs) != 0xf00)
                return 0;       /* not a PMU interrupt */
 
        if (ppmu->flags & PPMU_ALT_SIPR) {
-               if (mmcra & POWER6_MMCRA_SIHV)
-                       return PERF_RECORD_MISC_HYPERVISOR;
-               return (mmcra & POWER6_MMCRA_SIPR) ?
-                       PERF_RECORD_MISC_USER : PERF_RECORD_MISC_KERNEL;
+               sihv = POWER6_MMCRA_SIHV;
+               sipr = POWER6_MMCRA_SIPR;
        }
-       if (mmcra & MMCRA_SIHV)
+
+       /* PR has priority over HV, so order below is important */
+       if (mmcra & sipr)
+               return PERF_RECORD_MISC_USER;
+       if ((mmcra & sihv) && (freeze_events_kernel != MMCR0_FCHV))
                return PERF_RECORD_MISC_HYPERVISOR;
-       return (mmcra & MMCRA_SIPR) ? PERF_RECORD_MISC_USER :
-               PERF_RECORD_MISC_KERNEL;
+       return PERF_RECORD_MISC_KERNEL;
 }
 
 /*
index 1168c5f..c930ac3 100644 (file)
@@ -1016,9 +1016,13 @@ void show_stack(struct task_struct *tsk, unsigned long *stack)
 #ifdef CONFIG_FUNCTION_GRAPH_TRACER
        int curr_frame = current->curr_ret_stack;
        extern void return_to_handler(void);
-       unsigned long addr = (unsigned long)return_to_handler;
+       unsigned long rth = (unsigned long)return_to_handler;
+       unsigned long mrth = -1;
 #ifdef CONFIG_PPC64
-       addr = *(unsigned long*)addr;
+       extern void mod_return_to_handler(void);
+       rth = *(unsigned long *)rth;
+       mrth = (unsigned long)mod_return_to_handler;
+       mrth = *(unsigned long *)mrth;
 #endif
 #endif
 
@@ -1044,7 +1048,7 @@ void show_stack(struct task_struct *tsk, unsigned long *stack)
                if (!firstframe || ip != lr) {
                        printk("["REG"] ["REG"] %pS", sp, ip, (void *)ip);
 #ifdef CONFIG_FUNCTION_GRAPH_TRACER
-                       if (ip == addr && curr_frame >= 0) {
+                       if ((ip == rth || ip == mrth) && curr_frame >= 0) {
                                printk(" (%pS)",
                                       (void *)current->ret_stack[curr_frame].ret);
                                curr_frame--;
@@ -1168,7 +1172,7 @@ unsigned long arch_randomize_brk(struct mm_struct *mm)
        unsigned long base = mm->brk;
        unsigned long ret;
 
-#ifdef CONFIG_PPC64
+#ifdef CONFIG_PPC_STD_MMU_64
        /*
         * If we are using 1TB segments and we are allowed to randomise
         * the heap, we can put it above 1TB so it is backed by a 1TB
index 797ea95..04f638d 100644 (file)
@@ -57,7 +57,6 @@
 #include <asm/cache.h>
 #include <asm/page.h>
 #include <asm/mmu.h>
-#include <asm/mmu-hash64.h>
 #include <asm/firmware.h>
 #include <asm/xmon.h>
 #include <asm/udbg.h>
index 94e2df3..137dc22 100644 (file)
@@ -50,6 +50,9 @@
 /* Max supported size for symbol names */
 #define MAX_SYMNAME    64
 
+/* The alignment of the vDSO */
+#define VDSO_ALIGNMENT (1 << 16)
+
 extern char vdso32_start, vdso32_end;
 static void *vdso32_kbase = &vdso32_start;
 static unsigned int vdso32_pages;
@@ -231,15 +234,21 @@ int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp)
         * pick a base address for the vDSO in process space. We try to put it
         * at vdso_base which is the "natural" base for it, but we might fail
         * and end up putting it elsewhere.
+        * Add enough to the size so that the result can be aligned.
         */
        down_write(&mm->mmap_sem);
        vdso_base = get_unmapped_area(NULL, vdso_base,
-                                     vdso_pages << PAGE_SHIFT, 0, 0);
+                                     (vdso_pages << PAGE_SHIFT) +
+                                     ((VDSO_ALIGNMENT - 1) & PAGE_MASK),
+                                     0, 0);
        if (IS_ERR_VALUE(vdso_base)) {
                rc = vdso_base;
                goto fail_mmapsem;
        }
 
+       /* Add required alignment. */
+       vdso_base = ALIGN(vdso_base, VDSO_ALIGNMENT);
+
        /*
         * Put vDSO base into mm struct. We need to do this before calling
         * install_special_mapping or the perf counter mmap tracking code
index 904ef13..0546bcd 100644 (file)
@@ -25,7 +25,7 @@ SECTIONS
        . = ALIGN(16);
        .text           : {
                *(.text .stub .text.* .gnu.linkonce.t.* __ftr_alt_*)
-       }
+       }                                               :text
        PROVIDE(__etext = .);
        PROVIDE(_etext = .);
        PROVIDE(etext = .);
@@ -56,7 +56,7 @@ SECTIONS
        .fixup          : { *(.fixup) }
 
        .dynamic        : { *(.dynamic) }               :text   :dynamic
-       .got            : { *(.got) }
+       .got            : { *(.got) }                   :text
        .plt            : { *(.plt) }
 
        _end = .;
index f564293..27735a7 100644 (file)
@@ -236,6 +236,7 @@ SECTIONS
                READ_MOSTLY_DATA(L1_CACHE_BYTES)
        }
 
+       . = ALIGN(PAGE_SIZE);
        .data_nosave : AT(ADDR(.data_nosave) - LOAD_OFFSET) {
                NOSAVE_DATA
        }
index bc44dc4..95ce355 100644 (file)
@@ -72,19 +72,17 @@ _GLOBAL(slb_miss_kernel_load_vmemmap)
 1:
 #endif /* CONFIG_SPARSEMEM_VMEMMAP */
 
-       /* vmalloc/ioremap mapping encoding bits, the "li" instructions below
-        * will be patched by the kernel at boot
+       /* vmalloc mapping gets the encoding from the PACA as the mapping
+        * can be demoted from 64K -> 4K dynamically on some machines
         */
-BEGIN_FTR_SECTION
-       /* check whether this is in vmalloc or ioremap space */
        clrldi  r11,r10,48
        cmpldi  r11,(VMALLOC_SIZE >> 28) - 1
        bgt     5f
        lhz     r11,PACAVMALLOCSLLP(r13)
        b       6f
 5:
-END_FTR_SECTION_IFCLR(CPU_FTR_CI_LARGE_PAGE)
-_GLOBAL(slb_miss_kernel_load_io)
+       /* IO mapping */
+       _GLOBAL(slb_miss_kernel_load_io)
        li      r11,0
 6:
 BEGIN_FTR_SECTION
index c31e5b5..d45be5b 100644 (file)
@@ -51,6 +51,8 @@ static void __init mpc5200_simple_setup_arch(void)
 /* list of the supported boards */
 static char *board[] __initdata = {
        "intercontrol,digsy-mtc",
+       "manroland,mucmc52",
+       "manroland,uc101",
        "phytec,pcm030",
        "phytec,pcm032",
        "promess,motionpro",
index aca5741..a86c34b 100644 (file)
@@ -365,7 +365,7 @@ static int axon_msi_probe(struct of_device *device,
                printk(KERN_ERR
                       "axon_msi: couldn't parse dcr properties on %s\n",
                        dn->full_name);
-               goto out;
+               goto out_free_msic;
        }
 
        msic->dcr_host = dcr_map(dn, dcr_base, dcr_len);
index cc7161f..ce01492 100644 (file)
@@ -1,18 +1,9 @@
 EXTRA_CFLAGS   += -mno-minimal-toc
 
-extra-y += dt.o
-
 obj-y += exception.o
-obj-y += hvlog.o hvlpconfig.o lpardata.o setup.o dt_mod.o mf.o lpevents.o \
+obj-y += hvlog.o hvlpconfig.o lpardata.o setup.o dt.o mf.o lpevents.o \
        hvcall.o proc.o htab.o iommu.o misc.o irq.o
 obj-$(CONFIG_PCI) += pci.o
 obj-$(CONFIG_SMP) += smp.o
 obj-$(CONFIG_VIOPATH) += viopath.o vio.o
 obj-$(CONFIG_MODULES) += ksyms.o
-
-quiet_cmd_dt_strings = DT_STR  $@
-      cmd_dt_strings = $(OBJCOPY) --rename-section .rodata.str1.8=.dt_strings \
-                               $< $@
-
-$(obj)/dt_mod.o:       $(obj)/dt.o
-       $(call if_changed,dt_strings)
index c5a87a7..7f45a51 100644 (file)
 
 /*
  * These are created by the linker script at the start and end
- * of the section containing all the strings from this file.
+ * of the section containing all the strings marked with the DS macro.
  */
 extern char __dt_strings_start[];
 extern char __dt_strings_end[];
 
+#define DS(s)  ({      \
+       static const char __s[] __attribute__((section(".dt_strings"))) = s; \
+       __s;            \
+})
+
 struct iseries_flat_dt {
        struct boot_param_header header;
        u64 reserve_map[2];
@@ -64,9 +69,8 @@ struct iseries_flat_dt {
 static void * __initdata dt_data;
 
 /*
- * Putting these strings here keeps them out of the section
- * that we rename to .dt_strings using objcopy and capture
- * for the strings blob of the flattened device tree.
+ * Putting these strings here keeps them out of the .dt_strings section
+ * that we capture for the strings blob of the flattened device tree.
  */
 static char __initdata device_type_cpu[] = "cpu";
 static char __initdata device_type_memory[] = "memory";
@@ -173,7 +177,7 @@ static void __init dt_start_node(struct iseries_flat_dt *dt, const char *name)
 
 #define dt_end_node(dt) dt_push_u32(dt, OF_DT_END_NODE)
 
-static void __init dt_prop(struct iseries_flat_dt *dt, const char *name,
+static void __init __dt_prop(struct iseries_flat_dt *dt, const char *name,
                const void *data, int len)
 {
        unsigned long offset;
@@ -191,44 +195,32 @@ static void __init dt_prop(struct iseries_flat_dt *dt, const char *name,
        /* The actual data. */
        dt_push_bytes(dt, data, len);
 }
+#define dt_prop(dt, name, data, len)   __dt_prop((dt), DS(name), (data), (len))
 
-static void __init dt_prop_str(struct iseries_flat_dt *dt, const char *name,
-               const char *data)
-{
-       dt_prop(dt, name, data, strlen(data) + 1); /* + 1 for NULL */
-}
+#define dt_prop_str(dt, name, data)    \
+       dt_prop((dt), name, (data), strlen((data)) + 1); /* + 1 for NULL */
 
-static void __init dt_prop_u32(struct iseries_flat_dt *dt, const char *name,
+static void __init __dt_prop_u32(struct iseries_flat_dt *dt, const char *name,
                u32 data)
 {
-       dt_prop(dt, name, &data, sizeof(u32));
+       __dt_prop(dt, name, &data, sizeof(u32));
 }
+#define dt_prop_u32(dt, name, data)    __dt_prop_u32((dt), DS(name), (data))
 
-static void __init __maybe_unused dt_prop_u64(struct iseries_flat_dt *dt,
-                                             const char *name,
-               u64 data)
+static void __init __maybe_unused __dt_prop_u64(struct iseries_flat_dt *dt,
+               const char *name, u64 data)
 {
-       dt_prop(dt, name, &data, sizeof(u64));
+       __dt_prop(dt, name, &data, sizeof(u64));
 }
+#define dt_prop_u64(dt, name, data)    __dt_prop_u64((dt), DS(name), (data))
 
-static void __init dt_prop_u64_list(struct iseries_flat_dt *dt,
-               const char *name, u64 *data, int n)
-{
-       dt_prop(dt, name, data, sizeof(u64) * n);
-}
+#define dt_prop_u64_list(dt, name, data, n)    \
+       dt_prop((dt), name, (data), sizeof(u64) * (n))
 
-static void __init dt_prop_u32_list(struct iseries_flat_dt *dt,
-               const char *name, u32 *data, int n)
-{
-       dt_prop(dt, name, data, sizeof(u32) * n);
-}
+#define dt_prop_u32_list(dt, name, data, n)    \
+       dt_prop((dt), name, (data), sizeof(u32) * (n))
 
-#ifdef notyet
-static void __init dt_prop_empty(struct iseries_flat_dt *dt, const char *name)
-{
-       dt_prop(dt, name, NULL, 0);
-}
-#endif
+#define dt_prop_empty(dt, name)                dt_prop((dt), name, NULL, 0)
 
 static void __init dt_cpus(struct iseries_flat_dt *dt)
 {
index 21226b7..414ca98 100644 (file)
@@ -540,8 +540,11 @@ static struct pmac_i2c_host_kw *__init kw_i2c_host_init(struct device_node *np)
        /* Make sure IRQ is disabled */
        kw_write_reg(reg_ier, 0);
 
-       /* Request chip interrupt */
-       if (request_irq(host->irq, kw_i2c_irq, 0, "keywest i2c", host))
+       /* Request chip interrupt. We set IRQF_TIMER because we don't
+        * want that interrupt disabled between the 2 passes of driver
+        * suspend or we'll have issues running the pfuncs
+        */
+       if (request_irq(host->irq, kw_i2c_irq, IRQF_TIMER, "keywest i2c", host))
                host->irq = NO_IRQ;
 
        printk(KERN_INFO "KeyWest i2c @0x%08x irq %d %s\n",
index 5a707da..0a14d8c 100644 (file)
@@ -51,11 +51,10 @@ firmware_features_table[FIRMWARE_MAX_FEATURES] = {
        {FW_FEATURE_VIO,                "hcall-vio"},
        {FW_FEATURE_RDMA,               "hcall-rdma"},
        {FW_FEATURE_LLAN,               "hcall-lLAN"},
-       {FW_FEATURE_BULK,               "hcall-bulk"},
+       {FW_FEATURE_BULK_REMOVE,        "hcall-bulk"},
        {FW_FEATURE_XDABR,              "hcall-xdabr"},
        {FW_FEATURE_MULTITCE,           "hcall-multi-tce"},
        {FW_FEATURE_SPLPAR,             "hcall-splpar"},
-       {FW_FEATURE_BULK_REMOVE,        "hcall-bulk"},
 };
 
 /* Build up the firmware features bitmask using the contents of
index c6f0a71..bdbe96c 100644 (file)
@@ -517,6 +517,15 @@ static int xmon_core(struct pt_regs *regs, int fromipi)
        in_xmon = 0;
 #endif
 
+#ifdef CONFIG_BOOKE
+       if (regs->msr & MSR_DE) {
+               bp = at_breakpoint(regs->nip);
+               if (bp != NULL) {
+                       regs->nip = (unsigned long) &bp->instr[0];
+                       atomic_inc(&bp->ref_count);
+               }
+       }
+#else
        if ((regs->msr & (MSR_IR|MSR_PR|MSR_SF)) == (MSR_IR|MSR_SF)) {
                bp = at_breakpoint(regs->nip);
                if (bp != NULL) {
@@ -530,7 +539,7 @@ static int xmon_core(struct pt_regs *regs, int fromipi)
                        }
                }
        }
-
+#endif
        insert_cpu_bpts();
 
        local_irq_restore(flags);
@@ -894,6 +903,14 @@ cmds(struct pt_regs *excp)
        }
 }
 
+#ifdef CONFIG_BOOKE
+static int do_step(struct pt_regs *regs)
+{
+       regs->msr |= MSR_DE;
+       mtspr(SPRN_DBCR0, mfspr(SPRN_DBCR0) | DBCR0_IC | DBCR0_IDM);
+       return 1;
+}
+#else
 /*
  * Step a single instruction.
  * Some instructions we emulate, others we execute with MSR_SE set.
@@ -924,6 +941,7 @@ static int do_step(struct pt_regs *regs)
        regs->msr |= MSR_SE;
        return 1;
 }
+#endif
 
 static void bootcmds(void)
 {
index 704dd39..77df726 100644 (file)
@@ -438,7 +438,7 @@ static int diag204_probe(void)
                }
                if (diag204((unsigned long)SUBC_STIB6 |
                            (unsigned long)INFO_EXT, pages, buf) >= 0) {
-                       diag204_store_sc = SUBC_STIB7;
+                       diag204_store_sc = SUBC_STIB6;
                        diag204_info_type = INFO_EXT;
                        goto out;
                }
index 24b1244..f23961a 100644 (file)
@@ -78,7 +78,7 @@ cputime64_to_jiffies64(cputime64_t cputime)
 static inline unsigned int
 cputime_to_msecs(const cputime_t cputime)
 {
-       return __div(cputime, 4096000);
+       return cputime_div(cputime, 4096000);
 }
 
 static inline cputime_t
@@ -160,7 +160,7 @@ cputime_to_timeval(const cputime_t cputime, struct timeval *value)
 static inline clock_t
 cputime_to_clock_t(cputime_t cputime)
 {
-       return __div(cputime, 4096000000ULL / USER_HZ);
+       return cputime_div(cputime, 4096000000ULL / USER_HZ);
 }
 
 static inline cputime_t
@@ -175,7 +175,7 @@ clock_t_to_cputime(unsigned long x)
 static inline clock_t
 cputime64_to_clock_t(cputime64_t cputime)
 {
-       return __div(cputime, 4096000000ULL / USER_HZ);
+       return cputime_div(cputime, 4096000000ULL / USER_HZ);
 }
 
 struct s390_idle_data {
index a356c95..8a096b8 100644 (file)
 #ifndef _S390_DELAY_H
 #define _S390_DELAY_H
 
-extern void __udelay(unsigned long usecs);
-extern void udelay_simple(unsigned long usecs);
+extern void __udelay(unsigned long long usecs);
+extern void udelay_simple(unsigned long long usecs);
 extern void __delay(unsigned long loops);
 
-#define udelay(n) __udelay(n)
+#define udelay(n) __udelay((unsigned long long) (n))
+#define mdelay(n) __udelay((unsigned long long) (n) * 1000)
 
 #endif /* defined(_S390_DELAY_H) */
index 74d0bbb..e885442 100644 (file)
 /* Keep this the last entry.  */
 #define R_390_NUM      61
 
+/* Bits present in AT_HWCAP. */
+#define HWCAP_S390_ESAN3       1
+#define HWCAP_S390_ZARCH       2
+#define HWCAP_S390_STFLE       4
+#define HWCAP_S390_MSA         8
+#define HWCAP_S390_LDISP       16
+#define HWCAP_S390_EIMM                32
+#define HWCAP_S390_DFP         64
+#define HWCAP_S390_HPAGE       128
+#define HWCAP_S390_ETF3EH      256
+#define HWCAP_S390_HIGH_GPRS   512
+
 /*
  * These are used to set parameters in the core dumps.
  */
index 539263f..95dcf18 100644 (file)
@@ -311,6 +311,10 @@ typedef struct
        __u32           orig_gpr2;
 } s390_compat_regs;
 
+typedef struct
+{
+       __u32           gprs_high[NUM_GPRS];
+} s390_compat_regs_high;
 
 #ifdef __KERNEL__
 
index d69bec0..cfb874e 100644 (file)
@@ -9,6 +9,21 @@
 #ifndef _ASM_S390_UCONTEXT_H
 #define _ASM_S390_UCONTEXT_H
 
+#define UC_EXTENDED    0x00000001
+
+#ifndef __s390x__
+
+struct ucontext_extended {
+       unsigned long     uc_flags;
+       struct ucontext  *uc_link;
+       stack_t           uc_stack;
+       _sigregs          uc_mcontext;
+       unsigned long     uc_sigmask[2];
+       unsigned long     uc_gprs_high[16];
+};
+
+#endif
+
 struct ucontext {
        unsigned long     uc_flags;
        struct ucontext  *uc_link;
index b537cb0..eee9998 100644 (file)
@@ -39,6 +39,7 @@ typedef struct
        struct sigcontext32 sc;
        _sigregs32 sregs;
        int signo;
+       __u32 gprs_high[NUM_GPRS];
        __u8 retcode[S390_SYSCALL_SIZE];
 } sigframe32;
 
@@ -48,6 +49,7 @@ typedef struct
        __u8 retcode[S390_SYSCALL_SIZE];
        compat_siginfo_t info;
        struct ucontext32 uc;
+       __u32 gprs_high[NUM_GPRS];
 } rt_sigframe32;
 
 int copy_siginfo_to_user32(compat_siginfo_t __user *to, siginfo_t *from)
@@ -344,6 +346,30 @@ static int restore_sigregs32(struct pt_regs *regs,_sigregs32 __user *sregs)
        return 0;
 }
 
+static int save_sigregs_gprs_high(struct pt_regs *regs, __u32 __user *uregs)
+{
+       __u32 gprs_high[NUM_GPRS];
+       int i;
+
+       for (i = 0; i < NUM_GPRS; i++)
+               gprs_high[i] = regs->gprs[i] >> 32;
+
+       return __copy_to_user(uregs, &gprs_high, sizeof(gprs_high));
+}
+
+static int restore_sigregs_gprs_high(struct pt_regs *regs, __u32 __user *uregs)
+{
+       __u32 gprs_high[NUM_GPRS];
+       int err, i;
+
+       err = __copy_from_user(&gprs_high, uregs, sizeof(gprs_high));
+       if (err)
+               return err;
+       for (i = 0; i < NUM_GPRS; i++)
+               *(__u32 *)&regs->gprs[i] = gprs_high[i];
+       return 0;
+}
+
 asmlinkage long sys32_sigreturn(void)
 {
        struct pt_regs *regs = task_pt_regs(current);
@@ -363,6 +389,8 @@ asmlinkage long sys32_sigreturn(void)
 
        if (restore_sigregs32(regs, &frame->sregs))
                goto badframe;
+       if (restore_sigregs_gprs_high(regs, frame->gprs_high))
+               goto badframe;
 
        return regs->gprs[2];
 
@@ -394,6 +422,8 @@ asmlinkage long sys32_rt_sigreturn(void)
 
        if (restore_sigregs32(regs, &frame->uc.uc_mcontext))
                goto badframe;
+       if (restore_sigregs_gprs_high(regs, frame->gprs_high))
+               goto badframe;
 
        err = __get_user(ss_sp, &frame->uc.uc_stack.ss_sp);
        st.ss_sp = compat_ptr(ss_sp);
@@ -474,6 +504,8 @@ static int setup_frame32(int sig, struct k_sigaction *ka,
 
        if (save_sigregs32(regs, &frame->sregs))
                goto give_sigsegv;
+       if (save_sigregs_gprs_high(regs, frame->gprs_high))
+               goto give_sigsegv;
        if (__put_user((unsigned long) &frame->sregs, &frame->sc.sregs))
                goto give_sigsegv;
 
@@ -529,13 +561,14 @@ static int setup_rt_frame32(int sig, struct k_sigaction *ka, siginfo_t *info,
                goto give_sigsegv;
 
        /* Create the ucontext.  */
-       err |= __put_user(0, &frame->uc.uc_flags);
+       err |= __put_user(UC_EXTENDED, &frame->uc.uc_flags);
        err |= __put_user(0, &frame->uc.uc_link);
        err |= __put_user(current->sas_ss_sp, &frame->uc.uc_stack.ss_sp);
        err |= __put_user(sas_ss_flags(regs->gprs[15]),
                          &frame->uc.uc_stack.ss_flags);
        err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size);
        err |= save_sigregs32(regs, &frame->uc.uc_mcontext);
+       err |= save_sigregs_gprs_high(regs, frame->gprs_high);
        err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
        if (err)
                goto give_sigsegv;
index 682fb69..cbd9901 100644 (file)
@@ -409,7 +409,7 @@ sys32_munmap_wrapper:
        .globl  sys32_truncate_wrapper
 sys32_truncate_wrapper:
        llgtr   %r2,%r2                 # const char *
-       llgfr   %r3,%r3                 # unsigned long
+       lgfr    %r3,%r3                 # long
        jg      sys_truncate            # branch to system call
 
        .globl  sys32_ftruncate_wrapper
index 57bdcb1..f5fe34d 100644 (file)
@@ -185,9 +185,6 @@ unsigned long prepare_ftrace_return(unsigned long ip, unsigned long parent)
 {
        struct ftrace_graph_ent trace;
 
-       /* Nmi's are currently unsupported. */
-       if (unlikely(in_nmi()))
-               goto out;
        if (unlikely(atomic_read(&current->tracing_graph_pause)))
                goto out;
        if (ftrace_push_return_trace(parent, ip, &trace.depth, 0) == -EBUSY)
index ee57a42..4890ac6 100644 (file)
@@ -1595,10 +1595,9 @@ static void stop_run(struct shutdown_trigger *trigger)
 {
        if (strcmp(trigger->name, ON_PANIC_STR) == 0)
                disabled_wait((unsigned long) __builtin_return_address(0));
-       else {
-               signal_processor(smp_processor_id(), sigp_stop);
-               for (;;);
-       }
+       while (signal_processor(smp_processor_id(), sigp_stop) == sigp_busy)
+               cpu_relax();
+       for (;;);
 }
 
 static struct shutdown_action stop_action = {SHUTDOWN_ACTION_STOP_STR,
index ab2e3ed..639380a 100644 (file)
@@ -55,6 +55,8 @@ void *module_alloc(unsigned long size)
 /* Free memory returned from module_alloc */
 void module_free(struct module *mod, void *module_region)
 {
+       vfree(mod->arch.syminfo);
+       mod->arch.syminfo = NULL;
        vfree(module_region);
 }
 
@@ -402,6 +404,7 @@ int module_finalize(const Elf_Ehdr *hdr,
                    struct module *me)
 {
        vfree(me->arch.syminfo);
+       me->arch.syminfo = NULL;
        return module_bug_finalize(hdr, sechdrs, me);
 }
 
index 802c8ab..0729f36 100644 (file)
@@ -31,9 +31,9 @@ void __cpuinit print_cpu_info(void)
 
 static int show_cpuinfo(struct seq_file *m, void *v)
 {
-       static const char *hwcap_str[9] = {
+       static const char *hwcap_str[10] = {
                "esan3", "zarch", "stfle", "msa", "ldisp", "eimm", "dfp",
-               "edat", "etf3eh"
+               "edat", "etf3eh", "highgprs"
        };
        struct _lowcore *lc;
        unsigned long n = (unsigned long) v - 1;
@@ -48,7 +48,7 @@ static int show_cpuinfo(struct seq_file *m, void *v)
                           num_online_cpus(), loops_per_jiffy/(500000/HZ),
                           (loops_per_jiffy/(5000/HZ))%100);
                seq_puts(m, "features\t: ");
-               for (i = 0; i < 9; i++)
+               for (i = 0; i < 10; i++)
                        if (hwcap_str[i] && (elf_hwcap & (1UL << i)))
                                seq_printf(m, "%s ", hwcap_str[i]);
                seq_puts(m, "\n");
index a873867..653c6a1 100644 (file)
@@ -57,6 +57,7 @@
 enum s390_regset {
        REGSET_GENERAL,
        REGSET_FP,
+       REGSET_GENERAL_EXTENDED,
 };
 
 static void
@@ -879,6 +880,67 @@ static int s390_compat_regs_set(struct task_struct *target,
        return rc;
 }
 
+static int s390_compat_regs_high_get(struct task_struct *target,
+                                    const struct user_regset *regset,
+                                    unsigned int pos, unsigned int count,
+                                    void *kbuf, void __user *ubuf)
+{
+       compat_ulong_t *gprs_high;
+
+       gprs_high = (compat_ulong_t *)
+               &task_pt_regs(target)->gprs[pos / sizeof(compat_ulong_t)];
+       if (kbuf) {
+               compat_ulong_t *k = kbuf;
+               while (count > 0) {
+                       *k++ = *gprs_high;
+                       gprs_high += 2;
+                       count -= sizeof(*k);
+               }
+       } else {
+               compat_ulong_t __user *u = ubuf;
+               while (count > 0) {
+                       if (__put_user(*gprs_high, u++))
+                               return -EFAULT;
+                       gprs_high += 2;
+                       count -= sizeof(*u);
+               }
+       }
+       return 0;
+}
+
+static int s390_compat_regs_high_set(struct task_struct *target,
+                                    const struct user_regset *regset,
+                                    unsigned int pos, unsigned int count,
+                                    const void *kbuf, const void __user *ubuf)
+{
+       compat_ulong_t *gprs_high;
+       int rc = 0;
+
+       gprs_high = (compat_ulong_t *)
+               &task_pt_regs(target)->gprs[pos / sizeof(compat_ulong_t)];
+       if (kbuf) {
+               const compat_ulong_t *k = kbuf;
+               while (count > 0) {
+                       *gprs_high = *k++;
+                       *gprs_high += 2;
+                       count -= sizeof(*k);
+               }
+       } else {
+               const compat_ulong_t  __user *u = ubuf;
+               while (count > 0 && !rc) {
+                       unsigned long word;
+                       rc = __get_user(word, u++);
+                       if (rc)
+                               break;
+                       *gprs_high = word;
+                       *gprs_high += 2;
+                       count -= sizeof(*u);
+               }
+       }
+
+       return rc;
+}
+
 static const struct user_regset s390_compat_regsets[] = {
        [REGSET_GENERAL] = {
                .core_note_type = NT_PRSTATUS,
@@ -896,6 +958,14 @@ static const struct user_regset s390_compat_regsets[] = {
                .get = s390_fpregs_get,
                .set = s390_fpregs_set,
        },
+       [REGSET_GENERAL_EXTENDED] = {
+               .core_note_type = NT_PRXSTATUS,
+               .n = sizeof(s390_compat_regs_high) / sizeof(compat_long_t),
+               .size = sizeof(compat_long_t),
+               .align = sizeof(compat_long_t),
+               .get = s390_compat_regs_high_get,
+               .set = s390_compat_regs_high_set,
+       },
 };
 
 static const struct user_regset_view user_s390_compat_view = {
index 9ed13a1..061479f 100644 (file)
@@ -729,7 +729,7 @@ static void __init setup_hwcaps(void)
 
        if ((facility_list & (1UL << (31 - 22)))
            && (facility_list & (1UL << (31 - 30))))
-               elf_hwcap |= 1UL << 8;
+               elf_hwcap |= HWCAP_S390_ETF3EH;
 
        /*
         * Check for additional facilities with store-facility-list-extended.
@@ -748,11 +748,20 @@ static void __init setup_hwcaps(void)
            __stfle(&facility_list_extended, 1) > 0) {
                if ((facility_list_extended & (1ULL << (63 - 42)))
                    && (facility_list_extended & (1ULL << (63 - 44))))
-                       elf_hwcap |= 1UL << 6;
+                       elf_hwcap |= HWCAP_S390_DFP;
        }
 
+       /*
+        * Huge page support HWCAP_S390_HPAGE is bit 7.
+        */
        if (MACHINE_HAS_HPAGE)
-               elf_hwcap |= 1UL << 7;
+               elf_hwcap |= HWCAP_S390_HPAGE;
+
+       /*
+        * 64-bit register support for 31-bit processes
+        * HWCAP_S390_HIGH_GPRS is bit 9.
+        */
+       elf_hwcap |= HWCAP_S390_HIGH_GPRS;
 
        switch (S390_lowcore.cpu_id.machine) {
        case 0x9672:
index c932caa..93e5203 100644 (file)
@@ -76,7 +76,6 @@ static int cpu_stopped(int cpu)
        __u32 status;
 
        switch (signal_processor_ps(&status, 0, cpu, sigp_sense)) {
-       case sigp_order_code_accepted:
        case sigp_status_stored:
                /* Check for stopped and check stop state */
                if (status & 0x50)
@@ -638,6 +637,8 @@ void __cpu_die(unsigned int cpu)
        /* Wait until target cpu is down */
        while (!cpu_stopped(cpu))
                cpu_relax();
+       while (signal_processor_p(0, cpu, sigp_set_prefix) == sigp_busy)
+               udelay(10);
        smp_free_lowcore(cpu);
        pr_info("Processor %d stopped\n", cpu);
 }
@@ -645,8 +646,8 @@ void __cpu_die(unsigned int cpu)
 void cpu_die(void)
 {
        idle_task_exit();
-       signal_processor(smp_processor_id(), sigp_stop);
-       BUG();
+       while (signal_processor(smp_processor_id(), sigp_stop) == sigp_busy)
+               cpu_relax();
        for (;;);
 }
 
index fe927d0..0c26cc1 100644 (file)
@@ -43,7 +43,7 @@ swsusp_arch_suspend:
        lghi    %r1,0x1000
 
        /* Save CPU address */
-       stap    __LC_CPU_ADDRESS(%r1)
+       stap    __LC_CPU_ADDRESS(%r0)
 
        /* Store registers */
        mvc     0x318(4,%r1),__SF_EMPTY(%r15)   /* move prefix to lowcore */
@@ -69,8 +69,21 @@ swsusp_arch_suspend:
        stmg    %r0,%r15,0x280(%r1)             /* store general registers */
 
        stpt    0x328(%r1)                      /* store timer */
+       stck    __SF_EMPTY(%r15)                /* store clock */
        stckc   0x330(%r1)                      /* store clock comparator */
 
+       /* Update cputime accounting before going to sleep */
+       lg      %r0,__LC_LAST_UPDATE_TIMER
+       slg     %r0,0x328(%r1)
+       alg     %r0,__LC_SYSTEM_TIMER
+       stg     %r0,__LC_SYSTEM_TIMER
+       mvc     __LC_LAST_UPDATE_TIMER(8),0x328(%r1)
+       lg      %r0,__LC_LAST_UPDATE_CLOCK
+       slg     %r0,__SF_EMPTY(%r15)
+       alg     %r0,__LC_STEAL_TIMER
+       stg     %r0,__LC_STEAL_TIMER
+       mvc     __LC_LAST_UPDATE_CLOCK(8),__SF_EMPTY(%r15)
+
        /* Activate DAT */
        stosm   __SF_EMPTY(%r15),0x04
 
@@ -159,8 +172,7 @@ pgm_check_entry:
        larl    %r1,.Lresume_cpu                /* Resume CPU address: r2 */
        stap    0(%r1)
        llgh    %r2,0(%r1)
-       lghi    %r3,0x1000
-       llgh    %r1,__LC_CPU_ADDRESS(%r3)       /* Suspend CPU address: r1 */
+       llgh    %r1,__LC_CPU_ADDRESS(%r0)       /* Suspend CPU address: r1 */
        cgr     %r1,%r2
        je      restore_registers               /* r1 = r2 -> nothing to do */
        larl    %r4,.Lrestart_suspend_psw       /* Set new restart PSW */
@@ -187,6 +199,7 @@ pgm_check_entry:
        brc     2,4b                    /* busy, try again */
 5:
        sigp    %r9,%r2,__SIGP_STOP     /* stop resume (current) CPU */
+       brc     2,5b                    /* busy, try again */
 6:     j       6b
 
 restart_suspend:
@@ -194,14 +207,18 @@ restart_suspend:
        llgh    %r2,0(%r1)
 7:
        sigp    %r9,%r2,__SIGP_SENSE    /* Wait for resume CPU */
+       brc     8,7b                    /* accepted, status 0, still running */
        brc     2,7b                    /* busy, try again */
        tmll    %r9,0x40                /* Test if resume CPU is stopped */
        jz      7b
 
 restore_registers:
        /* Restore registers */
-       lghi    %r13,0x1000             /* %r1 = pointer to save arae */
+       lghi    %r13,0x1000             /* %r1 = pointer to save area */
 
+       /* Ignore time spent in suspended state. */
+       llgf    %r1,0x318(%r13)
+       stck    __LC_LAST_UPDATE_CLOCK(%r1)
        spt     0x328(%r13)             /* reprogram timer */
        //sckc  0x330(%r13)             /* set clock comparator */
 
@@ -229,9 +246,6 @@ restore_registers:
        /* Load old stack */
        lg      %r15,0x2f8(%r13)
 
-       /* Pointer to save area */
-       lghi    %r13,0x1000
-
        /* Restore prefix register */
        spx     0x318(%r13)
 
index 45a3e9a..adfb32a 100644 (file)
@@ -247,6 +247,13 @@ int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp)
        }
 
        /*
+        * Put vDSO base into mm struct. We need to do this before calling
+        * install_special_mapping or the perf counter mmap tracking code
+        * will fail to recognise it as a vDSO (since arch_vma_name fails).
+        */
+       current->mm->context.vdso_base = vdso_base;
+
+       /*
         * our vma flags don't have VM_WRITE so by default, the process
         * isn't allowed to write those pages.
         * gdb can break that with ptrace interface, and thus trigger COW
@@ -267,14 +274,7 @@ int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp)
                                     VM_ALWAYSDUMP,
                                     vdso_pagelist);
        if (rc)
-               goto out_up;
-
-       /* Put vDSO base into mm struct */
-       current->mm->context.vdso_base = vdso_base;
-
-       up_write(&mm->mmap_sem);
-       return 0;
-
+               current->mm->context.vdso_base = 0;
 out_up:
        up_write(&mm->mmap_sem);
        return rc;
index bc15ef9..a68ac10 100644 (file)
@@ -51,6 +51,7 @@ SECTIONS
 
        . = ALIGN(PAGE_SIZE);
        _eshared = .;           /* End of shareable data */
+       _sdata = .;             /* Start of data section */
 
        EXCEPTION_TABLE(16) :data
 
index ec5eee7..06cce82 100644 (file)
@@ -58,7 +58,7 @@ int kvm_s390_inject_vcpu(struct kvm_vcpu *vcpu,
 int kvm_s390_inject_program_int(struct kvm_vcpu *vcpu, u16 code);
 int kvm_s390_inject_sigp_stop(struct kvm_vcpu *vcpu, int action);
 
-static inline int kvm_s390_vcpu_get_memsize(struct kvm_vcpu *vcpu)
+static inline long kvm_s390_vcpu_get_memsize(struct kvm_vcpu *vcpu)
 {
        return vcpu->arch.sie_block->gmslm
                - vcpu->arch.sie_block->gmsor
index 97c1eca..752b362 100644 (file)
@@ -25,13 +25,13 @@ void __delay(unsigned long loops)
        asm volatile("0: brct %0,0b" : : "d" ((loops/2) + 1));
 }
 
-static void __udelay_disabled(unsigned long usecs)
+static void __udelay_disabled(unsigned long long usecs)
 {
        unsigned long mask, cr0, cr0_saved;
        u64 clock_saved;
 
        clock_saved = local_tick_disable();
-       set_clock_comparator(get_clock() + ((u64) usecs << 12));
+       set_clock_comparator(get_clock() + (usecs << 12));
        __ctl_store(cr0_saved, 0, 0);
        cr0 = (cr0_saved & 0xffff00e0) | 0x00000800;
        __ctl_load(cr0 , 0, 0);
@@ -46,20 +46,25 @@ static void __udelay_disabled(unsigned long usecs)
        set_clock_comparator(S390_lowcore.clock_comparator);
 }
 
-static void __udelay_enabled(unsigned long usecs)
+static void __udelay_enabled(unsigned long long usecs)
 {
        unsigned long mask;
-       u64 end, time;
+       u64 clock_saved;
+       u64 end;
 
        mask = psw_kernel_bits | PSW_MASK_WAIT | PSW_MASK_EXT | PSW_MASK_IO;
-       end = get_clock() + ((u64) usecs << 12);
+       end = get_clock() + (usecs << 12);
        do {
-               time = end < S390_lowcore.clock_comparator ?
-                       end : S390_lowcore.clock_comparator;
-               set_clock_comparator(time);
+               clock_saved = 0;
+               if (end < S390_lowcore.clock_comparator) {
+                       clock_saved = local_tick_disable();
+                       set_clock_comparator(end);
+               }
                trace_hardirqs_on();
                __load_psw_mask(mask);
                local_irq_disable();
+               if (clock_saved)
+                       local_tick_enable(clock_saved);
        } while (get_clock() < end);
        set_clock_comparator(S390_lowcore.clock_comparator);
 }
@@ -67,7 +72,7 @@ static void __udelay_enabled(unsigned long usecs)
 /*
  * Waits for 'usecs' microseconds using the TOD clock comparator.
  */
-void __udelay(unsigned long usecs)
+void __udelay(unsigned long long usecs)
 {
        unsigned long flags;
 
@@ -101,11 +106,11 @@ EXPORT_SYMBOL(__udelay);
  * Simple udelay variant. To be used on startup and reboot
  * when the interrupt handler isn't working.
  */
-void udelay_simple(unsigned long usecs)
+void udelay_simple(unsigned long long usecs)
 {
        u64 end;
 
-       end = get_clock() + ((u64) usecs << 12);
+       end = get_clock() + (usecs << 12);
        while (get_clock() < end)
                cpu_relax();
 }
index 3f15aaf..58da3f4 100644 (file)
@@ -36,7 +36,7 @@ static size_t copy_from_user_mvcos(size_t size, const void __user *ptr, void *x)
        tmp1 = -4096UL;
        asm volatile(
                "0: .insn ss,0xc80000000000,0(%0,%2),0(%1),0\n"
-               "   jz    7f\n"
+               "9: jz    7f\n"
                "1:"ALR"  %0,%3\n"
                "  "SLR"  %1,%3\n"
                "  "SLR"  %2,%3\n"
@@ -47,7 +47,7 @@ static size_t copy_from_user_mvcos(size_t size, const void __user *ptr, void *x)
                "  "CLR"  %0,%4\n"      /* copy crosses next page boundary? */
                "   jnh   4f\n"
                "3: .insn ss,0xc80000000000,0(%4,%2),0(%1),0\n"
-               "  "SLR"  %0,%4\n"
+               "10:"SLR"  %0,%4\n"
                "  "ALR"  %2,%4\n"
                "4:"LHI"  %4,-1\n"
                "  "ALR"  %4,%0\n"      /* copy remaining size, subtract 1 */
@@ -61,7 +61,7 @@ static size_t copy_from_user_mvcos(size_t size, const void __user *ptr, void *x)
                "   j     8f\n"
                "7:"SLR"  %0,%0\n"
                "8: \n"
-               EX_TABLE(0b,2b) EX_TABLE(3b,4b)
+               EX_TABLE(0b,2b) EX_TABLE(3b,4b) EX_TABLE(9b,2b) EX_TABLE(10b,4b)
                : "+a" (size), "+a" (ptr), "+a" (x), "+a" (tmp1), "=a" (tmp2)
                : "d" (reg0) : "cc", "memory");
        return size;
@@ -82,7 +82,7 @@ static size_t copy_to_user_mvcos(size_t size, void __user *ptr, const void *x)
        tmp1 = -4096UL;
        asm volatile(
                "0: .insn ss,0xc80000000000,0(%0,%1),0(%2),0\n"
-               "   jz    4f\n"
+               "6: jz    4f\n"
                "1:"ALR"  %0,%3\n"
                "  "SLR"  %1,%3\n"
                "  "SLR"  %2,%3\n"
@@ -93,11 +93,11 @@ static size_t copy_to_user_mvcos(size_t size, void __user *ptr, const void *x)
                "  "CLR"  %0,%4\n"      /* copy crosses next page boundary? */
                "   jnh   5f\n"
                "3: .insn ss,0xc80000000000,0(%4,%1),0(%2),0\n"
-               "  "SLR"  %0,%4\n"
+               "7:"SLR"  %0,%4\n"
                "   j     5f\n"
                "4:"SLR"  %0,%0\n"
                "5: \n"
-               EX_TABLE(0b,2b) EX_TABLE(3b,5b)
+               EX_TABLE(0b,2b) EX_TABLE(3b,5b) EX_TABLE(6b,2b) EX_TABLE(7b,5b)
                : "+a" (size), "+a" (ptr), "+a" (x), "+a" (tmp1), "=a" (tmp2)
                : "d" (reg0) : "cc", "memory");
        return size;
index d2ffbad..07deaee 100644 (file)
@@ -36,12 +36,12 @@ size_t copy_from_user_std(size_t size, const void __user *ptr, void *x)
        tmp1 = -256UL;
        asm volatile(
                "0: mvcp  0(%0,%2),0(%1),%3\n"
-               "   jz    8f\n"
+               "10:jz    8f\n"
                "1:"ALR"  %0,%3\n"
                "   la    %1,256(%1)\n"
                "   la    %2,256(%2)\n"
                "2: mvcp  0(%0,%2),0(%1),%3\n"
-               "   jnz   1b\n"
+               "11:jnz   1b\n"
                "   j     8f\n"
                "3: la    %4,255(%1)\n" /* %4 = ptr + 255 */
                "  "LHI"  %3,-4096\n"
@@ -50,7 +50,7 @@ size_t copy_from_user_std(size_t size, const void __user *ptr, void *x)
                "  "CLR"  %0,%4\n"      /* copy crosses next page boundary? */
                "   jnh   5f\n"
                "4: mvcp  0(%4,%2),0(%1),%3\n"
-               "  "SLR"  %0,%4\n"
+               "12:"SLR"  %0,%4\n"
                "  "ALR"  %2,%4\n"
                "5:"LHI"  %4,-1\n"
                "  "ALR"  %4,%0\n"      /* copy remaining size, subtract 1 */
@@ -65,6 +65,7 @@ size_t copy_from_user_std(size_t size, const void __user *ptr, void *x)
                "8:"SLR"  %0,%0\n"
                "9: \n"
                EX_TABLE(0b,3b) EX_TABLE(2b,3b) EX_TABLE(4b,5b)
+               EX_TABLE(10b,3b) EX_TABLE(11b,3b) EX_TABLE(12b,5b)
                : "+a" (size), "+a" (ptr), "+a" (x), "+a" (tmp1), "=a" (tmp2)
                : : "cc", "memory");
        return size;
@@ -85,12 +86,12 @@ size_t copy_to_user_std(size_t size, void __user *ptr, const void *x)
        tmp1 = -256UL;
        asm volatile(
                "0: mvcs  0(%0,%1),0(%2),%3\n"
-               "   jz    5f\n"
+               "7: jz    5f\n"
                "1:"ALR"  %0,%3\n"
                "   la    %1,256(%1)\n"
                "   la    %2,256(%2)\n"
                "2: mvcs  0(%0,%1),0(%2),%3\n"
-               "   jnz   1b\n"
+               "8: jnz   1b\n"
                "   j     5f\n"
                "3: la    %4,255(%1)\n" /* %4 = ptr + 255 */
                "  "LHI"  %3,-4096\n"
@@ -99,11 +100,12 @@ size_t copy_to_user_std(size_t size, void __user *ptr, const void *x)
                "  "CLR"  %0,%4\n"      /* copy crosses next page boundary? */
                "   jnh   6f\n"
                "4: mvcs  0(%4,%1),0(%2),%3\n"
-               "  "SLR"  %0,%4\n"
+               "9:"SLR"  %0,%4\n"
                "   j     6f\n"
                "5:"SLR"  %0,%0\n"
                "6: \n"
                EX_TABLE(0b,3b) EX_TABLE(2b,3b) EX_TABLE(4b,6b)
+               EX_TABLE(7b,3b) EX_TABLE(8b,3b) EX_TABLE(9b,6b)
                : "+a" (size), "+a" (ptr), "+a" (x), "+a" (tmp1), "=a" (tmp2)
                : : "cc", "memory");
        return size;
index c60bfb3..2757c56 100644 (file)
@@ -279,7 +279,10 @@ int s390_enable_sie(void)
        /* lets check if we are allowed to replace the mm */
        task_lock(tsk);
        if (!tsk->mm || atomic_read(&tsk->mm->mm_users) > 1 ||
-           tsk->mm != tsk->active_mm || !hlist_empty(&tsk->mm->ioctx_list)) {
+#ifdef CONFIG_AIO
+           !hlist_empty(&tsk->mm->ioctx_list) ||
+#endif
+           tsk->mm != tsk->active_mm) {
                task_unlock(tsk);
                return -EINVAL;
        }
@@ -295,7 +298,10 @@ int s390_enable_sie(void)
        /* Now lets check again if something happened */
        task_lock(tsk);
        if (!tsk->mm || atomic_read(&tsk->mm->mm_users) > 1 ||
-           tsk->mm != tsk->active_mm || !hlist_empty(&tsk->mm->ioctx_list)) {
+#ifdef CONFIG_AIO
+           !hlist_empty(&tsk->mm->ioctx_list) ||
+#endif
+           tsk->mm != tsk->active_mm) {
                mmput(mm);
                task_unlock(tsk);
                return -EINVAL;
index b940424..88cdeb9 100644 (file)
@@ -37,7 +37,6 @@ config SUPERH32
        select HAVE_FTRACE_MCOUNT_RECORD
        select HAVE_DYNAMIC_FTRACE
        select HAVE_FUNCTION_TRACE_MCOUNT_TEST
-       select HAVE_FTRACE_SYSCALLS
        select HAVE_FUNCTION_GRAPH_TRACER
        select HAVE_ARCH_KGDB
        select ARCH_HIBERNATION_POSSIBLE if MMU
@@ -122,6 +121,9 @@ config SYS_SUPPORTS_APM_EMULATION
        bool
        select ARCH_SUSPEND_POSSIBLE
 
+config SYS_SUPPORTS_HUGETLBFS
+       bool
+
 config SYS_SUPPORTS_SMP
        bool
 
@@ -196,6 +198,7 @@ config CPU_SH4
        select CPU_HAS_SR_RB
        select CPU_HAS_FPU if !CPU_SH4AL_DSP
        select SYS_SUPPORTS_TMU
+       select SYS_SUPPORTS_HUGETLBFS if MMU
 
 config CPU_SH4A
        bool
@@ -210,6 +213,7 @@ config CPU_SH5
        bool
        select CPU_HAS_FPU
        select SYS_SUPPORTS_TMU
+       select SYS_SUPPORTS_HUGETLBFS if MMU
 
 config CPU_SHX2
        bool
index fc51a91..66e40aa 100644 (file)
@@ -199,7 +199,7 @@ endif
 libs-$(CONFIG_SUPERH32)                := arch/sh/lib/ $(libs-y)
 libs-$(CONFIG_SUPERH64)                := arch/sh/lib64/ $(libs-y)
 
-BOOT_TARGETS = uImage uImage.bz2 uImage.gz uImage.lzma uImage.srec \
+BOOT_TARGETS = uImage uImage.bz2 uImage.gz uImage.lzma uImage.srec uImage.bin \
               zImage vmlinux.srec romImage
 PHONY += maketools $(BOOT_TARGETS) FORCE
 
@@ -225,6 +225,7 @@ define archhelp
        @echo '  vmlinux.srec              - Create an ELF S-record'
        @echo '* uImage                    - Alias to bootable U-Boot image'
        @echo '  uImage.srec               - Create an S-record for U-Boot'
+       @echo '  uImage.bin                - Kernel-only image for U-Boot (bin)'
        @echo '* uImage.gz                 - Kernel-only image for U-Boot (gzip)'
        @echo '  uImage.bz2                - Kernel-only image for U-Boot (bzip2)'
        @echo '  uImage.lzma               - Kernel-only image for U-Boot (lzma)'
index 0a37c8b..99ffc5f 100644 (file)
@@ -205,8 +205,6 @@ static void __init setup_port_multiplexing(void)
 
 static void __init mpr2_setup(char **cmdline_p)
 {
-       __set_io_port_base(0xa0000000);
-
        /* set Pin Select Register A:
         * /PCC_CD1, /PCC_CD2,  PCC_BVD1, PCC_BVD2,
         * /IOIS16,  IRQ4,      IRQ5,     USB1d_SUSPEND
index ebe9922..a4b7402 100644 (file)
@@ -42,8 +42,6 @@ static void __init dreamcast_setup(char **cmdline_p)
        /* Acknowledge any previous events */
        /* XXX */
 
-       __set_io_port_base(0xa0000000);
-
        /* Assign all virtual IRQs to the System ASIC int. handler */
        for (i = HW_EVENT_IRQ_BASE; i < HW_EVENT_IRQ_MAX; i++)
                set_irq_chip_and_handler(i, &systemasic_int,
index 5f9881e..3b1ceb4 100644 (file)
@@ -18,6 +18,7 @@
 #include <linux/delay.h>
 #include <linux/usb/r8a66597.h>
 #include <linux/i2c.h>
+#include <linux/i2c/tsc2007.h>
 #include <linux/input.h>
 #include <video/sh_mobile_lcdc.h>
 #include <media/sh_mobile_ceu.h>
  *  0x1800_0000  MFI              16bit
  */
 
+/* SWITCH
+ *------------------------------
+ * DS2[1] = FlashROM write protect  ON     : write protect
+ *                                  OFF    : No write protect
+ * DS2[2] = RMII / TS, SCIF         ON     : RMII
+ *                                  OFF    : TS, SCIF3
+ * DS2[3] = Camera / Video          ON     : Camera
+ *                                  OFF    : NTSC/PAL (IN)
+ * DS2[5] = NTSC_OUT Clock          ON     : On board OSC
+ *                                  OFF    : SH7724 DV_CLK
+ * DS2[6-7] = MMC / SD              ON-OFF : SD
+ *                                  OFF-ON : MMC
+ */
+
 /* Heartbeat */
 static unsigned char led_pos[] = { 0, 1, 2, 3 };
 static struct heartbeat_data heartbeat_data = {
@@ -70,7 +85,7 @@ static struct mtd_partition nor_flash_partitions[] = {
                .name = "boot loader",
                .offset = 0,
                .size = (5 * 1024 * 1024),
-               .mask_flags = MTD_CAP_ROM,
+               .mask_flags = MTD_WRITEABLE,  /* force read-only */
        }, {
                .name = "free-area",
                .offset = MTDPART_OFS_APPEND,
@@ -376,6 +391,43 @@ static struct platform_device keysc_device = {
        },
 };
 
+/* TouchScreen */
+#define IRQ0 32
+static int ts_get_pendown_state(void)
+{
+       int val = 0;
+       gpio_free(GPIO_FN_INTC_IRQ0);
+       gpio_request(GPIO_PTZ0, NULL);
+       gpio_direction_input(GPIO_PTZ0);
+
+       val = gpio_get_value(GPIO_PTZ0);
+
+       gpio_free(GPIO_PTZ0);
+       gpio_request(GPIO_FN_INTC_IRQ0, NULL);
+
+       return val ? 0 : 1;
+}
+
+static int ts_init(void)
+{
+       gpio_request(GPIO_FN_INTC_IRQ0, NULL);
+       return 0;
+}
+
+struct tsc2007_platform_data tsc2007_info = {
+       .model                  = 2007,
+       .x_plate_ohms           = 180,
+       .get_pendown_state      = ts_get_pendown_state,
+       .init_platform_hw       = ts_init,
+};
+
+static struct i2c_board_info ts_i2c_clients = {
+       I2C_BOARD_INFO("tsc2007", 0x48),
+       .type           = "tsc2007",
+       .platform_data  = &tsc2007_info,
+       .irq            = IRQ0,
+};
+
 static struct platform_device *ecovec_devices[] __initdata = {
        &heartbeat_device,
        &nor_flash_device,
@@ -460,6 +512,11 @@ static void __init sh_eth_init(void)
 #define IODRIVEA  0xA405018A
 static int __init arch_setup(void)
 {
+       /* enable STATUS0, STATUS2 and PDSTATUS */
+       gpio_request(GPIO_FN_STATUS0, NULL);
+       gpio_request(GPIO_FN_STATUS2, NULL);
+       gpio_request(GPIO_FN_PDSTATUS, NULL);
+
        /* enable SCIFA0 */
        gpio_request(GPIO_FN_SCIF0_TXD, NULL);
        gpio_request(GPIO_FN_SCIF0_RXD, NULL);
@@ -590,6 +647,10 @@ static int __init arch_setup(void)
                 */
                gpio_request(GPIO_PTF4, NULL);
                gpio_direction_output(GPIO_PTF4, 1);
+
+               /* enable TouchScreen */
+               i2c_register_board_info(0, &ts_i2c_clients, 1);
+               set_irq_type(IRQ0, IRQ_TYPE_LEVEL_LOW);
        }
 
        /* enable CEU0 */
index 25cdf73..5280131 100644 (file)
@@ -14,7 +14,6 @@
  */
 #include <linux/module.h>
 #include <linux/init.h>
-#include <linux/smp_lock.h>
 #include <linux/kdev_t.h>
 #include <linux/cdev.h>
 #include <linux/fs.h>
@@ -35,7 +34,7 @@ static int gio_open(struct inode *inode, struct file *filp)
        int minor;
        int ret = -ENOENT;
 
-       lock_kernel();
+       preempt_disable();
        minor = MINOR(inode->i_rdev);
        if (minor < DEVCOUNT) {
                if (openCnt > 0) {
@@ -45,7 +44,7 @@ static int gio_open(struct inode *inode, struct file *filp)
                        ret = 0;
                }
        }
-       unlock_kernel();
+       preempt_enable();
        return ret;
 }
 
@@ -60,8 +59,7 @@ static int gio_close(struct inode *inode, struct file *filp)
        return 0;
 }
 
-static int gio_ioctl(struct inode *inode, struct file *filp,
-                            unsigned int cmd, unsigned long arg)
+static long gio_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
 {
        unsigned int data;
        static unsigned int addr = 0;
@@ -129,7 +127,7 @@ static const struct file_operations gio_fops = {
        .owner = THIS_MODULE,
        .open = gio_open,       /* open */
        .release = gio_close,   /* release */
-       .ioctl = gio_ioctl,     /* ioctl */
+       .unlocked_ioctl = gio_ioctl,
 };
 
 static int __init gio_init(void)
index 4af3a77..c37617e 100644 (file)
 #include <linux/types.h>
 #include <linux/platform_device.h>
 #include <linux/interrupt.h>
-#include <linux/mtd/mtd.h>
-#include <linux/mtd/partitions.h>
-#include <linux/mtd/physmap.h>
-#include <linux/mtd/map.h>
 #include <linux/smsc911x.h>
 #include <linux/gpio.h>
 #include <linux/leds.h>
index af64d03..a5c0df7 100644 (file)
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/partitions.h>
 #include <linux/mtd/physmap.h>
+#ifdef CONFIG_MTD
 #include <linux/mtd/map.h>
+#endif
 #include <asm/machvec.h>
 #include <asm/io.h>
 
-static const char *probes[] = { "cmdlinepart", NULL };
-
-static struct mtd_partition *parsed_partitions;
-
 static struct mtd_partition rsk_partitions[] = {
        {
                .name           = "Bootloader",
@@ -41,6 +39,8 @@ static struct mtd_partition rsk_partitions[] = {
 };
 
 static struct physmap_flash_data flash_data = {
+       .parts          = rsk_partitions,
+       .nr_parts       = ARRAY_SIZE(rsk_partitions),
        .width          = 2,
 };
 
@@ -60,7 +60,8 @@ static struct platform_device flash_device = {
        },
 };
 
-static struct mtd_info *flash_mtd;
+#ifdef CONFIG_MTD
+static const char *probes[] = { "cmdlinepart", NULL };
 
 static struct map_info rsk_flash_map = {
        .name           = "RSK+ Flash",
@@ -68,6 +69,10 @@ static struct map_info rsk_flash_map = {
        .bankwidth      = 2,
 };
 
+static struct mtd_info *flash_mtd;
+
+static struct mtd_partition *parsed_partitions;
+
 static void __init set_mtd_partitions(void)
 {
        int nr_parts = 0;
@@ -77,14 +82,14 @@ static void __init set_mtd_partitions(void)
        nr_parts = parse_mtd_partitions(flash_mtd, probes,
                                        &parsed_partitions, 0);
        /* If there is no partition table, used the hard coded table */
-       if (nr_parts <= 0) {
-               flash_data.parts = rsk_partitions;
-               flash_data.nr_parts = ARRAY_SIZE(rsk_partitions);
-       } else {
+       if (nr_parts > 0) {
                flash_data.nr_parts = nr_parts;
                flash_data.parts = parsed_partitions;
        }
 }
+#else
+static inline void set_mtd_partitions(void) {}
+#endif
 
 static struct platform_device *rsk_devices[] __initdata = {
        &flash_device,
index a131687..cb8cf55 100644 (file)
@@ -20,11 +20,12 @@ CONFIG_BOOT_LINK_OFFSET     ?= 0x00800000
 CONFIG_ZERO_PAGE_OFFSET        ?= 0x00001000
 CONFIG_ENTRY_OFFSET    ?= 0x00001000
 
+suffix-y := bin
 suffix-$(CONFIG_KERNEL_GZIP)  := gz
 suffix-$(CONFIG_KERNEL_BZIP2) := bz2
 suffix-$(CONFIG_KERNEL_LZMA)  := lzma
 
-targets := zImage vmlinux.srec romImage uImage uImage.srec uImage.gz uImage.bz2 uImage.lzma
+targets := zImage vmlinux.srec romImage uImage uImage.srec uImage.gz uImage.bz2 uImage.lzma uImage.bin
 extra-y += vmlinux.bin vmlinux.bin.gz vmlinux.bin.bz2 vmlinux.bin.lzma
 subdir- := compressed romimage
 
@@ -88,6 +89,9 @@ $(obj)/uImage.gz: $(obj)/vmlinux.bin.gz
 $(obj)/uImage.lzma: $(obj)/vmlinux.bin.lzma
        $(call if_changed,uimage,lzma)
 
+$(obj)/uImage.bin: $(obj)/vmlinux.bin
+       $(call if_changed,uimage,none)
+
 OBJCOPYFLAGS_vmlinux.srec := -I binary -O srec
 $(obj)/vmlinux.srec: $(obj)/compressed/vmlinux
        $(call if_changed,objcopy)
index 0151933..bb407ef 100644 (file)
@@ -152,8 +152,6 @@ call_do_page_fault:
        mov.l   1f, r0
        mov.l   @r0, r6
 
-       sti
-
        mov.l   3f, r0
        mov.l   4f, r1
        mov     r15, r4
index 03b3616..2d07084 100644 (file)
@@ -20,6 +20,7 @@
 #include <linux/list.h>
 #include <linux/mempool.h>
 #include <linux/mm.h>
+#include <linux/ftrace.h>
 #include <asm/dwarf.h>
 #include <asm/unwinder.h>
 #include <asm/sections.h>
@@ -557,6 +558,27 @@ struct dwarf_frame * dwarf_unwind_stack(unsigned long pc,
        if (!pc && !prev)
                pc = (unsigned long)current_text_addr();
 
+#ifdef CONFIG_FUNCTION_GRAPH_TRACER
+       /*
+        * If our stack has been patched by the function graph tracer
+        * then we might see the address of return_to_handler() where we
+        * expected to find the real return address.
+        */
+       if (pc == (unsigned long)&return_to_handler) {
+               int index = current->curr_ret_stack;
+
+               /*
+                * We currently have no way of tracking how many
+                * return_to_handler()'s we've seen. If there is more
+                * than one patched return address on our stack,
+                * complain loudly.
+                */
+               WARN_ON(index > 0);
+
+               pc = current->ret_stack[index].ret;
+       }
+#endif
+
        frame = mempool_alloc(dwarf_frame_pool, GFP_ATOMIC);
        if (!frame) {
                printk(KERN_ERR "Unable to allocate a dwarf frame\n");
index 68d9223..3eb8493 100644 (file)
@@ -121,7 +121,7 @@ noresched:
 ENTRY(resume_userspace)
        ! r8: current_thread_info
        cli
-       TRACE_IRQS_OfF
+       TRACE_IRQS_OFF
        mov.l   @(TI_FLAGS,r8), r0              ! current_thread_info->flags
        tst     #(_TIF_WORK_MASK & 0xff), r0
        bt/s    __restore_all
index a3dcc6d..2c48e26 100644 (file)
@@ -291,31 +291,48 @@ struct syscall_metadata *syscall_nr_to_meta(int nr)
        return syscalls_metadata[nr];
 }
 
-void arch_init_ftrace_syscalls(void)
+int syscall_name_to_nr(char *name)
+{
+       int i;
+
+       if (!syscalls_metadata)
+               return -1;
+       for (i = 0; i < NR_syscalls; i++)
+               if (syscalls_metadata[i])
+                       if (!strcmp(syscalls_metadata[i]->name, name))
+                               return i;
+       return -1;
+}
+
+void set_syscall_enter_id(int num, int id)
+{
+       syscalls_metadata[num]->enter_id = id;
+}
+
+void set_syscall_exit_id(int num, int id)
+{
+       syscalls_metadata[num]->exit_id = id;
+}
+
+static int __init arch_init_ftrace_syscalls(void)
 {
        int i;
        struct syscall_metadata *meta;
        unsigned long **psys_syscall_table = &sys_call_table;
-       static atomic_t refs;
-
-       if (atomic_inc_return(&refs) != 1)
-               goto end;
 
        syscalls_metadata = kzalloc(sizeof(*syscalls_metadata) *
                                        FTRACE_SYSCALL_MAX, GFP_KERNEL);
        if (!syscalls_metadata) {
                WARN_ON(1);
-               return;
+               return -ENOMEM;
        }
 
        for (i = 0; i < FTRACE_SYSCALL_MAX; i++) {
                meta = find_syscall_meta(psys_syscall_table[i]);
                syscalls_metadata[i] = meta;
        }
-       return;
 
-       /* Paranoid: avoid overflow */
-end:
-       atomic_dec(&refs);
+       return 0;
 }
+arch_initcall(arch_init_ftrace_syscalls);
 #endif /* CONFIG_FTRACE_SYSCALLS */
index 4ff5072..b8fa652 100644 (file)
@@ -147,6 +147,9 @@ void generic_outsl(unsigned long port, const void *src, unsigned long count)
 
 void __iomem *generic_ioport_map(unsigned long addr, unsigned int size)
 {
+       if (PXSEG(addr) >= P1SEG)
+               return (void __iomem *)addr;
+
        return (void __iomem *)(addr + generic_io_base);
 }
 
index 7cb933b..eac7da7 100644 (file)
@@ -11,6 +11,7 @@
 #include <linux/module.h>
 #include <linux/kernel_stat.h>
 #include <linux/seq_file.h>
+#include <linux/ftrace.h>
 #include <asm/processor.h>
 #include <asm/machvec.h>
 #include <asm/uaccess.h>
@@ -106,7 +107,7 @@ static union irq_ctx *hardirq_ctx[NR_CPUS] __read_mostly;
 static union irq_ctx *softirq_ctx[NR_CPUS] __read_mostly;
 #endif
 
-asmlinkage int do_IRQ(unsigned int irq, struct pt_regs *regs)
+asmlinkage __irq_entry int do_IRQ(unsigned int irq, struct pt_regs *regs)
 {
        struct pt_regs *old_regs = set_irq_regs(regs);
 #ifdef CONFIG_IRQSTACKS
index 548f660..cbce639 100644 (file)
@@ -14,6 +14,7 @@
 #include <linux/string.h>
 #include <asm/machvec.h>
 #include <asm/sections.h>
+#include <asm/addrspace.h>
 #include <asm/setup.h>
 #include <asm/io.h>
 #include <asm/irq.h>
@@ -133,4 +134,6 @@ void __init sh_mv_setup(void)
 
        if (!sh_mv.mv_nr_irqs)
                sh_mv.mv_nr_irqs = NR_IRQS;
+
+       __set_io_port_base(P2SEG);
 }
index f9d44f8..99b4fb5 100644 (file)
@@ -549,6 +549,8 @@ static int show_cpuinfo(struct seq_file *m, void *v)
 
        if (cpu == 0)
                seq_printf(m, "machine\t\t: %s\n", get_system_type());
+       else
+               seq_printf(m, "\n");
 
        seq_printf(m, "processor\t: %d\n", cpu);
        seq_printf(m, "cpu family\t: %s\n", init_utsname()->machine);
index 8dbe26b..444cce3 100644 (file)
@@ -84,6 +84,21 @@ DECLARE_EXPORT(__movstrSI60);
 DECLARE_EXPORT(__movstr_i4_even);
 DECLARE_EXPORT(__movstr_i4_odd);
 DECLARE_EXPORT(__movstrSI12_i4);
+DECLARE_EXPORT(__movmem);
+DECLARE_EXPORT(__movmemSI8);
+DECLARE_EXPORT(__movmemSI12);
+DECLARE_EXPORT(__movmemSI16);
+DECLARE_EXPORT(__movmemSI20);
+DECLARE_EXPORT(__movmemSI24);
+DECLARE_EXPORT(__movmemSI28);
+DECLARE_EXPORT(__movmemSI32);
+DECLARE_EXPORT(__movmemSI36);
+DECLARE_EXPORT(__movmemSI40);
+DECLARE_EXPORT(__movmemSI44);
+DECLARE_EXPORT(__movmemSI48);
+DECLARE_EXPORT(__movmemSI52);
+DECLARE_EXPORT(__movmemSI56);
+DECLARE_EXPORT(__movmemSI60);
 DECLARE_EXPORT(__movmem_i4_even);
 DECLARE_EXPORT(__movmem_i4_odd);
 DECLARE_EXPORT(__movmemSI12_i4);
index 6729703..3db3742 100644 (file)
@@ -145,7 +145,7 @@ static inline int restore_sigcontext_fpu(struct sigcontext __user *sc)
 {
        struct task_struct *tsk = current;
 
-       if (!(current_cpu_data.flags & CPU_HAS_FPU))
+       if (!(boot_cpu_data.flags & CPU_HAS_FPU))
                return 0;
 
        set_used_math();
@@ -158,7 +158,7 @@ static inline int save_sigcontext_fpu(struct sigcontext __user *sc,
 {
        struct task_struct *tsk = current;
 
-       if (!(current_cpu_data.flags & CPU_HAS_FPU))
+       if (!(boot_cpu_data.flags & CPU_HAS_FPU))
                return 0;
 
        if (!used_math()) {
@@ -199,7 +199,7 @@ restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc, int *r0_p
 #undef COPY
 
 #ifdef CONFIG_SH_FPU
-       if (current_cpu_data.flags & CPU_HAS_FPU) {
+       if (boot_cpu_data.flags & CPU_HAS_FPU) {
                int owned_fp;
                struct task_struct *tsk = current;
 
@@ -472,6 +472,7 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
                err |= __put_user(OR_R0_R0, &frame->retcode[6]);
                err |= __put_user((__NR_rt_sigreturn), &frame->retcode[7]);
                regs->pr = (unsigned long) frame->retcode;
+               flush_icache_range(regs->pr, regs->pr + sizeof(frame->retcode));
        }
 
        if (err)
@@ -497,8 +498,6 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
        pr_debug("SIG deliver (%s:%d): sp=%p pc=%08lx pr=%08lx\n",
                 current->comm, task_pid_nr(current), frame, regs->pc, regs->pr);
 
-       flush_icache_range(regs->pr, regs->pr + sizeof(frame->retcode));
-
        return 0;
 
 give_sigsegv:
index 442d8d4..160db10 100644 (file)
@@ -35,6 +35,8 @@ static inline void __init smp_store_cpu_info(unsigned int cpu)
 {
        struct sh_cpuinfo *c = cpu_data + cpu;
 
+       memcpy(c, &boot_cpu_data, sizeof(struct sh_cpuinfo));
+
        c->loops_per_jiffy = loops_per_jiffy;
 }
 
index 69bb165..7a2ee3a 100644 (file)
@@ -25,6 +25,7 @@
 #include <linux/kexec.h>
 #include <linux/limits.h>
 #include <linux/proc_fs.h>
+#include <linux/sysfs.h>
 #include <asm/system.h>
 #include <asm/uaccess.h>
 #include <asm/fpu.h>
@@ -54,8 +55,8 @@ static unsigned long se_multi;
 /* bitfield: 1: warn 2: fixup 4: signal -> combinations 2|4 && 1|2|4 are not
    valid! */
 static int se_usermode = 3;
-/* 0: no warning 1: print a warning message */
-static int se_kernmode_warn = 1;
+/* 0: no warning 1: print a warning message, disabled by default */
+static int se_kernmode_warn;
 
 #ifdef CONFIG_PROC_FS
 static const char *se_usermode_action[] = {
@@ -159,12 +160,12 @@ void die(const char * str, struct pt_regs * regs, long err)
 
        oops_enter();
 
-       console_verbose();
        spin_lock_irq(&die_lock);
+       console_verbose();
        bust_spinlocks(1);
 
        printk("%s: %04lx [#%d]\n", str, err & 0xffff, ++die_counter);
-
+       sysfs_printk_last_file();
        print_modules();
        show_regs(regs);
 
@@ -180,6 +181,7 @@ void die(const char * str, struct pt_regs * regs, long err)
        bust_spinlocks(0);
        add_taint(TAINT_DIE);
        spin_unlock_irq(&die_lock);
+       oops_exit();
 
        if (kexec_should_crash(current))
                crash_kexec(regs);
@@ -190,7 +192,6 @@ void die(const char * str, struct pt_regs * regs, long err)
        if (panic_on_oops)
                panic("Fatal exception");
 
-       oops_exit();
        do_exit(SIGSEGV);
 }
 
index 64dc1ad..7f7b52f 100644 (file)
@@ -227,7 +227,7 @@ endchoice
 
 choice
        prompt "HugeTLB page size"
-       depends on HUGETLB_PAGE && (CPU_SH4 || CPU_SH5) && MMU
+       depends on HUGETLB_PAGE
        default HUGETLB_PAGE_SIZE_1MB if PAGE_SIZE_64KB
        default HUGETLB_PAGE_SIZE_64K
 
index b2453bb..519e2d1 100644 (file)
@@ -26,7 +26,7 @@
 #define MAX_DCACHE_PAGES       64      /* XXX: Tune for ways */
 #define MAX_ICACHE_PAGES       32
 
-static void __flush_cache_4096(unsigned long addr, unsigned long phys,
+static void __flush_cache_one(unsigned long addr, unsigned long phys,
                               unsigned long exec_offset);
 
 /*
@@ -43,7 +43,7 @@ static void (*__flush_dcache_segment_fn)(unsigned long, unsigned long) =
  * Called from kernel/module.c:sys_init_module and routine for a.out format,
  * signal handler code and kprobes code
  */
-static void sh4_flush_icache_range(void *args)
+static void __uses_jump_to_uncached sh4_flush_icache_range(void *args)
 {
        struct flusher_data *data = args;
        unsigned long start, end;
@@ -89,8 +89,7 @@ static void sh4_flush_icache_range(void *args)
        local_irq_restore(flags);
 }
 
-static inline void flush_cache_4096(unsigned long start,
-                                   unsigned long phys)
+static inline void flush_cache_one(unsigned long start, unsigned long phys)
 {
        unsigned long flags, exec_offset = 0;
 
@@ -103,8 +102,7 @@ static inline void flush_cache_4096(unsigned long start,
                exec_offset = 0x20000000;
 
        local_irq_save(flags);
-       __flush_cache_4096(start | SH_CACHE_ASSOC,
-                          P1SEGADDR(phys), exec_offset);
+       __flush_cache_one(start | SH_CACHE_ASSOC, P1SEGADDR(phys), exec_offset);
        local_irq_restore(flags);
 }
 
@@ -129,8 +127,8 @@ static void sh4_flush_dcache_page(void *arg)
 
                /* Loop all the D-cache */
                n = boot_cpu_data.dcache.n_aliases;
-               for (i = 0; i < n; i++, addr += 4096)
-                       flush_cache_4096(addr, phys);
+               for (i = 0; i < n; i++, addr += PAGE_SIZE)
+                       flush_cache_one(addr, phys);
        }
 
        wmb();
@@ -318,11 +316,11 @@ static void sh4_flush_cache_page(void *args)
        /* We only need to flush D-cache when we have alias */
        if ((address^phys) & alias_mask) {
                /* Loop 4K of the D-cache */
-               flush_cache_4096(
+               flush_cache_one(
                        CACHE_OC_ADDRESS_ARRAY | (address & alias_mask),
                        phys);
                /* Loop another 4K of the D-cache */
-               flush_cache_4096(
+               flush_cache_one(
                        CACHE_OC_ADDRESS_ARRAY | (phys & alias_mask),
                        phys);
        }
@@ -337,7 +335,7 @@ static void sh4_flush_cache_page(void *args)
                 * kernel has never executed the code through its identity
                 * translation.
                 */
-               flush_cache_4096(
+               flush_cache_one(
                        CACHE_IC_ADDRESS_ARRAY | (address & alias_mask),
                        phys);
        }
@@ -393,7 +391,7 @@ static void sh4_flush_cache_range(void *args)
 }
 
 /**
- * __flush_cache_4096
+ * __flush_cache_one
  *
  * @addr:  address in memory mapped cache array
  * @phys:  P1 address to flush (has to match tags if addr has 'A' bit
@@ -406,7 +404,7 @@ static void sh4_flush_cache_range(void *args)
  * operation (purge/write-back) is selected by the lower 2 bits of
  * 'phys'.
  */
-static void __flush_cache_4096(unsigned long addr, unsigned long phys,
+static void __flush_cache_one(unsigned long addr, unsigned long phys,
                               unsigned long exec_offset)
 {
        int way_count;
index 2cadee2..2601935 100644 (file)
@@ -78,7 +78,7 @@ static void sh7705_flush_icache_range(void *args)
 /*
  * Writeback&Invalidate the D-cache of the page
  */
-static void __flush_dcache_page(unsigned long phys)
+static void __uses_jump_to_uncached __flush_dcache_page(unsigned long phys)
 {
        unsigned long ways, waysize, addrstart;
        unsigned long flags;
@@ -144,7 +144,7 @@ static void sh7705_flush_dcache_page(void *arg)
                __flush_dcache_page(PHYSADDR(page_address(page)));
 }
 
-static void sh7705_flush_cache_all(void *args)
+static void __uses_jump_to_uncached sh7705_flush_cache_all(void *args)
 {
        unsigned long flags;
 
index 35c37b7..a2dc7f9 100644 (file)
@@ -128,7 +128,7 @@ void __update_cache(struct vm_area_struct *vma,
                return;
 
        page = pfn_to_page(pfn);
-       if (pfn_valid(pfn) && page_mapping(page)) {
+       if (pfn_valid(pfn)) {
                int dirty = test_and_clear_bit(PG_dcache_dirty, &page->flags);
                if (dirty) {
                        unsigned long addr = (unsigned long)page_address(page);
@@ -265,6 +265,8 @@ static void __init emit_cache_params(void)
 
 void __init cpu_cache_init(void)
 {
+       unsigned int cache_disabled = !(__raw_readl(CCR) & CCR_CACHE_ENABLE);
+
        compute_alias(&boot_cpu_data.icache);
        compute_alias(&boot_cpu_data.dcache);
        compute_alias(&boot_cpu_data.scache);
@@ -273,6 +275,13 @@ void __init cpu_cache_init(void)
        __flush_purge_region            = noop__flush_region;
        __flush_invalidate_region       = noop__flush_region;
 
+       /*
+        * No flushing is necessary in the disabled cache case so we can
+        * just keep the noop functions in local_flush_..() and __flush_..()
+        */
+       if (unlikely(cache_disabled))
+               goto skip;
+
        if (boot_cpu_data.family == CPU_FAMILY_SH2) {
                extern void __weak sh2_cache_init(void);
 
@@ -312,5 +321,6 @@ void __init cpu_cache_init(void)
                sh5_cache_init();
        }
 
+skip:
        emit_cache_params();
 }
index c325061..a86eaa9 100644 (file)
@@ -83,7 +83,7 @@ void __iomem *__ioremap(unsigned long phys_addr, unsigned long size,
         *
         * PMB entries are all pre-faulted.
         */
-       if (unlikely(size >= 0x1000000)) {
+       if (unlikely(phys_addr >= P1SEG)) {
                unsigned long mapped = pmb_remap(addr, phys_addr, size, flags);
 
                if (likely(mapped)) {
index b1a714a..aade311 100644 (file)
@@ -33,6 +33,8 @@
 
 #define NR_PMB_ENTRIES 16
 
+static void __pmb_unmap(struct pmb_entry *);
+
 static struct kmem_cache *pmb_cache;
 static unsigned long pmb_map;
 
@@ -218,9 +220,10 @@ static struct {
 long pmb_remap(unsigned long vaddr, unsigned long phys,
               unsigned long size, unsigned long flags)
 {
-       struct pmb_entry *pmbp;
+       struct pmb_entry *pmbp, *pmbe;
        unsigned long wanted;
        int pmb_flags, i;
+       long err;
 
        /* Convert typical pgprot value to the PMB equivalent */
        if (flags & _PAGE_CACHABLE) {
@@ -236,20 +239,22 @@ long pmb_remap(unsigned long vaddr, unsigned long phys,
 
 again:
        for (i = 0; i < ARRAY_SIZE(pmb_sizes); i++) {
-               struct pmb_entry *pmbe;
                int ret;
 
                if (size < pmb_sizes[i].size)
                        continue;
 
                pmbe = pmb_alloc(vaddr, phys, pmb_flags | pmb_sizes[i].flag);
-               if (IS_ERR(pmbe))
-                       return PTR_ERR(pmbe);
+               if (IS_ERR(pmbe)) {
+                       err = PTR_ERR(pmbe);
+                       goto out;
+               }
 
                ret = set_pmb_entry(pmbe);
                if (ret != 0) {
                        pmb_free(pmbe);
-                       return -EBUSY;
+                       err = -EBUSY;
+                       goto out;
                }
 
                phys    += pmb_sizes[i].size;
@@ -264,12 +269,25 @@ again:
                        pmbp->link = pmbe;
 
                pmbp = pmbe;
+
+               /*
+                * Instead of trying smaller sizes on every iteration
+                * (even if we succeed in allocating space), try using
+                * pmb_sizes[i].size again.
+                */
+               i--;
        }
 
        if (size >= 0x1000000)
                goto again;
 
        return wanted - size;
+
+out:
+       if (pmbp)
+               __pmb_unmap(pmbp);
+
+       return err;
 }
 
 void pmb_unmap(unsigned long addr)
@@ -283,12 +301,19 @@ void pmb_unmap(unsigned long addr)
        if (unlikely(!pmbe))
                return;
 
+       __pmb_unmap(pmbe);
+}
+
+static void __pmb_unmap(struct pmb_entry *pmbe)
+{
        WARN_ON(!test_bit(pmbe->entry, &pmb_map));
 
        do {
                struct pmb_entry *pmblink = pmbe;
 
-               clear_pmb_entry(pmbe);
+               if (pmbe->entry != PMB_NO_ENTRY)
+                       clear_pmb_entry(pmbe);
+
                pmbe = pmblink->link;
 
                pmb_free(pmblink);
index ac45aab..05ef538 100644 (file)
@@ -26,6 +26,7 @@ config SPARC
        select RTC_CLASS
        select RTC_DRV_M48T59
        select HAVE_PERF_EVENTS
+       select PERF_USE_VMALLOC
        select HAVE_DMA_ATTRS
        select HAVE_DMA_API_DEBUG
 
@@ -48,6 +49,7 @@ config SPARC64
        select RTC_DRV_SUN4V
        select RTC_DRV_STARFIRE
        select HAVE_PERF_EVENTS
+       select PERF_USE_VMALLOC
 
 config ARCH_DEFCONFIG
        string
index 4f63ed8..1620076 100644 (file)
@@ -7,17 +7,7 @@
 #ifndef __SPARC_HARDIRQ_H
 #define __SPARC_HARDIRQ_H
 
-#include <linux/threads.h>
-#include <linux/spinlock.h>
-#include <linux/cache.h>
-
-/* entry.S is sensitive to the offsets of these fields */ /* XXX P3 Is it? */
-typedef struct {
-       unsigned int __softirq_pending;
-} ____cacheline_aligned irq_cpustat_t;
-
-#include <linux/irq_cpustat.h> /* Standard mappings for irq_cpustat_t above */
-
 #define HARDIRQ_BITS    8
+#include <asm-generic/hardirq.h>
 
 #endif /* __SPARC_HARDIRQ_H */
index ea43057..cbf4801 100644 (file)
@@ -6,10 +6,10 @@
 #ifndef _SPARC_IRQ_H
 #define _SPARC_IRQ_H
 
-#include <linux/interrupt.h>
-
 #define NR_IRQS    16
 
+#include <linux/interrupt.h>
+
 #define irq_canonicalize(irq)  (irq)
 
 extern void __init init_IRQ(void);
index 0ff92fa..f3cb790 100644 (file)
@@ -41,8 +41,8 @@
 #define LOW_OBP_ADDRESS                _AC(0x00000000f0000000,UL)
 #define HI_OBP_ADDRESS         _AC(0x0000000100000000,UL)
 #define VMALLOC_START          _AC(0x0000000100000000,UL)
-#define VMALLOC_END            _AC(0x0000000200000000,UL)
-#define VMEMMAP_BASE           _AC(0x0000000200000000,UL)
+#define VMALLOC_END            _AC(0x0000010000000000,UL)
+#define VMEMMAP_BASE           _AC(0x0000010000000000,UL)
 
 #define vmemmap                        ((struct page *)VMEMMAP_BASE)
 
index 3ea6e8c..1d36147 100644 (file)
@@ -280,8 +280,8 @@ kvmap_dtlb_nonlinear:
 
 #ifdef CONFIG_SPARSEMEM_VMEMMAP
        /* Do not use the TSB for vmemmap.  */
-       mov             (VMEMMAP_BASE >> 24), %g5
-       sllx            %g5, 24, %g5
+       mov             (VMEMMAP_BASE >> 40), %g5
+       sllx            %g5, 40, %g5
        cmp             %g4,%g5
        bgeu,pn         %xcc, kvmap_vmemmap
         nop
@@ -293,8 +293,8 @@ kvmap_dtlb_tsbmiss:
        sethi           %hi(MODULES_VADDR), %g5
        cmp             %g4, %g5
        blu,pn          %xcc, kvmap_dtlb_longpath
-        mov            (VMALLOC_END >> 24), %g5
-       sllx            %g5, 24, %g5
+        mov            (VMALLOC_END >> 40), %g5
+       sllx            %g5, 40, %g5
        cmp             %g4, %g5
        bgeu,pn         %xcc, kvmap_dtlb_longpath
         nop
index adf5f27..cb3c72c 100644 (file)
@@ -1242,13 +1242,13 @@ int ldc_bind(struct ldc_channel *lp, const char *name)
        snprintf(lp->tx_irq_name, LDC_IRQ_NAME_MAX, "%s TX", name);
 
        err = request_irq(lp->cfg.rx_irq, ldc_rx,
-                         IRQF_SAMPLE_RANDOM | IRQF_SHARED,
+                         IRQF_SAMPLE_RANDOM | IRQF_DISABLED | IRQF_SHARED,
                          lp->rx_irq_name, lp);
        if (err)
                return err;
 
        err = request_irq(lp->cfg.tx_irq, ldc_tx,
-                         IRQF_SAMPLE_RANDOM | IRQF_SHARED,
+                         IRQF_SAMPLE_RANDOM | IRQF_DISABLED | IRQF_SHARED,
                          lp->tx_irq_name, lp);
        if (err) {
                free_irq(lp->cfg.rx_irq, lp);
index 2d6a1b1..fa5936e 100644 (file)
@@ -56,7 +56,8 @@ struct cpu_hw_events {
        struct perf_event       *events[MAX_HWEVENTS];
        unsigned long           used_mask[BITS_TO_LONGS(MAX_HWEVENTS)];
        unsigned long           active_mask[BITS_TO_LONGS(MAX_HWEVENTS)];
-       int enabled;
+       u64                     pcr;
+       int                     enabled;
 };
 DEFINE_PER_CPU(struct cpu_hw_events, cpu_hw_events) = { .enabled = 1, };
 
@@ -68,8 +69,30 @@ struct perf_event_map {
 #define PIC_LOWER      0x02
 };
 
+static unsigned long perf_event_encode(const struct perf_event_map *pmap)
+{
+       return ((unsigned long) pmap->encoding << 16) | pmap->pic_mask;
+}
+
+static void perf_event_decode(unsigned long val, u16 *enc, u8 *msk)
+{
+       *msk = val & 0xff;
+       *enc = val >> 16;
+}
+
+#define C(x) PERF_COUNT_HW_CACHE_##x
+
+#define CACHE_OP_UNSUPPORTED   0xfffe
+#define CACHE_OP_NONSENSE      0xffff
+
+typedef struct perf_event_map cache_map_t
+                               [PERF_COUNT_HW_CACHE_MAX]
+                               [PERF_COUNT_HW_CACHE_OP_MAX]
+                               [PERF_COUNT_HW_CACHE_RESULT_MAX];
+
 struct sparc_pmu {
        const struct perf_event_map     *(*event_map)(int);
+       const cache_map_t               *cache_map;
        int                             max_events;
        int                             upper_shift;
        int                             lower_shift;
@@ -80,21 +103,109 @@ struct sparc_pmu {
        int                             lower_nop;
 };
 
-static const struct perf_event_map ultra3i_perfmon_event_map[] = {
+static const struct perf_event_map ultra3_perfmon_event_map[] = {
        [PERF_COUNT_HW_CPU_CYCLES] = { 0x0000, PIC_UPPER | PIC_LOWER },
        [PERF_COUNT_HW_INSTRUCTIONS] = { 0x0001, PIC_UPPER | PIC_LOWER },
        [PERF_COUNT_HW_CACHE_REFERENCES] = { 0x0009, PIC_LOWER },
        [PERF_COUNT_HW_CACHE_MISSES] = { 0x0009, PIC_UPPER },
 };
 
-static const struct perf_event_map *ultra3i_event_map(int event_id)
+static const struct perf_event_map *ultra3_event_map(int event_id)
 {
-       return &ultra3i_perfmon_event_map[event_id];
+       return &ultra3_perfmon_event_map[event_id];
 }
 
-static const struct sparc_pmu ultra3i_pmu = {
-       .event_map      = ultra3i_event_map,
-       .max_events     = ARRAY_SIZE(ultra3i_perfmon_event_map),
+static const cache_map_t ultra3_cache_map = {
+[C(L1D)] = {
+       [C(OP_READ)] = {
+               [C(RESULT_ACCESS)] = { 0x09, PIC_LOWER, },
+               [C(RESULT_MISS)] = { 0x09, PIC_UPPER, },
+       },
+       [C(OP_WRITE)] = {
+               [C(RESULT_ACCESS)] = { 0x0a, PIC_LOWER },
+               [C(RESULT_MISS)] = { 0x0a, PIC_UPPER },
+       },
+       [C(OP_PREFETCH)] = {
+               [C(RESULT_ACCESS)] = { CACHE_OP_UNSUPPORTED },
+               [C(RESULT_MISS)] = { CACHE_OP_UNSUPPORTED },
+       },
+},
+[C(L1I)] = {
+       [C(OP_READ)] = {
+               [C(RESULT_ACCESS)] = { 0x09, PIC_LOWER, },
+               [C(RESULT_MISS)] = { 0x09, PIC_UPPER, },
+       },
+       [ C(OP_WRITE) ] = {
+               [ C(RESULT_ACCESS) ] = { CACHE_OP_NONSENSE },
+               [ C(RESULT_MISS)   ] = { CACHE_OP_NONSENSE },
+       },
+       [ C(OP_PREFETCH) ] = {
+               [ C(RESULT_ACCESS) ] = { CACHE_OP_UNSUPPORTED },
+               [ C(RESULT_MISS)   ] = { CACHE_OP_UNSUPPORTED },
+       },
+},
+[C(LL)] = {
+       [C(OP_READ)] = {
+               [C(RESULT_ACCESS)] = { 0x0c, PIC_LOWER, },
+               [C(RESULT_MISS)] = { 0x0c, PIC_UPPER, },
+       },
+       [C(OP_WRITE)] = {
+               [C(RESULT_ACCESS)] = { 0x0c, PIC_LOWER },
+               [C(RESULT_MISS)] = { 0x0c, PIC_UPPER },
+       },
+       [C(OP_PREFETCH)] = {
+               [C(RESULT_ACCESS)] = { CACHE_OP_UNSUPPORTED },
+               [C(RESULT_MISS)] = { CACHE_OP_UNSUPPORTED },
+       },
+},
+[C(DTLB)] = {
+       [C(OP_READ)] = {
+               [C(RESULT_ACCESS)] = { CACHE_OP_UNSUPPORTED },
+               [C(RESULT_MISS)] = { 0x12, PIC_UPPER, },
+       },
+       [ C(OP_WRITE) ] = {
+               [ C(RESULT_ACCESS) ] = { CACHE_OP_UNSUPPORTED },
+               [ C(RESULT_MISS)   ] = { CACHE_OP_UNSUPPORTED },
+       },
+       [ C(OP_PREFETCH) ] = {
+               [ C(RESULT_ACCESS) ] = { CACHE_OP_UNSUPPORTED },
+               [ C(RESULT_MISS)   ] = { CACHE_OP_UNSUPPORTED },
+       },
+},
+[C(ITLB)] = {
+       [C(OP_READ)] = {
+               [C(RESULT_ACCESS)] = { CACHE_OP_UNSUPPORTED },
+               [C(RESULT_MISS)] = { 0x11, PIC_UPPER, },
+       },
+       [ C(OP_WRITE) ] = {
+               [ C(RESULT_ACCESS) ] = { CACHE_OP_UNSUPPORTED },
+               [ C(RESULT_MISS)   ] = { CACHE_OP_UNSUPPORTED },
+       },
+       [ C(OP_PREFETCH) ] = {
+               [ C(RESULT_ACCESS) ] = { CACHE_OP_UNSUPPORTED },
+               [ C(RESULT_MISS)   ] = { CACHE_OP_UNSUPPORTED },
+       },
+},
+[C(BPU)] = {
+       [C(OP_READ)] = {
+               [C(RESULT_ACCESS)] = { CACHE_OP_UNSUPPORTED },
+               [C(RESULT_MISS)] = { CACHE_OP_UNSUPPORTED },
+       },
+       [ C(OP_WRITE) ] = {
+               [ C(RESULT_ACCESS) ] = { CACHE_OP_UNSUPPORTED },
+               [ C(RESULT_MISS)   ] = { CACHE_OP_UNSUPPORTED },
+       },
+       [ C(OP_PREFETCH) ] = {
+               [ C(RESULT_ACCESS) ] = { CACHE_OP_UNSUPPORTED },
+               [ C(RESULT_MISS)   ] = { CACHE_OP_UNSUPPORTED },
+       },
+},
+};
+
+static const struct sparc_pmu ultra3_pmu = {
+       .event_map      = ultra3_event_map,
+       .cache_map      = &ultra3_cache_map,
+       .max_events     = ARRAY_SIZE(ultra3_perfmon_event_map),
        .upper_shift    = 11,
        .lower_shift    = 4,
        .event_mask     = 0x3f,
@@ -102,6 +213,121 @@ static const struct sparc_pmu ultra3i_pmu = {
        .lower_nop      = 0x14,
 };
 
+/* Niagara1 is very limited.  The upper PIC is hard-locked to count
+ * only instructions, so it is free running which creates all kinds of
+ * problems.  Some hardware designs make one wonder if the creator
+ * even looked at how this stuff gets used by software.
+ */
+static const struct perf_event_map niagara1_perfmon_event_map[] = {
+       [PERF_COUNT_HW_CPU_CYCLES] = { 0x00, PIC_UPPER },
+       [PERF_COUNT_HW_INSTRUCTIONS] = { 0x00, PIC_UPPER },
+       [PERF_COUNT_HW_CACHE_REFERENCES] = { 0, PIC_NONE },
+       [PERF_COUNT_HW_CACHE_MISSES] = { 0x03, PIC_LOWER },
+};
+
+static const struct perf_event_map *niagara1_event_map(int event_id)
+{
+       return &niagara1_perfmon_event_map[event_id];
+}
+
+static const cache_map_t niagara1_cache_map = {
+[C(L1D)] = {
+       [C(OP_READ)] = {
+               [C(RESULT_ACCESS)] = { CACHE_OP_UNSUPPORTED },
+               [C(RESULT_MISS)] = { 0x03, PIC_LOWER, },
+       },
+       [C(OP_WRITE)] = {
+               [C(RESULT_ACCESS)] = { CACHE_OP_UNSUPPORTED },
+               [C(RESULT_MISS)] = { 0x03, PIC_LOWER, },
+       },
+       [C(OP_PREFETCH)] = {
+               [C(RESULT_ACCESS)] = { CACHE_OP_UNSUPPORTED },
+               [C(RESULT_MISS)] = { CACHE_OP_UNSUPPORTED },
+       },
+},
+[C(L1I)] = {
+       [C(OP_READ)] = {
+               [C(RESULT_ACCESS)] = { 0x00, PIC_UPPER },
+               [C(RESULT_MISS)] = { 0x02, PIC_LOWER, },
+       },
+       [ C(OP_WRITE) ] = {
+               [ C(RESULT_ACCESS) ] = { CACHE_OP_NONSENSE },
+               [ C(RESULT_MISS)   ] = { CACHE_OP_NONSENSE },
+       },
+       [ C(OP_PREFETCH) ] = {
+               [ C(RESULT_ACCESS) ] = { CACHE_OP_UNSUPPORTED },
+               [ C(RESULT_MISS)   ] = { CACHE_OP_UNSUPPORTED },
+       },
+},
+[C(LL)] = {
+       [C(OP_READ)] = {
+               [C(RESULT_ACCESS)] = { CACHE_OP_UNSUPPORTED },
+               [C(RESULT_MISS)] = { 0x07, PIC_LOWER, },
+       },
+       [C(OP_WRITE)] = {
+               [C(RESULT_ACCESS)] = { CACHE_OP_UNSUPPORTED },
+               [C(RESULT_MISS)] = { 0x07, PIC_LOWER, },
+       },
+       [C(OP_PREFETCH)] = {
+               [C(RESULT_ACCESS)] = { CACHE_OP_UNSUPPORTED },
+               [C(RESULT_MISS)] = { CACHE_OP_UNSUPPORTED },
+       },
+},
+[C(DTLB)] = {
+       [C(OP_READ)] = {
+               [C(RESULT_ACCESS)] = { CACHE_OP_UNSUPPORTED },
+               [C(RESULT_MISS)] = { 0x05, PIC_LOWER, },
+       },
+       [ C(OP_WRITE) ] = {
+               [ C(RESULT_ACCESS) ] = { CACHE_OP_UNSUPPORTED },
+               [ C(RESULT_MISS)   ] = { CACHE_OP_UNSUPPORTED },
+       },
+       [ C(OP_PREFETCH) ] = {
+               [ C(RESULT_ACCESS) ] = { CACHE_OP_UNSUPPORTED },
+               [ C(RESULT_MISS)   ] = { CACHE_OP_UNSUPPORTED },
+       },
+},
+[C(ITLB)] = {
+       [C(OP_READ)] = {
+               [C(RESULT_ACCESS)] = { CACHE_OP_UNSUPPORTED },
+               [C(RESULT_MISS)] = { 0x04, PIC_LOWER, },
+       },
+       [ C(OP_WRITE) ] = {
+               [ C(RESULT_ACCESS) ] = { CACHE_OP_UNSUPPORTED },
+               [ C(RESULT_MISS)   ] = { CACHE_OP_UNSUPPORTED },
+       },
+       [ C(OP_PREFETCH) ] = {
+               [ C(RESULT_ACCESS) ] = { CACHE_OP_UNSUPPORTED },
+               [ C(RESULT_MISS)   ] = { CACHE_OP_UNSUPPORTED },
+       },
+},
+[C(BPU)] = {
+       [C(OP_READ)] = {
+               [C(RESULT_ACCESS)] = { CACHE_OP_UNSUPPORTED },
+               [C(RESULT_MISS)] = { CACHE_OP_UNSUPPORTED },
+       },
+       [ C(OP_WRITE) ] = {
+               [ C(RESULT_ACCESS) ] = { CACHE_OP_UNSUPPORTED },
+               [ C(RESULT_MISS)   ] = { CACHE_OP_UNSUPPORTED },
+       },
+       [ C(OP_PREFETCH) ] = {
+               [ C(RESULT_ACCESS) ] = { CACHE_OP_UNSUPPORTED },
+               [ C(RESULT_MISS)   ] = { CACHE_OP_UNSUPPORTED },
+       },
+},
+};
+
+static const struct sparc_pmu niagara1_pmu = {
+       .event_map      = niagara1_event_map,
+       .cache_map      = &niagara1_cache_map,
+       .max_events     = ARRAY_SIZE(niagara1_perfmon_event_map),
+       .upper_shift    = 0,
+       .lower_shift    = 4,
+       .event_mask     = 0x7,
+       .upper_nop      = 0x0,
+       .lower_nop      = 0x0,
+};
+
 static const struct perf_event_map niagara2_perfmon_event_map[] = {
        [PERF_COUNT_HW_CPU_CYCLES] = { 0x02ff, PIC_UPPER | PIC_LOWER },
        [PERF_COUNT_HW_INSTRUCTIONS] = { 0x02ff, PIC_UPPER | PIC_LOWER },
@@ -116,14 +342,102 @@ static const struct perf_event_map *niagara2_event_map(int event_id)
        return &niagara2_perfmon_event_map[event_id];
 }
 
+static const cache_map_t niagara2_cache_map = {
+[C(L1D)] = {
+       [C(OP_READ)] = {
+               [C(RESULT_ACCESS)] = { 0x0208, PIC_UPPER | PIC_LOWER, },
+               [C(RESULT_MISS)] = { 0x0302, PIC_UPPER | PIC_LOWER, },
+       },
+       [C(OP_WRITE)] = {
+               [C(RESULT_ACCESS)] = { 0x0210, PIC_UPPER | PIC_LOWER, },
+               [C(RESULT_MISS)] = { 0x0302, PIC_UPPER | PIC_LOWER, },
+       },
+       [C(OP_PREFETCH)] = {
+               [C(RESULT_ACCESS)] = { CACHE_OP_UNSUPPORTED },
+               [C(RESULT_MISS)] = { CACHE_OP_UNSUPPORTED },
+       },
+},
+[C(L1I)] = {
+       [C(OP_READ)] = {
+               [C(RESULT_ACCESS)] = { 0x02ff, PIC_UPPER | PIC_LOWER, },
+               [C(RESULT_MISS)] = { 0x0301, PIC_UPPER | PIC_LOWER, },
+       },
+       [ C(OP_WRITE) ] = {
+               [ C(RESULT_ACCESS) ] = { CACHE_OP_NONSENSE },
+               [ C(RESULT_MISS)   ] = { CACHE_OP_NONSENSE },
+       },
+       [ C(OP_PREFETCH) ] = {
+               [ C(RESULT_ACCESS) ] = { CACHE_OP_UNSUPPORTED },
+               [ C(RESULT_MISS)   ] = { CACHE_OP_UNSUPPORTED },
+       },
+},
+[C(LL)] = {
+       [C(OP_READ)] = {
+               [C(RESULT_ACCESS)] = { 0x0208, PIC_UPPER | PIC_LOWER, },
+               [C(RESULT_MISS)] = { 0x0330, PIC_UPPER | PIC_LOWER, },
+       },
+       [C(OP_WRITE)] = {
+               [C(RESULT_ACCESS)] = { 0x0210, PIC_UPPER | PIC_LOWER, },
+               [C(RESULT_MISS)] = { 0x0320, PIC_UPPER | PIC_LOWER, },
+       },
+       [C(OP_PREFETCH)] = {
+               [C(RESULT_ACCESS)] = { CACHE_OP_UNSUPPORTED },
+               [C(RESULT_MISS)] = { CACHE_OP_UNSUPPORTED },
+       },
+},
+[C(DTLB)] = {
+       [C(OP_READ)] = {
+               [C(RESULT_ACCESS)] = { CACHE_OP_UNSUPPORTED },
+               [C(RESULT_MISS)] = { 0x0b08, PIC_UPPER | PIC_LOWER, },
+       },
+       [ C(OP_WRITE) ] = {
+               [ C(RESULT_ACCESS) ] = { CACHE_OP_UNSUPPORTED },
+               [ C(RESULT_MISS)   ] = { CACHE_OP_UNSUPPORTED },
+       },
+       [ C(OP_PREFETCH) ] = {
+               [ C(RESULT_ACCESS) ] = { CACHE_OP_UNSUPPORTED },
+               [ C(RESULT_MISS)   ] = { CACHE_OP_UNSUPPORTED },
+       },
+},
+[C(ITLB)] = {
+       [C(OP_READ)] = {
+               [C(RESULT_ACCESS)] = { CACHE_OP_UNSUPPORTED },
+               [C(RESULT_MISS)] = { 0xb04, PIC_UPPER | PIC_LOWER, },
+       },
+       [ C(OP_WRITE) ] = {
+               [ C(RESULT_ACCESS) ] = { CACHE_OP_UNSUPPORTED },
+               [ C(RESULT_MISS)   ] = { CACHE_OP_UNSUPPORTED },
+       },
+       [ C(OP_PREFETCH) ] = {
+               [ C(RESULT_ACCESS) ] = { CACHE_OP_UNSUPPORTED },
+               [ C(RESULT_MISS)   ] = { CACHE_OP_UNSUPPORTED },
+       },
+},
+[C(BPU)] = {
+       [C(OP_READ)] = {
+               [C(RESULT_ACCESS)] = { CACHE_OP_UNSUPPORTED },
+               [C(RESULT_MISS)] = { CACHE_OP_UNSUPPORTED },
+       },
+       [ C(OP_WRITE) ] = {
+               [ C(RESULT_ACCESS) ] = { CACHE_OP_UNSUPPORTED },
+               [ C(RESULT_MISS)   ] = { CACHE_OP_UNSUPPORTED },
+       },
+       [ C(OP_PREFETCH) ] = {
+               [ C(RESULT_ACCESS) ] = { CACHE_OP_UNSUPPORTED },
+               [ C(RESULT_MISS)   ] = { CACHE_OP_UNSUPPORTED },
+       },
+},
+};
+
 static const struct sparc_pmu niagara2_pmu = {
        .event_map      = niagara2_event_map,
+       .cache_map      = &niagara2_cache_map,
        .max_events     = ARRAY_SIZE(niagara2_perfmon_event_map),
        .upper_shift    = 19,
        .lower_shift    = 6,
        .event_mask     = 0xfff,
        .hv_bit         = 0x8,
-       .irq_bit        = 0x03,
+       .irq_bit        = 0x30,
        .upper_nop      = 0x220,
        .lower_nop      = 0x220,
 };
@@ -151,23 +465,30 @@ static u64 nop_for_index(int idx)
                              sparc_pmu->lower_nop, idx);
 }
 
-static inline void sparc_pmu_enable_event(struct hw_perf_event *hwc,
-                                           int idx)
+static inline void sparc_pmu_enable_event(struct cpu_hw_events *cpuc, struct hw_perf_event *hwc, int idx)
 {
        u64 val, mask = mask_for_index(idx);
 
-       val = pcr_ops->read();
-       pcr_ops->write((val & ~mask) | hwc->config);
+       val = cpuc->pcr;
+       val &= ~mask;
+       val |= hwc->config;
+       cpuc->pcr = val;
+
+       pcr_ops->write(cpuc->pcr);
 }
 
-static inline void sparc_pmu_disable_event(struct hw_perf_event *hwc,
-                                            int idx)
+static inline void sparc_pmu_disable_event(struct cpu_hw_events *cpuc, struct hw_perf_event *hwc, int idx)
 {
        u64 mask = mask_for_index(idx);
        u64 nop = nop_for_index(idx);
-       u64 val = pcr_ops->read();
+       u64 val;
 
-       pcr_ops->write((val & ~mask) | nop);
+       val = cpuc->pcr;
+       val &= ~mask;
+       val |= nop;
+       cpuc->pcr = val;
+
+       pcr_ops->write(cpuc->pcr);
 }
 
 void hw_perf_enable(void)
@@ -182,7 +503,7 @@ void hw_perf_enable(void)
        cpuc->enabled = 1;
        barrier();
 
-       val = pcr_ops->read();
+       val = cpuc->pcr;
 
        for (i = 0; i < MAX_HWEVENTS; i++) {
                struct perf_event *cp = cpuc->events[i];
@@ -194,7 +515,9 @@ void hw_perf_enable(void)
                val |= hwc->config_base;
        }
 
-       pcr_ops->write(val);
+       cpuc->pcr = val;
+
+       pcr_ops->write(cpuc->pcr);
 }
 
 void hw_perf_disable(void)
@@ -207,10 +530,12 @@ void hw_perf_disable(void)
 
        cpuc->enabled = 0;
 
-       val = pcr_ops->read();
+       val = cpuc->pcr;
        val &= ~(PCR_UTRACE | PCR_STRACE |
                 sparc_pmu->hv_bit | sparc_pmu->irq_bit);
-       pcr_ops->write(val);
+       cpuc->pcr = val;
+
+       pcr_ops->write(cpuc->pcr);
 }
 
 static u32 read_pmc(int idx)
@@ -242,7 +567,7 @@ static void write_pmc(int idx, u64 val)
 }
 
 static int sparc_perf_event_set_period(struct perf_event *event,
-                                        struct hw_perf_event *hwc, int idx)
+                                      struct hw_perf_event *hwc, int idx)
 {
        s64 left = atomic64_read(&hwc->period_left);
        s64 period = hwc->sample_period;
@@ -282,19 +607,19 @@ static int sparc_pmu_enable(struct perf_event *event)
        if (test_and_set_bit(idx, cpuc->used_mask))
                return -EAGAIN;
 
-       sparc_pmu_disable_event(hwc, idx);
+       sparc_pmu_disable_event(cpuc, hwc, idx);
 
        cpuc->events[idx] = event;
        set_bit(idx, cpuc->active_mask);
 
        sparc_perf_event_set_period(event, hwc, idx);
-       sparc_pmu_enable_event(hwc, idx);
+       sparc_pmu_enable_event(cpuc, hwc, idx);
        perf_event_update_userpage(event);
        return 0;
 }
 
 static u64 sparc_perf_event_update(struct perf_event *event,
-                                    struct hw_perf_event *hwc, int idx)
+                                  struct hw_perf_event *hwc, int idx)
 {
        int shift = 64 - 32;
        u64 prev_raw_count, new_raw_count;
@@ -324,7 +649,7 @@ static void sparc_pmu_disable(struct perf_event *event)
        int idx = hwc->idx;
 
        clear_bit(idx, cpuc->active_mask);
-       sparc_pmu_disable_event(hwc, idx);
+       sparc_pmu_disable_event(cpuc, hwc, idx);
 
        barrier();
 
@@ -338,18 +663,29 @@ static void sparc_pmu_disable(struct perf_event *event)
 static void sparc_pmu_read(struct perf_event *event)
 {
        struct hw_perf_event *hwc = &event->hw;
+
        sparc_perf_event_update(event, hwc, hwc->idx);
 }
 
 static void sparc_pmu_unthrottle(struct perf_event *event)
 {
+       struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
        struct hw_perf_event *hwc = &event->hw;
-       sparc_pmu_enable_event(hwc, hwc->idx);
+
+       sparc_pmu_enable_event(cpuc, hwc, hwc->idx);
 }
 
 static atomic_t active_events = ATOMIC_INIT(0);
 static DEFINE_MUTEX(pmc_grab_mutex);
 
+static void perf_stop_nmi_watchdog(void *unused)
+{
+       struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
+
+       stop_nmi_watchdog(NULL);
+       cpuc->pcr = pcr_ops->read();
+}
+
 void perf_event_grab_pmc(void)
 {
        if (atomic_inc_not_zero(&active_events))
@@ -358,7 +694,7 @@ void perf_event_grab_pmc(void)
        mutex_lock(&pmc_grab_mutex);
        if (atomic_read(&active_events) == 0) {
                if (atomic_read(&nmi_active) > 0) {
-                       on_each_cpu(stop_nmi_watchdog, NULL, 1);
+                       on_each_cpu(perf_stop_nmi_watchdog, NULL, 1);
                        BUG_ON(atomic_read(&nmi_active) != 0);
                }
                atomic_inc(&active_events);
@@ -375,30 +711,160 @@ void perf_event_release_pmc(void)
        }
 }
 
+static const struct perf_event_map *sparc_map_cache_event(u64 config)
+{
+       unsigned int cache_type, cache_op, cache_result;
+       const struct perf_event_map *pmap;
+
+       if (!sparc_pmu->cache_map)
+               return ERR_PTR(-ENOENT);
+
+       cache_type = (config >>  0) & 0xff;
+       if (cache_type >= PERF_COUNT_HW_CACHE_MAX)
+               return ERR_PTR(-EINVAL);
+
+       cache_op = (config >>  8) & 0xff;
+       if (cache_op >= PERF_COUNT_HW_CACHE_OP_MAX)
+               return ERR_PTR(-EINVAL);
+
+       cache_result = (config >> 16) & 0xff;
+       if (cache_result >= PERF_COUNT_HW_CACHE_RESULT_MAX)
+               return ERR_PTR(-EINVAL);
+
+       pmap = &((*sparc_pmu->cache_map)[cache_type][cache_op][cache_result]);
+
+       if (pmap->encoding == CACHE_OP_UNSUPPORTED)
+               return ERR_PTR(-ENOENT);
+
+       if (pmap->encoding == CACHE_OP_NONSENSE)
+               return ERR_PTR(-EINVAL);
+
+       return pmap;
+}
+
 static void hw_perf_event_destroy(struct perf_event *event)
 {
        perf_event_release_pmc();
 }
 
+/* Make sure all events can be scheduled into the hardware at
+ * the same time.  This is simplified by the fact that we only
+ * need to support 2 simultaneous HW events.
+ */
+static int sparc_check_constraints(unsigned long *events, int n_ev)
+{
+       if (n_ev <= perf_max_events) {
+               u8 msk1, msk2;
+               u16 dummy;
+
+               if (n_ev == 1)
+                       return 0;
+               BUG_ON(n_ev != 2);
+               perf_event_decode(events[0], &dummy, &msk1);
+               perf_event_decode(events[1], &dummy, &msk2);
+
+               /* If both events can go on any counter, OK.  */
+               if (msk1 == (PIC_UPPER | PIC_LOWER) &&
+                   msk2 == (PIC_UPPER | PIC_LOWER))
+                       return 0;
+
+               /* If one event is limited to a specific counter,
+                * and the other can go on both, OK.
+                */
+               if ((msk1 == PIC_UPPER || msk1 == PIC_LOWER) &&
+                   msk2 == (PIC_UPPER | PIC_LOWER))
+                       return 0;
+               if ((msk2 == PIC_UPPER || msk2 == PIC_LOWER) &&
+                   msk1 == (PIC_UPPER | PIC_LOWER))
+                       return 0;
+
+               /* If the events are fixed to different counters, OK.  */
+               if ((msk1 == PIC_UPPER && msk2 == PIC_LOWER) ||
+                   (msk1 == PIC_LOWER && msk2 == PIC_UPPER))
+                       return 0;
+
+               /* Otherwise, there is a conflict.  */
+       }
+
+       return -1;
+}
+
+static int check_excludes(struct perf_event **evts, int n_prev, int n_new)
+{
+       int eu = 0, ek = 0, eh = 0;
+       struct perf_event *event;
+       int i, n, first;
+
+       n = n_prev + n_new;
+       if (n <= 1)
+               return 0;
+
+       first = 1;
+       for (i = 0; i < n; i++) {
+               event = evts[i];
+               if (first) {
+                       eu = event->attr.exclude_user;
+                       ek = event->attr.exclude_kernel;
+                       eh = event->attr.exclude_hv;
+                       first = 0;
+               } else if (event->attr.exclude_user != eu ||
+                          event->attr.exclude_kernel != ek ||
+                          event->attr.exclude_hv != eh) {
+                       return -EAGAIN;
+               }
+       }
+
+       return 0;
+}
+
+static int collect_events(struct perf_event *group, int max_count,
+                         struct perf_event *evts[], unsigned long *events)
+{
+       struct perf_event *event;
+       int n = 0;
+
+       if (!is_software_event(group)) {
+               if (n >= max_count)
+                       return -1;
+               evts[n] = group;
+               events[n++] = group->hw.event_base;
+       }
+       list_for_each_entry(event, &group->sibling_list, group_entry) {
+               if (!is_software_event(event) &&
+                   event->state != PERF_EVENT_STATE_OFF) {
+                       if (n >= max_count)
+                               return -1;
+                       evts[n] = event;
+                       events[n++] = event->hw.event_base;
+               }
+       }
+       return n;
+}
+
 static int __hw_perf_event_init(struct perf_event *event)
 {
        struct perf_event_attr *attr = &event->attr;
+       struct perf_event *evts[MAX_HWEVENTS];
        struct hw_perf_event *hwc = &event->hw;
+       unsigned long events[MAX_HWEVENTS];
        const struct perf_event_map *pmap;
        u64 enc;
+       int n;
 
        if (atomic_read(&nmi_active) < 0)
                return -ENODEV;
 
-       if (attr->type != PERF_TYPE_HARDWARE)
+       if (attr->type == PERF_TYPE_HARDWARE) {
+               if (attr->config >= sparc_pmu->max_events)
+                       return -EINVAL;
+               pmap = sparc_pmu->event_map(attr->config);
+       } else if (attr->type == PERF_TYPE_HW_CACHE) {
+               pmap = sparc_map_cache_event(attr->config);
+               if (IS_ERR(pmap))
+                       return PTR_ERR(pmap);
+       } else
                return -EOPNOTSUPP;
 
-       if (attr->config >= sparc_pmu->max_events)
-               return -EINVAL;
-
-       perf_event_grab_pmc();
-       event->destroy = hw_perf_event_destroy;
-
        /* We save the enable bits in the config_base.  So to
         * turn off sampling just write 'config', and to enable
         * things write 'config | config_base'.
@@ -411,15 +877,39 @@ static int __hw_perf_event_init(struct perf_event *event)
        if (!attr->exclude_hv)
                hwc->config_base |= sparc_pmu->hv_bit;
 
+       hwc->event_base = perf_event_encode(pmap);
+
+       enc = pmap->encoding;
+
+       n = 0;
+       if (event->group_leader != event) {
+               n = collect_events(event->group_leader,
+                                  perf_max_events - 1,
+                                  evts, events);
+               if (n < 0)
+                       return -EINVAL;
+       }
+       events[n] = hwc->event_base;
+       evts[n] = event;
+
+       if (check_excludes(evts, n, 1))
+               return -EINVAL;
+
+       if (sparc_check_constraints(events, n + 1))
+               return -EINVAL;
+
+       /* Try to do all error checking before this point, as unwinding
+        * state after grabbing the PMC is difficult.
+        */
+       perf_event_grab_pmc();
+       event->destroy = hw_perf_event_destroy;
+
        if (!hwc->sample_period) {
                hwc->sample_period = MAX_PERIOD;
                hwc->last_period = hwc->sample_period;
                atomic64_set(&hwc->period_left, hwc->sample_period);
        }
 
-       pmap = sparc_pmu->event_map(attr->config);
-
-       enc = pmap->encoding;
        if (pmap->pic_mask & PIC_UPPER) {
                hwc->idx = PIC_UPPER_INDEX;
                enc <<= sparc_pmu->upper_shift;
@@ -472,7 +962,7 @@ void perf_event_print_debug(void)
 }
 
 static int __kprobes perf_event_nmi_handler(struct notifier_block *self,
-                                             unsigned long cmd, void *__args)
+                                           unsigned long cmd, void *__args)
 {
        struct die_args *args = __args;
        struct perf_sample_data data;
@@ -513,7 +1003,7 @@ static int __kprobes perf_event_nmi_handler(struct notifier_block *self,
                        continue;
 
                if (perf_event_overflow(event, 1, &data, regs))
-                       sparc_pmu_disable_event(hwc, idx);
+                       sparc_pmu_disable_event(cpuc, hwc, idx);
        }
 
        return NOTIFY_STOP;
@@ -525,8 +1015,15 @@ static __read_mostly struct notifier_block perf_event_nmi_notifier = {
 
 static bool __init supported_pmu(void)
 {
-       if (!strcmp(sparc_pmu_type, "ultra3i")) {
-               sparc_pmu = &ultra3i_pmu;
+       if (!strcmp(sparc_pmu_type, "ultra3") ||
+           !strcmp(sparc_pmu_type, "ultra3+") ||
+           !strcmp(sparc_pmu_type, "ultra3i") ||
+           !strcmp(sparc_pmu_type, "ultra4+")) {
+               sparc_pmu = &ultra3_pmu;
+               return true;
+       }
+       if (!strcmp(sparc_pmu_type, "niagara")) {
+               sparc_pmu = &niagara1_pmu;
                return true;
        }
        if (!strcmp(sparc_pmu_type, "niagara2")) {
index a70a5e1..1886d37 100644 (file)
@@ -265,7 +265,7 @@ static void flush_dcache(unsigned long pfn)
        struct page *page;
 
        page = pfn_to_page(pfn);
-       if (page && page_mapping(page)) {
+       if (page) {
                unsigned long pg_flags;
 
                pg_flags = page->flags;
index f97cb8b..f9024bc 100644 (file)
@@ -11,6 +11,7 @@
 #include <linux/oprofile.h>
 #include <linux/errno.h>
 #include <linux/init.h>
+#include <linux/param.h>       /* for HZ */
  
 #ifdef CONFIG_SPARC64
 #include <linux/notifier.h>
index 14a102e..cf8a97f 100644 (file)
@@ -5,6 +5,7 @@
 
 #include "linux/irqreturn.h"
 #include "linux/kd.h"
+#include "linux/sched.h"
 #include "chan_kern.h"
 #include "irq_kern.h"
 #include "irq_user.h"
index 1993008..4ebc8a3 100644 (file)
@@ -7,6 +7,7 @@
 #include "linux/interrupt.h"
 #include "linux/list.h"
 #include "linux/mutex.h"
+#include "linux/workqueue.h"
 #include "asm/atomic.h"
 #include "init.h"
 #include "irq_kern.h"
index 454cdb4..039270b 100644 (file)
@@ -10,6 +10,7 @@
 #include "linux/interrupt.h"
 #include "linux/kernel_stat.h"
 #include "linux/module.h"
+#include "linux/sched.h"
 #include "linux/seq_file.h"
 #include "as-layout.h"
 #include "kern_util.h"
index 8da9374..72ace95 100644 (file)
@@ -86,10 +86,6 @@ config STACKTRACE_SUPPORT
 config HAVE_LATENCYTOP_SUPPORT
        def_bool y
 
-config FAST_CMPXCHG_LOCAL
-       bool
-       default y
-
 config MMU
        def_bool y
 
@@ -495,7 +491,7 @@ if PARAVIRT_GUEST
 source "arch/x86/xen/Kconfig"
 
 config VMI
-       bool "VMI Guest support"
+       bool "VMI Guest support (DEPRECATED)"
        select PARAVIRT
        depends on X86_32
        ---help---
@@ -504,6 +500,15 @@ config VMI
          at the moment), by linking the kernel to a GPL-ed ROM module
          provided by the hypervisor.
 
+         As of September 2009, VMware has started a phased retirement
+         of this feature from VMware's products. Please see
+         feature-removal-schedule.txt for details.  If you are
+         planning to enable this option, please note that you cannot
+         live migrate a VMI enabled VM to a future VMware product,
+         which doesn't support VMI. So if you expect your kernel to
+         seamlessly migrate to newer VMware products, keep this
+         disabled.
+
 config KVM_CLOCK
        bool "KVM paravirtualized clock"
        select PARAVIRT
@@ -1438,12 +1443,8 @@ config SECCOMP
 
          If unsure, say Y. Only embedded should say N here.
 
-config CC_STACKPROTECTOR_ALL
-       bool
-
 config CC_STACKPROTECTOR
        bool "Enable -fstack-protector buffer overflow detection (EXPERIMENTAL)"
-       select CC_STACKPROTECTOR_ALL
        ---help---
          This option turns on the -fstack-protector GCC feature. This
          feature puts, at the beginning of functions, a canary value on
index 527519b..2649840 100644 (file)
@@ -400,7 +400,7 @@ config X86_TSC
 
 config X86_CMPXCHG64
        def_bool y
-       depends on X86_PAE || X86_64
+       depends on !M386 && !M486
 
 # this should be set for all -march=.. options where the compiler
 # generates cmov.
@@ -412,6 +412,7 @@ config X86_MINIMUM_CPU_FAMILY
        int
        default "64" if X86_64
        default "6" if X86_32 && X86_P6_NOP
+       default "5" if X86_32 && X86_CMPXCHG64
        default "4" if X86_32 && (X86_XADD || X86_CMPXCHG || X86_BSWAP || X86_WP_WORKS_OK)
        default "3"
 
index a012ee8..d2d24c9 100644 (file)
@@ -76,7 +76,6 @@ ifdef CONFIG_CC_STACKPROTECTOR
        cc_has_sp := $(srctree)/scripts/gcc-x86_$(BITS)-has-stack-protector.sh
         ifeq ($(shell $(CONFIG_SHELL) $(cc_has_sp) $(CC) $(biarch)),y)
                 stackp-y := -fstack-protector
-                stackp-$(CONFIG_CC_STACKPROTECTOR_ALL) += -fstack-protector-all
                 KBUILD_CFLAGS += $(stackp-y)
         else
                 $(warning stack protector enabled but no compiler support)
index 0f6ec45..03c0683 100644 (file)
@@ -53,6 +53,9 @@ SECTIONS
 
        /DISCARD/ : { *(.note*) }
 
+       /*
+        * The ASSERT() sink to . is intentional, for binutils 2.14 compatibility:
+        */
        . = ASSERT(_end <= 0x8000, "Setup too big!");
        . = ASSERT(hdr == 0x1f1, "The setup header has the wrong offset!");
        /* Necessary for the very-old-loader check to work... */
index 585edeb..49c552c 100644 (file)
@@ -82,7 +82,7 @@ static int aes_set_key_common(struct crypto_tfm *tfm, void *raw_ctx,
                return -EINVAL;
        }
 
-       if (irq_fpu_usable())
+       if (!irq_fpu_usable())
                err = crypto_aes_expand_key(ctx, in_key, key_len);
        else {
                kernel_fpu_begin();
@@ -103,7 +103,7 @@ static void aes_encrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
 {
        struct crypto_aes_ctx *ctx = aes_ctx(crypto_tfm_ctx(tfm));
 
-       if (irq_fpu_usable())
+       if (!irq_fpu_usable())
                crypto_aes_encrypt_x86(ctx, dst, src);
        else {
                kernel_fpu_begin();
@@ -116,7 +116,7 @@ static void aes_decrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
 {
        struct crypto_aes_ctx *ctx = aes_ctx(crypto_tfm_ctx(tfm));
 
-       if (irq_fpu_usable())
+       if (!irq_fpu_usable())
                crypto_aes_decrypt_x86(ctx, dst, src);
        else {
                kernel_fpu_begin();
@@ -342,7 +342,7 @@ static int ablk_encrypt(struct ablkcipher_request *req)
        struct crypto_ablkcipher *tfm = crypto_ablkcipher_reqtfm(req);
        struct async_aes_ctx *ctx = crypto_ablkcipher_ctx(tfm);
 
-       if (irq_fpu_usable()) {
+       if (!irq_fpu_usable()) {
                struct ablkcipher_request *cryptd_req =
                        ablkcipher_request_ctx(req);
                memcpy(cryptd_req, req, sizeof(*req));
@@ -363,7 +363,7 @@ static int ablk_decrypt(struct ablkcipher_request *req)
        struct crypto_ablkcipher *tfm = crypto_ablkcipher_reqtfm(req);
        struct async_aes_ctx *ctx = crypto_ablkcipher_ctx(tfm);
 
-       if (irq_fpu_usable()) {
+       if (!irq_fpu_usable()) {
                struct ablkcipher_request *cryptd_req =
                        ablkcipher_request_ctx(req);
                memcpy(cryptd_req, req, sizeof(*req));
index 74619c4..581b056 100644 (file)
@@ -21,8 +21,8 @@
 #define __AUDIT_ARCH_LE           0x40000000
 
 #ifndef CONFIG_AUDITSYSCALL
-#define sysexit_audit int_ret_from_sys_call
-#define sysretl_audit int_ret_from_sys_call
+#define sysexit_audit ia32_ret_from_sys_call
+#define sysretl_audit ia32_ret_from_sys_call
 #endif
 
 #define IA32_NR_syscalls ((ia32_syscall_end - ia32_sys_call_table)/8)
        .endm 
 
        /* clobbers %eax */     
-       .macro  CLEAR_RREGS _r9=rax
+       .macro  CLEAR_RREGS offset=0, _r9=rax
        xorl    %eax,%eax
-       movq    %rax,R11(%rsp)
-       movq    %rax,R10(%rsp)
-       movq    %\_r9,R9(%rsp)
-       movq    %rax,R8(%rsp)
+       movq    %rax,\offset+R11(%rsp)
+       movq    %rax,\offset+R10(%rsp)
+       movq    %\_r9,\offset+R9(%rsp)
+       movq    %rax,\offset+R8(%rsp)
        .endm
 
        /*
@@ -172,6 +172,10 @@ sysexit_from_sys_call:
        movl    RIP-R11(%rsp),%edx              /* User %eip */
        CFI_REGISTER rip,rdx
        RESTORE_ARGS 1,24,1,1,1,1
+       xorq    %r8,%r8
+       xorq    %r9,%r9
+       xorq    %r10,%r10
+       xorq    %r11,%r11
        popfq
        CFI_ADJUST_CFA_OFFSET -8
        /*CFI_RESTORE rflags*/
@@ -200,9 +204,9 @@ sysexit_from_sys_call:
        movl RDI-ARGOFFSET(%rsp),%r8d   /* reload 5th syscall arg */
        .endm
 
-       .macro auditsys_exit exit,ebpsave=RBP
+       .macro auditsys_exit exit
        testl $(_TIF_ALLWORK_MASK & ~_TIF_SYSCALL_AUDIT),TI_flags(%r10)
-       jnz int_ret_from_sys_call
+       jnz ia32_ret_from_sys_call
        TRACE_IRQS_ON
        sti
        movl %eax,%esi          /* second arg, syscall return value */
@@ -213,13 +217,13 @@ sysexit_from_sys_call:
        call audit_syscall_exit
        GET_THREAD_INFO(%r10)
        movl RAX-ARGOFFSET(%rsp),%eax   /* reload syscall return value */
-       movl \ebpsave-ARGOFFSET(%rsp),%ebp /* reload user register value */
        movl $(_TIF_ALLWORK_MASK & ~_TIF_SYSCALL_AUDIT),%edi
        cli
        TRACE_IRQS_OFF
        testl %edi,TI_flags(%r10)
-       jnz int_with_check
-       jmp \exit
+       jz \exit
+       CLEAR_RREGS -ARGOFFSET
+       jmp int_with_check
        .endm
 
 sysenter_auditsys:
@@ -329,6 +333,9 @@ sysretl_from_sys_call:
        CFI_REGISTER rip,rcx
        movl EFLAGS-ARGOFFSET(%rsp),%r11d       
        /*CFI_REGISTER rflags,r11*/
+       xorq    %r10,%r10
+       xorq    %r9,%r9
+       xorq    %r8,%r8
        TRACE_IRQS_ON
        movl RSP-ARGOFFSET(%rsp),%esp
        CFI_RESTORE rsp
@@ -343,7 +350,7 @@ cstar_auditsys:
        jmp cstar_dispatch
 
 sysretl_audit:
-       auditsys_exit sysretl_from_sys_call, RCX /* user %ebp in RCX slot */
+       auditsys_exit sysretl_from_sys_call
 #endif
 
 cstar_tracesys:
@@ -353,7 +360,7 @@ cstar_tracesys:
 #endif
        xchgl %r9d,%ebp
        SAVE_REST
-       CLEAR_RREGS r9
+       CLEAR_RREGS 0, r9
        movq $-ENOSYS,RAX(%rsp) /* ptrace can change this for a bad syscall */
        movq %rsp,%rdi        /* &pt_regs -> arg1 */
        call syscall_trace_enter
@@ -425,6 +432,8 @@ ia32_do_call:
        call *ia32_sys_call_table(,%rax,8) # xxx: rip relative
 ia32_sysret:
        movq %rax,RAX-ARGOFFSET(%rsp)
+ia32_ret_from_sys_call:
+       CLEAR_RREGS -ARGOFFSET
        jmp int_ret_from_sys_call 
 
 ia32_tracesys:                  
@@ -442,8 +451,8 @@ END(ia32_syscall)
 
 ia32_badsys:
        movq $0,ORIG_RAX-ARGOFFSET(%rsp)
-       movq $-ENOSYS,RAX-ARGOFFSET(%rsp)
-       jmp int_ret_from_sys_call
+       movq $-ENOSYS,%rax
+       jmp ia32_sysret
 
 quiet_ni_syscall:
        movq $-ENOSYS,%rax
index 3be0004..d838922 100644 (file)
@@ -796,6 +796,7 @@ asmlinkage void kvm_handle_fault_on_reboot(void);
 #define KVM_ARCH_WANT_MMU_NOTIFIER
 int kvm_unmap_hva(struct kvm *kvm, unsigned long hva);
 int kvm_age_hva(struct kvm *kvm, unsigned long hva);
+void kvm_set_spte_hva(struct kvm *kvm, unsigned long hva, pte_t pte);
 int cpuid_maxphyaddr(struct kvm_vcpu *vcpu);
 int kvm_cpu_has_interrupt(struct kvm_vcpu *vcpu);
 int kvm_arch_interrupt_allowed(struct kvm_vcpu *vcpu);
index b608a64..f1363b7 100644 (file)
@@ -133,6 +133,8 @@ static inline void winchip_mcheck_init(struct cpuinfo_x86 *c) {}
 static inline void enable_p5_mce(void) {}
 #endif
 
+extern void (*x86_mce_decode_callback)(struct mce *m);
+
 void mce_setup(struct mce *m);
 void mce_log(struct mce *m);
 DECLARE_PER_CPU(struct sys_device, mce_dev);
index 8aebcc4..efb3899 100644 (file)
@@ -840,42 +840,22 @@ static __always_inline void __raw_spin_unlock(struct raw_spinlock *lock)
 
 static inline unsigned long __raw_local_save_flags(void)
 {
-       unsigned long f;
-
-       asm volatile(paravirt_alt(PARAVIRT_CALL)
-                    : "=a"(f)
-                    : paravirt_type(pv_irq_ops.save_fl),
-                      paravirt_clobber(CLBR_EAX)
-                    : "memory", "cc");
-       return f;
+       return PVOP_CALLEE0(unsigned long, pv_irq_ops.save_fl);
 }
 
 static inline void raw_local_irq_restore(unsigned long f)
 {
-       asm volatile(paravirt_alt(PARAVIRT_CALL)
-                    : "=a"(f)
-                    : PV_FLAGS_ARG(f),
-                      paravirt_type(pv_irq_ops.restore_fl),
-                      paravirt_clobber(CLBR_EAX)
-                    : "memory", "cc");
+       PVOP_VCALLEE1(pv_irq_ops.restore_fl, f);
 }
 
 static inline void raw_local_irq_disable(void)
 {
-       asm volatile(paravirt_alt(PARAVIRT_CALL)
-                    :
-                    : paravirt_type(pv_irq_ops.irq_disable),
-                      paravirt_clobber(CLBR_EAX)
-                    : "memory", "eax", "cc");
+       PVOP_VCALLEE0(pv_irq_ops.irq_disable);
 }
 
 static inline void raw_local_irq_enable(void)
 {
-       asm volatile(paravirt_alt(PARAVIRT_CALL)
-                    :
-                    : paravirt_type(pv_irq_ops.irq_enable),
-                      paravirt_clobber(CLBR_EAX)
-                    : "memory", "eax", "cc");
+       PVOP_VCALLEE0(pv_irq_ops.irq_enable);
 }
 
 static inline unsigned long __raw_local_irq_save(void)
index dd0f5b3..9357473 100644 (file)
@@ -494,10 +494,11 @@ int paravirt_disable_iospace(void);
 #define EXTRA_CLOBBERS
 #define VEXTRA_CLOBBERS
 #else  /* CONFIG_X86_64 */
+/* [re]ax isn't an arg, but the return val */
 #define PVOP_VCALL_ARGS                                        \
        unsigned long __edi = __edi, __esi = __esi,     \
-               __edx = __edx, __ecx = __ecx
-#define PVOP_CALL_ARGS         PVOP_VCALL_ARGS, __eax
+               __edx = __edx, __ecx = __ecx, __eax = __eax
+#define PVOP_CALL_ARGS         PVOP_VCALL_ARGS
 
 #define PVOP_CALL_ARG1(x)              "D" ((unsigned long)(x))
 #define PVOP_CALL_ARG2(x)              "S" ((unsigned long)(x))
@@ -509,6 +510,7 @@ int paravirt_disable_iospace(void);
                                "=c" (__ecx)
 #define PVOP_CALL_CLOBBERS     PVOP_VCALL_CLOBBERS, "=a" (__eax)
 
+/* void functions are still allowed [re]ax for scratch */
 #define PVOP_VCALLEE_CLOBBERS  "=a" (__eax)
 #define PVOP_CALLEE_CLOBBERS   PVOP_VCALLEE_CLOBBERS
 
@@ -583,8 +585,8 @@ int paravirt_disable_iospace(void);
                       VEXTRA_CLOBBERS,                                 \
                       pre, post, ##__VA_ARGS__)
 
-#define __PVOP_VCALLEESAVE(rettype, op, pre, post, ...)                        \
-       ____PVOP_CALL(rettype, op.func, CLBR_RET_REG,                   \
+#define __PVOP_VCALLEESAVE(op, pre, post, ...)                         \
+       ____PVOP_VCALL(op.func, CLBR_RET_REG,                           \
                      PVOP_VCALLEE_CLOBBERS, ,                          \
                      pre, post, ##__VA_ARGS__)
 
index 25a9284..d823c24 100644 (file)
@@ -143,6 +143,7 @@ extern unsigned long node_remap_size[];
                                | 1*SD_BALANCE_FORK                     \
                                | 0*SD_BALANCE_WAKE                     \
                                | 1*SD_WAKE_AFFINE                      \
+                               | 1*SD_PREFER_LOCAL                     \
                                | 0*SD_SHARE_CPUPOWER                   \
                                | 0*SD_POWERSAVINGS_BALANCE             \
                                | 0*SD_SHARE_PKG_RESOURCES              \
index 04eb6c9..d1414af 100644 (file)
@@ -19,6 +19,8 @@
 #include <asm/types.h>
 #include <asm/percpu.h>
 #include <asm/uv/uv_mmrs.h>
+#include <asm/irq_vectors.h>
+#include <asm/io_apic.h>
 
 
 /*
 /*
  * The largest possible NASID of a C or M brick (+ 2)
  */
-#define UV_MAX_NASID_VALUE     (UV_MAX_NUMALINK_NODES * 2)
+#define UV_MAX_NASID_VALUE     (UV_MAX_NUMALINK_BLADES * 2)
 
 struct uv_scir_s {
        struct timer_list timer;
@@ -230,6 +232,20 @@ static inline unsigned long uv_gpa(void *v)
        return uv_soc_phys_ram_to_gpa(__pa(v));
 }
 
+/* gnode -> pnode */
+static inline unsigned long uv_gpa_to_gnode(unsigned long gpa)
+{
+       return gpa >> uv_hub_info->m_val;
+}
+
+/* gpa -> pnode */
+static inline int uv_gpa_to_pnode(unsigned long gpa)
+{
+       unsigned long n_mask = (1UL << uv_hub_info->n_val) - 1;
+
+       return uv_gpa_to_gnode(gpa) & n_mask;
+}
+
 /* pnode, offset --> socket virtual */
 static inline void *uv_pnode_offset_to_vaddr(int pnode, unsigned long offset)
 {
@@ -421,9 +437,14 @@ static inline void uv_set_cpu_scir_bits(int cpu, unsigned char value)
 static inline void uv_hub_send_ipi(int pnode, int apicid, int vector)
 {
        unsigned long val;
+       unsigned long dmode = dest_Fixed;
+
+       if (vector == NMI_VECTOR)
+               dmode = dest_NMI;
 
        val = (1UL << UVH_IPI_INT_SEND_SHFT) |
                        ((apicid) << UVH_IPI_INT_APIC_ID_SHFT) |
+                       (dmode << UVH_IPI_INT_DELIVERY_MODE_SHFT) |
                        (vector << UVH_IPI_INT_VECTOR_SHFT);
        uv_write_global_mmr64(pnode, UVH_IPI_INT, val);
 }
index 7da00b7..060fff8 100644 (file)
@@ -57,5 +57,8 @@ SECTIONS
                *(.note*)
        }
 
+       /*
+        * The ASSERT() sink to . is intentional, for binutils 2.14 compatibility:
+        */
        . = ASSERT(_end <= WAKEUP_SIZE, "Wakeup too big!");
 }
index f5f5886..326c254 100644 (file)
@@ -352,14 +352,14 @@ static __init void get_lowmem_redirect(unsigned long *base, unsigned long *size)
 
        for (i = 0; i < ARRAY_SIZE(redir_addrs); i++) {
                alias.v = uv_read_local_mmr(redir_addrs[i].alias);
-               if (alias.s.base == 0) {
+               if (alias.s.enable && alias.s.base == 0) {
                        *size = (1UL << alias.s.m_alias);
                        redirect.v = uv_read_local_mmr(redir_addrs[i].redirect);
                        *base = (unsigned long)redirect.s.dest_base << DEST_SHIFT;
                        return;
                }
        }
-       BUG();
+       *base = *size = 0;
 }
 
 enum map_type {map_wb, map_uc};
@@ -619,12 +619,12 @@ void __init uv_system_init(void)
                uv_cpu_hub_info(cpu)->lowmem_remap_base = lowmem_redir_base;
                uv_cpu_hub_info(cpu)->lowmem_remap_top = lowmem_redir_size;
                uv_cpu_hub_info(cpu)->m_val = m_val;
-               uv_cpu_hub_info(cpu)->n_val = m_val;
+               uv_cpu_hub_info(cpu)->n_val = n_val;
                uv_cpu_hub_info(cpu)->numa_blade_id = blade;
                uv_cpu_hub_info(cpu)->blade_processor_id = lcpu;
                uv_cpu_hub_info(cpu)->pnode = pnode;
                uv_cpu_hub_info(cpu)->pnode_mask = pnode_mask;
-               uv_cpu_hub_info(cpu)->gpa_mask = (1 << (m_val + n_val)) - 1;
+               uv_cpu_hub_info(cpu)->gpa_mask = (1UL << (m_val + n_val)) - 1;
                uv_cpu_hub_info(cpu)->gnode_upper = gnode_upper;
                uv_cpu_hub_info(cpu)->gnode_extra = gnode_extra;
                uv_cpu_hub_info(cpu)->global_mmr_base = mmr_base;
index 183c345..721a77c 100644 (file)
@@ -85,6 +85,18 @@ static DECLARE_WAIT_QUEUE_HEAD(mce_wait);
 static DEFINE_PER_CPU(struct mce, mces_seen);
 static int                     cpu_missing;
 
+static void default_decode_mce(struct mce *m)
+{
+       pr_emerg("No human readable MCE decoding support on this CPU type.\n");
+       pr_emerg("Run the message through 'mcelog --ascii' to decode.\n");
+}
+
+/*
+ * CPU/chipset specific EDAC code can register a callback here to print
+ * MCE errors in a human-readable form:
+ */
+void (*x86_mce_decode_callback)(struct mce *m) = default_decode_mce;
+EXPORT_SYMBOL(x86_mce_decode_callback);
 
 /* MCA banks polled by the period polling timer for corrected events */
 DEFINE_PER_CPU(mce_banks_t, mce_poll_banks) = {
@@ -165,46 +177,46 @@ void mce_log(struct mce *mce)
        set_bit(0, &mce_need_notify);
 }
 
-void __weak decode_mce(struct mce *m)
-{
-       return;
-}
-
 static void print_mce(struct mce *m)
 {
-       printk(KERN_EMERG
-              "CPU %d: Machine Check Exception: %16Lx Bank %d: %016Lx\n",
+       pr_emerg("CPU %d: Machine Check Exception: %16Lx Bank %d: %016Lx\n",
               m->extcpu, m->mcgstatus, m->bank, m->status);
+
        if (m->ip) {
-               printk(KERN_EMERG "RIP%s %02x:<%016Lx> ",
-                      !(m->mcgstatus & MCG_STATUS_EIPV) ? " !INEXACT!" : "",
-                      m->cs, m->ip);
+               pr_emerg("RIP%s %02x:<%016Lx> ",
+                       !(m->mcgstatus & MCG_STATUS_EIPV) ? " !INEXACT!" : "",
+                               m->cs, m->ip);
+
                if (m->cs == __KERNEL_CS)
                        print_symbol("{%s}", m->ip);
-               printk(KERN_CONT "\n");
+               pr_cont("\n");
        }
-       printk(KERN_EMERG "TSC %llx ", m->tsc);
+
+       pr_emerg("TSC %llx ", m->tsc);
        if (m->addr)
-               printk(KERN_CONT "ADDR %llx ", m->addr);
+               pr_cont("ADDR %llx ", m->addr);
        if (m->misc)
-               printk(KERN_CONT "MISC %llx ", m->misc);
-       printk(KERN_CONT "\n");
-       printk(KERN_EMERG "PROCESSOR %u:%x TIME %llu SOCKET %u APIC %x\n",
-                       m->cpuvendor, m->cpuid, m->time, m->socketid,
-                       m->apicid);
+               pr_cont("MISC %llx ", m->misc);
 
-       decode_mce(m);
+       pr_cont("\n");
+       pr_emerg("PROCESSOR %u:%x TIME %llu SOCKET %u APIC %x\n",
+               m->cpuvendor, m->cpuid, m->time, m->socketid, m->apicid);
+
+       /*
+        * Print out human-readable details about the MCE error,
+        * (if the CPU has an implementation for that):
+        */
+       x86_mce_decode_callback(m);
 }
 
 static void print_mce_head(void)
 {
-       printk(KERN_EMERG "\nHARDWARE ERROR\n");
+       pr_emerg("\nHARDWARE ERROR\n");
 }
 
 static void print_mce_tail(void)
 {
-       printk(KERN_EMERG "This is not a software problem!\n"
-              "Run through mcelog --ascii to decode and contact your hardware vendor\n");
+       pr_emerg("This is not a software problem!\n");
 }
 
 #define PANIC_TIMEOUT 5 /* 5 seconds */
@@ -218,6 +230,7 @@ static atomic_t mce_fake_paniced;
 static void wait_for_panic(void)
 {
        long timeout = PANIC_TIMEOUT*USEC_PER_SEC;
+
        preempt_disable();
        local_irq_enable();
        while (timeout-- > 0)
@@ -285,6 +298,7 @@ static void mce_panic(char *msg, struct mce *final, char *exp)
 static int msr_to_offset(u32 msr)
 {
        unsigned bank = __get_cpu_var(injectm.bank);
+
        if (msr == rip_msr)
                return offsetof(struct mce, ip);
        if (msr == MSR_IA32_MCx_STATUS(bank))
@@ -1200,7 +1214,8 @@ static int __cpuinit mce_cap_init(void)
        rdmsrl(MSR_IA32_MCG_CAP, cap);
 
        b = cap & MCG_BANKCNT_MASK;
-       printk(KERN_INFO "mce: CPU supports %d MCE banks\n", b);
+       if (!banks)
+               printk(KERN_INFO "mce: CPU supports %d MCE banks\n", b);
 
        if (b > MAX_NR_BANKS) {
                printk(KERN_WARNING
index 889f665..7c78563 100644 (file)
@@ -8,6 +8,7 @@
 #include <linux/init.h>
 #include <linux/interrupt.h>
 #include <linux/percpu.h>
+#include <linux/sched.h>
 #include <asm/apic.h>
 #include <asm/processor.h>
 #include <asm/msr.h>
index f04e725..3c1b12d 100644 (file)
@@ -96,17 +96,24 @@ mtrr_write(struct file *file, const char __user *buf, size_t len, loff_t * ppos)
        unsigned long long base, size;
        char *ptr;
        char line[LINE_SIZE];
+       int length;
        size_t linelen;
 
        if (!capable(CAP_SYS_ADMIN))
                return -EPERM;
-       if (!len)
-               return -EINVAL;
 
        memset(line, 0, LINE_SIZE);
-       if (len > LINE_SIZE)
-               len = LINE_SIZE;
-       if (copy_from_user(line, buf, len - 1))
+
+       length = len;
+       length--;
+
+       if (length > LINE_SIZE - 1)
+               length = LINE_SIZE - 1;
+
+       if (length < 0)
+               return -EINVAL;
+
+       if (copy_from_user(line, buf, length))
                return -EFAULT;
 
        linelen = strlen(line);
index f7cdb3b..cd97ce1 100644 (file)
@@ -16,6 +16,22 @@ static void *kdump_buf_page;
 /* Stores the physical address of elf header of crash image. */
 unsigned long long elfcorehdr_addr = ELFCORE_ADDR_MAX;
 
+static inline bool is_crashed_pfn_valid(unsigned long pfn)
+{
+#ifndef CONFIG_X86_PAE
+       /*
+        * non-PAE kdump kernel executed from a PAE one will crop high pte
+        * bits and poke unwanted space counting again from address 0, we
+        * don't want that. pte must fit into unsigned long. In fact the
+        * test checks high 12 bits for being zero (pfn will be shifted left
+        * by PAGE_SHIFT).
+        */
+       return pte_pfn(pfn_pte(pfn, __pgprot(0))) == pfn;
+#else
+       return true;
+#endif
+}
+
 /**
  * copy_oldmem_page - copy one page from "oldmem"
  * @pfn: page frame number to be copied
@@ -41,6 +57,9 @@ ssize_t copy_oldmem_page(unsigned long pfn, char *buf,
        if (!csize)
                return 0;
 
+       if (!is_crashed_pfn_valid(pfn))
+               return -EFAULT;
+
        vaddr = kmap_atomic_pfn(pfn, KM_PTE0);
 
        if (!userbuf) {
index 85419bb..d17d482 100644 (file)
@@ -1378,8 +1378,8 @@ static unsigned long ram_alignment(resource_size_t pos)
        if (mb < 16)
                return 1024*1024;
 
-       /* To 32MB for anything above that */
-       return 32*1024*1024;
+       /* To 64MB for anything above that */
+       return 64*1024*1024;
 }
 
 #define MAX_RESOURCE_SIZE ((resource_size_t)-1)
index 41fd965..b9c830c 100644 (file)
@@ -206,8 +206,11 @@ static int __init setup_early_printk(char *buf)
 
        while (*buf != '\0') {
                if (!strncmp(buf, "serial", 6)) {
-                       early_serial_init(buf + 6);
+                       buf += 6;
+                       early_serial_init(buf);
                        early_console_register(&early_serial_console, keep);
+                       if (!strncmp(buf, ",ttyS", 5))
+                               buf += 5;
                }
                if (!strncmp(buf, "ttyS", 4)) {
                        early_serial_init(buf + 4);
index ad5bd98..cdcfb12 100644 (file)
@@ -454,8 +454,10 @@ void __init efi_init(void)
        if (add_efi_memmap)
                do_add_efi_memmap();
 
+#ifdef CONFIG_X86_32
        x86_platform.get_wallclock = efi_get_time;
        x86_platform.set_wallclock = efi_set_rtc_mmss;
+#endif
 
        /* Setup for EFI runtime service */
        reboot_type = BOOT_EFI;
index 1736c5a..9c3bd4a 100644 (file)
@@ -15,8 +15,10 @@ EXPORT_SYMBOL(mcount);
  * the export, but dont use it from C code, it is used
  * by assembly code and is not using C calling convention!
  */
+#ifndef CONFIG_X86_CMPXCHG64
 extern void cmpxchg8b_emu(void);
 EXPORT_SYMBOL(cmpxchg8b_emu);
+#endif
 
 /* Networking helper routines. */
 EXPORT_SYMBOL(csum_partial_copy_generic);
index 74656d1..04bbd52 100644 (file)
@@ -63,10 +63,10 @@ static int show_other_interrupts(struct seq_file *p, int prec)
        for_each_online_cpu(j)
                seq_printf(p, "%10u ", irq_stats(j)->irq_spurious_count);
        seq_printf(p, "  Spurious interrupts\n");
-       seq_printf(p, "%*s: ", prec, "CNT");
+       seq_printf(p, "%*s: ", prec, "PMI");
        for_each_online_cpu(j)
                seq_printf(p, "%10u ", irq_stats(j)->apic_perf_irqs);
-       seq_printf(p, "  Performance counter interrupts\n");
+       seq_printf(p, "  Performance monitoring interrupts\n");
        seq_printf(p, "%*s: ", prec, "PND");
        for_each_online_cpu(j)
                seq_printf(p, "%10u ", irq_stats(j)->apic_pending_irqs);
index 64b838e..b2a71dc 100644 (file)
@@ -35,7 +35,7 @@ int iommu_detected __read_mostly = 0;
 
 /*
  * This variable becomes 1 if iommu=pt is passed on the kernel command line.
- * If this variable is 1, IOMMU implementations do no DMA ranslation for
+ * If this variable is 1, IOMMU implementations do no DMA translation for
  * devices and allow every device to access to whole physical memory. This is
  * useful if a user want to use an IOMMU only for KVM device assignment to
  * guests and not for driver dma translation.
@@ -311,7 +311,7 @@ void pci_iommu_shutdown(void)
        amd_iommu_shutdown();
 }
 /* Must execute after PCI subsystem */
-fs_initcall(pci_iommu_init);
+rootfs_initcall(pci_iommu_init);
 
 #ifdef CONFIG_PCI
 /* Many VIA bridges seem to corrupt data for DAC. Disable it here */
index 98a827e..a7f1b64 100644 (file)
@@ -16,6 +16,7 @@
 #include <linux/agp_backend.h>
 #include <linux/init.h>
 #include <linux/mm.h>
+#include <linux/sched.h>
 #include <linux/string.h>
 #include <linux/spinlock.h>
 #include <linux/pci.h>
index 27349f9..a1a3cdd 100644 (file)
@@ -4,6 +4,7 @@
 #include <linux/pm.h>
 #include <linux/efi.h>
 #include <linux/dmi.h>
+#include <linux/sched.h>
 #include <linux/tboot.h>
 #include <acpi/reboot.h>
 #include <asm/io.h>
index dcb00d2..be25734 100644 (file)
@@ -38,7 +38,8 @@ unsigned long profile_pc(struct pt_regs *regs)
 #ifdef CONFIG_FRAME_POINTER
                return *(unsigned long *)(regs->bp + sizeof(long));
 #else
-               unsigned long *sp = (unsigned long *)regs->sp;
+               unsigned long *sp =
+                       (unsigned long *)kernel_stack_pointer(regs);
                /*
                 * Return address is either directly at stack pointer
                 * or above a saved flags. Eflags has bits 22-31 zero,
index 503c1f2..1740c85 100644 (file)
@@ -23,8 +23,6 @@
 static struct bau_control      **uv_bau_table_bases __read_mostly;
 static int                     uv_bau_retry_limit __read_mostly;
 
-/* position of pnode (which is nasid>>1): */
-static int                     uv_nshift __read_mostly;
 /* base pnode in this partition */
 static int                     uv_partition_base_pnode __read_mostly;
 
@@ -723,7 +721,7 @@ uv_activation_descriptor_init(int node, int pnode)
        BUG_ON(!adp);
 
        pa = uv_gpa(adp); /* need the real nasid*/
-       n = pa >> uv_nshift;
+       n = uv_gpa_to_pnode(pa);
        m = pa & uv_mmask;
 
        uv_write_global_mmr64(pnode, UVH_LB_BAU_SB_DESCRIPTOR_BASE,
@@ -778,7 +776,7 @@ uv_payload_queue_init(int node, int pnode, struct bau_control *bau_tablesp)
         * need the pnode of where the memory was really allocated
         */
        pa = uv_gpa(pqp);
-       pn = pa >> uv_nshift;
+       pn = uv_gpa_to_pnode(pa);
        uv_write_global_mmr64(pnode,
                              UVH_LB_BAU_INTD_PAYLOAD_QUEUE_FIRST,
                              ((unsigned long)pn << UV_PAYLOADQ_PNODE_SHIFT) |
@@ -843,8 +841,7 @@ static int __init uv_bau_init(void)
                                       GFP_KERNEL, cpu_to_node(cur_cpu));
 
        uv_bau_retry_limit = 1;
-       uv_nshift = uv_hub_info->n_val;
-       uv_mmask = (1UL << uv_hub_info->n_val) - 1;
+       uv_mmask = (1UL << uv_hub_info->m_val) - 1;
        nblades = uv_num_possible_blades();
 
        uv_bau_table_bases = (struct bau_control **)
index 699f7ee..cd02212 100644 (file)
@@ -3,8 +3,16 @@
 #include <asm/trampoline.h>
 #include <asm/e820.h>
 
+#if defined(CONFIG_X86_64) && defined(CONFIG_ACPI_SLEEP)
+#define __trampinit
+#define __trampinitdata
+#else
+#define __trampinit __cpuinit
+#define __trampinitdata __cpuinitdata
+#endif
+
 /* ready for x86_64 and x86 */
-unsigned char *__cpuinitdata trampoline_base = __va(TRAMPOLINE_BASE);
+unsigned char *__trampinitdata trampoline_base = __va(TRAMPOLINE_BASE);
 
 void __init reserve_trampoline_memory(void)
 {
@@ -26,7 +34,7 @@ void __init reserve_trampoline_memory(void)
  * bootstrap into the page concerned. The caller
  * has made sure it's suitably aligned.
  */
-unsigned long __cpuinit setup_trampoline(void)
+unsigned long __trampinit setup_trampoline(void)
 {
        memcpy(trampoline_base, trampoline_data, TRAMPOLINE_SIZE);
        return virt_to_phys(trampoline_base);
index 596d54c..3af2dff 100644 (file)
 #include <asm/segment.h>
 #include <asm/processor-flags.h>
 
+#ifdef CONFIG_ACPI_SLEEP
+.section .rodata, "a", @progbits
+#else
 /* We can free up the trampoline after bootup if cpu hotplug is not supported. */
 __CPUINITRODATA
+#endif
 .code16
 
 ENTRY(trampoline_data)
index 31e6f6c..d430e4c 100644 (file)
@@ -648,7 +648,7 @@ static inline int __init activate_vmi(void)
 
        pv_info.paravirt_enabled = 1;
        pv_info.kernel_rpl = kernel_cs & SEGMENT_RPL_MASK;
-       pv_info.name = "vmi";
+       pv_info.name = "vmi [deprecated]";
 
        pv_init_ops.patch = vmi_patch;
 
index 92929fb..3c68fe2 100644 (file)
@@ -305,6 +305,9 @@ SECTIONS
 
 
 #ifdef CONFIG_X86_32
+/*
+ * The ASSERT() sink to . is intentional, for binutils 2.14 compatibility:
+ */
 . = ASSERT((_end - LOAD_OFFSET <= KERNEL_IMAGE_SIZE),
           "kernel image bigger than KERNEL_IMAGE_SIZE");
 #else
index 82ad523..144e7f6 100644 (file)
@@ -116,7 +116,7 @@ static s64 __kpit_elapsed(struct kvm *kvm)
         * itself with the initial count and continues counting
         * from there.
         */
-       remaining = hrtimer_expires_remaining(&ps->pit_timer.timer);
+       remaining = hrtimer_get_remaining(&ps->pit_timer.timer);
        elapsed = ps->pit_timer.period - ktime_to_ns(remaining);
        elapsed = mod_64(elapsed, ps->pit_timer.period);
 
index 1ae5ceb..23c2176 100644 (file)
@@ -521,7 +521,7 @@ static u32 apic_get_tmcct(struct kvm_lapic *apic)
        if (apic_get_reg(apic, APIC_TMICT) == 0)
                return 0;
 
-       remaining = hrtimer_expires_remaining(&apic->lapic_timer.timer);
+       remaining = hrtimer_get_remaining(&apic->lapic_timer.timer);
        if (ktime_to_ns(remaining) < 0)
                remaining = ktime_set(0, 0);
 
@@ -664,7 +664,7 @@ static void start_apic_timer(struct kvm_lapic *apic)
 {
        ktime_t now = apic->lapic_timer.timer.base->get_time();
 
-       apic->lapic_timer.period = apic_get_reg(apic, APIC_TMICT) *
+       apic->lapic_timer.period = (u64)apic_get_reg(apic, APIC_TMICT) *
                    APIC_BUS_CYCLE_NS * apic->divide_count;
        atomic_set(&apic->lapic_timer.pending, 0);
 
index eca41ae..818b92a 100644 (file)
@@ -156,6 +156,8 @@ module_param(oos_shadow, bool, 0644);
 #define CREATE_TRACE_POINTS
 #include "mmutrace.h"
 
+#define SPTE_HOST_WRITEABLE (1ULL << PT_FIRST_AVAIL_BITS_SHIFT)
+
 #define SHADOW_PT_INDEX(addr, level) PT64_INDEX(addr, level)
 
 struct kvm_rmap_desc {
@@ -634,9 +636,7 @@ static void rmap_remove(struct kvm *kvm, u64 *spte)
        if (*spte & shadow_accessed_mask)
                kvm_set_pfn_accessed(pfn);
        if (is_writeble_pte(*spte))
-               kvm_release_pfn_dirty(pfn);
-       else
-               kvm_release_pfn_clean(pfn);
+               kvm_set_pfn_dirty(pfn);
        rmapp = gfn_to_rmap(kvm, sp->gfns[spte - sp->spt], sp->role.level);
        if (!*rmapp) {
                printk(KERN_ERR "rmap_remove: %p %llx 0->BUG\n", spte, *spte);
@@ -748,7 +748,8 @@ static int rmap_write_protect(struct kvm *kvm, u64 gfn)
        return write_protected;
 }
 
-static int kvm_unmap_rmapp(struct kvm *kvm, unsigned long *rmapp)
+static int kvm_unmap_rmapp(struct kvm *kvm, unsigned long *rmapp,
+                          unsigned long data)
 {
        u64 *spte;
        int need_tlb_flush = 0;
@@ -763,8 +764,47 @@ static int kvm_unmap_rmapp(struct kvm *kvm, unsigned long *rmapp)
        return need_tlb_flush;
 }
 
+static int kvm_set_pte_rmapp(struct kvm *kvm, unsigned long *rmapp,
+                            unsigned long data)
+{
+       int need_flush = 0;
+       u64 *spte, new_spte;
+       pte_t *ptep = (pte_t *)data;
+       pfn_t new_pfn;
+
+       WARN_ON(pte_huge(*ptep));
+       new_pfn = pte_pfn(*ptep);
+       spte = rmap_next(kvm, rmapp, NULL);
+       while (spte) {
+               BUG_ON(!is_shadow_present_pte(*spte));
+               rmap_printk("kvm_set_pte_rmapp: spte %p %llx\n", spte, *spte);
+               need_flush = 1;
+               if (pte_write(*ptep)) {
+                       rmap_remove(kvm, spte);
+                       __set_spte(spte, shadow_trap_nonpresent_pte);
+                       spte = rmap_next(kvm, rmapp, NULL);
+               } else {
+                       new_spte = *spte &~ (PT64_BASE_ADDR_MASK);
+                       new_spte |= (u64)new_pfn << PAGE_SHIFT;
+
+                       new_spte &= ~PT_WRITABLE_MASK;
+                       new_spte &= ~SPTE_HOST_WRITEABLE;
+                       if (is_writeble_pte(*spte))
+                               kvm_set_pfn_dirty(spte_to_pfn(*spte));
+                       __set_spte(spte, new_spte);
+                       spte = rmap_next(kvm, rmapp, spte);
+               }
+       }
+       if (need_flush)
+               kvm_flush_remote_tlbs(kvm);
+
+       return 0;
+}
+
 static int kvm_handle_hva(struct kvm *kvm, unsigned long hva,
-                         int (*handler)(struct kvm *kvm, unsigned long *rmapp))
+                         unsigned long data,
+                         int (*handler)(struct kvm *kvm, unsigned long *rmapp,
+                                        unsigned long data))
 {
        int i, j;
        int retval = 0;
@@ -786,13 +826,15 @@ static int kvm_handle_hva(struct kvm *kvm, unsigned long hva,
                if (hva >= start && hva < end) {
                        gfn_t gfn_offset = (hva - start) >> PAGE_SHIFT;
 
-                       retval |= handler(kvm, &memslot->rmap[gfn_offset]);
+                       retval |= handler(kvm, &memslot->rmap[gfn_offset],
+                                         data);
 
                        for (j = 0; j < KVM_NR_PAGE_SIZES - 1; ++j) {
                                int idx = gfn_offset;
                                idx /= KVM_PAGES_PER_HPAGE(PT_DIRECTORY_LEVEL + j);
                                retval |= handler(kvm,
-                                       &memslot->lpage_info[j][idx].rmap_pde);
+                                       &memslot->lpage_info[j][idx].rmap_pde,
+                                       data);
                        }
                }
        }
@@ -802,10 +844,16 @@ static int kvm_handle_hva(struct kvm *kvm, unsigned long hva,
 
 int kvm_unmap_hva(struct kvm *kvm, unsigned long hva)
 {
-       return kvm_handle_hva(kvm, hva, kvm_unmap_rmapp);
+       return kvm_handle_hva(kvm, hva, 0, kvm_unmap_rmapp);
 }
 
-static int kvm_age_rmapp(struct kvm *kvm, unsigned long *rmapp)
+void kvm_set_spte_hva(struct kvm *kvm, unsigned long hva, pte_t pte)
+{
+       kvm_handle_hva(kvm, hva, (unsigned long)&pte, kvm_set_pte_rmapp);
+}
+
+static int kvm_age_rmapp(struct kvm *kvm, unsigned long *rmapp,
+                        unsigned long data)
 {
        u64 *spte;
        int young = 0;
@@ -841,13 +889,13 @@ static void rmap_recycle(struct kvm_vcpu *vcpu, u64 *spte, gfn_t gfn)
        gfn = unalias_gfn(vcpu->kvm, gfn);
        rmapp = gfn_to_rmap(vcpu->kvm, gfn, sp->role.level);
 
-       kvm_unmap_rmapp(vcpu->kvm, rmapp);
+       kvm_unmap_rmapp(vcpu->kvm, rmapp, 0);
        kvm_flush_remote_tlbs(vcpu->kvm);
 }
 
 int kvm_age_hva(struct kvm *kvm, unsigned long hva)
 {
-       return kvm_handle_hva(kvm, hva, kvm_age_rmapp);
+       return kvm_handle_hva(kvm, hva, 0, kvm_age_rmapp);
 }
 
 #ifdef MMU_DEBUG
@@ -1756,7 +1804,7 @@ static int set_spte(struct kvm_vcpu *vcpu, u64 *sptep,
                    unsigned pte_access, int user_fault,
                    int write_fault, int dirty, int level,
                    gfn_t gfn, pfn_t pfn, bool speculative,
-                   bool can_unsync)
+                   bool can_unsync, bool reset_host_protection)
 {
        u64 spte;
        int ret = 0;
@@ -1783,6 +1831,9 @@ static int set_spte(struct kvm_vcpu *vcpu, u64 *sptep,
                spte |= kvm_x86_ops->get_mt_mask(vcpu, gfn,
                        kvm_is_mmio_pfn(pfn));
 
+       if (reset_host_protection)
+               spte |= SPTE_HOST_WRITEABLE;
+
        spte |= (u64)pfn << PAGE_SHIFT;
 
        if ((pte_access & ACC_WRITE_MASK)
@@ -1828,7 +1879,8 @@ static void mmu_set_spte(struct kvm_vcpu *vcpu, u64 *sptep,
                         unsigned pt_access, unsigned pte_access,
                         int user_fault, int write_fault, int dirty,
                         int *ptwrite, int level, gfn_t gfn,
-                        pfn_t pfn, bool speculative)
+                        pfn_t pfn, bool speculative,
+                        bool reset_host_protection)
 {
        int was_rmapped = 0;
        int was_writeble = is_writeble_pte(*sptep);
@@ -1860,7 +1912,8 @@ static void mmu_set_spte(struct kvm_vcpu *vcpu, u64 *sptep,
        }
 
        if (set_spte(vcpu, sptep, pte_access, user_fault, write_fault,
-                     dirty, level, gfn, pfn, speculative, true)) {
+                     dirty, level, gfn, pfn, speculative, true,
+                     reset_host_protection)) {
                if (write_fault)
                        *ptwrite = 1;
                kvm_x86_ops->tlb_flush(vcpu);
@@ -1877,8 +1930,7 @@ static void mmu_set_spte(struct kvm_vcpu *vcpu, u64 *sptep,
        page_header_update_slot(vcpu->kvm, sptep, gfn);
        if (!was_rmapped) {
                rmap_count = rmap_add(vcpu, sptep, gfn);
-               if (!is_rmap_spte(*sptep))
-                       kvm_release_pfn_clean(pfn);
+               kvm_release_pfn_clean(pfn);
                if (rmap_count > RMAP_RECYCLE_THRESHOLD)
                        rmap_recycle(vcpu, sptep, gfn);
        } else {
@@ -1909,7 +1961,7 @@ static int __direct_map(struct kvm_vcpu *vcpu, gpa_t v, int write,
                if (iterator.level == level) {
                        mmu_set_spte(vcpu, iterator.sptep, ACC_ALL, ACC_ALL,
                                     0, write, 1, &pt_write,
-                                    level, gfn, pfn, false);
+                                    level, gfn, pfn, false, true);
                        ++vcpu->stat.pf_fixed;
                        break;
                }
index d2fec9c..72558f8 100644 (file)
@@ -273,9 +273,13 @@ static void FNAME(update_pte)(struct kvm_vcpu *vcpu, struct kvm_mmu_page *page,
        if (mmu_notifier_retry(vcpu, vcpu->arch.update_pte.mmu_seq))
                return;
        kvm_get_pfn(pfn);
+       /*
+        * we call mmu_set_spte() with reset_host_protection = true beacuse that
+        * vcpu->arch.update_pte.pfn was fetched from get_user_pages(write = 1).
+        */
        mmu_set_spte(vcpu, spte, page->role.access, pte_access, 0, 0,
                     gpte & PT_DIRTY_MASK, NULL, PT_PAGE_TABLE_LEVEL,
-                    gpte_to_gfn(gpte), pfn, true);
+                    gpte_to_gfn(gpte), pfn, true, true);
 }
 
 /*
@@ -308,7 +312,7 @@ static u64 *FNAME(fetch)(struct kvm_vcpu *vcpu, gva_t addr,
                                     user_fault, write_fault,
                                     gw->ptes[gw->level-1] & PT_DIRTY_MASK,
                                     ptwrite, level,
-                                    gw->gfn, pfn, false);
+                                    gw->gfn, pfn, false, true);
                        break;
                }
 
@@ -558,6 +562,7 @@ static void FNAME(prefetch_page)(struct kvm_vcpu *vcpu,
 static int FNAME(sync_page)(struct kvm_vcpu *vcpu, struct kvm_mmu_page *sp)
 {
        int i, offset, nr_present;
+       bool reset_host_protection;
 
        offset = nr_present = 0;
 
@@ -595,9 +600,16 @@ static int FNAME(sync_page)(struct kvm_vcpu *vcpu, struct kvm_mmu_page *sp)
 
                nr_present++;
                pte_access = sp->role.access & FNAME(gpte_access)(vcpu, gpte);
+               if (!(sp->spt[i] & SPTE_HOST_WRITEABLE)) {
+                       pte_access &= ~ACC_WRITE_MASK;
+                       reset_host_protection = 0;
+               } else {
+                       reset_host_protection = 1;
+               }
                set_spte(vcpu, &sp->spt[i], pte_access, 0, 0,
                         is_dirty_gpte(gpte), PT_PAGE_TABLE_LEVEL, gfn,
-                        spte_to_pfn(sp->spt[i]), true, false);
+                        spte_to_pfn(sp->spt[i]), true, false,
+                        reset_host_protection);
        }
 
        return !nr_present;
index 944cc9c..c17404a 100644 (file)
@@ -767,6 +767,8 @@ static void svm_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
                rdtscll(tsc_this);
                delta = vcpu->arch.host_tsc - tsc_this;
                svm->vmcb->control.tsc_offset += delta;
+               if (is_nested(svm))
+                       svm->nested.hsave->control.tsc_offset += delta;
                vcpu->cpu = cpu;
                kvm_migrate_timers(vcpu);
                svm->asid_generation = 0;
@@ -2057,10 +2059,14 @@ static int svm_get_msr(struct kvm_vcpu *vcpu, unsigned ecx, u64 *data)
 
        switch (ecx) {
        case MSR_IA32_TSC: {
-               u64 tsc;
+               u64 tsc_offset;
+
+               if (is_nested(svm))
+                       tsc_offset = svm->nested.hsave->control.tsc_offset;
+               else
+                       tsc_offset = svm->vmcb->control.tsc_offset;
 
-               rdtscll(tsc);
-               *data = svm->vmcb->control.tsc_offset + tsc;
+               *data = tsc_offset + native_read_tsc();
                break;
        }
        case MSR_K6_STAR:
@@ -2146,10 +2152,17 @@ static int svm_set_msr(struct kvm_vcpu *vcpu, unsigned ecx, u64 data)
 
        switch (ecx) {
        case MSR_IA32_TSC: {
-               u64 tsc;
+               u64 tsc_offset = data - native_read_tsc();
+               u64 g_tsc_offset = 0;
+
+               if (is_nested(svm)) {
+                       g_tsc_offset = svm->vmcb->control.tsc_offset -
+                                      svm->nested.hsave->control.tsc_offset;
+                       svm->nested.hsave->control.tsc_offset = tsc_offset;
+               }
+
+               svm->vmcb->control.tsc_offset = tsc_offset + g_tsc_offset;
 
-               rdtscll(tsc);
-               svm->vmcb->control.tsc_offset = data - tsc;
                break;
        }
        case MSR_K6_STAR:
index f381201..ed53b42 100644 (file)
@@ -709,7 +709,7 @@ static void vmx_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
        if (vcpu->cpu != cpu) {
                vcpu_clear(vmx);
                kvm_migrate_timers(vcpu);
-               vpid_sync_vcpu_all(vmx);
+               set_bit(KVM_REQ_TLB_FLUSH, &vcpu->requests);
                local_irq_disable();
                list_add(&vmx->local_vcpus_link,
                         &per_cpu(vcpus_on_cpu, cpu));
index be451ee..9b96953 100644 (file)
@@ -1591,6 +1591,8 @@ static int kvm_dev_ioctl_get_supported_cpuid(struct kvm_cpuid2 *cpuid,
 
        if (cpuid->nent < 1)
                goto out;
+       if (cpuid->nent > KVM_MAX_CPUID_ENTRIES)
+               cpuid->nent = KVM_MAX_CPUID_ENTRIES;
        r = -ENOMEM;
        cpuid_entries = vmalloc(sizeof(struct kvm_cpuid_entry2) * cpuid->nent);
        if (!cpuid_entries)
index 3e549b8..85f5db9 100644 (file)
@@ -15,8 +15,10 @@ ifeq ($(CONFIG_X86_32),y)
         obj-y += atomic64_32.o
         lib-y += checksum_32.o
         lib-y += strstr_32.o
-        lib-y += semaphore_32.o string_32.o cmpxchg8b_emu.o
-
+        lib-y += semaphore_32.o string_32.o
+ifneq ($(CONFIG_X86_CMPXCHG64),y)
+        lib-y += cmpxchg8b_emu.o
+endif
         lib-$(CONFIG_X86_USE_3DNOW) += mmx_32.o
 else
         obj-y += io_64.o iomap_copy_64.o
index 3439616..23a4d80 100644 (file)
@@ -1075,6 +1075,8 @@ asmlinkage void __init xen_start_kernel(void)
         * Set up some pagetable state before starting to set any ptes.
         */
 
+       xen_init_mmu_ops();
+
        /* Prevent unwanted bits from being set in PTEs. */
        __supported_pte_mask &= ~_PAGE_GLOBAL;
        if (!xen_initial_domain())
@@ -1099,7 +1101,6 @@ asmlinkage void __init xen_start_kernel(void)
         */
        xen_setup_stackprotector();
 
-       xen_init_mmu_ops();
        xen_init_irq_ops();
        xen_init_cpuid_mask();
 
index 19085ff..19f7df3 100644 (file)
@@ -13,6 +13,7 @@
  */
 
 #include <linux/errno.h>
+#include <linux/sched.h>
 #include <linux/time.h>
 #include <linux/clocksource.h>
 #include <linux/interrupt.h>
index 81f3431..71da511 100644 (file)
@@ -70,7 +70,7 @@ static void drive_stat_acct(struct request *rq, int new_io)
                part_stat_inc(cpu, part, merges[rw]);
        else {
                part_round_stats(cpu, part);
-               part_inc_in_flight(part);
+               part_inc_in_flight(part, rw);
        }
 
        part_stat_unlock();
@@ -1030,9 +1030,9 @@ static void part_round_stats_single(int cpu, struct hd_struct *part,
        if (now == part->stamp)
                return;
 
-       if (part->in_flight) {
+       if (part_in_flight(part)) {
                __part_stat_add(cpu, part, time_in_queue,
-                               part->in_flight * (now - part->stamp));
+                               part_in_flight(part) * (now - part->stamp));
                __part_stat_add(cpu, part, io_ticks, (now - part->stamp));
        }
        part->stamp = now;
@@ -1161,7 +1161,7 @@ static int __make_request(struct request_queue *q, struct bio *bio)
        const unsigned int ff = bio->bi_rw & REQ_FAILFAST_MASK;
        int rw_flags;
 
-       if (bio_rw_flagged(bio, BIO_RW_BARRIER) && bio_has_data(bio) &&
+       if (bio_rw_flagged(bio, BIO_RW_BARRIER) &&
            (q->next_ordered == QUEUE_ORDERED_NONE)) {
                bio_endio(bio, -EOPNOTSUPP);
                return 0;
@@ -1739,7 +1739,7 @@ static void blk_account_io_done(struct request *req)
                part_stat_inc(cpu, part, ios[rw]);
                part_stat_add(cpu, part, ticks[rw], duration);
                part_round_stats(cpu, part);
-               part_dec_in_flight(part);
+               part_dec_in_flight(part, rw);
 
                part_stat_unlock();
        }
@@ -2492,14 +2492,6 @@ int kblockd_schedule_work(struct request_queue *q, struct work_struct *work)
 }
 EXPORT_SYMBOL(kblockd_schedule_work);
 
-int kblockd_schedule_delayed_work(struct request_queue *q,
-                                 struct delayed_work *work,
-                                 unsigned long delay)
-{
-       return queue_delayed_work(kblockd_workqueue, work, delay);
-}
-EXPORT_SYMBOL(kblockd_schedule_delayed_work);
-
 int __init blk_dev_init(void)
 {
        BUILD_BUG_ON(__REQ_NR_BITS > 8 *
index b0de857..99cb5cf 100644 (file)
@@ -351,7 +351,7 @@ static void blk_account_io_merge(struct request *req)
                part = disk_map_sector_rcu(req->rq_disk, blk_rq_pos(req));
 
                part_round_stats(cpu, part);
-               part_dec_in_flight(part);
+               part_dec_in_flight(part, rq_data_dir(req));
 
                part_stat_unlock();
        }
index e0695bc..66d4aa8 100644 (file)
@@ -242,7 +242,7 @@ EXPORT_SYMBOL(blk_queue_max_hw_sectors);
 /**
  * blk_queue_max_discard_sectors - set max sectors for a single discard
  * @q:  the request queue for the device
- * @max_discard: maximum number of sectors to discard
+ * @max_discard_sectors: maximum number of sectors to discard
  **/
 void blk_queue_max_discard_sectors(struct request_queue *q,
                unsigned int max_discard_sectors)
index 2e5cfeb..6b0f52c 100644 (file)
@@ -359,7 +359,7 @@ int blk_queue_start_tag(struct request_queue *q, struct request *rq)
                max_depth -= 2;
                if (!max_depth)
                        max_depth = 1;
-               if (q->in_flight[0] > max_depth)
+               if (q->in_flight[BLK_RW_ASYNC] > max_depth)
                        return 1;
        }
 
index 9c4b679..069a610 100644 (file)
@@ -150,7 +150,7 @@ struct cfq_data {
         * idle window management
         */
        struct timer_list idle_slice_timer;
-       struct delayed_work unplug_work;
+       struct work_struct unplug_work;
 
        struct cfq_queue *active_queue;
        struct cfq_io_context *active_cic;
@@ -230,7 +230,7 @@ CFQ_CFQQ_FNS(coop);
        blk_add_trace_msg((cfqd)->queue, "cfq " fmt, ##args)
 
 static void cfq_dispatch_insert(struct request_queue *, struct request *);
-static struct cfq_queue *cfq_get_queue(struct cfq_data *, int,
+static struct cfq_queue *cfq_get_queue(struct cfq_data *, bool,
                                       struct io_context *, gfp_t);
 static struct cfq_io_context *cfq_cic_lookup(struct cfq_data *,
                                                struct io_context *);
@@ -241,40 +241,35 @@ static inline int rq_in_driver(struct cfq_data *cfqd)
 }
 
 static inline struct cfq_queue *cic_to_cfqq(struct cfq_io_context *cic,
-                                           int is_sync)
+                                           bool is_sync)
 {
-       return cic->cfqq[!!is_sync];
+       return cic->cfqq[is_sync];
 }
 
 static inline void cic_set_cfqq(struct cfq_io_context *cic,
-                               struct cfq_queue *cfqq, int is_sync)
+                               struct cfq_queue *cfqq, bool is_sync)
 {
-       cic->cfqq[!!is_sync] = cfqq;
+       cic->cfqq[is_sync] = cfqq;
 }
 
 /*
  * We regard a request as SYNC, if it's either a read or has the SYNC bit
  * set (in which case it could also be direct WRITE).
  */
-static inline int cfq_bio_sync(struct bio *bio)
+static inline bool cfq_bio_sync(struct bio *bio)
 {
-       if (bio_data_dir(bio) == READ || bio_rw_flagged(bio, BIO_RW_SYNCIO))
-               return 1;
-
-       return 0;
+       return bio_data_dir(bio) == READ || bio_rw_flagged(bio, BIO_RW_SYNCIO);
 }
 
 /*
  * scheduler run of queue, if there are requests pending and no one in the
  * driver that will restart queueing
  */
-static inline void cfq_schedule_dispatch(struct cfq_data *cfqd,
-                                        unsigned long delay)
+static inline void cfq_schedule_dispatch(struct cfq_data *cfqd)
 {
        if (cfqd->busy_queues) {
                cfq_log(cfqd, "schedule dispatch");
-               kblockd_schedule_delayed_work(cfqd->queue, &cfqd->unplug_work,
-                                               delay);
+               kblockd_schedule_work(cfqd->queue, &cfqd->unplug_work);
        }
 }
 
@@ -290,7 +285,7 @@ static int cfq_queue_empty(struct request_queue *q)
  * if a queue is marked sync and has sync io queued. A sync queue with async
  * io only, should not get full sync slice length.
  */
-static inline int cfq_prio_slice(struct cfq_data *cfqd, int sync,
+static inline int cfq_prio_slice(struct cfq_data *cfqd, bool sync,
                                 unsigned short prio)
 {
        const int base_slice = cfqd->cfq_slice[sync];
@@ -318,7 +313,7 @@ cfq_set_prio_slice(struct cfq_data *cfqd, struct cfq_queue *cfqq)
  * isn't valid until the first request from the dispatch is activated
  * and the slice time set.
  */
-static inline int cfq_slice_used(struct cfq_queue *cfqq)
+static inline bool cfq_slice_used(struct cfq_queue *cfqq)
 {
        if (cfq_cfqq_slice_new(cfqq))
                return 0;
@@ -493,7 +488,7 @@ static unsigned long cfq_slice_offset(struct cfq_data *cfqd,
  * we will service the queues.
  */
 static void cfq_service_tree_add(struct cfq_data *cfqd, struct cfq_queue *cfqq,
-                                int add_front)
+                                bool add_front)
 {
        struct rb_node **p, *parent;
        struct cfq_queue *__cfqq;
@@ -509,11 +504,20 @@ static void cfq_service_tree_add(struct cfq_data *cfqd, struct cfq_queue *cfqq,
                } else
                        rb_key += jiffies;
        } else if (!add_front) {
+               /*
+                * Get our rb key offset. Subtract any residual slice
+                * value carried from last service. A negative resid
+                * count indicates slice overrun, and this should position
+                * the next service time further away in the tree.
+                */
                rb_key = cfq_slice_offset(cfqd, cfqq) + jiffies;
-               rb_key += cfqq->slice_resid;
+               rb_key -= cfqq->slice_resid;
                cfqq->slice_resid = 0;
-       } else
-               rb_key = 0;
+       } else {
+               rb_key = -HZ;
+               __cfqq = cfq_rb_first(&cfqd->service_tree);
+               rb_key += __cfqq ? __cfqq->rb_key : jiffies;
+       }
 
        if (!RB_EMPTY_NODE(&cfqq->rb_node)) {
                /*
@@ -547,7 +551,7 @@ static void cfq_service_tree_add(struct cfq_data *cfqd, struct cfq_queue *cfqq,
                        n = &(*p)->rb_left;
                else if (cfq_class_idle(cfqq) > cfq_class_idle(__cfqq))
                        n = &(*p)->rb_right;
-               else if (rb_key < __cfqq->rb_key)
+               else if (time_before(rb_key, __cfqq->rb_key))
                        n = &(*p)->rb_left;
                else
                        n = &(*p)->rb_right;
@@ -827,8 +831,10 @@ cfq_merged_requests(struct request_queue *q, struct request *rq,
         * reposition in fifo if next is older than rq
         */
        if (!list_empty(&rq->queuelist) && !list_empty(&next->queuelist) &&
-           time_before(next->start_time, rq->start_time))
+           time_before(rq_fifo_time(next), rq_fifo_time(rq))) {
                list_move(&rq->queuelist, &next->queuelist);
+               rq_set_fifo_time(rq, rq_fifo_time(next));
+       }
 
        cfq_remove_request(next);
 }
@@ -844,7 +850,7 @@ static int cfq_allow_merge(struct request_queue *q, struct request *rq,
         * Disallow merge of a sync bio into an async request.
         */
        if (cfq_bio_sync(bio) && !rq_is_sync(rq))
-               return 0;
+               return false;
 
        /*
         * Lookup the cfqq that this bio will be queued with. Allow
@@ -852,13 +858,10 @@ static int cfq_allow_merge(struct request_queue *q, struct request *rq,
         */
        cic = cfq_cic_lookup(cfqd, current->io_context);
        if (!cic)
-               return 0;
+               return false;
 
        cfqq = cic_to_cfqq(cic, cfq_bio_sync(bio));
-       if (cfqq == RQ_CFQQ(rq))
-               return 1;
-
-       return 0;
+       return cfqq == RQ_CFQQ(rq);
 }
 
 static void __cfq_set_active_queue(struct cfq_data *cfqd,
@@ -886,7 +889,7 @@ static void __cfq_set_active_queue(struct cfq_data *cfqd,
  */
 static void
 __cfq_slice_expired(struct cfq_data *cfqd, struct cfq_queue *cfqq,
-                   int timed_out)
+                   bool timed_out)
 {
        cfq_log_cfqq(cfqd, cfqq, "slice expired t=%d", timed_out);
 
@@ -914,7 +917,7 @@ __cfq_slice_expired(struct cfq_data *cfqd, struct cfq_queue *cfqq,
        }
 }
 
-static inline void cfq_slice_expired(struct cfq_data *cfqd, int timed_out)
+static inline void cfq_slice_expired(struct cfq_data *cfqd, bool timed_out)
 {
        struct cfq_queue *cfqq = cfqd->active_queue;
 
@@ -1026,7 +1029,7 @@ static struct cfq_queue *cfqq_close(struct cfq_data *cfqd,
  */
 static struct cfq_queue *cfq_close_cooperator(struct cfq_data *cfqd,
                                              struct cfq_queue *cur_cfqq,
-                                             int probe)
+                                             bool probe)
 {
        struct cfq_queue *cfqq;
 
@@ -1090,6 +1093,15 @@ static void cfq_arm_slice_timer(struct cfq_data *cfqd)
        if (!cic || !atomic_read(&cic->ioc->nr_tasks))
                return;
 
+       /*
+        * If our average think time is larger than the remaining time
+        * slice, then don't idle. This avoids overrunning the allotted
+        * time slice.
+        */
+       if (sample_valid(cic->ttime_samples) &&
+           (cfqq->slice_end - jiffies < cic->ttime_mean))
+               return;
+
        cfq_mark_cfqq_wait_request(cfqq);
 
        /*
@@ -1129,9 +1141,7 @@ static void cfq_dispatch_insert(struct request_queue *q, struct request *rq)
  */
 static struct request *cfq_check_fifo(struct cfq_queue *cfqq)
 {
-       struct cfq_data *cfqd = cfqq->cfqd;
-       struct request *rq;
-       int fifo;
+       struct request *rq = NULL;
 
        if (cfq_cfqq_fifo_expire(cfqq))
                return NULL;
@@ -1141,13 +1151,11 @@ static struct request *cfq_check_fifo(struct cfq_queue *cfqq)
        if (list_empty(&cfqq->fifo))
                return NULL;
 
-       fifo = cfq_cfqq_sync(cfqq);
        rq = rq_entry_fifo(cfqq->fifo.next);
-
-       if (time_before(jiffies, rq->start_time + cfqd->cfq_fifo_expire[fifo]))
+       if (time_before(jiffies, rq_fifo_time(rq)))
                rq = NULL;
 
-       cfq_log_cfqq(cfqd, cfqq, "fifo=%p", rq);
+       cfq_log_cfqq(cfqq->cfqd, cfqq, "fifo=%p", rq);
        return rq;
 }
 
@@ -1248,67 +1256,21 @@ static int cfq_forced_dispatch(struct cfq_data *cfqd)
        return dispatched;
 }
 
-/*
- * Dispatch a request from cfqq, moving them to the request queue
- * dispatch list.
- */
-static void cfq_dispatch_request(struct cfq_data *cfqd, struct cfq_queue *cfqq)
+static bool cfq_may_dispatch(struct cfq_data *cfqd, struct cfq_queue *cfqq)
 {
-       struct request *rq;
-
-       BUG_ON(RB_EMPTY_ROOT(&cfqq->sort_list));
-
-       /*
-        * follow expired path, else get first next available
-        */
-       rq = cfq_check_fifo(cfqq);
-       if (!rq)
-               rq = cfqq->next_rq;
-
-       /*
-        * insert request into driver dispatch list
-        */
-       cfq_dispatch_insert(cfqd->queue, rq);
-
-       if (!cfqd->active_cic) {
-               struct cfq_io_context *cic = RQ_CIC(rq);
-
-               atomic_long_inc(&cic->ioc->refcount);
-               cfqd->active_cic = cic;
-       }
-}
-
-/*
- * Find the cfqq that we need to service and move a request from that to the
- * dispatch list
- */
-static int cfq_dispatch_requests(struct request_queue *q, int force)
-{
-       struct cfq_data *cfqd = q->elevator->elevator_data;
-       struct cfq_queue *cfqq;
        unsigned int max_dispatch;
 
-       if (!cfqd->busy_queues)
-               return 0;
-
-       if (unlikely(force))
-               return cfq_forced_dispatch(cfqd);
-
-       cfqq = cfq_select_queue(cfqd);
-       if (!cfqq)
-               return 0;
-
        /*
         * Drain async requests before we start sync IO
         */
        if (cfq_cfqq_idle_window(cfqq) && cfqd->rq_in_driver[BLK_RW_ASYNC])
-               return 0;
+               return false;
 
        /*
         * If this is an async queue and we have sync IO in flight, let it wait
         */
        if (cfqd->sync_flight && !cfq_cfqq_sync(cfqq))
-               return 0;
+               return false;
 
        max_dispatch = cfqd->cfq_quantum;
        if (cfq_class_idle(cfqq))
@@ -1322,13 +1284,13 @@ static int cfq_dispatch_requests(struct request_queue *q, int force)
                 * idle queue must always only have a single IO in flight
                 */
                if (cfq_class_idle(cfqq))
-                       return 0;
+                       return false;
 
                /*
                 * We have other queues, don't allow more IO from this one
                 */
                if (cfqd->busy_queues > 1)
-                       return 0;
+                       return false;
 
                /*
                 * Sole queue user, allow bigger slice
@@ -1352,13 +1314,72 @@ static int cfq_dispatch_requests(struct request_queue *q, int force)
                        max_dispatch = depth;
        }
 
-       if (cfqq->dispatched >= max_dispatch)
+       /*
+        * If we're below the current max, allow a dispatch
+        */
+       return cfqq->dispatched < max_dispatch;
+}
+
+/*
+ * Dispatch a request from cfqq, moving them to the request queue
+ * dispatch list.
+ */
+static bool cfq_dispatch_request(struct cfq_data *cfqd, struct cfq_queue *cfqq)
+{
+       struct request *rq;
+
+       BUG_ON(RB_EMPTY_ROOT(&cfqq->sort_list));
+
+       if (!cfq_may_dispatch(cfqd, cfqq))
+               return false;
+
+       /*
+        * follow expired path, else get first next available
+        */
+       rq = cfq_check_fifo(cfqq);
+       if (!rq)
+               rq = cfqq->next_rq;
+
+       /*
+        * insert request into driver dispatch list
+        */
+       cfq_dispatch_insert(cfqd->queue, rq);
+
+       if (!cfqd->active_cic) {
+               struct cfq_io_context *cic = RQ_CIC(rq);
+
+               atomic_long_inc(&cic->ioc->refcount);
+               cfqd->active_cic = cic;
+       }
+
+       return true;
+}
+
+/*
+ * Find the cfqq that we need to service and move a request from that to the
+ * dispatch list
+ */
+static int cfq_dispatch_requests(struct request_queue *q, int force)
+{
+       struct cfq_data *cfqd = q->elevator->elevator_data;
+       struct cfq_queue *cfqq;
+
+       if (!cfqd->busy_queues)
+               return 0;
+
+       if (unlikely(force))
+               return cfq_forced_dispatch(cfqd);
+
+       cfqq = cfq_select_queue(cfqd);
+       if (!cfqq)
                return 0;
 
        /*
-        * Dispatch a request from this cfqq
+        * Dispatch a request from this cfqq, if it is allowed
         */
-       cfq_dispatch_request(cfqd, cfqq);
+       if (!cfq_dispatch_request(cfqd, cfqq))
+               return 0;
+
        cfqq->slice_dispatch++;
        cfq_clear_cfqq_must_dispatch(cfqq);
 
@@ -1399,7 +1420,7 @@ static void cfq_put_queue(struct cfq_queue *cfqq)
 
        if (unlikely(cfqd->active_queue == cfqq)) {
                __cfq_slice_expired(cfqd, cfqq, 0);
-               cfq_schedule_dispatch(cfqd, 0);
+               cfq_schedule_dispatch(cfqd);
        }
 
        kmem_cache_free(cfq_pool, cfqq);
@@ -1494,7 +1515,7 @@ static void cfq_exit_cfqq(struct cfq_data *cfqd, struct cfq_queue *cfqq)
 {
        if (unlikely(cfqq == cfqd->active_queue)) {
                __cfq_slice_expired(cfqd, cfqq, 0);
-               cfq_schedule_dispatch(cfqd, 0);
+               cfq_schedule_dispatch(cfqd);
        }
 
        cfq_put_queue(cfqq);
@@ -1658,7 +1679,7 @@ static void cfq_ioc_set_ioprio(struct io_context *ioc)
 }
 
 static void cfq_init_cfqq(struct cfq_data *cfqd, struct cfq_queue *cfqq,
-                         pid_t pid, int is_sync)
+                         pid_t pid, bool is_sync)
 {
        RB_CLEAR_NODE(&cfqq->rb_node);
        RB_CLEAR_NODE(&cfqq->p_node);
@@ -1678,7 +1699,7 @@ static void cfq_init_cfqq(struct cfq_data *cfqd, struct cfq_queue *cfqq,
 }
 
 static struct cfq_queue *
-cfq_find_alloc_queue(struct cfq_data *cfqd, int is_sync,
+cfq_find_alloc_queue(struct cfq_data *cfqd, bool is_sync,
                     struct io_context *ioc, gfp_t gfp_mask)
 {
        struct cfq_queue *cfqq, *new_cfqq = NULL;
@@ -1742,7 +1763,7 @@ cfq_async_queue_prio(struct cfq_data *cfqd, int ioprio_class, int ioprio)
 }
 
 static struct cfq_queue *
-cfq_get_queue(struct cfq_data *cfqd, int is_sync, struct io_context *ioc,
+cfq_get_queue(struct cfq_data *cfqd, bool is_sync, struct io_context *ioc,
              gfp_t gfp_mask)
 {
        const int ioprio = task_ioprio(ioc);
@@ -1977,7 +1998,10 @@ cfq_update_idle_window(struct cfq_data *cfqd, struct cfq_queue *cfqq,
            (!cfqd->cfq_latency && cfqd->hw_tag && CIC_SEEKY(cic)))
                enable_idle = 0;
        else if (sample_valid(cic->ttime_samples)) {
-               if (cic->ttime_mean > cfqd->cfq_slice_idle)
+               unsigned int slice_idle = cfqd->cfq_slice_idle;
+               if (sample_valid(cic->seek_samples) && CIC_SEEKY(cic))
+                       slice_idle = msecs_to_jiffies(CFQ_MIN_TT);
+               if (cic->ttime_mean > slice_idle)
                        enable_idle = 0;
                else
                        enable_idle = 1;
@@ -1996,7 +2020,7 @@ cfq_update_idle_window(struct cfq_data *cfqd, struct cfq_queue *cfqq,
  * Check if new_cfqq should preempt the currently active queue. Return 0 for
  * no or if we aren't sure, a 1 will cause a preempt.
  */
-static int
+static bool
 cfq_should_preempt(struct cfq_data *cfqd, struct cfq_queue *new_cfqq,
                   struct request *rq)
 {
@@ -2004,48 +2028,48 @@ cfq_should_preempt(struct cfq_data *cfqd, struct cfq_queue *new_cfqq,
 
        cfqq = cfqd->active_queue;
        if (!cfqq)
-               return 0;
+               return false;
 
        if (cfq_slice_used(cfqq))
-               return 1;
+               return true;
 
        if (cfq_class_idle(new_cfqq))
-               return 0;
+               return false;
 
        if (cfq_class_idle(cfqq))
-               return 1;
+               return true;
 
        /*
         * if the new request is sync, but the currently running queue is
         * not, let the sync request have priority.
         */
        if (rq_is_sync(rq) && !cfq_cfqq_sync(cfqq))
-               return 1;
+               return true;
 
        /*
         * So both queues are sync. Let the new request get disk time if
         * it's a metadata request and the current queue is doing regular IO.
         */
        if (rq_is_meta(rq) && !cfqq->meta_pending)
-               return 1;
+               return false;
 
        /*
         * Allow an RT request to pre-empt an ongoing non-RT cfqq timeslice.
         */
        if (cfq_class_rt(new_cfqq) && !cfq_class_rt(cfqq))
-               return 1;
+               return true;
 
        if (!cfqd->active_cic || !cfq_cfqq_wait_request(cfqq))
-               return 0;
+               return false;
 
        /*
         * if this request is as-good as one we would expect from the
         * current cfqq, let it preempt
         */
        if (cfq_rq_close(cfqd, rq))
-               return 1;
+               return true;
 
-       return 0;
+       return false;
 }
 
 /*
@@ -2130,6 +2154,7 @@ static void cfq_insert_request(struct request_queue *q, struct request *rq)
 
        cfq_add_rq_rb(rq);
 
+       rq_set_fifo_time(rq, jiffies + cfqd->cfq_fifo_expire[rq_is_sync(rq)]);
        list_add_tail(&rq->queuelist, &cfqq->fifo);
 
        cfq_rq_enqueued(cfqd, cfqq, rq);
@@ -2211,7 +2236,7 @@ static void cfq_completed_request(struct request_queue *q, struct request *rq)
        }
 
        if (!rq_in_driver(cfqd))
-               cfq_schedule_dispatch(cfqd, 0);
+               cfq_schedule_dispatch(cfqd);
 }
 
 /*
@@ -2309,7 +2334,7 @@ cfq_set_request(struct request_queue *q, struct request *rq, gfp_t gfp_mask)
        struct cfq_data *cfqd = q->elevator->elevator_data;
        struct cfq_io_context *cic;
        const int rw = rq_data_dir(rq);
-       const int is_sync = rq_is_sync(rq);
+       const bool is_sync = rq_is_sync(rq);
        struct cfq_queue *cfqq;
        unsigned long flags;
 
@@ -2341,7 +2366,7 @@ queue_fail:
        if (cic)
                put_io_context(cic->ioc);
 
-       cfq_schedule_dispatch(cfqd, 0);
+       cfq_schedule_dispatch(cfqd);
        spin_unlock_irqrestore(q->queue_lock, flags);
        cfq_log(cfqd, "set_request fail");
        return 1;
@@ -2350,7 +2375,7 @@ queue_fail:
 static void cfq_kick_queue(struct work_struct *work)
 {
        struct cfq_data *cfqd =
-               container_of(work, struct cfq_data, unplug_work.work);
+               container_of(work, struct cfq_data, unplug_work);
        struct request_queue *q = cfqd->queue;
 
        spin_lock_irq(q->queue_lock);
@@ -2404,7 +2429,7 @@ static void cfq_idle_slice_timer(unsigned long data)
 expire:
        cfq_slice_expired(cfqd, timed_out);
 out_kick:
-       cfq_schedule_dispatch(cfqd, 0);
+       cfq_schedule_dispatch(cfqd);
 out_cont:
        spin_unlock_irqrestore(cfqd->queue->queue_lock, flags);
 }
@@ -2412,7 +2437,7 @@ out_cont:
 static void cfq_shutdown_timer_wq(struct cfq_data *cfqd)
 {
        del_timer_sync(&cfqd->idle_slice_timer);
-       cancel_delayed_work_sync(&cfqd->unplug_work);
+       cancel_work_sync(&cfqd->unplug_work);
 }
 
 static void cfq_put_async_queues(struct cfq_data *cfqd)
@@ -2494,7 +2519,7 @@ static void *cfq_init_queue(struct request_queue *q)
        cfqd->idle_slice_timer.function = cfq_idle_slice_timer;
        cfqd->idle_slice_timer.data = (unsigned long) cfqd;
 
-       INIT_DELAYED_WORK(&cfqd->unplug_work, cfq_kick_queue);
+       INIT_WORK(&cfqd->unplug_work, cfq_kick_queue);
 
        cfqd->cfq_quantum = cfq_quantum;
        cfqd->cfq_fifo_expire[0] = cfq_fifo_expire[0];
index 1975b61..a847046 100644 (file)
@@ -1059,9 +1059,7 @@ ssize_t elv_iosched_store(struct request_queue *q, const char *name,
                return count;
 
        strlcpy(elevator_name, name, sizeof(elevator_name));
-       strstrip(elevator_name);
-
-       e = elevator_get(elevator_name);
+       e = elevator_get(strstrip(elevator_name));
        if (!e) {
                printk(KERN_ERR "elevator: type %s not found\n", elevator_name);
                return -EINVAL;
index 5a0861d..517e433 100644 (file)
@@ -869,6 +869,7 @@ static DEVICE_ATTR(size, S_IRUGO, part_size_show, NULL);
 static DEVICE_ATTR(alignment_offset, S_IRUGO, disk_alignment_offset_show, NULL);
 static DEVICE_ATTR(capability, S_IRUGO, disk_capability_show, NULL);
 static DEVICE_ATTR(stat, S_IRUGO, part_stat_show, NULL);
+static DEVICE_ATTR(inflight, S_IRUGO, part_inflight_show, NULL);
 #ifdef CONFIG_FAIL_MAKE_REQUEST
 static struct device_attribute dev_attr_fail =
        __ATTR(make-it-fail, S_IRUGO|S_IWUSR, part_fail_show, part_fail_store);
@@ -888,6 +889,7 @@ static struct attribute *disk_attrs[] = {
        &dev_attr_alignment_offset.attr,
        &dev_attr_capability.attr,
        &dev_attr_stat.attr,
+       &dev_attr_inflight.attr,
 #ifdef CONFIG_FAIL_MAKE_REQUEST
        &dev_attr_fail.attr,
 #endif
@@ -1053,7 +1055,7 @@ static int diskstats_show(struct seq_file *seqf, void *v)
                           part_stat_read(hd, merges[1]),
                           (unsigned long long)part_stat_read(hd, sectors[1]),
                           jiffies_to_msecs(part_stat_read(hd, ticks[1])),
-                          hd->in_flight,
+                          part_in_flight(hd),
                           jiffies_to_msecs(part_stat_read(hd, io_ticks)),
                           jiffies_to_msecs(part_stat_read(hd, time_in_queue))
                        );
index d9aa733..0a55da7 100644 (file)
@@ -18,6 +18,7 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/rtnetlink.h>
+#include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/seq_file.h>
 
index b88db6d..6b5cc4f 100644 (file)
 #include <linux/async_tx.h>
 
 /**
- * scribble - space to hold throwaway P buffer for synchronous gen_syndrome
+ * pq_scribble_page - space to hold throwaway P or Q buffer for
+ * synchronous gen_syndrome
  */
-static struct page *scribble;
-
-static bool is_raid6_zero_block(struct page *p)
-{
-       return p == (void *) raid6_empty_zero_page;
-}
+static struct page *pq_scribble_page;
 
 /* the struct page *blocks[] parameter passed to async_gen_syndrome()
  * and async_syndrome_val() contains the 'P' destination address at
@@ -83,7 +79,7 @@ do_async_gen_syndrome(struct dma_chan *chan, struct page **blocks,
         * sources and update the coefficients accordingly
         */
        for (i = 0, idx = 0; i < src_cnt; i++) {
-               if (is_raid6_zero_block(blocks[i]))
+               if (blocks[i] == NULL)
                        continue;
                dma_src[idx] = dma_map_page(dma->dev, blocks[i], offset, len,
                                            DMA_TO_DEVICE);
@@ -160,9 +156,9 @@ do_sync_gen_syndrome(struct page **blocks, unsigned int offset, int disks,
                srcs = (void **) blocks;
 
        for (i = 0; i < disks; i++) {
-               if (is_raid6_zero_block(blocks[i])) {
+               if (blocks[i] == NULL) {
                        BUG_ON(i > disks - 3); /* P or Q can't be zero */
-                       srcs[i] = blocks[i];
+                       srcs[i] = (void*)raid6_empty_zero_page;
                } else
                        srcs[i] = page_address(blocks[i]) + offset;
        }
@@ -186,10 +182,14 @@ do_sync_gen_syndrome(struct page **blocks, unsigned int offset, int disks,
  * blocks[disks-1] to NULL.  When P or Q is omitted 'len' must be <=
  * PAGE_SIZE as a temporary buffer of this size is used in the
  * synchronous path.  'disks' always accounts for both destination
- * buffers.
+ * buffers.  If any source buffers (blocks[i] where i < disks - 2) are
+ * set to NULL those buffers will be replaced with the raid6_zero_page
+ * in the synchronous path and omitted in the hardware-asynchronous
+ * path.
  *
  * 'blocks' note: if submit->scribble is NULL then the contents of
- * 'blocks' may be overridden
+ * 'blocks' may be overwritten to perform address conversions
+ * (dma_map_page() or page_address()).
  */
 struct dma_async_tx_descriptor *
 async_gen_syndrome(struct page **blocks, unsigned int offset, int disks,
@@ -227,11 +227,11 @@ async_gen_syndrome(struct page **blocks, unsigned int offset, int disks,
        async_tx_quiesce(&submit->depend_tx);
 
        if (!P(blocks, disks)) {
-               P(blocks, disks) = scribble;
+               P(blocks, disks) = pq_scribble_page;
                BUG_ON(len + offset > PAGE_SIZE);
        }
        if (!Q(blocks, disks)) {
-               Q(blocks, disks) = scribble;
+               Q(blocks, disks) = pq_scribble_page;
                BUG_ON(len + offset > PAGE_SIZE);
        }
        do_sync_gen_syndrome(blocks, offset, disks, len, submit);
@@ -265,8 +265,10 @@ async_syndrome_val(struct page **blocks, unsigned int offset, int disks,
                                                      len);
        struct dma_device *device = chan ? chan->device : NULL;
        struct dma_async_tx_descriptor *tx;
+       unsigned char coefs[disks-2];
        enum dma_ctrl_flags dma_flags = submit->cb_fn ? DMA_PREP_INTERRUPT : 0;
        dma_addr_t *dma_src = NULL;
+       int src_cnt = 0;
 
        BUG_ON(disks < 4);
 
@@ -285,22 +287,32 @@ async_syndrome_val(struct page **blocks, unsigned int offset, int disks,
                         __func__, disks, len);
                if (!P(blocks, disks))
                        dma_flags |= DMA_PREP_PQ_DISABLE_P;
+               else
+                       pq[0] = dma_map_page(dev, P(blocks, disks),
+                                            offset, len,
+                                            DMA_TO_DEVICE);
                if (!Q(blocks, disks))
                        dma_flags |= DMA_PREP_PQ_DISABLE_Q;
+               else
+                       pq[1] = dma_map_page(dev, Q(blocks, disks),
+                                            offset, len,
+                                            DMA_TO_DEVICE);
+
                if (submit->flags & ASYNC_TX_FENCE)
                        dma_flags |= DMA_PREP_FENCE;
-               for (i = 0; i < disks; i++)
+               for (i = 0; i < disks-2; i++)
                        if (likely(blocks[i])) {
-                               BUG_ON(is_raid6_zero_block(blocks[i]));
-                               dma_src[i] = dma_map_page(dev, blocks[i],
-                                                         offset, len,
-                                                         DMA_TO_DEVICE);
+                               dma_src[src_cnt] = dma_map_page(dev, blocks[i],
+                                                               offset, len,
+                                                               DMA_TO_DEVICE);
+                               coefs[src_cnt] = raid6_gfexp[i];
+                               src_cnt++;
                        }
 
                for (;;) {
                        tx = device->device_prep_dma_pq_val(chan, pq, dma_src,
-                                                           disks - 2,
-                                                           raid6_gfexp,
+                                                           src_cnt,
+                                                           coefs,
                                                            len, pqres,
                                                            dma_flags);
                        if (likely(tx))
@@ -373,9 +385,9 @@ EXPORT_SYMBOL_GPL(async_syndrome_val);
 
 static int __init async_pq_init(void)
 {
-       scribble = alloc_page(GFP_KERNEL);
+       pq_scribble_page = alloc_page(GFP_KERNEL);
 
-       if (scribble)
+       if (pq_scribble_page)
                return 0;
 
        pr_err("%s: failed to allocate required spare page\n", __func__);
@@ -385,7 +397,7 @@ static int __init async_pq_init(void)
 
 static void __exit async_pq_exit(void)
 {
-       put_page(scribble);
+       put_page(pq_scribble_page);
 }
 
 module_init(async_pq_init);
index 6d73dde..943f2ab 100644 (file)
@@ -131,8 +131,8 @@ async_mult(struct page *dest, struct page *src, u8 coef, size_t len,
 }
 
 static struct dma_async_tx_descriptor *
-__2data_recov_4(size_t bytes, int faila, int failb, struct page **blocks,
-             struct async_submit_ctl *submit)
+__2data_recov_4(int disks, size_t bytes, int faila, int failb,
+               struct page **blocks, struct async_submit_ctl *submit)
 {
        struct dma_async_tx_descriptor *tx = NULL;
        struct page *p, *q, *a, *b;
@@ -143,8 +143,8 @@ __2data_recov_4(size_t bytes, int faila, int failb, struct page **blocks,
        void *cb_param = submit->cb_param;
        void *scribble = submit->scribble;
 
-       p = blocks[4-2];
-       q = blocks[4-1];
+       p = blocks[disks-2];
+       q = blocks[disks-1];
 
        a = blocks[faila];
        b = blocks[failb];
@@ -170,8 +170,8 @@ __2data_recov_4(size_t bytes, int faila, int failb, struct page **blocks,
 }
 
 static struct dma_async_tx_descriptor *
-__2data_recov_5(size_t bytes, int faila, int failb, struct page **blocks,
-             struct async_submit_ctl *submit)
+__2data_recov_5(int disks, size_t bytes, int faila, int failb,
+               struct page **blocks, struct async_submit_ctl *submit)
 {
        struct dma_async_tx_descriptor *tx = NULL;
        struct page *p, *q, *g, *dp, *dq;
@@ -181,21 +181,22 @@ __2data_recov_5(size_t bytes, int faila, int failb, struct page **blocks,
        dma_async_tx_callback cb_fn = submit->cb_fn;
        void *cb_param = submit->cb_param;
        void *scribble = submit->scribble;
-       int uninitialized_var(good);
-       int i;
+       int good_srcs, good, i;
 
-       for (i = 0; i < 3; i++) {
+       good_srcs = 0;
+       good = -1;
+       for (i = 0; i < disks-2; i++) {
+               if (blocks[i] == NULL)
+                       continue;
                if (i == faila || i == failb)
                        continue;
-               else {
-                       good = i;
-                       break;
-               }
+               good = i;
+               good_srcs++;
        }
-       BUG_ON(i >= 3);
+       BUG_ON(good_srcs > 1);
 
-       p = blocks[5-2];
-       q = blocks[5-1];
+       p = blocks[disks-2];
+       q = blocks[disks-1];
        g = blocks[good];
 
        /* Compute syndrome with zero for the missing data pages
@@ -263,10 +264,10 @@ __2data_recov_n(int disks, size_t bytes, int faila, int failb,
         * delta p and delta q
         */
        dp = blocks[faila];
-       blocks[faila] = (void *)raid6_empty_zero_page;
+       blocks[faila] = NULL;
        blocks[disks-2] = dp;
        dq = blocks[failb];
-       blocks[failb] = (void *)raid6_empty_zero_page;
+       blocks[failb] = NULL;
        blocks[disks-1] = dq;
 
        init_async_submit(submit, ASYNC_TX_FENCE, tx, NULL, NULL, scribble);
@@ -323,6 +324,8 @@ struct dma_async_tx_descriptor *
 async_raid6_2data_recov(int disks, size_t bytes, int faila, int failb,
                        struct page **blocks, struct async_submit_ctl *submit)
 {
+       int non_zero_srcs, i;
+
        BUG_ON(faila == failb);
        if (failb < faila)
                swap(faila, failb);
@@ -334,11 +337,13 @@ async_raid6_2data_recov(int disks, size_t bytes, int faila, int failb,
         */
        if (!submit->scribble) {
                void **ptrs = (void **) blocks;
-               int i;
 
                async_tx_quiesce(&submit->depend_tx);
                for (i = 0; i < disks; i++)
-                       ptrs[i] = page_address(blocks[i]);
+                       if (blocks[i] == NULL)
+                               ptrs[i] = (void *) raid6_empty_zero_page;
+                       else
+                               ptrs[i] = page_address(blocks[i]);
 
                raid6_2data_recov(disks, bytes, faila, failb, ptrs);
 
@@ -347,19 +352,30 @@ async_raid6_2data_recov(int disks, size_t bytes, int faila, int failb,
                return NULL;
        }
 
-       switch (disks) {
-       case 4:
+       non_zero_srcs = 0;
+       for (i = 0; i < disks-2 && non_zero_srcs < 4; i++)
+               if (blocks[i])
+                       non_zero_srcs++;
+       switch (non_zero_srcs) {
+       case 0:
+       case 1:
+               /* There must be at least 2 sources - the failed devices. */
+               BUG();
+
+       case 2:
                /* dma devices do not uniformly understand a zero source pq
                 * operation (in contrast to the synchronous case), so
-                * explicitly handle the 4 disk special case
+                * explicitly handle the special case of a 4 disk array with
+                * both data disks missing.
                 */
-               return __2data_recov_4(bytes, faila, failb, blocks, submit);
-       case 5:
+               return __2data_recov_4(disks, bytes, faila, failb, blocks, submit);
+       case 3:
                /* dma devices do not uniformly understand a single
                 * source pq operation (in contrast to the synchronous
-                * case), so explicitly handle the 5 disk special case
+                * case), so explicitly handle the special case of a 5 disk
+                * array with 2 of 3 data disks missing.
                 */
-               return __2data_recov_5(bytes, faila, failb, blocks, submit);
+               return __2data_recov_5(disks, bytes, faila, failb, blocks, submit);
        default:
                return __2data_recov_n(disks, bytes, faila, failb, blocks, submit);
        }
@@ -385,6 +401,7 @@ async_raid6_datap_recov(int disks, size_t bytes, int faila,
        dma_async_tx_callback cb_fn = submit->cb_fn;
        void *cb_param = submit->cb_param;
        void *scribble = submit->scribble;
+       int good_srcs, good, i;
        struct page *srcs[2];
 
        pr_debug("%s: disks: %d len: %zu\n", __func__, disks, bytes);
@@ -394,11 +411,13 @@ async_raid6_datap_recov(int disks, size_t bytes, int faila,
         */
        if (!scribble) {
                void **ptrs = (void **) blocks;
-               int i;
 
                async_tx_quiesce(&submit->depend_tx);
                for (i = 0; i < disks; i++)
-                       ptrs[i] = page_address(blocks[i]);
+                       if (blocks[i] == NULL)
+                               ptrs[i] = (void*)raid6_empty_zero_page;
+                       else
+                               ptrs[i] = page_address(blocks[i]);
 
                raid6_datap_recov(disks, bytes, faila, ptrs);
 
@@ -407,6 +426,20 @@ async_raid6_datap_recov(int disks, size_t bytes, int faila,
                return NULL;
        }
 
+       good_srcs = 0;
+       good = -1;
+       for (i = 0; i < disks-2; i++) {
+               if (i == faila)
+                       continue;
+               if (blocks[i]) {
+                       good = i;
+                       good_srcs++;
+                       if (good_srcs > 1)
+                               break;
+               }
+       }
+       BUG_ON(good_srcs == 0);
+
        p = blocks[disks-2];
        q = blocks[disks-1];
 
@@ -414,14 +447,13 @@ async_raid6_datap_recov(int disks, size_t bytes, int faila,
         * Use the dead data page as temporary storage for delta q
         */
        dq = blocks[faila];
-       blocks[faila] = (void *)raid6_empty_zero_page;
+       blocks[faila] = NULL;
        blocks[disks-1] = dq;
 
-       /* in the 4 disk case we only need to perform a single source
-        * multiplication
+       /* in the 4-disk case we only need to perform a single source
+        * multiplication with the one good data block.
         */
-       if (disks == 4) {
-               int good = faila == 0 ? 1 : 0;
+       if (good_srcs == 1) {
                struct page *g = blocks[good];
 
                init_async_submit(submit, ASYNC_TX_FENCE, tx, NULL, NULL,
index b459a90..79182dc 100644 (file)
@@ -44,20 +44,23 @@ do_async_xor(struct dma_chan *chan, struct page *dest, struct page **src_list,
        void *cb_param_orig = submit->cb_param;
        enum async_tx_flags flags_orig = submit->flags;
        enum dma_ctrl_flags dma_flags;
-       int xor_src_cnt;
+       int xor_src_cnt = 0;
        dma_addr_t dma_dest;
 
        /* map the dest bidrectional in case it is re-used as a source */
        dma_dest = dma_map_page(dma->dev, dest, offset, len, DMA_BIDIRECTIONAL);
        for (i = 0; i < src_cnt; i++) {
                /* only map the dest once */
+               if (!src_list[i])
+                       continue;
                if (unlikely(src_list[i] == dest)) {
-                       dma_src[i] = dma_dest;
+                       dma_src[xor_src_cnt++] = dma_dest;
                        continue;
                }
-               dma_src[i] = dma_map_page(dma->dev, src_list[i], offset,
-                                         len, DMA_TO_DEVICE);
+               dma_src[xor_src_cnt++] = dma_map_page(dma->dev, src_list[i], offset,
+                                                     len, DMA_TO_DEVICE);
        }
+       src_cnt = xor_src_cnt;
 
        while (src_cnt) {
                submit->flags = flags_orig;
@@ -123,7 +126,7 @@ do_sync_xor(struct page *dest, struct page **src_list, unsigned int offset,
            int src_cnt, size_t len, struct async_submit_ctl *submit)
 {
        int i;
-       int xor_src_cnt;
+       int xor_src_cnt = 0;
        int src_off = 0;
        void *dest_buf;
        void **srcs;
@@ -135,8 +138,9 @@ do_sync_xor(struct page *dest, struct page **src_list, unsigned int offset,
 
        /* convert to buffer pointers */
        for (i = 0; i < src_cnt; i++)
-               srcs[i] = page_address(src_list[i]) + offset;
-
+               if (src_list[i])
+                       srcs[xor_src_cnt++] = page_address(src_list[i]) + offset;
+       src_cnt = xor_src_cnt;
        /* set destination address */
        dest_buf = page_address(dest) + offset;
 
index 0ed42d8..93d2c79 100644 (file)
@@ -218,10 +218,10 @@ config ACPI_PROCESSOR_AGGREGATOR
        depends on X86
        help
          ACPI 4.0 defines processor Aggregator, which enables OS to perform
-         specfic processor configuration and control that applies to all
+         specific processor configuration and control that applies to all
          processors in the platform. Currently only logical processor idling
          is defined, which is to reduce power consumption. This driver
-         support the new device.
+         supports the new device.
 
 config ACPI_THERMAL
        tristate "Thermal Zone"
index 98b9690..b6ed60b 100644 (file)
@@ -245,6 +245,7 @@ static void acpi_ac_notify(struct acpi_device *device, u32 event)
                acpi_bus_generate_netlink_event(device->pnp.device_class,
                                                  dev_name(&device->dev), event,
                                                  (u32) ac->state);
+               acpi_notifier_call_chain(device, event, (u32) ac->state);
 #ifdef CONFIG_ACPI_SYSFS_POWER
                kobject_uevent(&ac->charger.dev->kobj, KOBJ_CHANGE);
 #endif
index 9335b87..0c9c6a9 100644 (file)
@@ -251,6 +251,9 @@ int acpi_lid_open(void)
        acpi_status status;
        unsigned long long state;
 
+       if (!lid_device)
+               return -ENODEV;
+
        status = acpi_evaluate_integer(lid_device->handle, "_LID", NULL,
                                       &state);
        if (ACPI_FAILURE(status))
index 3112221..1af8081 100644 (file)
@@ -389,6 +389,17 @@ struct pci_dev *acpi_get_pci_dev(acpi_handle handle)
 
                pbus = pdev->subordinate;
                pci_dev_put(pdev);
+
+               /*
+                * This function may be called for a non-PCI device that has a
+                * PCI parent (eg. a disk under a PCI SATA controller).  In that
+                * case pdev->subordinate will be NULL for the parent.
+                */
+               if (!pbus) {
+                       dev_dbg(&pdev->dev, "Not a PCI-to-PCI bridge\n");
+                       pdev = NULL;
+                       break;
+               }
        }
 out:
        list_for_each_entry_safe(node, tmp, &device_list, node)
index f6e54bf..64e3c58 100644 (file)
@@ -1109,7 +1109,12 @@ static int acpi_video_bus_check(struct acpi_video_bus *video)
         */
 
        /* Does this device support video switching? */
-       if (video->cap._DOS) {
+       if (video->cap._DOS || video->cap._DOD) {
+               if (!video->cap._DOS) {
+                       printk(KERN_WARNING FW_BUG
+                               "ACPI(%s) defines _DOD but not _DOS\n",
+                               acpi_device_bid(video->device));
+               }
                video->flags.multihead = 1;
                status = 0;
        }
index 7032f25..575593a 100644 (file)
@@ -84,7 +84,7 @@ long acpi_is_video_device(struct acpi_device *device)
                return 0;
 
        /* Does this device able to support video switching ? */
-       if (ACPI_SUCCESS(acpi_get_handle(device->handle, "_DOD", &h_dummy)) &&
+       if (ACPI_SUCCESS(acpi_get_handle(device->handle, "_DOD", &h_dummy)) ||
            ACPI_SUCCESS(acpi_get_handle(device->handle, "_DOS", &h_dummy)))
                video_caps |= ACPI_VIDEO_OUTPUT_SWITCHING;
 
index acd1162..a06f5d6 100644 (file)
@@ -122,6 +122,7 @@ enum {
        HOST_VERSION            = 0x10, /* AHCI spec. version compliancy */
        HOST_EM_LOC             = 0x1c, /* Enclosure Management location */
        HOST_EM_CTL             = 0x20, /* Enclosure Management Control */
+       HOST_CAP2               = 0x24, /* host capabilities, extended */
 
        /* HOST_CTL bits */
        HOST_RESET              = (1 << 0),  /* reset controller; self-clear */
@@ -129,16 +130,29 @@ enum {
        HOST_AHCI_EN            = (1 << 31), /* AHCI enabled */
 
        /* HOST_CAP bits */
+       HOST_CAP_SXS            = (1 << 5),  /* Supports External SATA */
        HOST_CAP_EMS            = (1 << 6),  /* Enclosure Management support */
-       HOST_CAP_SSC            = (1 << 14), /* Slumber capable */
+       HOST_CAP_CCC            = (1 << 7),  /* Command Completion Coalescing */
+       HOST_CAP_PART           = (1 << 13), /* Partial state capable */
+       HOST_CAP_SSC            = (1 << 14), /* Slumber state capable */
+       HOST_CAP_PIO_MULTI      = (1 << 15), /* PIO multiple DRQ support */
+       HOST_CAP_FBS            = (1 << 16), /* FIS-based switching support */
        HOST_CAP_PMP            = (1 << 17), /* Port Multiplier support */
+       HOST_CAP_ONLY           = (1 << 18), /* Supports AHCI mode only */
        HOST_CAP_CLO            = (1 << 24), /* Command List Override support */
+       HOST_CAP_LED            = (1 << 25), /* Supports activity LED */
        HOST_CAP_ALPM           = (1 << 26), /* Aggressive Link PM support */
        HOST_CAP_SSS            = (1 << 27), /* Staggered Spin-up */
+       HOST_CAP_MPS            = (1 << 28), /* Mechanical presence switch */
        HOST_CAP_SNTF           = (1 << 29), /* SNotification register */
        HOST_CAP_NCQ            = (1 << 30), /* Native Command Queueing */
        HOST_CAP_64             = (1 << 31), /* PCI DAC (64-bit DMA) support */
 
+       /* HOST_CAP2 bits */
+       HOST_CAP2_BOH           = (1 << 0),  /* BIOS/OS handoff supported */
+       HOST_CAP2_NVMHCI        = (1 << 1),  /* NVMHCI supported */
+       HOST_CAP2_APST          = (1 << 2),  /* Automatic partial to slumber */
+
        /* registers for each SATA port */
        PORT_LST_ADDR           = 0x00, /* command list DMA addr */
        PORT_LST_ADDR_HI        = 0x04, /* command list DMA addr hi */
@@ -267,8 +281,10 @@ struct ahci_em_priv {
 struct ahci_host_priv {
        unsigned int            flags;          /* AHCI_HFLAG_* */
        u32                     cap;            /* cap to use */
+       u32                     cap2;           /* cap2 to use */
        u32                     port_map;       /* port map to use */
        u32                     saved_cap;      /* saved initial cap */
+       u32                     saved_cap2;     /* saved initial cap2 */
        u32                     saved_port_map; /* saved initial port_map */
        u32                     em_loc; /* enclosure management location */
 };
@@ -331,12 +347,15 @@ static void ahci_init_sw_activity(struct ata_link *link);
 
 static ssize_t ahci_show_host_caps(struct device *dev,
                                   struct device_attribute *attr, char *buf);
+static ssize_t ahci_show_host_cap2(struct device *dev,
+                                  struct device_attribute *attr, char *buf);
 static ssize_t ahci_show_host_version(struct device *dev,
                                      struct device_attribute *attr, char *buf);
 static ssize_t ahci_show_port_cmd(struct device *dev,
                                  struct device_attribute *attr, char *buf);
 
 DEVICE_ATTR(ahci_host_caps, S_IRUGO, ahci_show_host_caps, NULL);
+DEVICE_ATTR(ahci_host_cap2, S_IRUGO, ahci_show_host_cap2, NULL);
 DEVICE_ATTR(ahci_host_version, S_IRUGO, ahci_show_host_version, NULL);
 DEVICE_ATTR(ahci_port_cmd, S_IRUGO, ahci_show_port_cmd, NULL);
 
@@ -345,6 +364,7 @@ static struct device_attribute *ahci_shost_attrs[] = {
        &dev_attr_em_message_type,
        &dev_attr_em_message,
        &dev_attr_ahci_host_caps,
+       &dev_attr_ahci_host_cap2,
        &dev_attr_ahci_host_version,
        &dev_attr_ahci_port_cmd,
        NULL
@@ -447,7 +467,8 @@ static const struct ata_port_info ahci_port_info[] = {
        [board_ahci_sb600] =
        {
                AHCI_HFLAGS     (AHCI_HFLAG_IGN_SERR_INTERNAL |
-                                AHCI_HFLAG_NO_MSI | AHCI_HFLAG_SECT255),
+                                AHCI_HFLAG_NO_MSI | AHCI_HFLAG_SECT255 |
+                                AHCI_HFLAG_32BIT_ONLY),
                .flags          = AHCI_FLAG_COMMON,
                .pio_mask       = ATA_PIO4,
                .udma_mask      = ATA_UDMA6,
@@ -554,7 +575,7 @@ static const struct pci_device_id ahci_pci_tbl[] = {
        { PCI_VDEVICE(ATI, 0x4395), board_ahci_sb700 }, /* ATI SB700/800 */
 
        /* AMD */
-       { PCI_VDEVICE(AMD, 0x7800), board_ahci }, /* AMD SB900 */
+       { PCI_VDEVICE(AMD, 0x7800), board_ahci }, /* AMD Hudson-2 */
        /* AMD is using RAID class only for ahci controllers */
        { PCI_VENDOR_ID_AMD, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,
          PCI_CLASS_STORAGE_RAID << 8, 0xffffff, board_ahci },
@@ -584,6 +605,7 @@ static const struct pci_device_id ahci_pci_tbl[] = {
        { PCI_VDEVICE(NVIDIA, 0x0559), board_ahci_yesncq },     /* MCP67 */
        { PCI_VDEVICE(NVIDIA, 0x055a), board_ahci_yesncq },     /* MCP67 */
        { PCI_VDEVICE(NVIDIA, 0x055b), board_ahci_yesncq },     /* MCP67 */
+       { PCI_VDEVICE(NVIDIA, 0x0580), board_ahci_yesncq },     /* Linux ID */
        { PCI_VDEVICE(NVIDIA, 0x07f0), board_ahci_yesncq },     /* MCP73 */
        { PCI_VDEVICE(NVIDIA, 0x07f1), board_ahci_yesncq },     /* MCP73 */
        { PCI_VDEVICE(NVIDIA, 0x07f2), board_ahci_yesncq },     /* MCP73 */
@@ -732,6 +754,16 @@ static ssize_t ahci_show_host_caps(struct device *dev,
        return sprintf(buf, "%x\n", hpriv->cap);
 }
 
+static ssize_t ahci_show_host_cap2(struct device *dev,
+                                  struct device_attribute *attr, char *buf)
+{
+       struct Scsi_Host *shost = class_to_shost(dev);
+       struct ata_port *ap = ata_shost_to_port(shost);
+       struct ahci_host_priv *hpriv = ap->host->private_data;
+
+       return sprintf(buf, "%x\n", hpriv->cap2);
+}
+
 static ssize_t ahci_show_host_version(struct device *dev,
                                   struct device_attribute *attr, char *buf)
 {
@@ -771,7 +803,7 @@ static void ahci_save_initial_config(struct pci_dev *pdev,
                                     struct ahci_host_priv *hpriv)
 {
        void __iomem *mmio = pcim_iomap_table(pdev)[AHCI_PCI_BAR];
-       u32 cap, port_map;
+       u32 cap, cap2, vers, port_map;
        int i;
        int mv;
 
@@ -784,6 +816,14 @@ static void ahci_save_initial_config(struct pci_dev *pdev,
        hpriv->saved_cap = cap = readl(mmio + HOST_CAP);
        hpriv->saved_port_map = port_map = readl(mmio + HOST_PORTS_IMPL);
 
+       /* CAP2 register is only defined for AHCI 1.2 and later */
+       vers = readl(mmio + HOST_VERSION);
+       if ((vers >> 16) > 1 ||
+          ((vers >> 16) == 1 && (vers & 0xFFFF) >= 0x200))
+               hpriv->saved_cap2 = cap2 = readl(mmio + HOST_CAP2);
+       else
+               hpriv->saved_cap2 = cap2 = 0;
+
        /* some chips have errata preventing 64bit use */
        if ((cap & HOST_CAP_64) && (hpriv->flags & AHCI_HFLAG_32BIT_ONLY)) {
                dev_printk(KERN_INFO, &pdev->dev,
@@ -869,6 +909,7 @@ static void ahci_save_initial_config(struct pci_dev *pdev,
 
        /* record values to use during operation */
        hpriv->cap = cap;
+       hpriv->cap2 = cap2;
        hpriv->port_map = port_map;
 }
 
@@ -887,6 +928,8 @@ static void ahci_restore_initial_config(struct ata_host *host)
        void __iomem *mmio = host->iomap[AHCI_PCI_BAR];
 
        writel(hpriv->saved_cap, mmio + HOST_CAP);
+       if (hpriv->saved_cap2)
+               writel(hpriv->saved_cap2, mmio + HOST_CAP2);
        writel(hpriv->saved_port_map, mmio + HOST_PORTS_IMPL);
        (void) readl(mmio + HOST_PORTS_IMPL);   /* flush */
 }
@@ -2534,13 +2577,14 @@ static void ahci_print_info(struct ata_host *host)
        struct ahci_host_priv *hpriv = host->private_data;
        struct pci_dev *pdev = to_pci_dev(host->dev);
        void __iomem *mmio = host->iomap[AHCI_PCI_BAR];
-       u32 vers, cap, impl, speed;
+       u32 vers, cap, cap2, impl, speed;
        const char *speed_s;
        u16 cc;
        const char *scc_s;
 
        vers = readl(mmio + HOST_VERSION);
        cap = hpriv->cap;
+       cap2 = hpriv->cap2;
        impl = hpriv->port_map;
 
        speed = (cap >> 20) & 0xf;
@@ -2583,25 +2627,29 @@ static void ahci_print_info(struct ata_host *host)
                "flags: "
                "%s%s%s%s%s%s%s"
                "%s%s%s%s%s%s%s"
-               "%s\n"
+               "%s%s%s%s%s%s\n"
                ,
 
-               cap & (1 << 31) ? "64bit " : "",
-               cap & (1 << 30) ? "ncq " : "",
-               cap & (1 << 29) ? "sntf " : "",
-               cap & (1 << 28) ? "ilck " : "",
-               cap & (1 << 27) ? "stag " : "",
-               cap & (1 << 26) ? "pm " : "",
-               cap & (1 << 25) ? "led " : "",
-
-               cap & (1 << 24) ? "clo " : "",
-               cap & (1 << 19) ? "nz " : "",
-               cap & (1 << 18) ? "only " : "",
-               cap & (1 << 17) ? "pmp " : "",
-               cap & (1 << 15) ? "pio " : "",
-               cap & (1 << 14) ? "slum " : "",
-               cap & (1 << 13) ? "part " : "",
-               cap & (1 << 6) ? "ems ": ""
+               cap & HOST_CAP_64 ? "64bit " : "",
+               cap & HOST_CAP_NCQ ? "ncq " : "",
+               cap & HOST_CAP_SNTF ? "sntf " : "",
+               cap & HOST_CAP_MPS ? "ilck " : "",
+               cap & HOST_CAP_SSS ? "stag " : "",
+               cap & HOST_CAP_ALPM ? "pm " : "",
+               cap & HOST_CAP_LED ? "led " : "",
+               cap & HOST_CAP_CLO ? "clo " : "",
+               cap & HOST_CAP_ONLY ? "only " : "",
+               cap & HOST_CAP_PMP ? "pmp " : "",
+               cap & HOST_CAP_FBS ? "fbs " : "",
+               cap & HOST_CAP_PIO_MULTI ? "pio " : "",
+               cap & HOST_CAP_SSC ? "slum " : "",
+               cap & HOST_CAP_PART ? "part " : "",
+               cap & HOST_CAP_CCC ? "ccc " : "",
+               cap & HOST_CAP_EMS ? "ems " : "",
+               cap & HOST_CAP_SXS ? "sxs " : "",
+               cap2 & HOST_CAP2_APST ? "apst " : "",
+               cap2 & HOST_CAP2_NVMHCI ? "nvmp " : "",
+               cap2 & HOST_CAP2_BOH ? "boh " : ""
                );
 }
 
@@ -2650,17 +2698,15 @@ static void ahci_p5wdh_workaround(struct ata_host *host)
        }
 }
 
-/*
- * SB600 ahci controller on certain boards can't do 64bit DMA with
- * older BIOS.
- */
-static bool ahci_sb600_32bit_only(struct pci_dev *pdev)
+/* only some SB600 ahci controllers can do 64bit DMA */
+static bool ahci_sb600_enable_64bit(struct pci_dev *pdev)
 {
        static const struct dmi_system_id sysids[] = {
                /*
                 * The oldest version known to be broken is 0901 and
                 * working is 1501 which was released on 2007-10-26.
-                * Force 32bit DMA on anything older than 1501.
+                * Enable 64bit DMA on 1501 and anything newer.
+                *
                 * Please read bko#9412 for more info.
                 */
                {
@@ -2672,48 +2718,29 @@ static bool ahci_sb600_32bit_only(struct pci_dev *pdev)
                        },
                        .driver_data = "20071026",      /* yyyymmdd */
                },
-               /*
-                * It's yet unknown whether more recent BIOS fixes the
-                * problem.  Blacklist the whole board for the time
-                * being.  Please read the following thread for more
-                * info.
-                *
-                * http://thread.gmane.org/gmane.linux.ide/42326
-                */
-               {
-                       .ident = "Gigabyte GA-MA69VM-S2",
-                       .matches = {
-                               DMI_MATCH(DMI_BOARD_VENDOR,
-                                         "Gigabyte Technology Co., Ltd."),
-                               DMI_MATCH(DMI_BOARD_NAME, "GA-MA69VM-S2"),
-                       },
-               },
                { }
        };
        const struct dmi_system_id *match;
+       int year, month, date;
+       char buf[9];
 
        match = dmi_first_match(sysids);
        if (pdev->bus->number != 0 || pdev->devfn != PCI_DEVFN(0x12, 0) ||
            !match)
                return false;
 
-       if (match->driver_data) {
-               int year, month, date;
-               char buf[9];
-
-               dmi_get_date(DMI_BIOS_DATE, &year, &month, &date);
-               snprintf(buf, sizeof(buf), "%04d%02d%02d", year, month, date);
-
-               if (strcmp(buf, match->driver_data) >= 0)
-                       return false;
+       dmi_get_date(DMI_BIOS_DATE, &year, &month, &date);
+       snprintf(buf, sizeof(buf), "%04d%02d%02d", year, month, date);
 
+       if (strcmp(buf, match->driver_data) >= 0) {
+               dev_printk(KERN_WARNING, &pdev->dev, "%s: enabling 64bit DMA\n",
+                          match->ident);
+               return true;
+       } else {
                dev_printk(KERN_WARNING, &pdev->dev, "%s: BIOS too old, "
                           "forcing 32bit DMA, update BIOS\n", match->ident);
-       } else
-               dev_printk(KERN_WARNING, &pdev->dev, "%s: this board can't "
-                          "do 64bit DMA, forcing 32bit\n", match->ident);
-
-       return true;
+               return false;
+       }
 }
 
 static bool ahci_broken_system_poweroff(struct pci_dev *pdev)
@@ -2858,6 +2885,55 @@ static bool ahci_broken_online(struct pci_dev *pdev)
        return pdev->bus->number == (val >> 8) && pdev->devfn == (val & 0xff);
 }
 
+#ifdef CONFIG_ATA_ACPI
+static void ahci_gtf_filter_workaround(struct ata_host *host)
+{
+       static const struct dmi_system_id sysids[] = {
+               /*
+                * Aspire 3810T issues a bunch of SATA enable commands
+                * via _GTF including an invalid one and one which is
+                * rejected by the device.  Among the successful ones
+                * is FPDMA non-zero offset enable which when enabled
+                * only on the drive side leads to NCQ command
+                * failures.  Filter it out.
+                */
+               {
+                       .ident = "Aspire 3810T",
+                       .matches = {
+                               DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
+                               DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 3810T"),
+                       },
+                       .driver_data = (void *)ATA_ACPI_FILTER_FPDMA_OFFSET,
+               },
+               { }
+       };
+       const struct dmi_system_id *dmi = dmi_first_match(sysids);
+       unsigned int filter;
+       int i;
+
+       if (!dmi)
+               return;
+
+       filter = (unsigned long)dmi->driver_data;
+       dev_printk(KERN_INFO, host->dev,
+                  "applying extra ACPI _GTF filter 0x%x for %s\n",
+                  filter, dmi->ident);
+
+       for (i = 0; i < host->n_ports; i++) {
+               struct ata_port *ap = host->ports[i];
+               struct ata_link *link;
+               struct ata_device *dev;
+
+               ata_for_each_link(link, ap, EDGE)
+                       ata_for_each_dev(dev, link, ALL)
+                               dev->gtf_filter |= filter;
+       }
+}
+#else
+static inline void ahci_gtf_filter_workaround(struct ata_host *host)
+{}
+#endif
+
 static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
        static int printed_version;
@@ -2926,9 +3002,9 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
        if (board_id == board_ahci_sb700 && pdev->revision >= 0x40)
                hpriv->flags &= ~AHCI_HFLAG_IGN_SERR_INTERNAL;
 
-       /* apply sb600 32bit only quirk */
-       if (ahci_sb600_32bit_only(pdev))
-               hpriv->flags |= AHCI_HFLAG_32BIT_ONLY;
+       /* only some SB600s can do 64bit DMA */
+       if (ahci_sb600_enable_64bit(pdev))
+               hpriv->flags &= ~AHCI_HFLAG_32BIT_ONLY;
 
        if ((hpriv->flags & AHCI_HFLAG_NO_MSI) || pci_enable_msi(pdev))
                pci_intx(pdev, 1);
@@ -3023,6 +3099,9 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
        /* apply workaround for ASUS P5W DH Deluxe mainboard */
        ahci_p5wdh_workaround(host);
 
+       /* apply gtf filter quirk */
+       ahci_gtf_filter_workaround(host);
+
        /* initialize adapter */
        rc = ahci_configure_dma_masks(pdev, hpriv->cap & HOST_CAP_64);
        if (rc)
index 01964b6..b0882cd 100644 (file)
 
 #include <acpi/acpi_bus.h>
 
-enum {
-       ATA_ACPI_FILTER_SETXFER = 1 << 0,
-       ATA_ACPI_FILTER_LOCK    = 1 << 1,
-       ATA_ACPI_FILTER_DIPM    = 1 << 2,
-
-       ATA_ACPI_FILTER_DEFAULT = ATA_ACPI_FILTER_SETXFER |
-                                 ATA_ACPI_FILTER_LOCK |
-                                 ATA_ACPI_FILTER_DIPM,
-};
-
-static unsigned int ata_acpi_gtf_filter = ATA_ACPI_FILTER_DEFAULT;
+unsigned int ata_acpi_gtf_filter = ATA_ACPI_FILTER_DEFAULT;
 module_param_named(acpi_gtf_filter, ata_acpi_gtf_filter, int, 0644);
-MODULE_PARM_DESC(acpi_gtf_filter, "filter mask for ACPI _GTF commands, set to filter out (0x1=set xfermode, 0x2=lock/freeze lock, 0x4=DIPM)");
+MODULE_PARM_DESC(acpi_gtf_filter, "filter mask for ACPI _GTF commands, set to filter out (0x1=set xfermode, 0x2=lock/freeze lock, 0x4=DIPM, 0x8=FPDMA non-zero offset, 0x10=FPDMA DMA Setup FIS auto-activate)");
 
 #define NO_PORT_MULT           0xffff
 #define SATA_ADR(root, pmp)    (((root) << 16) | (pmp))
@@ -613,10 +603,11 @@ static void ata_acpi_gtf_to_tf(struct ata_device *dev,
        tf->command = gtf->tf[6];       /* 0x1f7 */
 }
 
-static int ata_acpi_filter_tf(const struct ata_taskfile *tf,
+static int ata_acpi_filter_tf(struct ata_device *dev,
+                             const struct ata_taskfile *tf,
                              const struct ata_taskfile *ptf)
 {
-       if (ata_acpi_gtf_filter & ATA_ACPI_FILTER_SETXFER) {
+       if (dev->gtf_filter & ATA_ACPI_FILTER_SETXFER) {
                /* libata doesn't use ACPI to configure transfer mode.
                 * It will only confuse device configuration.  Skip.
                 */
@@ -625,7 +616,7 @@ static int ata_acpi_filter_tf(const struct ata_taskfile *tf,
                        return 1;
        }
 
-       if (ata_acpi_gtf_filter & ATA_ACPI_FILTER_LOCK) {
+       if (dev->gtf_filter & ATA_ACPI_FILTER_LOCK) {
                /* BIOS writers, sorry but we don't wanna lock
                 * features unless the user explicitly said so.
                 */
@@ -647,12 +638,23 @@ static int ata_acpi_filter_tf(const struct ata_taskfile *tf,
                        return 1;
        }
 
-       if (ata_acpi_gtf_filter & ATA_ACPI_FILTER_DIPM) {
+       if (tf->command == ATA_CMD_SET_FEATURES &&
+           tf->feature == SETFEATURES_SATA_ENABLE) {
                /* inhibit enabling DIPM */
-               if (tf->command == ATA_CMD_SET_FEATURES &&
-                   tf->feature == SETFEATURES_SATA_ENABLE &&
+               if (dev->gtf_filter & ATA_ACPI_FILTER_DIPM &&
                    tf->nsect == SATA_DIPM)
                        return 1;
+
+               /* inhibit FPDMA non-zero offset */
+               if (dev->gtf_filter & ATA_ACPI_FILTER_FPDMA_OFFSET &&
+                   (tf->nsect == SATA_FPDMA_OFFSET ||
+                    tf->nsect == SATA_FPDMA_IN_ORDER))
+                       return 1;
+
+               /* inhibit FPDMA auto activation */
+               if (dev->gtf_filter & ATA_ACPI_FILTER_FPDMA_AA &&
+                   tf->nsect == SATA_FPDMA_AA)
+                       return 1;
        }
 
        return 0;
@@ -704,7 +706,7 @@ static int ata_acpi_run_tf(struct ata_device *dev,
                pptf = &ptf;
        }
 
-       if (!ata_acpi_filter_tf(&tf, pptf)) {
+       if (!ata_acpi_filter_tf(dev, &tf, pptf)) {
                rtf = tf;
                err_mask = ata_exec_internal(dev, &rtf, NULL,
                                             DMA_NONE, NULL, 0, 0);
index 0ddaf43..d7f0f1b 100644 (file)
@@ -5028,12 +5028,14 @@ void ata_qc_complete(struct ata_queued_cmd *qc)
                        qc->flags |= ATA_QCFLAG_FAILED;
 
                if (unlikely(qc->flags & ATA_QCFLAG_FAILED)) {
-                       if (!ata_tag_internal(qc->tag)) {
-                               /* always fill result TF for failed qc */
-                               fill_result_tf(qc);
+                       /* always fill result TF for failed qc */
+                       fill_result_tf(qc);
+
+                       if (!ata_tag_internal(qc->tag))
                                ata_qc_schedule_eh(qc);
-                               return;
-                       }
+                       else
+                               __ata_qc_complete(qc);
+                       return;
                }
 
                WARN_ON_ONCE(ap->pflags & ATA_PFLAG_FROZEN);
@@ -5591,6 +5593,9 @@ void ata_link_init(struct ata_port *ap, struct ata_link *link, int pmp)
 
                dev->link = link;
                dev->devno = dev - link->device;
+#ifdef CONFIG_ATA_ACPI
+               dev->gtf_filter = ata_acpi_gtf_filter;
+#endif
                ata_dev_init(dev);
        }
 }
index a04488f..bba2ae5 100644 (file)
@@ -2667,14 +2667,14 @@ int ata_eh_reset(struct ata_link *link, int classify,
                dev->pio_mode = XFER_PIO_0;
                dev->flags &= ~ATA_DFLAG_SLEEPING;
 
-               if (!ata_phys_link_offline(ata_dev_phys_link(dev))) {
-                       /* apply class override */
-                       if (lflags & ATA_LFLAG_ASSUME_ATA)
-                               classes[dev->devno] = ATA_DEV_ATA;
-                       else if (lflags & ATA_LFLAG_ASSUME_SEMB)
-                               classes[dev->devno] = ATA_DEV_SEMB_UNSUP;
-               } else
-                       classes[dev->devno] = ATA_DEV_NONE;
+               if (ata_phys_link_offline(ata_dev_phys_link(dev)))
+                       continue;
+
+               /* apply class override */
+               if (lflags & ATA_LFLAG_ASSUME_ATA)
+                       classes[dev->devno] = ATA_DEV_ATA;
+               else if (lflags & ATA_LFLAG_ASSUME_SEMB)
+                       classes[dev->devno] = ATA_DEV_SEMB_UNSUP;
        }
 
        /* record current link speed */
@@ -2713,34 +2713,48 @@ int ata_eh_reset(struct ata_link *link, int classify,
        ap->pflags &= ~ATA_PFLAG_EH_PENDING;
        spin_unlock_irqrestore(link->ap->lock, flags);
 
-       /* Make sure onlineness and classification result correspond.
+       /*
+        * Make sure onlineness and classification result correspond.
         * Hotplug could have happened during reset and some
         * controllers fail to wait while a drive is spinning up after
         * being hotplugged causing misdetection.  By cross checking
-        * link onlineness and classification result, those conditions
-        * can be reliably detected and retried.
+        * link on/offlineness and classification result, those
+        * conditions can be reliably detected and retried.
         */
        nr_unknown = 0;
        ata_for_each_dev(dev, link, ALL) {
-               /* convert all ATA_DEV_UNKNOWN to ATA_DEV_NONE */
-               if (classes[dev->devno] == ATA_DEV_UNKNOWN) {
-                       classes[dev->devno] = ATA_DEV_NONE;
-                       if (ata_phys_link_online(ata_dev_phys_link(dev)))
+               if (ata_phys_link_online(ata_dev_phys_link(dev))) {
+                       if (classes[dev->devno] == ATA_DEV_UNKNOWN) {
+                               ata_dev_printk(dev, KERN_DEBUG, "link online "
+                                              "but device misclassifed\n");
+                               classes[dev->devno] = ATA_DEV_NONE;
                                nr_unknown++;
+                       }
+               } else if (ata_phys_link_offline(ata_dev_phys_link(dev))) {
+                       if (ata_class_enabled(classes[dev->devno]))
+                               ata_dev_printk(dev, KERN_DEBUG, "link offline, "
+                                              "clearing class %d to NONE\n",
+                                              classes[dev->devno]);
+                       classes[dev->devno] = ATA_DEV_NONE;
+               } else if (classes[dev->devno] == ATA_DEV_UNKNOWN) {
+                       ata_dev_printk(dev, KERN_DEBUG, "link status unknown, "
+                                      "clearing UNKNOWN to NONE\n");
+                       classes[dev->devno] = ATA_DEV_NONE;
                }
        }
 
        if (classify && nr_unknown) {
                if (try < max_tries) {
                        ata_link_printk(link, KERN_WARNING, "link online but "
-                                      "device misclassified, retrying\n");
+                                       "%d devices misclassified, retrying\n",
+                                       nr_unknown);
                        failed_link = link;
                        rc = -EAGAIN;
                        goto fail;
                }
                ata_link_printk(link, KERN_WARNING,
-                              "link online but device misclassified, "
-                              "device detection might fail\n");
+                               "link online but %d devices misclassified, "
+                               "device detection might fail\n", nr_unknown);
        }
 
        /* reset successful, schedule revalidation */
@@ -2967,12 +2981,14 @@ static int ata_eh_revalidate_and_attach(struct ata_link *link,
         * device detection messages backwards.
         */
        ata_for_each_dev(dev, link, ALL) {
-               if (!(new_mask & (1 << dev->devno)) ||
-                   dev->class == ATA_DEV_PMP)
+               if (!(new_mask & (1 << dev->devno)))
                        continue;
 
                dev->class = ehc->classes[dev->devno];
 
+               if (dev->class == ATA_DEV_PMP)
+                       continue;
+
                ehc->i.flags |= ATA_EHI_PRINTINFO;
                rc = ata_dev_configure(dev);
                ehc->i.flags &= ~ATA_EHI_PRINTINFO;
index be8e262..823e630 100644 (file)
@@ -118,6 +118,8 @@ extern void ata_lpm_schedule(struct ata_port *ap, enum link_pm);
 
 /* libata-acpi.c */
 #ifdef CONFIG_ATA_ACPI
+extern unsigned int ata_acpi_gtf_filter;
+
 extern void ata_acpi_associate_sata_port(struct ata_port *ap);
 extern void ata_acpi_associate(struct ata_host *host);
 extern void ata_acpi_dissociate(struct ata_host *host);
index fc9c5d6..1432dc9 100644 (file)
@@ -290,7 +290,7 @@ static void ali_warn_atapi_dma(struct ata_device *adev)
 
        if (print_info && adev->class == ATA_DEV_ATAPI && !ali_atapi_dma) {
                ata_dev_printk(adev, KERN_WARNING,
-                              "WARNING: ATAPI DMA disabled for reliablity issues.  It can be enabled\n");
+                              "WARNING: ATAPI DMA disabled for reliability issues.  It can be enabled\n");
                ata_dev_printk(adev, KERN_WARNING,
                               "WARNING: via pata_ali.atapi_dma modparam or corresponding sysfs node.\n");
        }
index aa4b3f6..ae4454d 100644 (file)
@@ -246,7 +246,7 @@ static const struct pci_device_id atiixp[] = {
        { PCI_VDEVICE(ATI, PCI_DEVICE_ID_ATI_IXP400_IDE), },
        { PCI_VDEVICE(ATI, PCI_DEVICE_ID_ATI_IXP600_IDE), },
        { PCI_VDEVICE(ATI, PCI_DEVICE_ID_ATI_IXP700_IDE), },
-       { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_SB900_IDE), },
+       { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_HUDSON2_IDE), },
 
        { },
 };
index 7990de9..6fe7ded 100644 (file)
@@ -118,20 +118,13 @@ struct atp867x_priv {
        int             pci66mhz;
 };
 
-static inline u8 atp867x_speed_to_mode(u8 speed)
-{
-       return speed - XFER_UDMA_0 + 1;
-}
-
 static void atp867x_set_dmamode(struct ata_port *ap, struct ata_device *adev)
 {
        struct pci_dev *pdev    = to_pci_dev(ap->host->dev);
        struct atp867x_priv *dp = ap->private_data;
        u8 speed = adev->dma_mode;
        u8 b;
-       u8 mode;
-
-       mode = atp867x_speed_to_mode(speed);
+       u8 mode = speed - XFER_UDMA_0 + 1;
 
        /*
         * Doc 6.6.9: decrease the udma mode value by 1 for safer UDMA speed
@@ -156,25 +149,38 @@ static void atp867x_set_dmamode(struct ata_port *ap, struct ata_device *adev)
        iowrite8(b, dp->dma_mode);
 }
 
-static int atp867x_get_active_clocks_shifted(unsigned int clk)
+static int atp867x_get_active_clocks_shifted(struct ata_port *ap,
+       unsigned int clk)
 {
+       struct atp867x_priv *dp = ap->private_data;
        unsigned char clocks = clk;
 
+       /*
+        * Doc 6.6.9: increase the clock value by 1 for safer PIO speed
+        * on 66MHz bus
+        */
+       if (dp->pci66mhz)
+               clocks++;
+
        switch (clocks) {
        case 0:
                clocks = 1;
                break;
-       case 1 ... 7:
-               break;
-       case 8 ... 12:
-               clocks = 7;
+       case 1 ... 6:
                break;
        default:
                printk(KERN_WARNING "ATP867X: active %dclk is invalid. "
-                       "Using default 8clk.\n", clk);
-               clocks = 0;     /* 8 clk */
+                       "Using 12clk.\n", clk);
+       case 9 ... 12:
+               clocks = 7;     /* 12 clk */
                break;
+       case 7:
+       case 8: /* default 8 clk */
+               clocks = 0;
+               goto active_clock_shift_done;
        }
+
+active_clock_shift_done:
        return clocks << ATP867X_IO_PIOSPD_ACTIVE_SHIFT;
 }
 
@@ -188,20 +194,20 @@ static int atp867x_get_recover_clocks_shifted(unsigned int clk)
                break;
        case 1 ... 11:
                break;
-       case 12:
-               clocks = 0;
-               break;
-       case 13: case 14:
-               --clocks;
+       case 13:
+       case 14:
+               --clocks;       /* by the spec */
                break;
        case 15:
                break;
        default:
                printk(KERN_WARNING "ATP867X: recover %dclk is invalid. "
-                       "Using default 15clk.\n", clk);
-               clocks = 0;     /* 12 clk */
+                       "Using default 12clk.\n", clk);
+       case 12:        /* default 12 clk */
+               clocks = 0;
                break;
        }
+
        return clocks << ATP867X_IO_PIOSPD_RECOVER_SHIFT;
 }
 
@@ -230,25 +236,38 @@ static void atp867x_set_piomode(struct ata_port *ap, struct ata_device *adev)
                b = (b & ~ATP867X_IO_DMAMODE_MSTR_MASK);
        iowrite8(b, dp->dma_mode);
 
-       b = atp867x_get_active_clocks_shifted(t.active) |
-               atp867x_get_recover_clocks_shifted(t.recover);
-       if (dp->pci66mhz)
-               b += 0x10;
+       b = atp867x_get_active_clocks_shifted(ap, t.active) |
+           atp867x_get_recover_clocks_shifted(t.recover);
 
        if (adev->devno & 1)
                iowrite8(b, dp->slave_piospd);
        else
                iowrite8(b, dp->mstr_piospd);
 
-       /*
-        * use the same value for comand timing as for PIO timimg
-        */
+       b = atp867x_get_active_clocks_shifted(ap, t.act8b) |
+           atp867x_get_recover_clocks_shifted(t.rec8b);
+
        iowrite8(b, dp->eightb_piospd);
 }
 
+static int atp867x_cable_override(struct pci_dev *pdev)
+{
+       if (pdev->subsystem_vendor == PCI_VENDOR_ID_ARTOP &&
+               (pdev->subsystem_device == PCI_DEVICE_ID_ARTOP_ATP867A ||
+                pdev->subsystem_device == PCI_DEVICE_ID_ARTOP_ATP867B)) {
+               return 1;
+       }
+       return 0;
+}
+
 static int atp867x_cable_detect(struct ata_port *ap)
 {
-       return ATA_CBL_PATA40_SHORT;
+       struct pci_dev *pdev = to_pci_dev(ap->host->dev);
+
+       if (atp867x_cable_override(pdev))
+               return ATA_CBL_PATA40_SHORT;
+
+       return ATA_CBL_PATA_UNK;
 }
 
 static struct scsi_host_template atp867x_sht = {
@@ -471,7 +490,6 @@ static int atp867x_init_one(struct pci_dev *pdev,
        static const struct ata_port_info info_867x = {
                .flags          = ATA_FLAG_SLAVE_POSS,
                .pio_mask       = ATA_PIO4,
-               .mwdma_mask     = ATA_MWDMA2,
                .udma_mask      = ATA_UDMA6,
                .port_ops       = &atp867x_ops,
        };
@@ -515,6 +533,23 @@ err_out:
        return rc;
 }
 
+#ifdef CONFIG_PM
+static int atp867x_reinit_one(struct pci_dev *pdev)
+{
+       struct ata_host *host = dev_get_drvdata(&pdev->dev);
+       int rc;
+
+       rc = ata_pci_device_do_resume(pdev);
+       if (rc)
+               return rc;
+
+       atp867x_fixup(host);
+
+       ata_host_resume(host);
+       return 0;
+}
+#endif
+
 static struct pci_device_id atp867x_pci_tbl[] = {
        { PCI_VDEVICE(ARTOP, PCI_DEVICE_ID_ARTOP_ATP867A),      0 },
        { PCI_VDEVICE(ARTOP, PCI_DEVICE_ID_ARTOP_ATP867B),      0 },
@@ -526,6 +561,10 @@ static struct pci_driver atp867x_driver = {
        .id_table       = atp867x_pci_tbl,
        .probe          = atp867x_init_one,
        .remove         = ata_pci_remove_one,
+#ifdef CONFIG_PM
+       .suspend        = ata_pci_device_suspend,
+       .resume         = atp867x_reinit_one,
+#endif
 };
 
 static int __init atp867x_init(void)
index f49814d..3bbed83 100644 (file)
@@ -235,8 +235,7 @@ static int sc1200_init_one(struct pci_dev *dev, const struct pci_device_id *id)
                .udma_mask = ATA_UDMA2,
                .port_ops = &sc1200_port_ops
        };
-       /* Can't enable port 2 yet, see top comments */
-       const struct ata_port_info *ppi[] = { &info, };
+       const struct ata_port_info *ppi[] = { &info, NULL };
 
        return ata_pci_sff_init_one(dev, ppi, &sc1200_sht, NULL);
 }
index 45657ca..88984b8 100644 (file)
@@ -111,7 +111,7 @@ static const struct via_isa_bridge {
        { "vt8251",     PCI_DEVICE_ID_VIA_8251,     0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST },
        { "cx700",      PCI_DEVICE_ID_VIA_CX700,    0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST | VIA_SATA_PATA },
        { "vt6410",     PCI_DEVICE_ID_VIA_6410,     0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST | VIA_NO_ENABLES },
-       { "vt6415",     PCI_DEVICE_ID_VIA_6415,     0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST | VIA_NO_ENABLES },
+       { "vt6415",     PCI_DEVICE_ID_VIA_6415,     0x00, 0xff, VIA_UDMA_133 | VIA_BAD_AST | VIA_NO_ENABLES },
        { "vt8237a",    PCI_DEVICE_ID_VIA_8237A,    0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST },
        { "vt8237",     PCI_DEVICE_ID_VIA_8237,     0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST },
        { "vt8235",     PCI_DEVICE_ID_VIA_8235,     0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST },
index 17f9ff9..6f5093b 100644 (file)
@@ -1382,6 +1382,25 @@ static int mv_qc_defer(struct ata_queued_cmd *qc)
         */
        if (pp->pp_flags & MV_PP_FLAG_DELAYED_EH)
                return ATA_DEFER_PORT;
+
+       /* PIO commands need exclusive link: no other commands [DMA or PIO]
+        * can run concurrently.
+        * set excl_link when we want to send a PIO command in DMA mode
+        * or a non-NCQ command in NCQ mode.
+        * When we receive a command from that link, and there are no
+        * outstanding commands, mark a flag to clear excl_link and let
+        * the command go through.
+        */
+       if (unlikely(ap->excl_link)) {
+               if (link == ap->excl_link) {
+                       if (ap->nr_active_links)
+                               return ATA_DEFER_PORT;
+                       qc->flags |= ATA_QCFLAG_CLEAR_EXCL;
+                       return 0;
+               } else
+                       return ATA_DEFER_PORT;
+       }
+
        /*
         * If the port is completely idle, then allow the new qc.
         */
@@ -1395,8 +1414,14 @@ static int mv_qc_defer(struct ata_queued_cmd *qc)
         * doesn't allow it.
         */
        if ((pp->pp_flags & MV_PP_FLAG_EDMA_EN) &&
-           (pp->pp_flags & MV_PP_FLAG_NCQ_EN) && ata_is_ncq(qc->tf.protocol))
-               return 0;
+           (pp->pp_flags & MV_PP_FLAG_NCQ_EN)) {
+               if (ata_is_ncq(qc->tf.protocol))
+                       return 0;
+               else {
+                       ap->excl_link = link;
+                       return ATA_DEFER_PORT;
+               }
+       }
 
        return ATA_DEFER_PORT;
 }
index 86a4058..1eb4e02 100644 (file)
@@ -1594,9 +1594,21 @@ static int nv_hardreset(struct ata_link *link, unsigned int *class,
            !ata_dev_enabled(link->device))
                sata_link_hardreset(link, sata_deb_timing_hotplug, deadline,
                                    NULL, NULL);
-       else if (!(ehc->i.flags & ATA_EHI_QUIET))
-               ata_link_printk(link, KERN_INFO,
-                               "nv: skipping hardreset on occupied port\n");
+       else {
+               const unsigned long *timing = sata_ehc_deb_timing(ehc);
+               int rc;
+
+               if (!(ehc->i.flags & ATA_EHI_QUIET))
+                       ata_link_printk(link, KERN_INFO, "nv: skipping "
+                                       "hardreset on occupied port\n");
+
+               /* make sure the link is online */
+               rc = sata_link_resume(link, timing, deadline);
+               /* whine about phy resume failure but proceed */
+               if (rc && rc != -EOPNOTSUPP)
+                       ata_link_printk(link, KERN_WARNING, "failed to resume "
+                                       "link (errno=%d)\n", rc);
+       }
 
        /* device signature acquisition is unreliable */
        return -EAGAIN;
index 973bf2a..63c143e 100644 (file)
@@ -689,15 +689,19 @@ int bus_add_driver(struct device_driver *drv)
                printk(KERN_ERR "%s: driver_add_attrs(%s) failed\n",
                        __func__, drv->name);
        }
-       error = add_bind_files(drv);
-       if (error) {
-               /* Ditto */
-               printk(KERN_ERR "%s: add_bind_files(%s) failed\n",
-                       __func__, drv->name);
+
+       if (!drv->suppress_bind_attrs) {
+               error = add_bind_files(drv);
+               if (error) {
+                       /* Ditto */
+                       printk(KERN_ERR "%s: add_bind_files(%s) failed\n",
+                               __func__, drv->name);
+               }
        }
 
        kobject_uevent(&priv->kobj, KOBJ_ADD);
        return 0;
+
 out_unregister:
        kfree(drv->p);
        drv->p = NULL;
@@ -720,7 +724,8 @@ void bus_remove_driver(struct device_driver *drv)
        if (!drv->bus)
                return;
 
-       remove_bind_files(drv);
+       if (!drv->suppress_bind_attrs)
+               remove_bind_files(drv);
        driver_remove_attrs(drv->bus, drv);
        driver_remove_file(drv, &driver_attr_uevent);
        klist_remove(&drv->p->knode_bus);
index ed2ebd3..f367885 100644 (file)
@@ -236,7 +236,7 @@ int driver_register(struct device_driver *drv)
                put_driver(other);
                printk(KERN_ERR "Error: Driver '%s' is already registered, "
                        "aborting...\n", drv->name);
-               return -EEXIST;
+               return -EBUSY;
        }
 
        ret = bus_add_driver(drv);
index ed156a1..4fa954b 100644 (file)
@@ -521,11 +521,15 @@ int __init_or_module platform_driver_probe(struct platform_driver *drv,
 {
        int retval, code;
 
+       /* make sure driver won't have bind/unbind attributes */
+       drv->driver.suppress_bind_attrs = true;
+
        /* temporary section violation during probe() */
        drv->probe = probe;
        retval = code = platform_driver_register(drv);
 
-       /* Fixup that section violation, being paranoid about code scanning
+       /*
+        * Fixup that section violation, being paranoid about code scanning
         * the list of drivers in order to probe new devices.  Check to see
         * if the probe was successful, and make sure any forced probes of
         * new devices fail.
index e0dc407..8aa2443 100644 (file)
@@ -511,6 +511,7 @@ static void dpm_complete(pm_message_t state)
 
        INIT_LIST_HEAD(&list);
        mutex_lock(&dpm_list_mtx);
+       transition_started = false;
        while (!list_empty(&dpm_list)) {
                struct device *dev = to_device(dpm_list.prev);
 
index 38556f6..a770498 100644 (file)
@@ -51,8 +51,6 @@ static int __pm_runtime_idle(struct device *dev)
 {
        int retval = 0;
 
-       dev_dbg(dev, "__pm_runtime_idle()!\n");
-
        if (dev->power.runtime_error)
                retval = -EINVAL;
        else if (dev->power.idle_notification)
@@ -93,8 +91,6 @@ static int __pm_runtime_idle(struct device *dev)
        wake_up_all(&dev->power.wait_queue);
 
  out:
-       dev_dbg(dev, "__pm_runtime_idle() returns %d!\n", retval);
-
        return retval;
 }
 
index fb5be2d..6399e50 100644 (file)
@@ -68,6 +68,12 @@ MODULE_SUPPORTED_DEVICE("HP SA5i SA5i+ SA532 SA5300 SA5312 SA641 SA642 SA6400"
 MODULE_VERSION("3.6.20");
 MODULE_LICENSE("GPL");
 
+static int cciss_allow_hpsa;
+module_param(cciss_allow_hpsa, int, S_IRUGO|S_IWUSR);
+MODULE_PARM_DESC(cciss_allow_hpsa,
+       "Prevent cciss driver from accessing hardware known to be "
+       " supported by the hpsa driver");
+
 #include "cciss_cmd.h"
 #include "cciss.h"
 #include <linux/cciss_ioctl.h>
@@ -101,8 +107,6 @@ static const struct pci_device_id cciss_pci_device_id[] = {
        {PCI_VENDOR_ID_HP,     PCI_DEVICE_ID_HP_CISSE,     0x103C, 0x3249},
        {PCI_VENDOR_ID_HP,     PCI_DEVICE_ID_HP_CISSE,     0x103C, 0x324A},
        {PCI_VENDOR_ID_HP,     PCI_DEVICE_ID_HP_CISSE,     0x103C, 0x324B},
-       {PCI_VENDOR_ID_HP,     PCI_ANY_ID,      PCI_ANY_ID, PCI_ANY_ID,
-               PCI_CLASS_STORAGE_RAID << 8, 0xffff << 8, 0},
        {0,}
 };
 
@@ -123,8 +127,6 @@ static struct board_type products[] = {
        {0x409D0E11, "Smart Array 6400 EM", &SA5_access},
        {0x40910E11, "Smart Array 6i", &SA5_access},
        {0x3225103C, "Smart Array P600", &SA5_access},
-       {0x3223103C, "Smart Array P800", &SA5_access},
-       {0x3234103C, "Smart Array P400", &SA5_access},
        {0x3235103C, "Smart Array P400i", &SA5_access},
        {0x3211103C, "Smart Array E200i", &SA5_access},
        {0x3212103C, "Smart Array E200", &SA5_access},
@@ -132,6 +134,10 @@ static struct board_type products[] = {
        {0x3214103C, "Smart Array E200i", &SA5_access},
        {0x3215103C, "Smart Array E200i", &SA5_access},
        {0x3237103C, "Smart Array E500", &SA5_access},
+/* controllers below this line are also supported by the hpsa driver. */
+#define HPSA_BOUNDARY 0x3223103C
+       {0x3223103C, "Smart Array P800", &SA5_access},
+       {0x3234103C, "Smart Array P400", &SA5_access},
        {0x323D103C, "Smart Array P700m", &SA5_access},
        {0x3241103C, "Smart Array P212", &SA5_access},
        {0x3243103C, "Smart Array P410", &SA5_access},
@@ -140,7 +146,6 @@ static struct board_type products[] = {
        {0x3249103C, "Smart Array P812", &SA5_access},
        {0x324A103C, "Smart Array P712m", &SA5_access},
        {0x324B103C, "Smart Array P711m", &SA5_access},
-       {0xFFFF103C, "Unknown Smart Array", &SA5_access},
 };
 
 /* How long to wait (in milliseconds) for board to go into simple mode */
@@ -3754,7 +3759,27 @@ static int __devinit cciss_pci_init(ctlr_info_t *c, struct pci_dev *pdev)
        __u64 cfg_offset;
        __u32 cfg_base_addr;
        __u64 cfg_base_addr_index;
-       int i, err;
+       int i, prod_index, err;
+
+       subsystem_vendor_id = pdev->subsystem_vendor;
+       subsystem_device_id = pdev->subsystem_device;
+       board_id = (((__u32) (subsystem_device_id << 16) & 0xffff0000) |
+                   subsystem_vendor_id);
+
+       for (i = 0; i < ARRAY_SIZE(products); i++) {
+               /* Stand aside for hpsa driver on request */
+               if (cciss_allow_hpsa && products[i].board_id == HPSA_BOUNDARY)
+                       return -ENODEV;
+               if (board_id == products[i].board_id)
+                       break;
+       }
+       prod_index = i;
+       if (prod_index == ARRAY_SIZE(products)) {
+               dev_warn(&pdev->dev,
+                       "unrecognized board ID: 0x%08lx, ignoring.\n",
+                       (unsigned long) board_id);
+               return -ENODEV;
+       }
 
        /* check to see if controller has been disabled */
        /* BEFORE trying to enable it */
@@ -3778,11 +3803,6 @@ static int __devinit cciss_pci_init(ctlr_info_t *c, struct pci_dev *pdev)
                return err;
        }
 
-       subsystem_vendor_id = pdev->subsystem_vendor;
-       subsystem_device_id = pdev->subsystem_device;
-       board_id = (((__u32) (subsystem_device_id << 16) & 0xffff0000) |
-                   subsystem_vendor_id);
-
 #ifdef CCISS_DEBUG
        printk("command = %x\n", command);
        printk("irq = %x\n", pdev->irq);
@@ -3868,14 +3888,9 @@ static int __devinit cciss_pci_init(ctlr_info_t *c, struct pci_dev *pdev)
         * leave a little room for ioctl calls.
         */
        c->max_commands = readl(&(c->cfgtable->CmdsOutMax));
-       for (i = 0; i < ARRAY_SIZE(products); i++) {
-               if (board_id == products[i].board_id) {
-                       c->product_name = products[i].product_name;
-                       c->access = *(products[i].access);
-                       c->nr_cmds = c->max_commands - 4;
-                       break;
-               }
-       }
+       c->product_name = products[prod_index].product_name;
+       c->access = *(products[prod_index].access);
+       c->nr_cmds = c->max_commands - 4;
        if ((readb(&c->cfgtable->Signature[0]) != 'C') ||
            (readb(&c->cfgtable->Signature[1]) != 'I') ||
            (readb(&c->cfgtable->Signature[2]) != 'S') ||
@@ -3884,27 +3899,6 @@ static int __devinit cciss_pci_init(ctlr_info_t *c, struct pci_dev *pdev)
                err = -ENODEV;
                goto err_out_free_res;
        }
-       /* We didn't find the controller in our list. We know the
-        * signature is valid. If it's an HP device let's try to
-        * bind to the device and fire it up. Otherwise we bail.
-        */
-       if (i == ARRAY_SIZE(products)) {
-               if (subsystem_vendor_id == PCI_VENDOR_ID_HP) {
-                       c->product_name = products[i-1].product_name;
-                       c->access = *(products[i-1].access);
-                       c->nr_cmds = c->max_commands - 4;
-                       printk(KERN_WARNING "cciss: This is an unknown "
-                               "Smart Array controller.\n"
-                               "cciss: Please update to the latest driver "
-                               "available from www.hp.com.\n");
-               } else {
-                       printk(KERN_WARNING "cciss: Sorry, I don't know how"
-                               " to access the Smart Array controller %08lx\n"
-                                       , (unsigned long)board_id);
-                       err = -ENODEV;
-                       goto err_out_free_res;
-               }
-       }
 #ifdef CONFIG_X86
        {
                /* Need to enable prefetch in the SCSI core for 6400 in x86 */
@@ -4254,7 +4248,7 @@ static int __devinit cciss_init_one(struct pci_dev *pdev,
        mutex_init(&hba[i]->busy_shutting_down);
 
        if (cciss_pci_init(hba[i], pdev) != 0)
-               goto clean0;
+               goto clean_no_release_regions;
 
        sprintf(hba[i]->devname, "cciss%d", i);
        hba[i]->ctlr = i;
@@ -4391,13 +4385,14 @@ clean2:
 clean1:
        cciss_destroy_hba_sysfs_entry(hba[i]);
 clean0:
+       pci_release_regions(pdev);
+clean_no_release_regions:
        hba[i]->busy_initializing = 0;
 
        /*
         * Deliberately omit pci_disable_device(): it does something nasty to
         * Smart Array controllers that pci_enable_device does not undo
         */
-       pci_release_regions(pdev);
        pci_set_drvdata(pdev, NULL);
        free_hba(i);
        return -1;
index edda9ea..bd112c8 100644 (file)
@@ -949,7 +949,7 @@ static int loop_clr_fd(struct loop_device *lo, struct block_device *bdev)
        lo->lo_state = Lo_unbound;
        /* This is safe: open() is still holding a reference. */
        module_put(THIS_MODULE);
-       if (max_part > 0)
+       if (max_part > 0 && bdev)
                ioctl_by_bdev(bdev, BLKRRPART, 0);
        mutex_unlock(&lo->lo_ctl_mutex);
        /*
index 43f1938..51042f0 100644 (file)
@@ -3,7 +3,6 @@
 #include <linux/blkdev.h>
 #include <linux/hdreg.h>
 #include <linux/virtio.h>
-#include <linux/virtio_ids.h>
 #include <linux/virtio_blk.h>
 #include <linux/scatterlist.h>
 
@@ -183,34 +182,6 @@ static void do_virtblk_request(struct request_queue *q)
                vblk->vq->vq_ops->kick(vblk->vq);
 }
 
-/* return ATA identify data
- */
-static int virtblk_identify(struct gendisk *disk, void *argp)
-{
-       struct virtio_blk *vblk = disk->private_data;
-       void *opaque;
-       int err = -ENOMEM;
-
-       opaque = kmalloc(VIRTIO_BLK_ID_BYTES, GFP_KERNEL);
-       if (!opaque)
-               goto out;
-
-       err = virtio_config_buf(vblk->vdev, VIRTIO_BLK_F_IDENTIFY,
-               offsetof(struct virtio_blk_config, identify), opaque,
-               VIRTIO_BLK_ID_BYTES);
-
-       if (err)
-               goto out_kfree;
-
-       if (copy_to_user(argp, opaque, VIRTIO_BLK_ID_BYTES))
-               err = -EFAULT;
-
-out_kfree:
-       kfree(opaque);
-out:
-       return err;
-}
-
 static void virtblk_prepare_flush(struct request_queue *q, struct request *req)
 {
        req->cmd_type = REQ_TYPE_LINUX_BLOCK;
@@ -222,10 +193,6 @@ static int virtblk_ioctl(struct block_device *bdev, fmode_t mode,
 {
        struct gendisk *disk = bdev->bd_disk;
        struct virtio_blk *vblk = disk->private_data;
-       void __user *argp = (void __user *)data;
-
-       if (cmd == HDIO_GET_IDENTITY)
-               return virtblk_identify(disk, argp);
 
        /*
         * Only allow the generic SCSI ioctls if the host can support it.
@@ -233,7 +200,8 @@ static int virtblk_ioctl(struct block_device *bdev, fmode_t mode,
        if (!virtio_has_feature(vblk->vdev, VIRTIO_BLK_F_SCSI))
                return -ENOTTY;
 
-       return scsi_cmd_ioctl(disk->queue, disk, mode, cmd, argp);
+       return scsi_cmd_ioctl(disk->queue, disk, mode, cmd,
+                             (void __user *)data);
 }
 
 /* We provide getgeo only to please some old bootloader/partitioning tools */
@@ -332,7 +300,6 @@ static int __devinit virtblk_probe(struct virtio_device *vdev)
        }
 
        vblk->disk->queue->queuedata = vblk;
-       queue_flag_set_unlocked(QUEUE_FLAG_VIRT, vblk->disk->queue);
 
        if (index < 26) {
                sprintf(vblk->disk->disk_name, "vd%c", 'a' + index % 26);
@@ -445,7 +412,7 @@ static struct virtio_device_id id_table[] = {
 static unsigned int features[] = {
        VIRTIO_BLK_F_BARRIER, VIRTIO_BLK_F_SEG_MAX, VIRTIO_BLK_F_SIZE_MAX,
        VIRTIO_BLK_F_GEOMETRY, VIRTIO_BLK_F_RO, VIRTIO_BLK_F_BLK_SIZE,
-       VIRTIO_BLK_F_SCSI, VIRTIO_BLK_F_IDENTIFY, VIRTIO_BLK_F_FLUSH
+       VIRTIO_BLK_F_SCSI, VIRTIO_BLK_F_FLUSH
 };
 
 /*
index 08a6f50..6aad99e 100644 (file)
@@ -323,7 +323,7 @@ config SPECIALIX
 
 config SX
        tristate "Specialix SX (and SI) card support"
-       depends on SERIAL_NONSTANDARD && (PCI || EISA || ISA)
+       depends on SERIAL_NONSTANDARD && (PCI || EISA || ISA) && BROKEN
        help
          This is a driver for the SX and SI multiport serial cards.
          Please read the file <file:Documentation/serial/sx.txt> for details.
@@ -334,7 +334,7 @@ config SX
 
 config RIO
        tristate "Specialix RIO system support"
-       depends on SERIAL_NONSTANDARD
+       depends on SERIAL_NONSTANDARD && BROKEN
        help
          This is a driver for the Specialix RIO, a smart serial card which
          drives an outboard box that can support up to 128 ports.  Product
@@ -395,7 +395,7 @@ config NOZOMI
 
 config A2232
        tristate "Commodore A2232 serial support (EXPERIMENTAL)"
-       depends on EXPERIMENTAL && ZORRO && BROKEN_ON_SMP
+       depends on EXPERIMENTAL && ZORRO && BROKEN
        ---help---
          This option supports the 2232 7-port serial card shipped with the
          Amiga 2000 and other Zorro-bus machines, dating from 1989.  At
index 60ab751..1c12921 100644 (file)
@@ -217,7 +217,7 @@ static const struct agp_bridge_driver parisc_agp_driver = {
        .configure              = parisc_agp_configure,
        .fetch_size             = parisc_agp_fetch_size,
        .tlb_flush              = parisc_agp_tlbflush,
-       .mask_memory            = parisc_agp_page_mask_memory,
+       .mask_memory            = parisc_agp_mask_memory,
        .masks                  = parisc_agp_masks,
        .agp_enable             = parisc_agp_enable,
        .cache_flush            = global_cache_flush,
index 73a0765..fe2cb2f 100644 (file)
@@ -23,6 +23,7 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/interrupt.h>
+#include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/errno.h>
 #include <linux/miscdevice.h>
index 9d589e3..dde5134 100644 (file)
@@ -30,6 +30,7 @@
 #include <linux/kernel.h>
 #include <linux/types.h>
 #include <linux/init.h>
+#include <linux/sched.h>
 #include <linux/serial.h>
 #include <linux/delay.h>
 #include <linux/ctype.h>
index 9e4e569..d400cbd 100644 (file)
@@ -22,6 +22,7 @@
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/tty.h>
+#include <linux/sched.h>
 #include <linux/serial.h>
 #include <linux/mm.h>
 #include <linux/generic_serial.h>
index aac0985..31e7c91 100644 (file)
@@ -43,6 +43,7 @@
 #define RTC_VERSION    "1.07"
 
 #include <linux/module.h>
+#include <linux/sched.h>
 #include <linux/errno.h>
 #include <linux/miscdevice.h>
 #include <linux/fcntl.h>
index 962968f..915157f 100644 (file)
@@ -21,7 +21,6 @@
 #include <linux/scatterlist.h>
 #include <linux/spinlock.h>
 #include <linux/virtio.h>
-#include <linux/virtio_ids.h>
 #include <linux/virtio_rng.h>
 
 /* The host will fill any buffer we give it with sweet, sweet randomness.  We
@@ -117,7 +116,7 @@ static int virtrng_probe(struct virtio_device *vdev)
        return 0;
 }
 
-static void virtrng_remove(struct virtio_device *vdev)
+static void __devexit virtrng_remove(struct virtio_device *vdev)
 {
        vdev->config->reset(vdev);
        hwrng_unregister(&virtio_hwrng);
index ab2f334..402838f 100644 (file)
@@ -19,6 +19,7 @@
 /*****************************************************************************/
 
 #include <linux/module.h>
+#include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/smp_lock.h>
 #include <linux/interrupt.h>
index ec58d8c..d3400b2 100644 (file)
@@ -48,6 +48,7 @@
 #include <linux/tty.h>
 #include <linux/tty_driver.h>
 #include <linux/tty_flip.h>
+#include <linux/sched.h>
 #include <linux/serial.h>
 #include <linux/interrupt.h>
 #include <linux/kmod.h>
index e066c4f..62f282e 100644 (file)
@@ -18,6 +18,7 @@
 #include <linux/tty.h>
 #include <linux/tty_flip.h>
 #include <linux/fcntl.h>
+#include <linux/sched.h>
 #include <linux/string.h>
 #include <linux/major.h>
 #include <linux/mm.h>
index 01f2654..f121357 100644 (file)
@@ -32,6 +32,7 @@
 */
 
 #include <linux/module.h>
+#include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/errno.h>
 #include <linux/tty.h>
index 7433955..7805063 100644 (file)
@@ -31,6 +31,7 @@
 */
 
 #include <linux/module.h>
+#include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/errno.h>
 #include <asm/io.h>
index 2fb49e8..47fab7c 100644 (file)
@@ -33,6 +33,7 @@
 #define __EXPLICIT_DEF_H__
 
 #include <linux/module.h>
+#include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/errno.h>
 #include <linux/tty.h>
index e0d0f8b..bc4ab3e 100644 (file)
@@ -74,6 +74,7 @@
 #include <linux/proc_fs.h>
 #include <linux/seq_file.h>
 #include <linux/spinlock.h>
+#include <linux/sched.h>
 #include <linux/sysctl.h>
 #include <linux/wait.h>
 #include <linux/bcd.h>
index 33a2b53..9610861 100644 (file)
@@ -89,6 +89,7 @@
 #include <linux/interrupt.h>
 #include <linux/kernel.h>
 #include <linux/errno.h>
+#include <linux/sched.h>
 #include <linux/tty.h>
 
 #include <asm/setup.h>
index fd3dced..8c262aa 100644 (file)
@@ -36,6 +36,7 @@
  */
 
 #include <linux/module.h>
+#include <linux/sched.h>
 #include <linux/input.h>
 #include <linux/pci.h>
 #include <linux/init.h>
index 53e504f..db6dcfa 100644 (file)
@@ -27,6 +27,7 @@
 /*****************************************************************************/
 
 #include <linux/module.h>
+#include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/interrupt.h>
 #include <linux/tty.h>
index 8f2284b..80ea6bc 100644 (file)
@@ -32,6 +32,7 @@
 #include <linux/kernel.h>      /* printk() */
 #include <linux/fs.h>          /* everything... */
 #include <linux/errno.h>       /* error codes */
+#include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/ioport.h>
 #include <linux/interrupt.h>
index 45d5800..47c2d27 100644 (file)
@@ -696,8 +696,7 @@ int __tpm_pcr_read(struct tpm_chip *chip, int pcr_idx, u8 *res_buf)
 
        cmd.header.in = pcrread_header;
        cmd.params.pcrread_in.pcr_idx = cpu_to_be32(pcr_idx);
-       BUG_ON(cmd.header.in.length > READ_PCR_RESULT_SIZE);
-       rc = transmit_cmd(chip, &cmd, cmd.header.in.length,
+       rc = transmit_cmd(chip, &cmd, READ_PCR_RESULT_SIZE,
                          "attempting to read a pcr value");
 
        if (rc == 0)
index 3108991..66fa4e1 100644 (file)
@@ -402,28 +402,26 @@ static void flush_to_ldisc(struct work_struct *work)
                container_of(work, struct tty_struct, buf.work.work);
        unsigned long   flags;
        struct tty_ldisc *disc;
-       struct tty_buffer *tbuf, *head;
-       char *char_buf;
-       unsigned char *flag_buf;
 
        disc = tty_ldisc_ref(tty);
        if (disc == NULL)       /*  !TTY_LDISC */
                return;
 
        spin_lock_irqsave(&tty->buf.lock, flags);
-       /* So we know a flush is running */
-       set_bit(TTY_FLUSHING, &tty->flags);
-       head = tty->buf.head;
-       if (head != NULL) {
-               tty->buf.head = NULL;
-               for (;;) {
-                       int count = head->commit - head->read;
+
+       if (!test_and_set_bit(TTY_FLUSHING, &tty->flags)) {
+               struct tty_buffer *head;
+               while ((head = tty->buf.head) != NULL) {
+                       int count;
+                       char *char_buf;
+                       unsigned char *flag_buf;
+
+                       count = head->commit - head->read;
                        if (!count) {
                                if (head->next == NULL)
                                        break;
-                               tbuf = head;
-                               head = head->next;
-                               tty_buffer_free(tty, tbuf);
+                               tty->buf.head = head->next;
+                               tty_buffer_free(tty, head);
                                continue;
                        }
                        /* Ldisc or user is trying to flush the buffers
@@ -445,9 +443,9 @@ static void flush_to_ldisc(struct work_struct *work)
                                                        flag_buf, count);
                        spin_lock_irqsave(&tty->buf.lock, flags);
                }
-               /* Restore the queue head */
-               tty->buf.head = head;
+               clear_bit(TTY_FLUSHING, &tty->flags);
        }
+
        /* We may have a deferred request to flush the input buffer,
           if so pull the chain under the lock and empty the queue */
        if (test_bit(TTY_FLUSHPENDING, &tty->flags)) {
@@ -455,7 +453,6 @@ static void flush_to_ldisc(struct work_struct *work)
                clear_bit(TTY_FLUSHPENDING, &tty->flags);
                wake_up(&tty->read_wait);
        }
-       clear_bit(TTY_FLUSHING, &tty->flags);
        spin_unlock_irqrestore(&tty->buf.lock, flags);
 
        tty_ldisc_deref(disc);
@@ -471,7 +468,7 @@ static void flush_to_ldisc(struct work_struct *work)
  */
 void tty_flush_to_ldisc(struct tty_struct *tty)
 {
-       flush_to_ldisc(&tty->buf.work.work);
+       flush_delayed_work(&tty->buf.work);
 }
 
 /**
index 0d328b5..a035ae3 100644 (file)
@@ -31,7 +31,6 @@
 #include <linux/err.h>
 #include <linux/init.h>
 #include <linux/virtio.h>
-#include <linux/virtio_ids.h>
 #include <linux/virtio_console.h>
 #include "hvc_console.h"
 
index 6b36ee5..ed86d3b 100644 (file)
@@ -1532,7 +1532,7 @@ long vt_compat_ioctl(struct tty_struct *tty, struct file * file,
 
        case PIO_UNIMAP:
        case GIO_UNIMAP:
-               ret = do_unimap_ioctl(cmd, up, perm, vc);
+               ret = compat_unimap_ioctl(cmd, up, perm, vc);
                break;
 
        /*
index abf4a25..6069790 100644 (file)
@@ -227,7 +227,8 @@ static void cn_proc_ack(int err, int rcvd_seq, int rcvd_ack)
  * cn_proc_mcast_ctl
  * @data: message sent from userspace via the connector
  */
-static void cn_proc_mcast_ctl(struct cn_msg *msg)
+static void cn_proc_mcast_ctl(struct cn_msg *msg,
+                             struct netlink_skb_parms *nsp)
 {
        enum proc_cn_mcast_op *mc_op = NULL;
        int err = 0;
index ad41f19..12fdd39 100644 (file)
@@ -76,8 +76,11 @@ static void cpuidle_idle_call(void)
 #endif
        /* ask the governor for the next state */
        next_state = cpuidle_curr_governor->select(dev);
-       if (need_resched())
+       if (need_resched()) {
+               local_irq_enable();
                return;
+       }
+
        target_state = &dev->states[next_state];
 
        /* enter the state and update stats */
index 76cb6b3..0af8057 100644 (file)
 #include <asm/i387.h>
 #include "padlock.h"
 
+#ifdef CONFIG_64BIT
+#define STACK_ALIGN 16
+#else
+#define STACK_ALIGN 4
+#endif
+
 struct padlock_sha_desc {
        struct shash_desc fallback;
 };
@@ -64,7 +70,9 @@ static int padlock_sha1_finup(struct shash_desc *desc, const u8 *in,
        /* We can't store directly to *out as it may be unaligned. */
        /* BTW Don't reduce the buffer size below 128 Bytes!
         *     PadLock microcode needs it that big. */
-       char result[128] __attribute__ ((aligned(PADLOCK_ALIGNMENT)));
+       char buf[128 + PADLOCK_ALIGNMENT - STACK_ALIGN] __attribute__
+               ((aligned(STACK_ALIGN)));
+       char *result = PTR_ALIGN(&buf[0], PADLOCK_ALIGNMENT);
        struct padlock_sha_desc *dctx = shash_desc_ctx(desc);
        struct sha1_state state;
        unsigned int space;
@@ -128,7 +136,9 @@ static int padlock_sha256_finup(struct shash_desc *desc, const u8 *in,
        /* We can't store directly to *out as it may be unaligned. */
        /* BTW Don't reduce the buffer size below 128 Bytes!
         *     PadLock microcode needs it that big. */
-       char result[128] __attribute__ ((aligned(PADLOCK_ALIGNMENT)));
+       char buf[128 + PADLOCK_ALIGNMENT - STACK_ALIGN] __attribute__
+               ((aligned(STACK_ALIGN)));
+       char *result = PTR_ALIGN(&buf[0], PADLOCK_ALIGNMENT);
        struct padlock_sha_desc *dctx = shash_desc_ctx(desc);
        struct sha256_state state;
        unsigned int space;
index 02127e5..55c9c59 100644 (file)
@@ -47,6 +47,18 @@ config EDAC_DEBUG_VERBOSE
          Source file name and line number where debugging message
          printed will be added to debugging message.
 
+ config EDAC_DECODE_MCE
+       tristate "Decode MCEs in human-readable form (only on AMD for now)"
+       depends on CPU_SUP_AMD && X86_MCE
+       default y
+       ---help---
+         Enable this option if you want to decode Machine Check Exceptions
+         occuring on your machine in human-readable form.
+
+         You should definitely say Y here in case you want to decode MCEs
+         which occur really early upon boot, before the module infrastructure
+         has been initialized.
+
 config EDAC_MM_EDAC
        tristate "Main Memory EDAC (Error Detection And Correction) reporting"
        help
@@ -59,7 +71,7 @@ config EDAC_MM_EDAC
 
 config EDAC_AMD64
        tristate "AMD64 (Opteron, Athlon64) K8, F10h, F11h"
-       depends on EDAC_MM_EDAC && K8_NB && X86_64 && PCI && CPU_SUP_AMD
+       depends on EDAC_MM_EDAC && K8_NB && X86_64 && PCI && EDAC_DECODE_MCE
        help
          Support for error detection and correction on the AMD 64
          Families of Memory Controllers (K8, F10h and F11h)
index 7a473bb..bc5dc23 100644 (file)
@@ -6,7 +6,6 @@
 # GNU General Public License.
 #
 
-
 obj-$(CONFIG_EDAC)                     := edac_stub.o
 obj-$(CONFIG_EDAC_MM_EDAC)             += edac_core.o
 
@@ -17,9 +16,7 @@ ifdef CONFIG_PCI
 edac_core-objs += edac_pci.o edac_pci_sysfs.o
 endif
 
-ifdef CONFIG_CPU_SUP_AMD
-edac_core-objs  += edac_mce_amd.o
-endif
+obj-$(CONFIG_EDAC_DECODE_MCE)          += edac_mce_amd.o
 
 obj-$(CONFIG_EDAC_AMD76X)              += amd76x_edac.o
 obj-$(CONFIG_EDAC_CPC925)              += cpc925_edac.o
index 4e551e6..d4560d9 100644 (file)
@@ -15,8 +15,8 @@ module_param(ecc_enable_override, int, 0644);
 
 /* Lookup table for all possible MC control instances */
 struct amd64_pvt;
-static struct mem_ctl_info *mci_lookup[MAX_NUMNODES];
-static struct amd64_pvt *pvt_lookup[MAX_NUMNODES];
+static struct mem_ctl_info *mci_lookup[EDAC_MAX_NUMNODES];
+static struct amd64_pvt *pvt_lookup[EDAC_MAX_NUMNODES];
 
 /*
  * See F2x80 for K8 and F2x[1,0]80 for Fam10 and later. The table below is only
@@ -189,7 +189,10 @@ static int amd64_get_scrub_rate(struct mem_ctl_info *mci, u32 *bw)
 /* Map from a CSROW entry to the mask entry that operates on it */
 static inline u32 amd64_map_to_dcs_mask(struct amd64_pvt *pvt, int csrow)
 {
-       return csrow >> (pvt->num_dcsm >> 3);
+       if (boot_cpu_data.x86 == 0xf && pvt->ext_model < OPTERON_CPU_REV_F)
+               return csrow;
+       else
+               return csrow >> 1;
 }
 
 /* return the 'base' address the i'th CS entry of the 'dct' DRAM controller */
@@ -279,29 +282,26 @@ static struct mem_ctl_info *find_mc_by_sys_addr(struct mem_ctl_info *mci,
        intlv_en = pvt->dram_IntlvEn[0];
 
        if (intlv_en == 0) {
-               for (node_id = 0; ) {
+               for (node_id = 0; node_id < DRAM_REG_COUNT; node_id++) {
                        if (amd64_base_limit_match(pvt, sys_addr, node_id))
-                               break;
-
-                       if (++node_id >= DRAM_REG_COUNT)
-                               goto err_no_match;
+                               goto found;
                }
-               goto found;
+               goto err_no_match;
        }
 
-       if (unlikely((intlv_en != (0x01 << 8)) &&
-                    (intlv_en != (0x03 << 8)) &&
-                    (intlv_en != (0x07 << 8)))) {
+       if (unlikely((intlv_en != 0x01) &&
+                    (intlv_en != 0x03) &&
+                    (intlv_en != 0x07))) {
                amd64_printk(KERN_WARNING, "junk value of 0x%x extracted from "
                             "IntlvEn field of DRAM Base Register for node 0: "
-                            "This probably indicates a BIOS bug.\n", intlv_en);
+                            "this probably indicates a BIOS bug.\n", intlv_en);
                return NULL;
        }
 
        bits = (((u32) sys_addr) >> 12) & intlv_en;
 
        for (node_id = 0; ; ) {
-               if ((pvt->dram_limit[node_id] & intlv_en) == bits)
+               if ((pvt->dram_IntlvSel[node_id] & intlv_en) == bits)
                        break;  /* intlv_sel field matches */
 
                if (++node_id >= DRAM_REG_COUNT)
@@ -311,10 +311,10 @@ static struct mem_ctl_info *find_mc_by_sys_addr(struct mem_ctl_info *mci,
        /* sanity test for sys_addr */
        if (unlikely(!amd64_base_limit_match(pvt, sys_addr, node_id))) {
                amd64_printk(KERN_WARNING,
-                         "%s(): sys_addr 0x%lx falls outside base/limit "
-                         "address range for node %d with node interleaving "
-                         "enabled.\n", __func__, (unsigned long)sys_addr,
-                         node_id);
+                            "%s(): sys_addr 0x%llx falls outside base/limit "
+                            "address range for node %d with node interleaving "
+                            "enabled.\n",
+                            __func__, sys_addr, node_id);
                return NULL;
        }
 
@@ -377,7 +377,7 @@ static int input_addr_to_csrow(struct mem_ctl_info *mci, u64 input_addr)
         * base/mask register pair, test the condition shown near the start of
         * section 3.5.4 (p. 84, BKDG #26094, K8, revA-E).
         */
-       for (csrow = 0; csrow < CHIPSELECT_COUNT; csrow++) {
+       for (csrow = 0; csrow < pvt->cs_count; csrow++) {
 
                /* This DRAM chip select is disabled on this node */
                if ((pvt->dcsb0[csrow] & K8_DCSB_CS_ENABLE) == 0)
@@ -734,7 +734,7 @@ static void find_csrow_limits(struct mem_ctl_info *mci, int csrow,
        u64 base, mask;
 
        pvt = mci->pvt_info;
-       BUG_ON((csrow < 0) || (csrow >= CHIPSELECT_COUNT));
+       BUG_ON((csrow < 0) || (csrow >= pvt->cs_count));
 
        base = base_from_dct_base(pvt, csrow);
        mask = mask_from_dct_mask(pvt, csrow);
@@ -962,35 +962,27 @@ err_reg:
  */
 static void amd64_set_dct_base_and_mask(struct amd64_pvt *pvt)
 {
-       if (pvt->ext_model >= OPTERON_CPU_REV_F) {
+
+       if (boot_cpu_data.x86 == 0xf && pvt->ext_model < OPTERON_CPU_REV_F) {
+               pvt->dcsb_base          = REV_E_DCSB_BASE_BITS;
+               pvt->dcsm_mask          = REV_E_DCSM_MASK_BITS;
+               pvt->dcs_mask_notused   = REV_E_DCS_NOTUSED_BITS;
+               pvt->dcs_shift          = REV_E_DCS_SHIFT;
+               pvt->cs_count           = 8;
+               pvt->num_dcsm           = 8;
+       } else {
                pvt->dcsb_base          = REV_F_F1Xh_DCSB_BASE_BITS;
                pvt->dcsm_mask          = REV_F_F1Xh_DCSM_MASK_BITS;
                pvt->dcs_mask_notused   = REV_F_F1Xh_DCS_NOTUSED_BITS;
                pvt->dcs_shift          = REV_F_F1Xh_DCS_SHIFT;
 
-               switch (boot_cpu_data.x86) {
-               case 0xf:
-                       pvt->num_dcsm = REV_F_DCSM_COUNT;
-                       break;
-
-               case 0x10:
-                       pvt->num_dcsm = F10_DCSM_COUNT;
-                       break;
-
-               case 0x11:
-                       pvt->num_dcsm = F11_DCSM_COUNT;
-                       break;
-
-               default:
-                       amd64_printk(KERN_ERR, "Unsupported family!\n");
-                       break;
+               if (boot_cpu_data.x86 == 0x11) {
+                       pvt->cs_count = 4;
+                       pvt->num_dcsm = 2;
+               } else {
+                       pvt->cs_count = 8;
+                       pvt->num_dcsm = 4;
                }
-       } else {
-               pvt->dcsb_base          = REV_E_DCSB_BASE_BITS;
-               pvt->dcsm_mask          = REV_E_DCSM_MASK_BITS;
-               pvt->dcs_mask_notused   = REV_E_DCS_NOTUSED_BITS;
-               pvt->dcs_shift          = REV_E_DCS_SHIFT;
-               pvt->num_dcsm           = REV_E_DCSM_COUNT;
        }
 }
 
@@ -1003,7 +995,7 @@ static void amd64_read_dct_base_mask(struct amd64_pvt *pvt)
 
        amd64_set_dct_base_and_mask(pvt);
 
-       for (cs = 0; cs < CHIPSELECT_COUNT; cs++) {
+       for (cs = 0; cs < pvt->cs_count; cs++) {
                reg = K8_DCSB0 + (cs * 4);
                err = pci_read_config_dword(pvt->dram_f2_ctl, reg,
                                                &pvt->dcsb0[cs]);
@@ -1193,7 +1185,7 @@ static void k8_map_sysaddr_to_csrow(struct mem_ctl_info *mci,
         * different from the node that detected the error.
         */
        src_mci = find_mc_by_sys_addr(mci, SystemAddress);
-       if (src_mci) {
+       if (!src_mci) {
                amd64_mc_printk(mci, KERN_ERR,
                             "failed to map error address 0x%lx to a node\n",
                             (unsigned long)SystemAddress);
@@ -1376,8 +1368,8 @@ static void f10_read_dram_base_limit(struct amd64_pvt *pvt, int dram)
 
        pvt->dram_IntlvEn[dram] = (low_base >> 8) & 0x7;
 
-       pvt->dram_base[dram] = (((((u64) high_base & 0x000000FF) << 32) |
-                               ((u64) low_base & 0xFFFF0000))) << 8;
+       pvt->dram_base[dram] = (((u64)high_base & 0x000000FF) << 40) |
+                              (((u64)low_base  & 0xFFFF0000) << 8);
 
        low_offset = K8_DRAM_LIMIT_LOW + (dram << 3);
        high_offset = F10_DRAM_LIMIT_HIGH + (dram << 3);
@@ -1398,9 +1390,9 @@ static void f10_read_dram_base_limit(struct amd64_pvt *pvt, int dram)
         * Extract address values and form a LIMIT address. Limit is the HIGHEST
         * memory location of the region, so low 24 bits need to be all ones.
         */
-       low_limit |= 0x0000FFFF;
-       pvt->dram_limit[dram] =
-               ((((u64) high_limit << 32) + (u64) low_limit) << 8) | (0xFF);
+       pvt->dram_limit[dram] = (((u64)high_limit & 0x000000FF) << 40) |
+                               (((u64) low_limit & 0xFFFF0000) << 8) |
+                               0x00FFFFFF;
 }
 
 static void f10_read_dram_ctl_register(struct amd64_pvt *pvt)
@@ -1566,7 +1558,7 @@ static int f10_lookup_addr_in_dct(u32 in_addr, u32 nid, u32 cs)
 
        debugf1("InputAddr=0x%x  channelselect=%d\n", in_addr, cs);
 
-       for (csrow = 0; csrow < CHIPSELECT_COUNT; csrow++) {
+       for (csrow = 0; csrow < pvt->cs_count; csrow++) {
 
                cs_base = amd64_get_dct_base(pvt, cs, csrow);
                if (!(cs_base & K8_DCSB_CS_ENABLE))
@@ -2497,7 +2489,7 @@ err_reg:
  * NOTE: CPU Revision Dependent code
  *
  * Input:
- *     @csrow_nr ChipSelect Row Number (0..CHIPSELECT_COUNT-1)
+ *     @csrow_nr ChipSelect Row Number (0..pvt->cs_count-1)
  *     k8 private pointer to -->
  *                     DRAM Bank Address mapping register
  *                     node_id
@@ -2577,7 +2569,7 @@ static int amd64_init_csrows(struct mem_ctl_info *mci)
                (pvt->nbcfg & K8_NBCFG_ECC_ENABLE) ? "Enabled" : "Disabled"
                );
 
-       for (i = 0; i < CHIPSELECT_COUNT; i++) {
+       for (i = 0; i < pvt->cs_count; i++) {
                csrow = &mci->csrows[i];
 
                if ((pvt->dcsb0[i] & K8_DCSB_CS_ENABLE) == 0) {
@@ -2988,7 +2980,7 @@ static int amd64_init_2nd_stage(struct amd64_pvt *pvt)
                goto err_exit;
 
        ret = -ENOMEM;
-       mci = edac_mc_alloc(0, CHIPSELECT_COUNT, pvt->channel_count, node_id);
+       mci = edac_mc_alloc(0, pvt->cs_count, pvt->channel_count, node_id);
        if (!mci)
                goto err_exit;
 
index 8ea07e2..c6f359a 100644 (file)
 #define EDAC_AMD64_VERSION             " Ver: 3.2.0 " __DATE__
 #define EDAC_MOD_STR                   "amd64_edac"
 
+#define EDAC_MAX_NUMNODES              8
+
 /* Extended Model from CPUID, for CPU Revision numbers */
 #define OPTERON_CPU_LE_REV_C           0
 #define OPTERON_CPU_REV_D              1
 #define OPTERON_CPU_REV_FA             5
 
 /* Hardware limit on ChipSelect rows per MC and processors per system */
-#define CHIPSELECT_COUNT               8
+#define MAX_CS_COUNT                   8
 #define DRAM_REG_COUNT                 8
 
 
  */
 #define REV_E_DCSB_BASE_BITS           (0xFFE0FE00ULL)
 #define REV_E_DCS_SHIFT                        4
-#define REV_E_DCSM_COUNT               8
 
 #define REV_F_F1Xh_DCSB_BASE_BITS      (0x1FF83FE0ULL)
 #define REV_F_F1Xh_DCS_SHIFT           8
  */
 #define REV_F_DCSB_BASE_BITS           (0x1FF83FE0ULL)
 #define REV_F_DCS_SHIFT                        8
-#define REV_F_DCSM_COUNT               4
-#define F10_DCSM_COUNT                 4
-#define F11_DCSM_COUNT                 2
 
 /* DRAM CS Mask Registers */
 #define K8_DCSM0                       0x60
@@ -374,13 +372,11 @@ enum {
 
 #define SET_NB_DRAM_INJECTION_WRITE(word, bits)  \
                                        (BIT(((word) & 0xF) + 20) | \
-                                       BIT(17) |  \
-                                       ((bits) & 0xF))
+                                       BIT(17) | bits)
 
 #define SET_NB_DRAM_INJECTION_READ(word, bits)  \
                                        (BIT(((word) & 0xF) + 20) | \
-                                       BIT(16) |  \
-                                       ((bits) & 0xF))
+                                       BIT(16) |  bits)
 
 #define K8_NBCAP                       0xE8
 #define K8_NBCAP_CORES                 (BIT(12)|BIT(13))
@@ -445,12 +441,12 @@ struct amd64_pvt {
        u32 dbam1;              /* DRAM Base Address Mapping reg for DCT1 */
 
        /* DRAM CS Base Address Registers F2x[1,0][5C:40] */
-       u32 dcsb0[CHIPSELECT_COUNT];
-       u32 dcsb1[CHIPSELECT_COUNT];
+       u32 dcsb0[MAX_CS_COUNT];
+       u32 dcsb1[MAX_CS_COUNT];
 
        /* DRAM CS Mask Registers F2x[1,0][6C:60] */
-       u32 dcsm0[CHIPSELECT_COUNT];
-       u32 dcsm1[CHIPSELECT_COUNT];
+       u32 dcsm0[MAX_CS_COUNT];
+       u32 dcsm1[MAX_CS_COUNT];
 
        /*
         * Decoded parts of DRAM BASE and LIMIT Registers
@@ -470,6 +466,7 @@ struct amd64_pvt {
         */
        u32 dcsb_base;          /* DCSB base bits */
        u32 dcsm_mask;          /* DCSM mask bits */
+       u32 cs_count;           /* num chip selects (== num DCSB registers) */
        u32 num_dcsm;           /* Number of DCSM registers */
        u32 dcs_mask_notused;   /* DCSM notused mask bits */
        u32 dcs_shift;          /* DCSB and DCSM shift value */
index d3675b7..29f1f7a 100644 (file)
@@ -1,5 +1,11 @@
 #include "amd64_edac.h"
 
+static ssize_t amd64_inject_section_show(struct mem_ctl_info *mci, char *buf)
+{
+       struct amd64_pvt *pvt = mci->pvt_info;
+       return sprintf(buf, "0x%x\n", pvt->injection.section);
+}
+
 /*
  * store error injection section value which refers to one of 4 16-byte sections
  * within a 64-byte cacheline
@@ -15,12 +21,26 @@ static ssize_t amd64_inject_section_store(struct mem_ctl_info *mci,
 
        ret = strict_strtoul(data, 10, &value);
        if (ret != -EINVAL) {
+
+               if (value > 3) {
+                       amd64_printk(KERN_WARNING,
+                                    "%s: invalid section 0x%lx\n",
+                                    __func__, value);
+                       return -EINVAL;
+               }
+
                pvt->injection.section = (u32) value;
                return count;
        }
        return ret;
 }
 
+static ssize_t amd64_inject_word_show(struct mem_ctl_info *mci, char *buf)
+{
+       struct amd64_pvt *pvt = mci->pvt_info;
+       return sprintf(buf, "0x%x\n", pvt->injection.word);
+}
+
 /*
  * store error injection word value which refers to one of 9 16-bit word of the
  * 16-byte (128-bit + ECC bits) section
@@ -37,14 +57,25 @@ static ssize_t amd64_inject_word_store(struct mem_ctl_info *mci,
        ret = strict_strtoul(data, 10, &value);
        if (ret != -EINVAL) {
 
-               value = (value <= 8) ? value : 0;
-               pvt->injection.word = (u32) value;
+               if (value > 8) {
+                       amd64_printk(KERN_WARNING,
+                                    "%s: invalid word 0x%lx\n",
+                                    __func__, value);
+                       return -EINVAL;
+               }
 
+               pvt->injection.word = (u32) value;
                return count;
        }
        return ret;
 }
 
+static ssize_t amd64_inject_ecc_vector_show(struct mem_ctl_info *mci, char *buf)
+{
+       struct amd64_pvt *pvt = mci->pvt_info;
+       return sprintf(buf, "0x%x\n", pvt->injection.bit_map);
+}
+
 /*
  * store 16 bit error injection vector which enables injecting errors to the
  * corresponding bit within the error injection word above. When used during a
@@ -60,8 +91,14 @@ static ssize_t amd64_inject_ecc_vector_store(struct mem_ctl_info *mci,
        ret = strict_strtoul(data, 16, &value);
        if (ret != -EINVAL) {
 
-               pvt->injection.bit_map = (u32) value & 0xFFFF;
+               if (value & 0xFFFF0000) {
+                       amd64_printk(KERN_WARNING,
+                                    "%s: invalid EccVector: 0x%lx\n",
+                                    __func__, value);
+                       return -EINVAL;
+               }
 
+               pvt->injection.bit_map = (u32) value;
                return count;
        }
        return ret;
@@ -147,7 +184,7 @@ struct mcidev_sysfs_attribute amd64_inj_attrs[] = {
                        .name = "inject_section",
                        .mode = (S_IRUGO | S_IWUSR)
                },
-               .show = NULL,
+               .show = amd64_inject_section_show,
                .store = amd64_inject_section_store,
        },
        {
@@ -155,7 +192,7 @@ struct mcidev_sysfs_attribute amd64_inj_attrs[] = {
                        .name = "inject_word",
                        .mode = (S_IRUGO | S_IWUSR)
                },
-               .show = NULL,
+               .show = amd64_inject_word_show,
                .store = amd64_inject_word_store,
        },
        {
@@ -163,7 +200,7 @@ struct mcidev_sysfs_attribute amd64_inj_attrs[] = {
                        .name = "inject_ecc_vector",
                        .mode = (S_IRUGO | S_IWUSR)
                },
-               .show = NULL,
+               .show = amd64_inject_ecc_vector_show,
                .store = amd64_inject_ecc_vector_store,
        },
        {
index 0c21c37..713ed7d 100644 (file)
@@ -3,6 +3,7 @@
 
 static bool report_gart_errors;
 static void (*nb_bus_decoder)(int node_id, struct err_regs *regs);
+static void (*orig_mce_callback)(struct mce *m);
 
 void amd_report_gart_errors(bool v)
 {
@@ -362,7 +363,7 @@ static inline void amd_decode_err_code(unsigned int ec)
                pr_warning("Huh? Unknown MCE error 0x%x\n", ec);
 }
 
-void decode_mce(struct mce *m)
+static void amd_decode_mce(struct mce *m)
 {
        struct err_regs regs;
        int node, ecc;
@@ -420,3 +421,32 @@ void decode_mce(struct mce *m)
 
        amd_decode_err_code(m->status & 0xffff);
 }
+
+static int __init mce_amd_init(void)
+{
+       /*
+        * We can decode MCEs for Opteron and later CPUs:
+        */
+       if ((boot_cpu_data.x86_vendor == X86_VENDOR_AMD) &&
+           (boot_cpu_data.x86 >= 0xf)) {
+               /* safe the default decode mce callback */
+               orig_mce_callback = x86_mce_decode_callback;
+
+               x86_mce_decode_callback = amd_decode_mce;
+       }
+
+       return 0;
+}
+early_initcall(mce_amd_init);
+
+#ifdef MODULE
+static void __exit mce_amd_exit(void)
+{
+       x86_mce_decode_callback = orig_mce_callback;
+}
+
+MODULE_DESCRIPTION("AMD MCE decoder");
+MODULE_ALIAS("edac-mce-amd");
+MODULE_LICENSE("GPL");
+module_exit(mce_amd_exit);
+#endif
index d335086..77a9579 100644 (file)
@@ -1173,7 +1173,7 @@ static void i5000_get_mc_regs(struct mem_ctl_info *mci)
                        pci_read_config_word(pvt->branch_1, where,
                                        &pvt->b1_mtr[slot_row]);
                        debugf2("MTR%d where=0x%x B1 value=0x%x\n", slot_row,
-                               where, pvt->b0_mtr[slot_row]);
+                               where, pvt->b1_mtr[slot_row]);
                } else {
                        pvt->b1_mtr[slot_row] = 0;
                }
@@ -1232,7 +1232,7 @@ static int i5000_init_csrows(struct mem_ctl_info *mci)
        struct csrow_info *p_csrow;
        int empty, channel_count;
        int max_csrows;
-       int mtr;
+       int mtr, mtr1;
        int csrow_megs;
        int channel;
        int csrow;
@@ -1251,9 +1251,10 @@ static int i5000_init_csrows(struct mem_ctl_info *mci)
 
                /* use branch 0 for the basis */
                mtr = pvt->b0_mtr[csrow >> 1];
+               mtr1 = pvt->b1_mtr[csrow >> 1];
 
                /* if no DIMMS on this row, continue */
-               if (!MTR_DIMMS_PRESENT(mtr))
+               if (!MTR_DIMMS_PRESENT(mtr) && !MTR_DIMMS_PRESENT(mtr1))
                        continue;
 
                /* FAKE OUT VALUES, FIXME */
index b08b6d8..f99d106 100644 (file)
 /* Limits for i5400 */
 #define NUM_MTRS_PER_BRANCH    4
 #define CHANNELS_PER_BRANCH    2
+#define MAX_DIMMS_PER_CHANNEL  NUM_MTRS_PER_BRANCH
 #define        MAX_CHANNELS            4
-#define MAX_DIMMS              (MAX_CHANNELS * 4)      /* Up to 4 DIMM's per channel */
-#define MAX_CSROWS             (MAX_DIMMS * 2)         /* max possible csrows per channel */
+/* max possible csrows per channel */
+#define MAX_CSROWS             (MAX_DIMMS_PER_CHANNEL)
 
 /* Device 16,
  * Function 0: System Address
@@ -331,7 +332,6 @@ static const struct i5400_dev_info i5400_devs[] = {
 
 struct i5400_dimm_info {
        int megabytes;          /* size, 0 means not present  */
-       int dual_rank;
 };
 
 /* driver private data structure */
@@ -849,11 +849,9 @@ static int determine_mtr(struct i5400_pvt *pvt, int csrow, int channel)
        int n;
 
        /* There is one MTR for each slot pair of FB-DIMMs,
-          Each slot may have one or two ranks (2 csrows),
           Each slot pair may be at branch 0 or branch 1.
-          So, csrow should be divided by eight
         */
-       n = csrow >> 3;
+       n = csrow;
 
        if (n >= NUM_MTRS_PER_BRANCH) {
                debugf0("ERROR: trying to access an invalid csrow: %d\n",
@@ -905,25 +903,22 @@ static void handle_channel(struct i5400_pvt *pvt, int csrow, int channel,
                amb_present_reg = determine_amb_present_reg(pvt, channel);
 
                /* Determine if there is a DIMM present in this DIMM slot */
-               if (amb_present_reg & (1 << (csrow >> 1))) {
-                       dinfo->dual_rank = MTR_DIMM_RANK(mtr);
-
-                       if (!((dinfo->dual_rank == 0) &&
-                               ((csrow & 0x1) == 0x1))) {
-                               /* Start with the number of bits for a Bank
-                                * on the DRAM */
-                               addrBits = MTR_DRAM_BANKS_ADDR_BITS(mtr);
-                               /* Add thenumber of ROW bits */
-                               addrBits += MTR_DIMM_ROWS_ADDR_BITS(mtr);
-                               /* add the number of COLUMN bits */
-                               addrBits += MTR_DIMM_COLS_ADDR_BITS(mtr);
-
-                               addrBits += 6;  /* add 64 bits per DIMM */
-                               addrBits -= 20; /* divide by 2^^20 */
-                               addrBits -= 3;  /* 8 bits per bytes */
-
-                               dinfo->megabytes = 1 << addrBits;
-                       }
+               if (amb_present_reg & (1 << csrow)) {
+                       /* Start with the number of bits for a Bank
+                        * on the DRAM */
+                       addrBits = MTR_DRAM_BANKS_ADDR_BITS(mtr);
+                       /* Add thenumber of ROW bits */
+                       addrBits += MTR_DIMM_ROWS_ADDR_BITS(mtr);
+                       /* add the number of COLUMN bits */
+                       addrBits += MTR_DIMM_COLS_ADDR_BITS(mtr);
+                       /* add the number of RANK bits */
+                       addrBits += MTR_DIMM_RANK(mtr);
+
+                       addrBits += 6;  /* add 64 bits per DIMM */
+                       addrBits -= 20; /* divide by 2^^20 */
+                       addrBits -= 3;  /* 8 bits per bytes */
+
+                       dinfo->megabytes = 1 << addrBits;
                }
        }
 }
@@ -951,12 +946,12 @@ static void calculate_dimm_size(struct i5400_pvt *pvt)
                return;
        }
 
-       /* Scan all the actual CSROWS (which is # of DIMMS * 2)
+       /* Scan all the actual CSROWS
         * and calculate the information for each DIMM
         * Start with the highest csrow first, to display it first
         * and work toward the 0th csrow
         */
-       max_csrows = pvt->maxdimmperch * 2;
+       max_csrows = pvt->maxdimmperch;
        for (csrow = max_csrows - 1; csrow >= 0; csrow--) {
 
                /* on an odd csrow, first output a 'boundary' marker,
@@ -1064,7 +1059,7 @@ static void i5400_get_mc_regs(struct mem_ctl_info *mci)
 
        /* Get the set of MTR[0-3] regs by each branch */
        for (slot_row = 0; slot_row < NUM_MTRS_PER_BRANCH; slot_row++) {
-               int where = MTR0 + (slot_row * sizeof(u32));
+               int where = MTR0 + (slot_row * sizeof(u16));
 
                /* Branch 0 set of MTR registers */
                pci_read_config_word(pvt->branch_0, where,
@@ -1146,7 +1141,7 @@ static int i5400_init_csrows(struct mem_ctl_info *mci)
        pvt = mci->pvt_info;
 
        channel_count = pvt->maxch;
-       max_csrows = pvt->maxdimmperch * 2;
+       max_csrows = pvt->maxdimmperch;
 
        empty = 1;              /* Assume NO memory */
 
@@ -1215,28 +1210,6 @@ static void i5400_enable_error_reporting(struct mem_ctl_info *mci)
 }
 
 /*
- * i5400_get_dimm_and_channel_counts(pdev, &num_csrows, &num_channels)
- *
- *     ask the device how many channels are present and how many CSROWS
- *      as well
- */
-static void i5400_get_dimm_and_channel_counts(struct pci_dev *pdev,
-                                       int *num_dimms_per_channel,
-                                       int *num_channels)
-{
-       u8 value;
-
-       /* Need to retrieve just how many channels and dimms per channel are
-        * supported on this memory controller
-        */
-       pci_read_config_byte(pdev, MAXDIMMPERCH, &value);
-       *num_dimms_per_channel = (int)value * 2;
-
-       pci_read_config_byte(pdev, MAXCH, &value);
-       *num_channels = (int)value;
-}
-
-/*
  *     i5400_probe1    Probe for ONE instance of device to see if it is
  *                     present.
  *     return:
@@ -1263,22 +1236,16 @@ static int i5400_probe1(struct pci_dev *pdev, int dev_idx)
        if (PCI_FUNC(pdev->devfn) != 0)
                return -ENODEV;
 
-       /* Ask the devices for the number of CSROWS and CHANNELS so
-        * that we can calculate the memory resources, etc
-        *
-        * The Chipset will report what it can handle which will be greater
-        * or equal to what the motherboard manufacturer will implement.
-        *
-        * As we don't have a motherboard identification routine to determine
+       /* As we don't have a motherboard identification routine to determine
         * actual number of slots/dimms per channel, we thus utilize the
         * resource as specified by the chipset. Thus, we might have
         * have more DIMMs per channel than actually on the mobo, but this
         * allows the driver to support upto the chipset max, without
         * some fancy mobo determination.
         */
-       i5400_get_dimm_and_channel_counts(pdev, &num_dimms_per_channel,
-                                       &num_channels);
-       num_csrows = num_dimms_per_channel * 2;
+       num_dimms_per_channel = MAX_DIMMS_PER_CHANNEL;
+       num_channels = MAX_CHANNELS;
+       num_csrows = num_dimms_per_channel;
 
        debugf0("MC: %s(): Number of - Channels= %d  DIMMS= %d  CSROWS= %d\n",
                __func__, num_channels, num_dimms_per_channel, num_csrows);
index 157f650..cf27402 100644 (file)
@@ -26,7 +26,9 @@
 #include "mpc85xx_edac.h"
 
 static int edac_dev_idx;
+#ifdef CONFIG_PCI
 static int edac_pci_idx;
+#endif
 static int edac_mc_idx;
 
 static u32 orig_ddr_err_disable;
index 50f0176..98dbbda 100644 (file)
@@ -188,14 +188,7 @@ static struct fw_device *target_device(struct sbp2_target *tgt)
 /* Impossible login_id, to detect logout attempt before successful login */
 #define INVALID_LOGIN_ID 0x10000
 
-/*
- * Per section 7.4.8 of the SBP-2 spec, a mgt_ORB_timeout value can be
- * provided in the config rom. Most devices do provide a value, which
- * we'll use for login management orbs, but with some sane limits.
- */
-#define SBP2_MIN_LOGIN_ORB_TIMEOUT     5000U   /* Timeout in ms */
-#define SBP2_MAX_LOGIN_ORB_TIMEOUT     40000U  /* Timeout in ms */
-#define SBP2_ORB_TIMEOUT               2000U   /* Timeout in ms */
+#define SBP2_ORB_TIMEOUT               2000U           /* Timeout in ms */
 #define SBP2_ORB_NULL                  0x80000000
 #define SBP2_RETRY_LIMIT               0xf             /* 15 retries */
 #define SBP2_CYCLE_LIMIT               (0xc8 << 12)    /* 200 125us cycles */
@@ -1034,7 +1027,6 @@ static int sbp2_scan_unit_dir(struct sbp2_target *tgt, u32 *directory,
 {
        struct fw_csr_iterator ci;
        int key, value;
-       unsigned int timeout;
 
        fw_csr_iterator_init(&ci, directory);
        while (fw_csr_iterator_next(&ci, &key, &value)) {
@@ -1059,17 +1051,7 @@ static int sbp2_scan_unit_dir(struct sbp2_target *tgt, u32 *directory,
 
                case SBP2_CSR_UNIT_CHARACTERISTICS:
                        /* the timeout value is stored in 500ms units */
-                       timeout = ((unsigned int) value >> 8 & 0xff) * 500;
-                       timeout = max(timeout, SBP2_MIN_LOGIN_ORB_TIMEOUT);
-                       tgt->mgt_orb_timeout =
-                                 min(timeout, SBP2_MAX_LOGIN_ORB_TIMEOUT);
-
-                       if (timeout > tgt->mgt_orb_timeout)
-                               fw_notify("%s: config rom contains %ds "
-                                         "management ORB timeout, limiting "
-                                         "to %ds\n", tgt->bus_id,
-                                         timeout / 1000,
-                                         tgt->mgt_orb_timeout / 1000);
+                       tgt->mgt_orb_timeout = (value >> 8 & 0xff) * 500;
                        break;
 
                case SBP2_CSR_LOGICAL_UNIT_NUMBER:
@@ -1087,6 +1069,22 @@ static int sbp2_scan_unit_dir(struct sbp2_target *tgt, u32 *directory,
        return 0;
 }
 
+/*
+ * Per section 7.4.8 of the SBP-2 spec, a mgt_ORB_timeout value can be
+ * provided in the config rom. Most devices do provide a value, which
+ * we'll use for login management orbs, but with some sane limits.
+ */
+static void sbp2_clamp_management_orb_timeout(struct sbp2_target *tgt)
+{
+       unsigned int timeout = tgt->mgt_orb_timeout;
+
+       if (timeout > 40000)
+               fw_notify("%s: %ds mgt_ORB_timeout limited to 40s\n",
+                         tgt->bus_id, timeout / 1000);
+
+       tgt->mgt_orb_timeout = clamp_val(timeout, 5000, 40000);
+}
+
 static void sbp2_init_workarounds(struct sbp2_target *tgt, u32 model,
                                  u32 firmware_revision)
 {
@@ -1171,6 +1169,7 @@ static int sbp2_probe(struct device *dev)
                               &firmware_revision) < 0)
                goto fail_tgt_put;
 
+       sbp2_clamp_management_orb_timeout(tgt);
        sbp2_init_workarounds(tgt, model, firmware_revision);
 
        /*
index 420a96e..051d1eb 100644 (file)
@@ -939,7 +939,7 @@ static int __init ibft_init(void)
 
        if (ibft_addr) {
                printk(KERN_INFO "iBFT detected at 0x%llx.\n",
-                      (u64)virt_to_phys((void *)ibft_addr));
+                      (u64)isa_virt_to_bus(ibft_addr));
 
                rc = ibft_check_device();
                if (rc)
index d53fbbf..dfb15c0 100644 (file)
@@ -65,10 +65,10 @@ void __init reserve_ibft_region(void)
                 * so skip that area */
                if (pos == VGA_MEM)
                        pos += VGA_SIZE;
-               virt = phys_to_virt(pos);
+               virt = isa_bus_to_virt(pos);
                if (memcmp(virt, IBFT_SIGN, IBFT_SIGN_LEN) == 0) {
                        unsigned long *addr =
-                           (unsigned long *)phys_to_virt(pos + 4);
+                           (unsigned long *)isa_bus_to_virt(pos + 4);
                        len = *addr;
                        /* if the length of the table extends past 1M,
                         * the table cannot be valid. */
index afad147..49384a7 100644 (file)
@@ -460,7 +460,8 @@ no_irqs:
        return ret;
 }
 
-static int __devexit gpio_twl4030_remove(struct platform_device *pdev)
+/* Cannot use __devexit as gpio_twl4030_probe() calls us */
+static int gpio_twl4030_remove(struct platform_device *pdev)
 {
        struct twl4030_gpio_platform_data *pdata = pdev->dev.platform_data;
        int status;
@@ -493,7 +494,7 @@ static struct platform_driver gpio_twl4030_driver = {
        .driver.name    = "twl4030_gpio",
        .driver.owner   = THIS_MODULE,
        .probe          = gpio_twl4030_probe,
-       .remove         = __devexit_p(gpio_twl4030_remove),
+       .remove         = gpio_twl4030_remove,
 };
 
 static int __init gpio_twl4030_init(void)
index 8e7b0eb..5cae0b3 100644 (file)
@@ -1556,8 +1556,6 @@ int drm_mode_cursor_ioctl(struct drm_device *dev,
        struct drm_crtc *crtc;
        int ret = 0;
 
-       DRM_DEBUG_KMS("\n");
-
        if (!req->flags) {
                DRM_ERROR("no operation set\n");
                return -EINVAL;
index 3c0d2b3..cea665d 100644 (file)
@@ -626,6 +626,12 @@ static struct drm_display_mode *drm_mode_detailed(struct drm_device *dev,
                return NULL;
        }
 
+       /* it is incorrect if hsync/vsync width is zero */
+       if (!hsync_pulse_width || !vsync_pulse_width) {
+               DRM_DEBUG_KMS("Incorrect Detailed timing. "
+                               "Wrong Hsync/Vsync pulse width\n");
+               return NULL;
+       }
        mode = drm_mode_create(dev);
        if (!mode)
                return NULL;
@@ -647,6 +653,15 @@ static struct drm_display_mode *drm_mode_detailed(struct drm_device *dev,
        mode->vsync_end = mode->vsync_start + vsync_pulse_width;
        mode->vtotal = mode->vdisplay + vblank;
 
+       /* perform the basic check for the detailed timing */
+       if (mode->hsync_end > mode->htotal ||
+               mode->vsync_end > mode->vtotal) {
+               drm_mode_destroy(dev, mode);
+               DRM_DEBUG_KMS("Incorrect detailed timing. "
+                               "Sync is beyond the blank.\n");
+               return NULL;
+       }
+
        drm_mode_set_name(mode);
 
        if (pt->misc & DRM_EDID_PT_INTERLACED)
index 819ddcb..9c92461 100644 (file)
@@ -454,6 +454,109 @@ out_free:
 }
 EXPORT_SYMBOL(drm_fb_helper_init_crtc_count);
 
+static int setcolreg(struct drm_crtc *crtc, u16 red, u16 green,
+                    u16 blue, u16 regno, struct fb_info *info)
+{
+       struct drm_fb_helper *fb_helper = info->par;
+       struct drm_framebuffer *fb = fb_helper->fb;
+       int pindex;
+
+       if (info->fix.visual == FB_VISUAL_TRUECOLOR) {
+               u32 *palette;
+               u32 value;
+               /* place color in psuedopalette */
+               if (regno > 16)
+                       return -EINVAL;
+               palette = (u32 *)info->pseudo_palette;
+               red >>= (16 - info->var.red.length);
+               green >>= (16 - info->var.green.length);
+               blue >>= (16 - info->var.blue.length);
+               value = (red << info->var.red.offset) |
+                       (green << info->var.green.offset) |
+                       (blue << info->var.blue.offset);
+               palette[regno] = value;
+               return 0;
+       }
+
+       pindex = regno;
+
+       if (fb->bits_per_pixel == 16) {
+               pindex = regno << 3;
+
+               if (fb->depth == 16 && regno > 63)
+                       return -EINVAL;
+               if (fb->depth == 15 && regno > 31)
+                       return -EINVAL;
+
+               if (fb->depth == 16) {
+                       u16 r, g, b;
+                       int i;
+                       if (regno < 32) {
+                               for (i = 0; i < 8; i++)
+                                       fb_helper->funcs->gamma_set(crtc, red,
+                                               green, blue, pindex + i);
+                       }
+
+                       fb_helper->funcs->gamma_get(crtc, &r,
+                                                   &g, &b,
+                                                   pindex >> 1);
+
+                       for (i = 0; i < 4; i++)
+                               fb_helper->funcs->gamma_set(crtc, r,
+                                                           green, b,
+                                                           (pindex >> 1) + i);
+               }
+       }
+
+       if (fb->depth != 16)
+               fb_helper->funcs->gamma_set(crtc, red, green, blue, pindex);
+       return 0;
+}
+
+int drm_fb_helper_setcmap(struct fb_cmap *cmap, struct fb_info *info)
+{
+       struct drm_fb_helper *fb_helper = info->par;
+       struct drm_device *dev = fb_helper->dev;
+       u16 *red, *green, *blue, *transp;
+       struct drm_crtc *crtc;
+       int i, rc = 0;
+       int start;
+
+       list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
+               struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
+               for (i = 0; i < fb_helper->crtc_count; i++) {
+                       if (crtc->base.id == fb_helper->crtc_info[i].crtc_id)
+                               break;
+               }
+               if (i == fb_helper->crtc_count)
+                       continue;
+
+               red = cmap->red;
+               green = cmap->green;
+               blue = cmap->blue;
+               transp = cmap->transp;
+               start = cmap->start;
+
+               for (i = 0; i < cmap->len; i++) {
+                       u16 hred, hgreen, hblue, htransp = 0xffff;
+
+                       hred = *red++;
+                       hgreen = *green++;
+                       hblue = *blue++;
+
+                       if (transp)
+                               htransp = *transp++;
+
+                       rc = setcolreg(crtc, hred, hgreen, hblue, start++, info);
+                       if (rc)
+                               return rc;
+               }
+               crtc_funcs->load_lut(crtc);
+       }
+       return rc;
+}
+EXPORT_SYMBOL(drm_fb_helper_setcmap);
+
 int drm_fb_helper_setcolreg(unsigned regno,
                            unsigned red,
                            unsigned green,
@@ -465,10 +568,13 @@ int drm_fb_helper_setcolreg(unsigned regno,
        struct drm_device *dev = fb_helper->dev;
        struct drm_crtc *crtc;
        int i;
+       int ret;
 
-       list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
-               struct drm_framebuffer *fb = fb_helper->fb;
+       if (regno > 255)
+               return 1;
 
+       list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
+               struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
                for (i = 0; i < fb_helper->crtc_count; i++) {
                        if (crtc->base.id == fb_helper->crtc_info[i].crtc_id)
                                break;
@@ -476,35 +582,11 @@ int drm_fb_helper_setcolreg(unsigned regno,
                if (i == fb_helper->crtc_count)
                        continue;
 
-               if (regno > 255)
-                       return 1;
-
-               if (fb->depth == 8) {
-                       fb_helper->funcs->gamma_set(crtc, red, green, blue, regno);
-                       return 0;
-               }
+               ret = setcolreg(crtc, red, green, blue, regno, info);
+               if (ret)
+                       return ret;
 
-               if (regno < 16) {
-                       switch (fb->depth) {
-                       case 15:
-                               fb->pseudo_palette[regno] = ((red & 0xf800) >> 1) |
-                                       ((green & 0xf800) >>  6) |
-                                       ((blue & 0xf800) >> 11);
-                               break;
-                       case 16:
-                               fb->pseudo_palette[regno] = (red & 0xf800) |
-                                       ((green & 0xfc00) >>  5) |
-                                       ((blue  & 0xf800) >> 11);
-                               break;
-                       case 24:
-                       case 32:
-                               fb->pseudo_palette[regno] =
-                                       (((red >> 8) & 0xff) << info->var.red.offset) |
-                                       (((green >> 8) & 0xff) << info->var.green.offset) |
-                                       (((blue >> 8) & 0xff) << info->var.blue.offset);
-                               break;
-                       }
-               }
+               crtc_funcs->load_lut(crtc);
        }
        return 0;
 }
@@ -674,6 +756,7 @@ int drm_fb_helper_pan_display(struct fb_var_screeninfo *var,
 EXPORT_SYMBOL(drm_fb_helper_pan_display);
 
 int drm_fb_helper_single_fb_probe(struct drm_device *dev,
+                                 int preferred_bpp,
                                  int (*fb_create)(struct drm_device *dev,
                                                   uint32_t fb_width,
                                                   uint32_t fb_height,
@@ -696,6 +779,11 @@ int drm_fb_helper_single_fb_probe(struct drm_device *dev,
        struct drm_fb_helper *fb_helper;
        uint32_t surface_depth = 24, surface_bpp = 32;
 
+       /* if driver picks 8 or 16 by default use that
+          for both depth/bpp */
+       if (preferred_bpp != surface_bpp) {
+               surface_depth = surface_bpp = preferred_bpp;
+       }
        /* first up get a count of crtcs now in use and new min/maxes width/heights */
        list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
                struct drm_fb_helper_connector *fb_help_conn = connector->fb_helper_private;
@@ -851,10 +939,12 @@ void drm_fb_helper_free(struct drm_fb_helper *helper)
 }
 EXPORT_SYMBOL(drm_fb_helper_free);
 
-void drm_fb_helper_fill_fix(struct fb_info *info, uint32_t pitch)
+void drm_fb_helper_fill_fix(struct fb_info *info, uint32_t pitch,
+                           uint32_t depth)
 {
        info->fix.type = FB_TYPE_PACKED_PIXELS;
-       info->fix.visual = FB_VISUAL_TRUECOLOR;
+       info->fix.visual = depth == 8 ? FB_VISUAL_PSEUDOCOLOR :
+               FB_VISUAL_TRUECOLOR;
        info->fix.type_aux = 0;
        info->fix.xpanstep = 1; /* doing it in hw */
        info->fix.ypanstep = 1; /* doing it in hw */
index 45d507e..92aeb91 100644 (file)
@@ -1468,6 +1468,7 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
        spin_lock_init(&dev_priv->user_irq_lock);
        spin_lock_init(&dev_priv->error_lock);
        dev_priv->user_irq_refcount = 0;
+       dev_priv->trace_irq_seqno = 0;
 
        ret = drm_vblank_init(dev, I915_NUM_PIPE);
 
index b93814c..7f436ec 100644 (file)
@@ -89,7 +89,8 @@ static int i915_suspend(struct drm_device *dev, pm_message_t state)
                pci_set_power_state(dev->pdev, PCI_D3hot);
        }
 
-       dev_priv->suspended = 1;
+       /* Modeset on resume, not lid events */
+       dev_priv->modeset_on_lid = 0;
 
        return 0;
 }
@@ -124,7 +125,7 @@ static int i915_resume(struct drm_device *dev)
                drm_helper_resume_force_mode(dev);
        }
 
-       dev_priv->suspended = 0;
+       dev_priv->modeset_on_lid = 0;
 
        return ret;
 }
index b24b2d1..c5df223 100644 (file)
@@ -202,6 +202,7 @@ typedef struct drm_i915_private {
        spinlock_t user_irq_lock;
        /** Refcount for i915_user_irq_get() versus i915_user_irq_put(). */
        int user_irq_refcount;
+       u32 trace_irq_seqno;
        /** Cached value of IMR to avoid reads in updating the bitfield */
        u32 irq_mask_reg;
        u32 pipestat[2];
@@ -273,7 +274,7 @@ typedef struct drm_i915_private {
        struct drm_i915_display_funcs display;
 
        /* Register state */
-       bool suspended;
+       bool modeset_on_lid;
        u8 saveLBB;
        u32 saveDSPACNTR;
        u32 saveDSPBCNTR;
@@ -665,6 +666,7 @@ extern int i915_irq_emit(struct drm_device *dev, void *data,
 extern int i915_irq_wait(struct drm_device *dev, void *data,
                         struct drm_file *file_priv);
 void i915_user_irq_get(struct drm_device *dev);
+void i915_trace_irq_get(struct drm_device *dev, u32 seqno);
 void i915_user_irq_put(struct drm_device *dev);
 extern void i915_enable_interrupt (struct drm_device *dev);
 
index 40727d4..abfc27b 100644 (file)
@@ -1770,7 +1770,7 @@ i915_gem_retire_requests(struct drm_device *dev)
        drm_i915_private_t *dev_priv = dev->dev_private;
        uint32_t seqno;
 
-       if (!dev_priv->hw_status_page)
+       if (!dev_priv->hw_status_page || list_empty(&dev_priv->mm.request_list))
                return;
 
        seqno = i915_get_gem_seqno(dev);
@@ -1794,6 +1794,12 @@ i915_gem_retire_requests(struct drm_device *dev)
                } else
                        break;
        }
+
+       if (unlikely (dev_priv->trace_irq_seqno &&
+                     i915_seqno_passed(dev_priv->trace_irq_seqno, seqno))) {
+               i915_user_irq_put(dev);
+               dev_priv->trace_irq_seqno = 0;
+       }
 }
 
 void
@@ -3352,7 +3358,7 @@ i915_dispatch_gem_execbuffer(struct drm_device *dev,
        exec_start = (uint32_t) exec_offset + exec->batch_start_offset;
        exec_len = (uint32_t) exec->batch_len;
 
-       trace_i915_gem_request_submit(dev, dev_priv->mm.next_gem_seqno);
+       trace_i915_gem_request_submit(dev, dev_priv->mm.next_gem_seqno + 1);
 
        count = nbox ? nbox : 1;
 
index 4dfeec7..c3ceffa 100644 (file)
@@ -725,6 +725,16 @@ void i915_user_irq_put(struct drm_device *dev)
        spin_unlock_irqrestore(&dev_priv->user_irq_lock, irqflags);
 }
 
+void i915_trace_irq_get(struct drm_device *dev, u32 seqno)
+{
+       drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
+
+       if (dev_priv->trace_irq_seqno == 0)
+               i915_user_irq_get(dev);
+
+       dev_priv->trace_irq_seqno = seqno;
+}
+
 static int i915_wait_irq(struct drm_device * dev, int irq_nr)
 {
        drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
index 5567a40..01840d9 100644 (file)
@@ -158,16 +158,17 @@ TRACE_EVENT(i915_gem_request_submit,
            TP_ARGS(dev, seqno),
 
            TP_STRUCT__entry(
-                            __field(struct drm_device *, dev)
+                            __field(u32, dev)
                             __field(u32, seqno)
                             ),
 
            TP_fast_assign(
-                          __entry->dev = dev;
+                          __entry->dev = dev->primary->index;
                           __entry->seqno = seqno;
+                          i915_trace_irq_get(dev, seqno);
                           ),
 
-           TP_printk("dev=%p, seqno=%u", __entry->dev, __entry->seqno)
+           TP_printk("dev=%u, seqno=%u", __entry->dev, __entry->seqno)
 );
 
 TRACE_EVENT(i915_gem_request_flush,
@@ -178,20 +179,20 @@ TRACE_EVENT(i915_gem_request_flush,
            TP_ARGS(dev, seqno, flush_domains, invalidate_domains),
 
            TP_STRUCT__entry(
-                            __field(struct drm_device *, dev)
+                            __field(u32, dev)
                             __field(u32, seqno)
                             __field(u32, flush_domains)
                             __field(u32, invalidate_domains)
                             ),
 
            TP_fast_assign(
-                          __entry->dev = dev;
+                          __entry->dev = dev->primary->index;
                           __entry->seqno = seqno;
                           __entry->flush_domains = flush_domains;
                           __entry->invalidate_domains = invalidate_domains;
                           ),
 
-           TP_printk("dev=%p, seqno=%u, flush=%04x, invalidate=%04x",
+           TP_printk("dev=%u, seqno=%u, flush=%04x, invalidate=%04x",
                      __entry->dev, __entry->seqno,
                      __entry->flush_domains, __entry->invalidate_domains)
 );
@@ -204,16 +205,16 @@ TRACE_EVENT(i915_gem_request_complete,
            TP_ARGS(dev, seqno),
 
            TP_STRUCT__entry(
-                            __field(struct drm_device *, dev)
+                            __field(u32, dev)
                             __field(u32, seqno)
                             ),
 
            TP_fast_assign(
-                          __entry->dev = dev;
+                          __entry->dev = dev->primary->index;
                           __entry->seqno = seqno;
                           ),
 
-           TP_printk("dev=%p, seqno=%u", __entry->dev, __entry->seqno)
+           TP_printk("dev=%u, seqno=%u", __entry->dev, __entry->seqno)
 );
 
 TRACE_EVENT(i915_gem_request_retire,
@@ -223,16 +224,16 @@ TRACE_EVENT(i915_gem_request_retire,
            TP_ARGS(dev, seqno),
 
            TP_STRUCT__entry(
-                            __field(struct drm_device *, dev)
+                            __field(u32, dev)
                             __field(u32, seqno)
                             ),
 
            TP_fast_assign(
-                          __entry->dev = dev;
+                          __entry->dev = dev->primary->index;
                           __entry->seqno = seqno;
                           ),
 
-           TP_printk("dev=%p, seqno=%u", __entry->dev, __entry->seqno)
+           TP_printk("dev=%u, seqno=%u", __entry->dev, __entry->seqno)
 );
 
 TRACE_EVENT(i915_gem_request_wait_begin,
@@ -242,16 +243,16 @@ TRACE_EVENT(i915_gem_request_wait_begin,
            TP_ARGS(dev, seqno),
 
            TP_STRUCT__entry(
-                            __field(struct drm_device *, dev)
+                            __field(u32, dev)
                             __field(u32, seqno)
                             ),
 
            TP_fast_assign(
-                          __entry->dev = dev;
+                          __entry->dev = dev->primary->index;
                           __entry->seqno = seqno;
                           ),
 
-           TP_printk("dev=%p, seqno=%u", __entry->dev, __entry->seqno)
+           TP_printk("dev=%u, seqno=%u", __entry->dev, __entry->seqno)
 );
 
 TRACE_EVENT(i915_gem_request_wait_end,
@@ -261,16 +262,16 @@ TRACE_EVENT(i915_gem_request_wait_end,
            TP_ARGS(dev, seqno),
 
            TP_STRUCT__entry(
-                            __field(struct drm_device *, dev)
+                            __field(u32, dev)
                             __field(u32, seqno)
                             ),
 
            TP_fast_assign(
-                          __entry->dev = dev;
+                          __entry->dev = dev->primary->index;
                           __entry->seqno = seqno;
                           ),
 
-           TP_printk("dev=%p, seqno=%u", __entry->dev, __entry->seqno)
+           TP_printk("dev=%u, seqno=%u", __entry->dev, __entry->seqno)
 );
 
 TRACE_EVENT(i915_ring_wait_begin,
@@ -280,14 +281,14 @@ TRACE_EVENT(i915_ring_wait_begin,
            TP_ARGS(dev),
 
            TP_STRUCT__entry(
-                            __field(struct drm_device *, dev)
+                            __field(u32, dev)
                             ),
 
            TP_fast_assign(
-                          __entry->dev = dev;
+                          __entry->dev = dev->primary->index;
                           ),
 
-           TP_printk("dev=%p", __entry->dev)
+           TP_printk("dev=%u", __entry->dev)
 );
 
 TRACE_EVENT(i915_ring_wait_end,
@@ -297,14 +298,14 @@ TRACE_EVENT(i915_ring_wait_end,
            TP_ARGS(dev),
 
            TP_STRUCT__entry(
-                            __field(struct drm_device *, dev)
+                            __field(u32, dev)
                             ),
 
            TP_fast_assign(
-                          __entry->dev = dev;
+                          __entry->dev = dev->primary->index;
                           ),
 
-           TP_printk("dev=%p", __entry->dev)
+           TP_printk("dev=%u", __entry->dev)
 );
 
 #endif /* _I915_TRACE_H_ */
index 93ff6c0..3c14240 100644 (file)
@@ -3095,7 +3095,6 @@ static int intel_crtc_cursor_set(struct drm_crtc *crtc,
        struct drm_gem_object *bo;
        struct drm_i915_gem_object *obj_priv;
        int pipe = intel_crtc->pipe;
-       int plane = intel_crtc->plane;
        uint32_t control = (pipe == 0) ? CURACNTR : CURBCNTR;
        uint32_t base = (pipe == 0) ? CURABASE : CURBBASE;
        uint32_t temp = I915_READ(control);
@@ -3182,9 +3181,6 @@ static int intel_crtc_cursor_set(struct drm_crtc *crtc,
                drm_gem_object_unreference(intel_crtc->cursor_bo);
        }
 
-       if ((IS_I965G(dev) || plane == 0))
-               intel_update_fbc(crtc, &crtc->mode);
-
        mutex_unlock(&dev->struct_mutex);
 
        intel_crtc->cursor_addr = addr;
@@ -3244,6 +3240,16 @@ void intel_crtc_fb_gamma_set(struct drm_crtc *crtc, u16 red, u16 green,
        intel_crtc->lut_b[regno] = blue >> 8;
 }
 
+void intel_crtc_fb_gamma_get(struct drm_crtc *crtc, u16 *red, u16 *green,
+                            u16 *blue, int regno)
+{
+       struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+
+       *red = intel_crtc->lut_r[regno] << 8;
+       *green = intel_crtc->lut_g[regno] << 8;
+       *blue = intel_crtc->lut_b[regno] << 8;
+}
+
 static void intel_crtc_gamma_set(struct drm_crtc *crtc, u16 *red, u16 *green,
                                 u16 *blue, uint32_t size)
 {
@@ -3835,6 +3841,7 @@ static const struct drm_crtc_helper_funcs intel_helper_funcs = {
        .mode_set_base = intel_pipe_set_base,
        .prepare = intel_crtc_prepare,
        .commit = intel_crtc_commit,
+       .load_lut = intel_crtc_load_lut,
 };
 
 static const struct drm_crtc_funcs intel_crtc_funcs = {
index 8aa4b7f..ef61fe9 100644 (file)
@@ -175,6 +175,8 @@ extern int intelfb_resize(struct drm_device *dev, struct drm_crtc *crtc);
 extern void intelfb_restore(void);
 extern void intel_crtc_fb_gamma_set(struct drm_crtc *crtc, u16 red, u16 green,
                                    u16 blue, int regno);
+extern void intel_crtc_fb_gamma_get(struct drm_crtc *crtc, u16 *red, u16 *green,
+                                   u16 *blue, int regno);
 
 extern int intel_framebuffer_create(struct drm_device *dev,
                                    struct drm_mode_fb_cmd *mode_cmd,
index e85d7e9..2b0fe54 100644 (file)
@@ -60,10 +60,12 @@ static struct fb_ops intelfb_ops = {
        .fb_imageblit = cfb_imageblit,
        .fb_pan_display = drm_fb_helper_pan_display,
        .fb_blank = drm_fb_helper_blank,
+       .fb_setcmap = drm_fb_helper_setcmap,
 };
 
 static struct drm_fb_helper_funcs intel_fb_helper_funcs = {
        .gamma_set = intel_crtc_fb_gamma_set,
+       .gamma_get = intel_crtc_fb_gamma_get,
 };
 
 
@@ -123,6 +125,10 @@ static int intelfb_create(struct drm_device *dev, uint32_t fb_width,
        struct device *device = &dev->pdev->dev;
        int size, ret, mmio_bar = IS_I9XX(dev) ? 0 : 1;
 
+       /* we don't do packed 24bpp */
+       if (surface_bpp == 24)
+               surface_bpp = 32;
+
        mode_cmd.width = surface_width;
        mode_cmd.height = surface_height;
 
@@ -206,7 +212,7 @@ static int intelfb_create(struct drm_device *dev, uint32_t fb_width,
 
 //     memset(info->screen_base, 0, size);
 
-       drm_fb_helper_fill_fix(info, fb->pitch);
+       drm_fb_helper_fill_fix(info, fb->pitch, fb->depth);
        drm_fb_helper_fill_var(info, fb, fb_width, fb_height);
 
        /* FIXME: we really shouldn't expose mmio space at all */
@@ -244,7 +250,7 @@ int intelfb_probe(struct drm_device *dev)
        int ret;
 
        DRM_DEBUG("\n");
-       ret = drm_fb_helper_single_fb_probe(dev, intelfb_create);
+       ret = drm_fb_helper_single_fb_probe(dev, 32, intelfb_create);
        return ret;
 }
 EXPORT_SYMBOL(intelfb_probe);
index fa304e1..663ab6d 100644 (file)
@@ -223,7 +223,7 @@ void intel_hdmi_init(struct drm_device *dev, int sdvox_reg)
 
        connector = &intel_output->base;
        drm_connector_init(dev, connector, &intel_hdmi_connector_funcs,
-                          DRM_MODE_CONNECTOR_DVID);
+                          DRM_MODE_CONNECTOR_HDMIA);
        drm_connector_helper_add(connector, &intel_hdmi_connector_helper_funcs);
 
        intel_output->type = INTEL_OUTPUT_HDMI;
index 98ae3d7..808bbe4 100644 (file)
@@ -656,6 +656,15 @@ static int intel_lvds_get_modes(struct drm_connector *connector)
        return 0;
 }
 
+/*
+ * Lid events. Note the use of 'modeset_on_lid':
+ *  - we set it on lid close, and reset it on open
+ *  - we use it as a "only once" bit (ie we ignore
+ *    duplicate events where it was already properly
+ *    set/reset)
+ *  - the suspend/resume paths will also set it to
+ *    zero, since they restore the mode ("lid open").
+ */
 static int intel_lid_notify(struct notifier_block *nb, unsigned long val,
                            void *unused)
 {
@@ -663,13 +672,19 @@ static int intel_lid_notify(struct notifier_block *nb, unsigned long val,
                container_of(nb, struct drm_i915_private, lid_notifier);
        struct drm_device *dev = dev_priv->dev;
 
-       if (acpi_lid_open() && !dev_priv->suspended) {
-               mutex_lock(&dev->mode_config.mutex);
-               drm_helper_resume_force_mode(dev);
-               mutex_unlock(&dev->mode_config.mutex);
+       if (!acpi_lid_open()) {
+               dev_priv->modeset_on_lid = 1;
+               return NOTIFY_OK;
        }
 
-       drm_sysfs_hotplug_event(dev_priv->dev);
+       if (!dev_priv->modeset_on_lid)
+               return NOTIFY_OK;
+
+       dev_priv->modeset_on_lid = 0;
+
+       mutex_lock(&dev->mode_config.mutex);
+       drm_helper_resume_force_mode(dev);
+       mutex_unlock(&dev->mode_config.mutex);
 
        return NOTIFY_OK;
 }
index c64eab4..9ca9179 100644 (file)
@@ -1082,7 +1082,8 @@ intel_tv_mode_valid(struct drm_connector *connector, struct drm_display_mode *mo
        const struct tv_mode *tv_mode = intel_tv_mode_find(intel_output);
 
        /* Ensure TV refresh is close to desired refresh */
-       if (tv_mode && abs(tv_mode->refresh - drm_mode_vrefresh(mode)) < 10)
+       if (tv_mode && abs(tv_mode->refresh - drm_mode_vrefresh(mode) * 1000)
+                               < 1000)
                return MODE_OK;
        return MODE_CLOCK_RANGE;
 }
index 6a01592..14fa970 100644 (file)
@@ -733,6 +733,7 @@ static const struct drm_crtc_helper_funcs atombios_helper_funcs = {
        .mode_set_base = atombios_crtc_set_base,
        .prepare = atombios_crtc_prepare,
        .commit = atombios_crtc_commit,
+       .load_lut = radeon_crtc_load_lut,
 };
 
 void radeon_atombios_init_crtc(struct drm_device *dev,
index e6cce24..161094c 100644 (file)
@@ -32,6 +32,9 @@
 #include "radeon_reg.h"
 #include "radeon.h"
 #include "r100d.h"
+#include "rs100d.h"
+#include "rv200d.h"
+#include "rv250d.h"
 
 #include <linux/firmware.h>
 #include <linux/platform_device.h>
@@ -60,18 +63,7 @@ MODULE_FIRMWARE(FIRMWARE_R520);
 
 /* This files gather functions specifics to:
  * r100,rv100,rs100,rv200,rs200,r200,rv250,rs300,rv280
- *
- * Some of these functions might be used by newer ASICs.
  */
-int r200_init(struct radeon_device *rdev);
-void r100_hdp_reset(struct radeon_device *rdev);
-void r100_gpu_init(struct radeon_device *rdev);
-int r100_gui_wait_for_idle(struct radeon_device *rdev);
-int r100_mc_wait_for_idle(struct radeon_device *rdev);
-void r100_gpu_wait_for_vsync(struct radeon_device *rdev);
-void r100_gpu_wait_for_vsync2(struct radeon_device *rdev);
-int r100_debugfs_mc_info_init(struct radeon_device *rdev);
-
 
 /*
  * PCI GART
@@ -152,136 +144,6 @@ void r100_pci_gart_fini(struct radeon_device *rdev)
        radeon_gart_fini(rdev);
 }
 
-
-/*
- * MC
- */
-void r100_mc_disable_clients(struct radeon_device *rdev)
-{
-       uint32_t ov0_scale_cntl, crtc_ext_cntl, crtc_gen_cntl, crtc2_gen_cntl;
-
-       /* FIXME: is this function correct for rs100,rs200,rs300 ? */
-       if (r100_gui_wait_for_idle(rdev)) {
-               printk(KERN_WARNING "Failed to wait GUI idle while "
-                      "programming pipes. Bad things might happen.\n");
-       }
-
-       /* stop display and memory access */
-       ov0_scale_cntl = RREG32(RADEON_OV0_SCALE_CNTL);
-       WREG32(RADEON_OV0_SCALE_CNTL, ov0_scale_cntl & ~RADEON_SCALER_ENABLE);
-       crtc_ext_cntl = RREG32(RADEON_CRTC_EXT_CNTL);
-       WREG32(RADEON_CRTC_EXT_CNTL, crtc_ext_cntl | RADEON_CRTC_DISPLAY_DIS);
-       crtc_gen_cntl = RREG32(RADEON_CRTC_GEN_CNTL);
-
-       r100_gpu_wait_for_vsync(rdev);
-
-       WREG32(RADEON_CRTC_GEN_CNTL,
-              (crtc_gen_cntl & ~(RADEON_CRTC_CUR_EN | RADEON_CRTC_ICON_EN)) |
-              RADEON_CRTC_DISP_REQ_EN_B | RADEON_CRTC_EXT_DISP_EN);
-
-       if (!(rdev->flags & RADEON_SINGLE_CRTC)) {
-               crtc2_gen_cntl = RREG32(RADEON_CRTC2_GEN_CNTL);
-
-               r100_gpu_wait_for_vsync2(rdev);
-               WREG32(RADEON_CRTC2_GEN_CNTL,
-                      (crtc2_gen_cntl &
-                       ~(RADEON_CRTC2_CUR_EN | RADEON_CRTC2_ICON_EN)) |
-                      RADEON_CRTC2_DISP_REQ_EN_B);
-       }
-
-       udelay(500);
-}
-
-void r100_mc_setup(struct radeon_device *rdev)
-{
-       uint32_t tmp;
-       int r;
-
-       r = r100_debugfs_mc_info_init(rdev);
-       if (r) {
-               DRM_ERROR("Failed to register debugfs file for R100 MC !\n");
-       }
-       /* Write VRAM size in case we are limiting it */
-       WREG32(RADEON_CONFIG_MEMSIZE, rdev->mc.real_vram_size);
-       /* Novell bug 204882 for RN50/M6/M7 with 8/16/32MB VRAM,
-        * if the aperture is 64MB but we have 32MB VRAM
-        * we report only 32MB VRAM but we have to set MC_FB_LOCATION
-        * to 64MB, otherwise the gpu accidentially dies */
-       tmp = rdev->mc.vram_location + rdev->mc.mc_vram_size - 1;
-       tmp = REG_SET(RADEON_MC_FB_TOP, tmp >> 16);
-       tmp |= REG_SET(RADEON_MC_FB_START, rdev->mc.vram_location >> 16);
-       WREG32(RADEON_MC_FB_LOCATION, tmp);
-
-       /* Enable bus mastering */
-       tmp = RREG32(RADEON_BUS_CNTL) & ~RADEON_BUS_MASTER_DIS;
-       WREG32(RADEON_BUS_CNTL, tmp);
-
-       if (rdev->flags & RADEON_IS_AGP) {
-               tmp = rdev->mc.gtt_location + rdev->mc.gtt_size - 1;
-               tmp = REG_SET(RADEON_MC_AGP_TOP, tmp >> 16);
-               tmp |= REG_SET(RADEON_MC_AGP_START, rdev->mc.gtt_location >> 16);
-               WREG32(RADEON_MC_AGP_LOCATION, tmp);
-               WREG32(RADEON_AGP_BASE, rdev->mc.agp_base);
-       } else {
-               WREG32(RADEON_MC_AGP_LOCATION, 0x0FFFFFFF);
-               WREG32(RADEON_AGP_BASE, 0);
-       }
-
-       tmp = RREG32(RADEON_HOST_PATH_CNTL) & RADEON_HDP_APER_CNTL;
-       tmp |= (7 << 28);
-       WREG32(RADEON_HOST_PATH_CNTL, tmp | RADEON_HDP_SOFT_RESET | RADEON_HDP_READ_BUFFER_INVALIDATE);
-       (void)RREG32(RADEON_HOST_PATH_CNTL);
-       WREG32(RADEON_HOST_PATH_CNTL, tmp);
-       (void)RREG32(RADEON_HOST_PATH_CNTL);
-}
-
-int r100_mc_init(struct radeon_device *rdev)
-{
-       int r;
-
-       if (r100_debugfs_rbbm_init(rdev)) {
-               DRM_ERROR("Failed to register debugfs file for RBBM !\n");
-       }
-
-       r100_gpu_init(rdev);
-       /* Disable gart which also disable out of gart access */
-       r100_pci_gart_disable(rdev);
-
-       /* Setup GPU memory space */
-       rdev->mc.gtt_location = 0xFFFFFFFFUL;
-       if (rdev->flags & RADEON_IS_AGP) {
-               r = radeon_agp_init(rdev);
-               if (r) {
-                       printk(KERN_WARNING "[drm] Disabling AGP\n");
-                       rdev->flags &= ~RADEON_IS_AGP;
-                       rdev->mc.gtt_size = radeon_gart_size * 1024 * 1024;
-               } else {
-                       rdev->mc.gtt_location = rdev->mc.agp_base;
-               }
-       }
-       r = radeon_mc_setup(rdev);
-       if (r) {
-               return r;
-       }
-
-       r100_mc_disable_clients(rdev);
-       if (r100_mc_wait_for_idle(rdev)) {
-               printk(KERN_WARNING "Failed to wait MC idle while "
-                      "programming pipes. Bad things might happen.\n");
-       }
-
-       r100_mc_setup(rdev);
-       return 0;
-}
-
-void r100_mc_fini(struct radeon_device *rdev)
-{
-}
-
-
-/*
- * Interrupts
- */
 int r100_irq_set(struct radeon_device *rdev)
 {
        uint32_t tmp = 0;
@@ -358,10 +220,6 @@ u32 r100_get_vblank_counter(struct radeon_device *rdev, int crtc)
                return RREG32(RADEON_CRTC2_CRNT_FRAME);
 }
 
-
-/*
- * Fence emission
- */
 void r100_fence_ring_emit(struct radeon_device *rdev,
                          struct radeon_fence *fence)
 {
@@ -377,10 +235,6 @@ void r100_fence_ring_emit(struct radeon_device *rdev,
        radeon_ring_write(rdev, RADEON_SW_INT_FIRE);
 }
 
-
-/*
- * Writeback
- */
 int r100_wb_init(struct radeon_device *rdev)
 {
        int r;
@@ -504,10 +358,6 @@ int r100_copy_blit(struct radeon_device *rdev,
        return r;
 }
 
-
-/*
- * CP
- */
 static int r100_cp_wait_for_idle(struct radeon_device *rdev)
 {
        unsigned i;
@@ -612,6 +462,7 @@ static int r100_cp_init_microcode(struct radeon_device *rdev)
        }
        return err;
 }
+
 static void r100_cp_load_microcode(struct radeon_device *rdev)
 {
        const __be32 *fw_data;
@@ -978,7 +829,7 @@ int r100_cs_packet_parse_vline(struct radeon_cs_parser *p)
 
        header = radeon_get_ib_value(p, h_idx);
        crtc_id = radeon_get_ib_value(p, h_idx + 5);
-       reg = header >> 2;
+       reg = CP_PACKET0_GET_REG(header);
        mutex_lock(&p->rdev->ddev->mode_config.mutex);
        obj = drm_mode_object_find(p->rdev->ddev, crtc_id, DRM_MODE_OBJECT_CRTC);
        if (!obj) {
@@ -1990,7 +1841,7 @@ void r100_pll_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v)
        r100_pll_errata_after_data(rdev);
 }
 
-int r100_init(struct radeon_device *rdev)
+void r100_set_safe_registers(struct radeon_device *rdev)
 {
        if (ASIC_IS_RN50(rdev)) {
                rdev->config.r100.reg_safe_bm = rn50_reg_safe_bm;
@@ -1999,9 +1850,8 @@ int r100_init(struct radeon_device *rdev)
                rdev->config.r100.reg_safe_bm = r100_reg_safe_bm;
                rdev->config.r100.reg_safe_bm_size = ARRAY_SIZE(r100_reg_safe_bm);
        } else {
-               return r200_init(rdev);
+               r200_set_safe_registers(rdev);
        }
-       return 0;
 }
 
 /*
@@ -2299,9 +2149,11 @@ void r100_bandwidth_update(struct radeon_device *rdev)
                mode1 = &rdev->mode_info.crtcs[0]->base.mode;
                pixel_bytes1 = rdev->mode_info.crtcs[0]->base.fb->bits_per_pixel / 8;
        }
-       if (rdev->mode_info.crtcs[1]->base.enabled) {
-               mode2 = &rdev->mode_info.crtcs[1]->base.mode;
-               pixel_bytes2 = rdev->mode_info.crtcs[1]->base.fb->bits_per_pixel / 8;
+       if (!(rdev->flags & RADEON_SINGLE_CRTC)) {
+               if (rdev->mode_info.crtcs[1]->base.enabled) {
+                       mode2 = &rdev->mode_info.crtcs[1]->base.mode;
+                       pixel_bytes2 = rdev->mode_info.crtcs[1]->base.fb->bits_per_pixel / 8;
+               }
        }
 
        min_mem_eff.full = rfixed_const_8(0);
@@ -3114,7 +2966,7 @@ void r100_mc_stop(struct radeon_device *rdev, struct r100_mc_save *save)
        WREG32(R_000740_CP_CSQ_CNTL, 0);
 
        /* Save few CRTC registers */
-       save->GENMO_WT = RREG32(R_0003C0_GENMO_WT);
+       save->GENMO_WT = RREG8(R_0003C2_GENMO_WT);
        save->CRTC_EXT_CNTL = RREG32(R_000054_CRTC_EXT_CNTL);
        save->CRTC_GEN_CNTL = RREG32(R_000050_CRTC_GEN_CNTL);
        save->CUR_OFFSET = RREG32(R_000260_CUR_OFFSET);
@@ -3124,7 +2976,7 @@ void r100_mc_stop(struct radeon_device *rdev, struct r100_mc_save *save)
        }
 
        /* Disable VGA aperture access */
-       WREG32(R_0003C0_GENMO_WT, C_0003C0_VGA_RAM_EN & save->GENMO_WT);
+       WREG8(R_0003C2_GENMO_WT, C_0003C2_VGA_RAM_EN & save->GENMO_WT);
        /* Disable cursor, overlay, crtc */
        WREG32(R_000260_CUR_OFFSET, save->CUR_OFFSET | S_000260_CUR_LOCK(1));
        WREG32(R_000054_CRTC_EXT_CNTL, save->CRTC_EXT_CNTL |
@@ -3156,10 +3008,264 @@ void r100_mc_resume(struct radeon_device *rdev, struct r100_mc_save *save)
                                rdev->mc.vram_location);
        }
        /* Restore CRTC registers */
-       WREG32(R_0003C0_GENMO_WT, save->GENMO_WT);
+       WREG8(R_0003C2_GENMO_WT, save->GENMO_WT);
        WREG32(R_000054_CRTC_EXT_CNTL, save->CRTC_EXT_CNTL);
        WREG32(R_000050_CRTC_GEN_CNTL, save->CRTC_GEN_CNTL);
        if (!(rdev->flags & RADEON_SINGLE_CRTC)) {
                WREG32(R_0003F8_CRTC2_GEN_CNTL, save->CRTC2_GEN_CNTL);
        }
 }
+
+void r100_vga_render_disable(struct radeon_device *rdev)
+{
+       u32 tmp;
+
+       tmp = RREG8(R_0003C2_GENMO_WT);
+       WREG8(R_0003C2_GENMO_WT, C_0003C2_VGA_RAM_EN & tmp);
+}
+
+static void r100_debugfs(struct radeon_device *rdev)
+{
+       int r;
+
+       r = r100_debugfs_mc_info_init(rdev);
+       if (r)
+               dev_warn(rdev->dev, "Failed to create r100_mc debugfs file.\n");
+}
+
+static void r100_mc_program(struct radeon_device *rdev)
+{
+       struct r100_mc_save save;
+
+       /* Stops all mc clients */
+       r100_mc_stop(rdev, &save);
+       if (rdev->flags & RADEON_IS_AGP) {
+               WREG32(R_00014C_MC_AGP_LOCATION,
+                       S_00014C_MC_AGP_START(rdev->mc.gtt_start >> 16) |
+                       S_00014C_MC_AGP_TOP(rdev->mc.gtt_end >> 16));
+               WREG32(R_000170_AGP_BASE, lower_32_bits(rdev->mc.agp_base));
+               if (rdev->family > CHIP_RV200)
+                       WREG32(R_00015C_AGP_BASE_2,
+                               upper_32_bits(rdev->mc.agp_base) & 0xff);
+       } else {
+               WREG32(R_00014C_MC_AGP_LOCATION, 0x0FFFFFFF);
+               WREG32(R_000170_AGP_BASE, 0);
+               if (rdev->family > CHIP_RV200)
+                       WREG32(R_00015C_AGP_BASE_2, 0);
+       }
+       /* Wait for mc idle */
+       if (r100_mc_wait_for_idle(rdev))
+               dev_warn(rdev->dev, "Wait for MC idle timeout.\n");
+       /* Program MC, should be a 32bits limited address space */
+       WREG32(R_000148_MC_FB_LOCATION,
+               S_000148_MC_FB_START(rdev->mc.vram_start >> 16) |
+               S_000148_MC_FB_TOP(rdev->mc.vram_end >> 16));
+       r100_mc_resume(rdev, &save);
+}
+
+void r100_clock_startup(struct radeon_device *rdev)
+{
+       u32 tmp;
+
+       if (radeon_dynclks != -1 && radeon_dynclks)
+               radeon_legacy_set_clock_gating(rdev, 1);
+       /* We need to force on some of the block */
+       tmp = RREG32_PLL(R_00000D_SCLK_CNTL);
+       tmp |= S_00000D_FORCE_CP(1) | S_00000D_FORCE_VIP(1);
+       if ((rdev->family == CHIP_RV250) || (rdev->family == CHIP_RV280))
+               tmp |= S_00000D_FORCE_DISP1(1) | S_00000D_FORCE_DISP2(1);
+       WREG32_PLL(R_00000D_SCLK_CNTL, tmp);
+}
+
+static int r100_startup(struct radeon_device *rdev)
+{
+       int r;
+
+       r100_mc_program(rdev);
+       /* Resume clock */
+       r100_clock_startup(rdev);
+       /* Initialize GPU configuration (# pipes, ...) */
+       r100_gpu_init(rdev);
+       /* Initialize GART (initialize after TTM so we can allocate
+        * memory through TTM but finalize after TTM) */
+       if (rdev->flags & RADEON_IS_PCI) {
+               r = r100_pci_gart_enable(rdev);
+               if (r)
+                       return r;
+       }
+       /* Enable IRQ */
+       rdev->irq.sw_int = true;
+       r100_irq_set(rdev);
+       /* 1M ring buffer */
+       r = r100_cp_init(rdev, 1024 * 1024);
+       if (r) {
+               dev_err(rdev->dev, "failled initializing CP (%d).\n", r);
+               return r;
+       }
+       r = r100_wb_init(rdev);
+       if (r)
+               dev_err(rdev->dev, "failled initializing WB (%d).\n", r);
+       r = r100_ib_init(rdev);
+       if (r) {
+               dev_err(rdev->dev, "failled initializing IB (%d).\n", r);
+               return r;
+       }
+       return 0;
+}
+
+int r100_resume(struct radeon_device *rdev)
+{
+       /* Make sur GART are not working */
+       if (rdev->flags & RADEON_IS_PCI)
+               r100_pci_gart_disable(rdev);
+       /* Resume clock before doing reset */
+       r100_clock_startup(rdev);
+       /* Reset gpu before posting otherwise ATOM will enter infinite loop */
+       if (radeon_gpu_reset(rdev)) {
+               dev_warn(rdev->dev, "GPU reset failed ! (0xE40=0x%08X, 0x7C0=0x%08X)\n",
+                       RREG32(R_000E40_RBBM_STATUS),
+                       RREG32(R_0007C0_CP_STAT));
+       }
+       /* post */
+       radeon_combios_asic_init(rdev->ddev);
+       /* Resume clock after posting */
+       r100_clock_startup(rdev);
+       return r100_startup(rdev);
+}
+
+int r100_suspend(struct radeon_device *rdev)
+{
+       r100_cp_disable(rdev);
+       r100_wb_disable(rdev);
+       r100_irq_disable(rdev);
+       if (rdev->flags & RADEON_IS_PCI)
+               r100_pci_gart_disable(rdev);
+       return 0;
+}
+
+void r100_fini(struct radeon_device *rdev)
+{
+       r100_suspend(rdev);
+       r100_cp_fini(rdev);
+       r100_wb_fini(rdev);
+       r100_ib_fini(rdev);
+       radeon_gem_fini(rdev);
+       if (rdev->flags & RADEON_IS_PCI)
+               r100_pci_gart_fini(rdev);
+       radeon_irq_kms_fini(rdev);
+       radeon_fence_driver_fini(rdev);
+       radeon_object_fini(rdev);
+       radeon_atombios_fini(rdev);
+       kfree(rdev->bios);
+       rdev->bios = NULL;
+}
+
+int r100_mc_init(struct radeon_device *rdev)
+{
+       int r;
+       u32 tmp;
+
+       /* Setup GPU memory space */
+       rdev->mc.vram_location = 0xFFFFFFFFUL;
+       rdev->mc.gtt_location = 0xFFFFFFFFUL;
+       if (rdev->flags & RADEON_IS_IGP) {
+               tmp = G_00015C_MC_FB_START(RREG32(R_00015C_NB_TOM));
+               rdev->mc.vram_location = tmp << 16;
+       }
+       if (rdev->flags & RADEON_IS_AGP) {
+               r = radeon_agp_init(rdev);
+               if (r) {
+                       printk(KERN_WARNING "[drm] Disabling AGP\n");
+                       rdev->flags &= ~RADEON_IS_AGP;
+                       rdev->mc.gtt_size = radeon_gart_size * 1024 * 1024;
+               } else {
+                       rdev->mc.gtt_location = rdev->mc.agp_base;
+               }
+       }
+       r = radeon_mc_setup(rdev);
+       if (r)
+               return r;
+       return 0;
+}
+
+int r100_init(struct radeon_device *rdev)
+{
+       int r;
+
+       /* Register debugfs file specific to this group of asics */
+       r100_debugfs(rdev);
+       /* Disable VGA */
+       r100_vga_render_disable(rdev);
+       /* Initialize scratch registers */
+       radeon_scratch_init(rdev);
+       /* Initialize surface registers */
+       radeon_surface_init(rdev);
+       /* TODO: disable VGA need to use VGA request */
+       /* BIOS*/
+       if (!radeon_get_bios(rdev)) {
+               if (ASIC_IS_AVIVO(rdev))
+                       return -EINVAL;
+       }
+       if (rdev->is_atom_bios) {
+               dev_err(rdev->dev, "Expecting combios for RS400/RS480 GPU\n");
+               return -EINVAL;
+       } else {
+               r = radeon_combios_init(rdev);
+               if (r)
+                       return r;
+       }
+       /* Reset gpu before posting otherwise ATOM will enter infinite loop */
+       if (radeon_gpu_reset(rdev)) {
+               dev_warn(rdev->dev,
+                       "GPU reset failed ! (0xE40=0x%08X, 0x7C0=0x%08X)\n",
+                       RREG32(R_000E40_RBBM_STATUS),
+                       RREG32(R_0007C0_CP_STAT));
+       }
+       /* check if cards are posted or not */
+       if (!radeon_card_posted(rdev) && rdev->bios) {
+               DRM_INFO("GPU not posted. posting now...\n");
+               radeon_combios_asic_init(rdev->ddev);
+       }
+       /* Set asic errata */
+       r100_errata(rdev);
+       /* Initialize clocks */
+       radeon_get_clock_info(rdev->ddev);
+       /* Get vram informations */
+       r100_vram_info(rdev);
+       /* Initialize memory controller (also test AGP) */
+       r = r100_mc_init(rdev);
+       if (r)
+               return r;
+       /* Fence driver */
+       r = radeon_fence_driver_init(rdev);
+       if (r)
+               return r;
+       r = radeon_irq_kms_init(rdev);
+       if (r)
+               return r;
+       /* Memory manager */
+       r = radeon_object_init(rdev);
+       if (r)
+               return r;
+       if (rdev->flags & RADEON_IS_PCI) {
+               r = r100_pci_gart_init(rdev);
+               if (r)
+                       return r;
+       }
+       r100_set_safe_registers(rdev);
+       rdev->accel_working = true;
+       r = r100_startup(rdev);
+       if (r) {
+               /* Somethings want wront with the accel init stop accel */
+               dev_err(rdev->dev, "Disabling GPU acceleration\n");
+               r100_suspend(rdev);
+               r100_cp_fini(rdev);
+               r100_wb_fini(rdev);
+               r100_ib_fini(rdev);
+               if (rdev->flags & RADEON_IS_PCI)
+                       r100_pci_gart_fini(rdev);
+               radeon_irq_kms_fini(rdev);
+               rdev->accel_working = false;
+       }
+       return 0;
+}
index c4b257e..df29a63 100644 (file)
 #define   S_000054_VCRTC_IDX_MASTER(x)                 (((x) & 0x7F) << 24)
 #define   G_000054_VCRTC_IDX_MASTER(x)                 (((x) >> 24) & 0x7F)
 #define   C_000054_VCRTC_IDX_MASTER                    0x80FFFFFF
+#define R_000148_MC_FB_LOCATION                      0x000148
+#define   S_000148_MC_FB_START(x)                      (((x) & 0xFFFF) << 0)
+#define   G_000148_MC_FB_START(x)                      (((x) >> 0) & 0xFFFF)
+#define   C_000148_MC_FB_START                         0xFFFF0000
+#define   S_000148_MC_FB_TOP(x)                        (((x) & 0xFFFF) << 16)
+#define   G_000148_MC_FB_TOP(x)                        (((x) >> 16) & 0xFFFF)
+#define   C_000148_MC_FB_TOP                           0x0000FFFF
+#define R_00014C_MC_AGP_LOCATION                     0x00014C
+#define   S_00014C_MC_AGP_START(x)                     (((x) & 0xFFFF) << 0)
+#define   G_00014C_MC_AGP_START(x)                     (((x) >> 0) & 0xFFFF)
+#define   C_00014C_MC_AGP_START                        0xFFFF0000
+#define   S_00014C_MC_AGP_TOP(x)                       (((x) & 0xFFFF) << 16)
+#define   G_00014C_MC_AGP_TOP(x)                       (((x) >> 16) & 0xFFFF)
+#define   C_00014C_MC_AGP_TOP                          0x0000FFFF
+#define R_000170_AGP_BASE                            0x000170
+#define   S_000170_AGP_BASE_ADDR(x)                    (((x) & 0xFFFFFFFF) << 0)
+#define   G_000170_AGP_BASE_ADDR(x)                    (((x) >> 0) & 0xFFFFFFFF)
+#define   C_000170_AGP_BASE_ADDR                       0x00000000
 #define R_00023C_DISPLAY_BASE_ADDR                   0x00023C
 #define   S_00023C_DISPLAY_BASE_ADDR(x)                (((x) & 0xFFFFFFFF) << 0)
 #define   G_00023C_DISPLAY_BASE_ADDR(x)                (((x) >> 0) & 0xFFFFFFFF)
 #define   S_000360_CUR2_LOCK(x)                        (((x) & 0x1) << 31)
 #define   G_000360_CUR2_LOCK(x)                        (((x) >> 31) & 0x1)
 #define   C_000360_CUR2_LOCK                           0x7FFFFFFF
-#define R_0003C0_GENMO_WT                            0x0003C0
-#define   S_0003C0_GENMO_MONO_ADDRESS_B(x)             (((x) & 0x1) << 0)
-#define   G_0003C0_GENMO_MONO_ADDRESS_B(x)             (((x) >> 0) & 0x1)
-#define   C_0003C0_GENMO_MONO_ADDRESS_B                0xFFFFFFFE
-#define   S_0003C0_VGA_RAM_EN(x)                       (((x) & 0x1) << 1)
-#define   G_0003C0_VGA_RAM_EN(x)                       (((x) >> 1) & 0x1)
-#define   C_0003C0_VGA_RAM_EN                          0xFFFFFFFD
-#define   S_0003C0_VGA_CKSEL(x)                        (((x) & 0x3) << 2)
-#define   G_0003C0_VGA_CKSEL(x)                        (((x) >> 2) & 0x3)
-#define   C_0003C0_VGA_CKSEL                           0xFFFFFFF3
-#define   S_0003C0_ODD_EVEN_MD_PGSEL(x)                (((x) & 0x1) << 5)
-#define   G_0003C0_ODD_EVEN_MD_PGSEL(x)                (((x) >> 5) & 0x1)
-#define   C_0003C0_ODD_EVEN_MD_PGSEL                   0xFFFFFFDF
-#define   S_0003C0_VGA_HSYNC_POL(x)                    (((x) & 0x1) << 6)
-#define   G_0003C0_VGA_HSYNC_POL(x)                    (((x) >> 6) & 0x1)
-#define   C_0003C0_VGA_HSYNC_POL                       0xFFFFFFBF
-#define   S_0003C0_VGA_VSYNC_POL(x)                    (((x) & 0x1) << 7)
-#define   G_0003C0_VGA_VSYNC_POL(x)                    (((x) >> 7) & 0x1)
-#define   C_0003C0_VGA_VSYNC_POL                       0xFFFFFF7F
+#define R_0003C2_GENMO_WT                            0x0003C0
+#define   S_0003C2_GENMO_MONO_ADDRESS_B(x)             (((x) & 0x1) << 0)
+#define   G_0003C2_GENMO_MONO_ADDRESS_B(x)             (((x) >> 0) & 0x1)
+#define   C_0003C2_GENMO_MONO_ADDRESS_B                0xFE
+#define   S_0003C2_VGA_RAM_EN(x)                       (((x) & 0x1) << 1)
+#define   G_0003C2_VGA_RAM_EN(x)                       (((x) >> 1) & 0x1)
+#define   C_0003C2_VGA_RAM_EN                          0xFD
+#define   S_0003C2_VGA_CKSEL(x)                        (((x) & 0x3) << 2)
+#define   G_0003C2_VGA_CKSEL(x)                        (((x) >> 2) & 0x3)
+#define   C_0003C2_VGA_CKSEL                           0xF3
+#define   S_0003C2_ODD_EVEN_MD_PGSEL(x)                (((x) & 0x1) << 5)
+#define   G_0003C2_ODD_EVEN_MD_PGSEL(x)                (((x) >> 5) & 0x1)
+#define   C_0003C2_ODD_EVEN_MD_PGSEL                   0xDF
+#define   S_0003C2_VGA_HSYNC_POL(x)                    (((x) & 0x1) << 6)
+#define   G_0003C2_VGA_HSYNC_POL(x)                    (((x) >> 6) & 0x1)
+#define   C_0003C2_VGA_HSYNC_POL                       0xBF
+#define   S_0003C2_VGA_VSYNC_POL(x)                    (((x) & 0x1) << 7)
+#define   G_0003C2_VGA_VSYNC_POL(x)                    (((x) >> 7) & 0x1)
+#define   C_0003C2_VGA_VSYNC_POL                       0x7F
 #define R_0003F8_CRTC2_GEN_CNTL                      0x0003F8
 #define   S_0003F8_CRTC2_DBL_SCAN_EN(x)                (((x) & 0x1) << 0)
 #define   G_0003F8_CRTC2_DBL_SCAN_EN(x)                (((x) >> 0) & 0x1)
 #define   S_000774_SCRATCH_ADDR(x)                     (((x) & 0x7FFFFFF) << 5)
 #define   G_000774_SCRATCH_ADDR(x)                     (((x) >> 5) & 0x7FFFFFF)
 #define   C_000774_SCRATCH_ADDR                        0x0000001F
+#define R_0007C0_CP_STAT                             0x0007C0
+#define   S_0007C0_MRU_BUSY(x)                         (((x) & 0x1) << 0)
+#define   G_0007C0_MRU_BUSY(x)                         (((x) >> 0) & 0x1)
+#define   C_0007C0_MRU_BUSY                            0xFFFFFFFE
+#define   S_0007C0_MWU_BUSY(x)                         (((x) & 0x1) << 1)
+#define   G_0007C0_MWU_BUSY(x)                         (((x) >> 1) & 0x1)
+#define   C_0007C0_MWU_BUSY                            0xFFFFFFFD
+#define   S_0007C0_RSIU_BUSY(x)                        (((x) & 0x1) << 2)
+#define   G_0007C0_RSIU_BUSY(x)                        (((x) >> 2) & 0x1)
+#define   C_0007C0_RSIU_BUSY                           0xFFFFFFFB
+#define   S_0007C0_RCIU_BUSY(x)                        (((x) & 0x1) << 3)
+#define   G_0007C0_RCIU_BUSY(x)                        (((x) >> 3) & 0x1)
+#define   C_0007C0_RCIU_BUSY                           0xFFFFFFF7
+#define   S_0007C0_CSF_PRIMARY_BUSY(x)                 (((x) & 0x1) << 9)
+#define   G_0007C0_CSF_PRIMARY_BUSY(x)                 (((x) >> 9) & 0x1)
+#define   C_0007C0_CSF_PRIMARY_BUSY                    0xFFFFFDFF
+#define   S_0007C0_CSF_INDIRECT_BUSY(x)                (((x) & 0x1) << 10)
+#define   G_0007C0_CSF_INDIRECT_BUSY(x)                (((x) >> 10) & 0x1)
+#define   C_0007C0_CSF_INDIRECT_BUSY                   0xFFFFFBFF
+#define   S_0007C0_CSQ_PRIMARY_BUSY(x)                 (((x) & 0x1) << 11)
+#define   G_0007C0_CSQ_PRIMARY_BUSY(x)                 (((x) >> 11) & 0x1)
+#define   C_0007C0_CSQ_PRIMARY_BUSY                    0xFFFFF7FF
+#define   S_0007C0_CSQ_INDIRECT_BUSY(x)                (((x) & 0x1) << 12)
+#define   G_0007C0_CSQ_INDIRECT_BUSY(x)                (((x) >> 12) & 0x1)
+#define   C_0007C0_CSQ_INDIRECT_BUSY                   0xFFFFEFFF
+#define   S_0007C0_CSI_BUSY(x)                         (((x) & 0x1) << 13)
+#define   G_0007C0_CSI_BUSY(x)                         (((x) >> 13) & 0x1)
+#define   C_0007C0_CSI_BUSY                            0xFFFFDFFF
+#define   S_0007C0_GUIDMA_BUSY(x)                      (((x) & 0x1) << 28)
+#define   G_0007C0_GUIDMA_BUSY(x)                      (((x) >> 28) & 0x1)
+#define   C_0007C0_GUIDMA_BUSY                         0xEFFFFFFF
+#define   S_0007C0_VIDDMA_BUSY(x)                      (((x) & 0x1) << 29)
+#define   G_0007C0_VIDDMA_BUSY(x)                      (((x) >> 29) & 0x1)
+#define   C_0007C0_VIDDMA_BUSY                         0xDFFFFFFF
+#define   S_0007C0_CMDSTRM_BUSY(x)                     (((x) & 0x1) << 30)
+#define   G_0007C0_CMDSTRM_BUSY(x)                     (((x) >> 30) & 0x1)
+#define   C_0007C0_CMDSTRM_BUSY                        0xBFFFFFFF
+#define   S_0007C0_CP_BUSY(x)                          (((x) & 0x1) << 31)
+#define   G_0007C0_CP_BUSY(x)                          (((x) >> 31) & 0x1)
+#define   C_0007C0_CP_BUSY                             0x7FFFFFFF
 #define R_000E40_RBBM_STATUS                         0x000E40
 #define   S_000E40_CMDFIFO_AVAIL(x)                    (((x) & 0x7F) << 0)
 #define   G_000E40_CMDFIFO_AVAIL(x)                    (((x) >> 0) & 0x7F)
 #define   G_000E40_GUI_ACTIVE(x)                       (((x) >> 31) & 0x1)
 #define   C_000E40_GUI_ACTIVE                          0x7FFFFFFF
 
+
+#define R_00000D_SCLK_CNTL                           0x00000D
+#define   S_00000D_SCLK_SRC_SEL(x)                     (((x) & 0x7) << 0)
+#define   G_00000D_SCLK_SRC_SEL(x)                     (((x) >> 0) & 0x7)
+#define   C_00000D_SCLK_SRC_SEL                        0xFFFFFFF8
+#define   S_00000D_TCLK_SRC_SEL(x)                     (((x) & 0x7) << 8)
+#define   G_00000D_TCLK_SRC_SEL(x)                     (((x) >> 8) & 0x7)
+#define   C_00000D_TCLK_SRC_SEL                        0xFFFFF8FF
+#define   S_00000D_FORCE_CP(x)                         (((x) & 0x1) << 16)
+#define   G_00000D_FORCE_CP(x)                         (((x) >> 16) & 0x1)
+#define   C_00000D_FORCE_CP                            0xFFFEFFFF
+#define   S_00000D_FORCE_HDP(x)                        (((x) & 0x1) << 17)
+#define   G_00000D_FORCE_HDP(x)                        (((x) >> 17) & 0x1)
+#define   C_00000D_FORCE_HDP                           0xFFFDFFFF
+#define   S_00000D_FORCE_DISP(x)                       (((x) & 0x1) << 18)
+#define   G_00000D_FORCE_DISP(x)                       (((x) >> 18) & 0x1)
+#define   C_00000D_FORCE_DISP                          0xFFFBFFFF
+#define   S_00000D_FORCE_TOP(x)                        (((x) & 0x1) << 19)
+#define   G_00000D_FORCE_TOP(x)                        (((x) >> 19) & 0x1)
+#define   C_00000D_FORCE_TOP                           0xFFF7FFFF
+#define   S_00000D_FORCE_E2(x)                         (((x) & 0x1) << 20)
+#define   G_00000D_FORCE_E2(x)                         (((x) >> 20) & 0x1)
+#define   C_00000D_FORCE_E2                            0xFFEFFFFF
+#define   S_00000D_FORCE_SE(x)                         (((x) & 0x1) << 21)
+#define   G_00000D_FORCE_SE(x)                         (((x) >> 21) & 0x1)
+#define   C_00000D_FORCE_SE                            0xFFDFFFFF
+#define   S_00000D_FORCE_IDCT(x)                       (((x) & 0x1) << 22)
+#define   G_00000D_FORCE_IDCT(x)                       (((x) >> 22) & 0x1)
+#define   C_00000D_FORCE_IDCT                          0xFFBFFFFF
+#define   S_00000D_FORCE_VIP(x)                        (((x) & 0x1) << 23)
+#define   G_00000D_FORCE_VIP(x)                        (((x) >> 23) & 0x1)
+#define   C_00000D_FORCE_VIP                           0xFF7FFFFF
+#define   S_00000D_FORCE_RE(x)                         (((x) & 0x1) << 24)
+#define   G_00000D_FORCE_RE(x)                         (((x) >> 24) & 0x1)
+#define   C_00000D_FORCE_RE                            0xFEFFFFFF
+#define   S_00000D_FORCE_PB(x)                         (((x) & 0x1) << 25)
+#define   G_00000D_FORCE_PB(x)                         (((x) >> 25) & 0x1)
+#define   C_00000D_FORCE_PB                            0xFDFFFFFF
+#define   S_00000D_FORCE_TAM(x)                        (((x) & 0x1) << 26)
+#define   G_00000D_FORCE_TAM(x)                        (((x) >> 26) & 0x1)
+#define   C_00000D_FORCE_TAM                           0xFBFFFFFF
+#define   S_00000D_FORCE_TDM(x)                        (((x) & 0x1) << 27)
+#define   G_00000D_FORCE_TDM(x)                        (((x) >> 27) & 0x1)
+#define   C_00000D_FORCE_TDM                           0xF7FFFFFF
+#define   S_00000D_FORCE_RB(x)                         (((x) & 0x1) << 28)
+#define   G_00000D_FORCE_RB(x)                         (((x) >> 28) & 0x1)
+#define   C_00000D_FORCE_RB                            0xEFFFFFFF
+
+
 #endif
index cf7fea5..eb740fc 100644 (file)
@@ -447,9 +447,8 @@ int r200_packet0_check(struct radeon_cs_parser *p,
        return 0;
 }
 
-int r200_init(struct radeon_device *rdev)
+void r200_set_safe_registers(struct radeon_device *rdev)
 {
        rdev->config.r100.reg_safe_bm = r200_reg_safe_bm;
        rdev->config.r100.reg_safe_bm_size = ARRAY_SIZE(r200_reg_safe_bm);
-       return 0;
 }
index 1ebea8c..e08c4a8 100644 (file)
 #include "radeon_drm.h"
 #include "r100_track.h"
 #include "r300d.h"
-
+#include "rv350d.h"
 #include "r300_reg_safe.h"
 
-/* r300,r350,rv350,rv370,rv380 depends on : */
-void r100_hdp_reset(struct radeon_device *rdev);
-int r100_cp_reset(struct radeon_device *rdev);
-int r100_rb2d_reset(struct radeon_device *rdev);
-int r100_cp_init(struct radeon_device *rdev, unsigned ring_size);
-int r100_pci_gart_enable(struct radeon_device *rdev);
-void r100_mc_setup(struct radeon_device *rdev);
-void r100_mc_disable_clients(struct radeon_device *rdev);
-int r100_gui_wait_for_idle(struct radeon_device *rdev);
-int r100_cs_packet_parse(struct radeon_cs_parser *p,
-                        struct radeon_cs_packet *pkt,
-                        unsigned idx);
-int r100_cs_packet_parse_vline(struct radeon_cs_parser *p);
-int r100_cs_parse_packet0(struct radeon_cs_parser *p,
-                         struct radeon_cs_packet *pkt,
-                         const unsigned *auth, unsigned n,
-                         radeon_packet0_check_t check);
-int r100_cs_track_check_pkt3_indx_buffer(struct radeon_cs_parser *p,
-                                        struct radeon_cs_packet *pkt,
-                                        struct radeon_object *robj);
-
-/* This files gather functions specifics to:
- * r300,r350,rv350,rv370,rv380
- *
- * Some of these functions might be used by newer ASICs.
- */
-void r300_gpu_init(struct radeon_device *rdev);
-int r300_mc_wait_for_idle(struct radeon_device *rdev);
-int rv370_debugfs_pcie_gart_info_init(struct radeon_device *rdev);
-
+/* This files gather functions specifics to: r300,r350,rv350,rv370,rv380 */
 
 /*
  * rv370,rv380 PCIE GART
  */
+static int rv370_debugfs_pcie_gart_info_init(struct radeon_device *rdev);
+
 void rv370_pcie_gart_tlb_flush(struct radeon_device *rdev)
 {
        uint32_t tmp;
@@ -182,59 +155,6 @@ void rv370_pcie_gart_fini(struct radeon_device *rdev)
        radeon_gart_fini(rdev);
 }
 
-/*
- * MC
- */
-int r300_mc_init(struct radeon_device *rdev)
-{
-       int r;
-
-       if (r100_debugfs_rbbm_init(rdev)) {
-               DRM_ERROR("Failed to register debugfs file for RBBM !\n");
-       }
-
-       r300_gpu_init(rdev);
-       r100_pci_gart_disable(rdev);
-       if (rdev->flags & RADEON_IS_PCIE) {
-               rv370_pcie_gart_disable(rdev);
-       }
-
-       /* Setup GPU memory space */
-       rdev->mc.vram_location = 0xFFFFFFFFUL;
-       rdev->mc.gtt_location = 0xFFFFFFFFUL;
-       if (rdev->flags & RADEON_IS_AGP) {
-               r = radeon_agp_init(rdev);
-               if (r) {
-                       printk(KERN_WARNING "[drm] Disabling AGP\n");
-                       rdev->flags &= ~RADEON_IS_AGP;
-                       rdev->mc.gtt_size = radeon_gart_size * 1024 * 1024;
-               } else {
-                       rdev->mc.gtt_location = rdev->mc.agp_base;
-               }
-       }
-       r = radeon_mc_setup(rdev);
-       if (r) {
-               return r;
-       }
-
-       /* Program GPU memory space */
-       r100_mc_disable_clients(rdev);
-       if (r300_mc_wait_for_idle(rdev)) {
-               printk(KERN_WARNING "Failed to wait MC idle while "
-                      "programming pipes. Bad things might happen.\n");
-       }
-       r100_mc_setup(rdev);
-       return 0;
-}
-
-void r300_mc_fini(struct radeon_device *rdev)
-{
-}
-
-
-/*
- * Fence emission
- */
 void r300_fence_ring_emit(struct radeon_device *rdev,
                          struct radeon_fence *fence)
 {
@@ -260,10 +180,6 @@ void r300_fence_ring_emit(struct radeon_device *rdev,
        radeon_ring_write(rdev, RADEON_SW_INT_FIRE);
 }
 
-
-/*
- * Global GPU functions
- */
 int r300_copy_dma(struct radeon_device *rdev,
                  uint64_t src_offset,
                  uint64_t dst_offset,
@@ -582,11 +498,6 @@ void r300_vram_info(struct radeon_device *rdev)
        r100_vram_init_sizes(rdev);
 }
 
-
-/*
- * PCIE Lanes
- */
-
 void rv370_set_pcie_lanes(struct radeon_device *rdev, int lanes)
 {
        uint32_t link_width_cntl, mask;
@@ -646,10 +557,6 @@ void rv370_set_pcie_lanes(struct radeon_device *rdev, int lanes)
 
 }
 
-
-/*
- * Debugfs info
- */
 #if defined(CONFIG_DEBUG_FS)
 static int rv370_debugfs_pcie_gart_info(struct seq_file *m, void *data)
 {
@@ -680,7 +587,7 @@ static struct drm_info_list rv370_pcie_gart_info_list[] = {
 };
 #endif
 
-int rv370_debugfs_pcie_gart_info_init(struct radeon_device *rdev)
+static int rv370_debugfs_pcie_gart_info_init(struct radeon_device *rdev)
 {
 #if defined(CONFIG_DEBUG_FS)
        return radeon_debugfs_add_files(rdev, rv370_pcie_gart_info_list, 1);
@@ -689,10 +596,6 @@ int rv370_debugfs_pcie_gart_info_init(struct radeon_device *rdev)
 #endif
 }
 
-
-/*
- * CS functions
- */
 static int r300_packet0_check(struct radeon_cs_parser *p,
                struct radeon_cs_packet *pkt,
                unsigned idx, unsigned reg)
@@ -1226,12 +1129,6 @@ void r300_set_reg_safe(struct radeon_device *rdev)
        rdev->config.r300.reg_safe_bm_size = ARRAY_SIZE(r300_reg_safe_bm);
 }
 
-int r300_init(struct radeon_device *rdev)
-{
-       r300_set_reg_safe(rdev);
-       return 0;
-}
-
 void r300_mc_program(struct radeon_device *rdev)
 {
        struct r100_mc_save save;
@@ -1265,3 +1162,198 @@ void r300_mc_program(struct radeon_device *rdev)
                S_000148_MC_FB_TOP(rdev->mc.vram_end >> 16));
        r100_mc_resume(rdev, &save);
 }
+
+void r300_clock_startup(struct radeon_device *rdev)
+{
+       u32 tmp;
+
+       if (radeon_dynclks != -1 && radeon_dynclks)
+               radeon_legacy_set_clock_gating(rdev, 1);
+       /* We need to force on some of the block */
+       tmp = RREG32_PLL(R_00000D_SCLK_CNTL);
+       tmp |= S_00000D_FORCE_CP(1) | S_00000D_FORCE_VIP(1);
+       if ((rdev->family == CHIP_RV350) || (rdev->family == CHIP_RV380))
+               tmp |= S_00000D_FORCE_VAP(1);
+       WREG32_PLL(R_00000D_SCLK_CNTL, tmp);
+}
+
+static int r300_startup(struct radeon_device *rdev)
+{
+       int r;
+
+       r300_mc_program(rdev);
+       /* Resume clock */
+       r300_clock_startup(rdev);
+       /* Initialize GPU configuration (# pipes, ...) */
+       r300_gpu_init(rdev);
+       /* Initialize GART (initialize after TTM so we can allocate
+        * memory through TTM but finalize after TTM) */
+       if (rdev->flags & RADEON_IS_PCIE) {
+               r = rv370_pcie_gart_enable(rdev);
+               if (r)
+                       return r;
+       }
+       if (rdev->flags & RADEON_IS_PCI) {
+               r = r100_pci_gart_enable(rdev);
+               if (r)
+                       return r;
+       }
+       /* Enable IRQ */
+       rdev->irq.sw_int = true;
+       r100_irq_set(rdev);
+       /* 1M ring buffer */
+       r = r100_cp_init(rdev, 1024 * 1024);
+       if (r) {
+               dev_err(rdev->dev, "failled initializing CP (%d).\n", r);
+               return r;
+       }
+       r = r100_wb_init(rdev);
+       if (r)
+               dev_err(rdev->dev, "failled initializing WB (%d).\n", r);
+       r = r100_ib_init(rdev);
+       if (r) {
+               dev_err(rdev->dev, "failled initializing IB (%d).\n", r);
+               return r;
+       }
+       return 0;
+}
+
+int r300_resume(struct radeon_device *rdev)
+{
+       /* Make sur GART are not working */
+       if (rdev->flags & RADEON_IS_PCIE)
+               rv370_pcie_gart_disable(rdev);
+       if (rdev->flags & RADEON_IS_PCI)
+               r100_pci_gart_disable(rdev);
+       /* Resume clock before doing reset */
+       r300_clock_startup(rdev);
+       /* Reset gpu before posting otherwise ATOM will enter infinite loop */
+       if (radeon_gpu_reset(rdev)) {
+               dev_warn(rdev->dev, "GPU reset failed ! (0xE40=0x%08X, 0x7C0=0x%08X)\n",
+                       RREG32(R_000E40_RBBM_STATUS),
+                       RREG32(R_0007C0_CP_STAT));
+       }
+       /* post */
+       radeon_combios_asic_init(rdev->ddev);
+       /* Resume clock after posting */
+       r300_clock_startup(rdev);
+       return r300_startup(rdev);
+}
+
+int r300_suspend(struct radeon_device *rdev)
+{
+       r100_cp_disable(rdev);
+       r100_wb_disable(rdev);
+       r100_irq_disable(rdev);
+       if (rdev->flags & RADEON_IS_PCIE)
+               rv370_pcie_gart_disable(rdev);
+       if (rdev->flags & RADEON_IS_PCI)
+               r100_pci_gart_disable(rdev);
+       return 0;
+}
+
+void r300_fini(struct radeon_device *rdev)
+{
+       r300_suspend(rdev);
+       r100_cp_fini(rdev);
+       r100_wb_fini(rdev);
+       r100_ib_fini(rdev);
+       radeon_gem_fini(rdev);
+       if (rdev->flags & RADEON_IS_PCIE)
+               rv370_pcie_gart_fini(rdev);
+       if (rdev->flags & RADEON_IS_PCI)
+               r100_pci_gart_fini(rdev);
+       radeon_irq_kms_fini(rdev);
+       radeon_fence_driver_fini(rdev);
+       radeon_object_fini(rdev);
+       radeon_atombios_fini(rdev);
+       kfree(rdev->bios);
+       rdev->bios = NULL;
+}
+
+int r300_init(struct radeon_device *rdev)
+{
+       int r;
+
+       /* Disable VGA */
+       r100_vga_render_disable(rdev);
+       /* Initialize scratch registers */
+       radeon_scratch_init(rdev);
+       /* Initialize surface registers */
+       radeon_surface_init(rdev);
+       /* TODO: disable VGA need to use VGA request */
+       /* BIOS*/
+       if (!radeon_get_bios(rdev)) {
+               if (ASIC_IS_AVIVO(rdev))
+                       return -EINVAL;
+       }
+       if (rdev->is_atom_bios) {
+               dev_err(rdev->dev, "Expecting combios for RS400/RS480 GPU\n");
+               return -EINVAL;
+       } else {
+               r = radeon_combios_init(rdev);
+               if (r)
+                       return r;
+       }
+       /* Reset gpu before posting otherwise ATOM will enter infinite loop */
+       if (radeon_gpu_reset(rdev)) {
+               dev_warn(rdev->dev,
+                       "GPU reset failed ! (0xE40=0x%08X, 0x7C0=0x%08X)\n",
+                       RREG32(R_000E40_RBBM_STATUS),
+                       RREG32(R_0007C0_CP_STAT));
+       }
+       /* check if cards are posted or not */
+       if (!radeon_card_posted(rdev) && rdev->bios) {
+               DRM_INFO("GPU not posted. posting now...\n");
+               radeon_combios_asic_init(rdev->ddev);
+       }
+       /* Set asic errata */
+       r300_errata(rdev);
+       /* Initialize clocks */
+       radeon_get_clock_info(rdev->ddev);
+       /* Get vram informations */
+       r300_vram_info(rdev);
+       /* Initialize memory controller (also test AGP) */
+       r = r420_mc_init(rdev);
+       if (r)
+               return r;
+       /* Fence driver */
+       r = radeon_fence_driver_init(rdev);
+       if (r)
+               return r;
+       r = radeon_irq_kms_init(rdev);
+       if (r)
+               return r;
+       /* Memory manager */
+       r = radeon_object_init(rdev);
+       if (r)
+               return r;
+       if (rdev->flags & RADEON_IS_PCIE) {
+               r = rv370_pcie_gart_init(rdev);
+               if (r)
+                       return r;
+       }
+       if (rdev->flags & RADEON_IS_PCI) {
+               r = r100_pci_gart_init(rdev);
+               if (r)
+                       return r;
+       }
+       r300_set_reg_safe(rdev);
+       rdev->accel_working = true;
+       r = r300_startup(rdev);
+       if (r) {
+               /* Somethings want wront with the accel init stop accel */
+               dev_err(rdev->dev, "Disabling GPU acceleration\n");
+               r300_suspend(rdev);
+               r100_cp_fini(rdev);
+               r100_wb_fini(rdev);
+               r100_ib_fini(rdev);
+               if (rdev->flags & RADEON_IS_PCIE)
+                       rv370_pcie_gart_fini(rdev);
+               if (rdev->flags & RADEON_IS_PCI)
+                       r100_pci_gart_fini(rdev);
+               radeon_irq_kms_fini(rdev);
+               rdev->accel_working = false;
+       }
+       return 0;
+}
index d4fa3eb..4c73114 100644 (file)
 #define   S_000170_AGP_BASE_ADDR(x)                    (((x) & 0xFFFFFFFF) << 0)
 #define   G_000170_AGP_BASE_ADDR(x)                    (((x) >> 0) & 0xFFFFFFFF)
 #define   C_000170_AGP_BASE_ADDR                       0x00000000
+#define R_0007C0_CP_STAT                             0x0007C0
+#define   S_0007C0_MRU_BUSY(x)                         (((x) & 0x1) << 0)
+#define   G_0007C0_MRU_BUSY(x)                         (((x) >> 0) & 0x1)
+#define   C_0007C0_MRU_BUSY                            0xFFFFFFFE
+#define   S_0007C0_MWU_BUSY(x)                         (((x) & 0x1) << 1)
+#define   G_0007C0_MWU_BUSY(x)                         (((x) >> 1) & 0x1)
+#define   C_0007C0_MWU_BUSY                            0xFFFFFFFD
+#define   S_0007C0_RSIU_BUSY(x)                        (((x) & 0x1) << 2)
+#define   G_0007C0_RSIU_BUSY(x)                        (((x) >> 2) & 0x1)
+#define   C_0007C0_RSIU_BUSY                           0xFFFFFFFB
+#define   S_0007C0_RCIU_BUSY(x)                        (((x) & 0x1) << 3)
+#define   G_0007C0_RCIU_BUSY(x)                        (((x) >> 3) & 0x1)
+#define   C_0007C0_RCIU_BUSY                           0xFFFFFFF7
+#define   S_0007C0_CSF_PRIMARY_BUSY(x)                 (((x) & 0x1) << 9)
+#define   G_0007C0_CSF_PRIMARY_BUSY(x)                 (((x) >> 9) & 0x1)
+#define   C_0007C0_CSF_PRIMARY_BUSY                    0xFFFFFDFF
+#define   S_0007C0_CSF_INDIRECT_BUSY(x)                (((x) & 0x1) << 10)
+#define   G_0007C0_CSF_INDIRECT_BUSY(x)                (((x) >> 10) & 0x1)
+#define   C_0007C0_CSF_INDIRECT_BUSY                   0xFFFFFBFF
+#define   S_0007C0_CSQ_PRIMARY_BUSY(x)                 (((x) & 0x1) << 11)
+#define   G_0007C0_CSQ_PRIMARY_BUSY(x)                 (((x) >> 11) & 0x1)
+#define   C_0007C0_CSQ_PRIMARY_BUSY                    0xFFFFF7FF
+#define   S_0007C0_CSQ_INDIRECT_BUSY(x)                (((x) & 0x1) << 12)
+#define   G_0007C0_CSQ_INDIRECT_BUSY(x)                (((x) >> 12) & 0x1)
+#define   C_0007C0_CSQ_INDIRECT_BUSY                   0xFFFFEFFF
+#define   S_0007C0_CSI_BUSY(x)                         (((x) & 0x1) << 13)
+#define   G_0007C0_CSI_BUSY(x)                         (((x) >> 13) & 0x1)
+#define   C_0007C0_CSI_BUSY                            0xFFFFDFFF
+#define   S_0007C0_CSF_INDIRECT2_BUSY(x)               (((x) & 0x1) << 14)
+#define   G_0007C0_CSF_INDIRECT2_BUSY(x)               (((x) >> 14) & 0x1)
+#define   C_0007C0_CSF_INDIRECT2_BUSY                  0xFFFFBFFF
+#define   S_0007C0_CSQ_INDIRECT2_BUSY(x)               (((x) & 0x1) << 15)
+#define   G_0007C0_CSQ_INDIRECT2_BUSY(x)               (((x) >> 15) & 0x1)
+#define   C_0007C0_CSQ_INDIRECT2_BUSY                  0xFFFF7FFF
+#define   S_0007C0_GUIDMA_BUSY(x)                      (((x) & 0x1) << 28)
+#define   G_0007C0_GUIDMA_BUSY(x)                      (((x) >> 28) & 0x1)
+#define   C_0007C0_GUIDMA_BUSY                         0xEFFFFFFF
+#define   S_0007C0_VIDDMA_BUSY(x)                      (((x) & 0x1) << 29)
+#define   G_0007C0_VIDDMA_BUSY(x)                      (((x) >> 29) & 0x1)
+#define   C_0007C0_VIDDMA_BUSY                         0xDFFFFFFF
+#define   S_0007C0_CMDSTRM_BUSY(x)                     (((x) & 0x1) << 30)
+#define   G_0007C0_CMDSTRM_BUSY(x)                     (((x) >> 30) & 0x1)
+#define   C_0007C0_CMDSTRM_BUSY                        0xBFFFFFFF
+#define   S_0007C0_CP_BUSY(x)                          (((x) & 0x1) << 31)
+#define   G_0007C0_CP_BUSY(x)                          (((x) >> 31) & 0x1)
+#define   C_0007C0_CP_BUSY                             0x7FFFFFFF
+#define R_000E40_RBBM_STATUS                         0x000E40
+#define   S_000E40_CMDFIFO_AVAIL(x)                    (((x) & 0x7F) << 0)
+#define   G_000E40_CMDFIFO_AVAIL(x)                    (((x) >> 0) & 0x7F)
+#define   C_000E40_CMDFIFO_AVAIL                       0xFFFFFF80
+#define   S_000E40_HIRQ_ON_RBB(x)                      (((x) & 0x1) << 8)
+#define   G_000E40_HIRQ_ON_RBB(x)                      (((x) >> 8) & 0x1)
+#define   C_000E40_HIRQ_ON_RBB                         0xFFFFFEFF
+#define   S_000E40_CPRQ_ON_RBB(x)                      (((x) & 0x1) << 9)
+#define   G_000E40_CPRQ_ON_RBB(x)                      (((x) >> 9) & 0x1)
+#define   C_000E40_CPRQ_ON_RBB                         0xFFFFFDFF
+#define   S_000E40_CFRQ_ON_RBB(x)                      (((x) & 0x1) << 10)
+#define   G_000E40_CFRQ_ON_RBB(x)                      (((x) >> 10) & 0x1)
+#define   C_000E40_CFRQ_ON_RBB                         0xFFFFFBFF
+#define   S_000E40_HIRQ_IN_RTBUF(x)                    (((x) & 0x1) << 11)
+#define   G_000E40_HIRQ_IN_RTBUF(x)                    (((x) >> 11) & 0x1)
+#define   C_000E40_HIRQ_IN_RTBUF                       0xFFFFF7FF
+#define   S_000E40_CPRQ_IN_RTBUF(x)                    (((x) & 0x1) << 12)
+#define   G_000E40_CPRQ_IN_RTBUF(x)                    (((x) >> 12) & 0x1)
+#define   C_000E40_CPRQ_IN_RTBUF                       0xFFFFEFFF
+#define   S_000E40_CFRQ_IN_RTBUF(x)                    (((x) & 0x1) << 13)
+#define   G_000E40_CFRQ_IN_RTBUF(x)                    (((x) >> 13) & 0x1)
+#define   C_000E40_CFRQ_IN_RTBUF                       0xFFFFDFFF
+#define   S_000E40_CF_PIPE_BUSY(x)                     (((x) & 0x1) << 14)
+#define   G_000E40_CF_PIPE_BUSY(x)                     (((x) >> 14) & 0x1)
+#define   C_000E40_CF_PIPE_BUSY                        0xFFFFBFFF
+#define   S_000E40_ENG_EV_BUSY(x)                      (((x) & 0x1) << 15)
+#define   G_000E40_ENG_EV_BUSY(x)                      (((x) >> 15) & 0x1)
+#define   C_000E40_ENG_EV_BUSY                         0xFFFF7FFF
+#define   S_000E40_CP_CMDSTRM_BUSY(x)                  (((x) & 0x1) << 16)
+#define   G_000E40_CP_CMDSTRM_BUSY(x)                  (((x) >> 16) & 0x1)
+#define   C_000E40_CP_CMDSTRM_BUSY                     0xFFFEFFFF
+#define   S_000E40_E2_BUSY(x)                          (((x) & 0x1) << 17)
+#define   G_000E40_E2_BUSY(x)                          (((x) >> 17) & 0x1)
+#define   C_000E40_E2_BUSY                             0xFFFDFFFF
+#define   S_000E40_RB2D_BUSY(x)                        (((x) & 0x1) << 18)
+#define   G_000E40_RB2D_BUSY(x)                        (((x) >> 18) & 0x1)
+#define   C_000E40_RB2D_BUSY                           0xFFFBFFFF
+#define   S_000E40_RB3D_BUSY(x)                        (((x) & 0x1) << 19)
+#define   G_000E40_RB3D_BUSY(x)                        (((x) >> 19) & 0x1)
+#define   C_000E40_RB3D_BUSY                           0xFFF7FFFF
+#define   S_000E40_VAP_BUSY(x)                         (((x) & 0x1) << 20)
+#define   G_000E40_VAP_BUSY(x)                         (((x) >> 20) & 0x1)
+#define   C_000E40_VAP_BUSY                            0xFFEFFFFF
+#define   S_000E40_RE_BUSY(x)                          (((x) & 0x1) << 21)
+#define   G_000E40_RE_BUSY(x)                          (((x) >> 21) & 0x1)
+#define   C_000E40_RE_BUSY                             0xFFDFFFFF
+#define   S_000E40_TAM_BUSY(x)                         (((x) & 0x1) << 22)
+#define   G_000E40_TAM_BUSY(x)                         (((x) >> 22) & 0x1)
+#define   C_000E40_TAM_BUSY                            0xFFBFFFFF
+#define   S_000E40_TDM_BUSY(x)                         (((x) & 0x1) << 23)
+#define   G_000E40_TDM_BUSY(x)                         (((x) >> 23) & 0x1)
+#define   C_000E40_TDM_BUSY                            0xFF7FFFFF
+#define   S_000E40_PB_BUSY(x)                          (((x) & 0x1) << 24)
+#define   G_000E40_PB_BUSY(x)                          (((x) >> 24) & 0x1)
+#define   C_000E40_PB_BUSY                             0xFEFFFFFF
+#define   S_000E40_TIM_BUSY(x)                         (((x) & 0x1) << 25)
+#define   G_000E40_TIM_BUSY(x)                         (((x) >> 25) & 0x1)
+#define   C_000E40_TIM_BUSY                            0xFDFFFFFF
+#define   S_000E40_GA_BUSY(x)                          (((x) & 0x1) << 26)
+#define   G_000E40_GA_BUSY(x)                          (((x) >> 26) & 0x1)
+#define   C_000E40_GA_BUSY                             0xFBFFFFFF
+#define   S_000E40_CBA2D_BUSY(x)                       (((x) & 0x1) << 27)
+#define   G_000E40_CBA2D_BUSY(x)                       (((x) >> 27) & 0x1)
+#define   C_000E40_CBA2D_BUSY                          0xF7FFFFFF
+#define   S_000E40_GUI_ACTIVE(x)                       (((x) & 0x1) << 31)
+#define   G_000E40_GUI_ACTIVE(x)                       (((x) >> 31) & 0x1)
+#define   C_000E40_GUI_ACTIVE                          0x7FFFFFFF
 
 
+#define R_00000D_SCLK_CNTL                           0x00000D
+#define   S_00000D_SCLK_SRC_SEL(x)                     (((x) & 0x7) << 0)
+#define   G_00000D_SCLK_SRC_SEL(x)                     (((x) >> 0) & 0x7)
+#define   C_00000D_SCLK_SRC_SEL                        0xFFFFFFF8
+#define   S_00000D_CP_MAX_DYN_STOP_LAT(x)              (((x) & 0x1) << 3)
+#define   G_00000D_CP_MAX_DYN_STOP_LAT(x)              (((x) >> 3) & 0x1)
+#define   C_00000D_CP_MAX_DYN_STOP_LAT                 0xFFFFFFF7
+#define   S_00000D_HDP_MAX_DYN_STOP_LAT(x)             (((x) & 0x1) << 4)
+#define   G_00000D_HDP_MAX_DYN_STOP_LAT(x)             (((x) >> 4) & 0x1)
+#define   C_00000D_HDP_MAX_DYN_STOP_LAT                0xFFFFFFEF
+#define   S_00000D_TV_MAX_DYN_STOP_LAT(x)              (((x) & 0x1) << 5)
+#define   G_00000D_TV_MAX_DYN_STOP_LAT(x)              (((x) >> 5) & 0x1)
+#define   C_00000D_TV_MAX_DYN_STOP_LAT                 0xFFFFFFDF
+#define   S_00000D_E2_MAX_DYN_STOP_LAT(x)              (((x) & 0x1) << 6)
+#define   G_00000D_E2_MAX_DYN_STOP_LAT(x)              (((x) >> 6) & 0x1)
+#define   C_00000D_E2_MAX_DYN_STOP_LAT                 0xFFFFFFBF
+#define   S_00000D_SE_MAX_DYN_STOP_LAT(x)              (((x) & 0x1) << 7)
+#define   G_00000D_SE_MAX_DYN_STOP_LAT(x)              (((x) >> 7) & 0x1)
+#define   C_00000D_SE_MAX_DYN_STOP_LAT                 0xFFFFFF7F
+#define   S_00000D_IDCT_MAX_DYN_STOP_LAT(x)            (((x) & 0x1) << 8)
+#define   G_00000D_IDCT_MAX_DYN_STOP_LAT(x)            (((x) >> 8) & 0x1)
+#define   C_00000D_IDCT_MAX_DYN_STOP_LAT               0xFFFFFEFF
+#define   S_00000D_VIP_MAX_DYN_STOP_LAT(x)             (((x) & 0x1) << 9)
+#define   G_00000D_VIP_MAX_DYN_STOP_LAT(x)             (((x) >> 9) & 0x1)
+#define   C_00000D_VIP_MAX_DYN_STOP_LAT                0xFFFFFDFF
+#define   S_00000D_RE_MAX_DYN_STOP_LAT(x)              (((x) & 0x1) << 10)
+#define   G_00000D_RE_MAX_DYN_STOP_LAT(x)              (((x) >> 10) & 0x1)
+#define   C_00000D_RE_MAX_DYN_STOP_LAT                 0xFFFFFBFF
+#define   S_00000D_PB_MAX_DYN_STOP_LAT(x)              (((x) & 0x1) << 11)
+#define   G_00000D_PB_MAX_DYN_STOP_LAT(x)              (((x) >> 11) & 0x1)
+#define   C_00000D_PB_MAX_DYN_STOP_LAT                 0xFFFFF7FF
+#define   S_00000D_TAM_MAX_DYN_STOP_LAT(x)             (((x) & 0x1) << 12)
+#define   G_00000D_TAM_MAX_DYN_STOP_LAT(x)             (((x) >> 12) & 0x1)
+#define   C_00000D_TAM_MAX_DYN_STOP_LAT                0xFFFFEFFF
+#define   S_00000D_TDM_MAX_DYN_STOP_LAT(x)             (((x) & 0x1) << 13)
+#define   G_00000D_TDM_MAX_DYN_STOP_LAT(x)             (((x) >> 13) & 0x1)
+#define   C_00000D_TDM_MAX_DYN_STOP_LAT                0xFFFFDFFF
+#define   S_00000D_RB_MAX_DYN_STOP_LAT(x)              (((x) & 0x1) << 14)
+#define   G_00000D_RB_MAX_DYN_STOP_LAT(x)              (((x) >> 14) & 0x1)
+#define   C_00000D_RB_MAX_DYN_STOP_LAT                 0xFFFFBFFF
+#define   S_00000D_FORCE_DISP2(x)                      (((x) & 0x1) << 15)
+#define   G_00000D_FORCE_DISP2(x)                      (((x) >> 15) & 0x1)
+#define   C_00000D_FORCE_DISP2                         0xFFFF7FFF
+#define   S_00000D_FORCE_CP(x)                         (((x) & 0x1) << 16)
+#define   G_00000D_FORCE_CP(x)                         (((x) >> 16) & 0x1)
+#define   C_00000D_FORCE_CP                            0xFFFEFFFF
+#define   S_00000D_FORCE_HDP(x)                        (((x) & 0x1) << 17)
+#define   G_00000D_FORCE_HDP(x)                        (((x) >> 17) & 0x1)
+#define   C_00000D_FORCE_HDP                           0xFFFDFFFF
+#define   S_00000D_FORCE_DISP1(x)                      (((x) & 0x1) << 18)
+#define   G_00000D_FORCE_DISP1(x)                      (((x) >> 18) & 0x1)
+#define   C_00000D_FORCE_DISP1                         0xFFFBFFFF
+#define   S_00000D_FORCE_TOP(x)                        (((x) & 0x1) << 19)
+#define   G_00000D_FORCE_TOP(x)                        (((x) >> 19) & 0x1)
+#define   C_00000D_FORCE_TOP                           0xFFF7FFFF
+#define   S_00000D_FORCE_E2(x)                         (((x) & 0x1) << 20)
+#define   G_00000D_FORCE_E2(x)                         (((x) >> 20) & 0x1)
+#define   C_00000D_FORCE_E2                            0xFFEFFFFF
+#define   S_00000D_FORCE_SE(x)                         (((x) & 0x1) << 21)
+#define   G_00000D_FORCE_SE(x)                         (((x) >> 21) & 0x1)
+#define   C_00000D_FORCE_SE                            0xFFDFFFFF
+#define   S_00000D_FORCE_IDCT(x)                       (((x) & 0x1) << 22)
+#define   G_00000D_FORCE_IDCT(x)                       (((x) >> 22) & 0x1)
+#define   C_00000D_FORCE_IDCT                          0xFFBFFFFF
+#define   S_00000D_FORCE_VIP(x)                        (((x) & 0x1) << 23)
+#define   G_00000D_FORCE_VIP(x)                        (((x) >> 23) & 0x1)
+#define   C_00000D_FORCE_VIP                           0xFF7FFFFF
+#define   S_00000D_FORCE_RE(x)                         (((x) & 0x1) << 24)
+#define   G_00000D_FORCE_RE(x)                         (((x) >> 24) & 0x1)
+#define   C_00000D_FORCE_RE                            0xFEFFFFFF
+#define   S_00000D_FORCE_PB(x)                         (((x) & 0x1) << 25)
+#define   G_00000D_FORCE_PB(x)                         (((x) >> 25) & 0x1)
+#define   C_00000D_FORCE_PB                            0xFDFFFFFF
+#define   S_00000D_FORCE_TAM(x)                        (((x) & 0x1) << 26)
+#define   G_00000D_FORCE_TAM(x)                        (((x) >> 26) & 0x1)
+#define   C_00000D_FORCE_TAM                           0xFBFFFFFF
+#define   S_00000D_FORCE_TDM(x)                        (((x) & 0x1) << 27)
+#define   G_00000D_FORCE_TDM(x)                        (((x) >> 27) & 0x1)
+#define   C_00000D_FORCE_TDM                           0xF7FFFFFF
+#define   S_00000D_FORCE_RB(x)                         (((x) & 0x1) << 28)
+#define   G_00000D_FORCE_RB(x)                         (((x) >> 28) & 0x1)
+#define   C_00000D_FORCE_RB                            0xEFFFFFFF
+#define   S_00000D_FORCE_TV_SCLK(x)                    (((x) & 0x1) << 29)
+#define   G_00000D_FORCE_TV_SCLK(x)                    (((x) >> 29) & 0x1)
+#define   C_00000D_FORCE_TV_SCLK                       0xDFFFFFFF
+#define   S_00000D_FORCE_SUBPIC(x)                     (((x) & 0x1) << 30)
+#define   G_00000D_FORCE_SUBPIC(x)                     (((x) >> 30) & 0x1)
+#define   C_00000D_FORCE_SUBPIC                        0xBFFFFFFF
+#define   S_00000D_FORCE_OV0(x)                        (((x) & 0x1) << 31)
+#define   G_00000D_FORCE_OV0(x)                        (((x) >> 31) & 0x1)
+#define   C_00000D_FORCE_OV0                           0x7FFFFFFF
+
 #endif
index 49a2fdc..5c7fe52 100644 (file)
@@ -155,6 +155,9 @@ static void r420_debugfs(struct radeon_device *rdev)
 static void r420_clock_resume(struct radeon_device *rdev)
 {
        u32 sclk_cntl;
+
+       if (radeon_dynclks != -1 && radeon_dynclks)
+               radeon_atom_set_clock_gating(rdev, 1);
        sclk_cntl = RREG32_PLL(R_00000D_SCLK_CNTL);
        sclk_cntl |= S_00000D_FORCE_CP(1) | S_00000D_FORCE_VIP(1);
        if (rdev->family == CHIP_R420)
@@ -167,6 +170,8 @@ static int r420_startup(struct radeon_device *rdev)
        int r;
 
        r300_mc_program(rdev);
+       /* Resume clock */
+       r420_clock_resume(rdev);
        /* Initialize GART (initialize after TTM so we can allocate
         * memory through TTM but finalize after TTM) */
        if (rdev->flags & RADEON_IS_PCIE) {
@@ -267,7 +272,6 @@ int r420_init(struct radeon_device *rdev)
 {
        int r;
 
-       rdev->new_init_path = true;
        /* Initialize scratch registers */
        radeon_scratch_init(rdev);
        /* Initialize surface registers */
index a48a7db..fc78d31 100644 (file)
 #define   S_00000D_FORCE_E2(x)                         (((x) & 0x1) << 20)
 #define   G_00000D_FORCE_E2(x)                         (((x) >> 20) & 0x1)
 #define   C_00000D_FORCE_E2                            0xFFEFFFFF
-#define   S_00000D_FORCE_SE(x)                         (((x) & 0x1) << 21)
-#define   G_00000D_FORCE_SE(x)                         (((x) >> 21) & 0x1)
-#define   C_00000D_FORCE_SE                            0xFFDFFFFF
+#define   S_00000D_FORCE_VAP(x)                        (((x) & 0x1) << 21)
+#define   G_00000D_FORCE_VAP(x)                        (((x) >> 21) & 0x1)
+#define   C_00000D_FORCE_VAP                           0xFFDFFFFF
 #define   S_00000D_FORCE_IDCT(x)                       (((x) & 0x1) << 22)
 #define   G_00000D_FORCE_IDCT(x)                       (((x) >> 22) & 0x1)
 #define   C_00000D_FORCE_IDCT                          0xFFBFFFFF
 #define   S_00000D_FORCE_RE(x)                         (((x) & 0x1) << 24)
 #define   G_00000D_FORCE_RE(x)                         (((x) >> 24) & 0x1)
 #define   C_00000D_FORCE_RE                            0xFEFFFFFF
-#define   S_00000D_FORCE_PB(x)                         (((x) & 0x1) << 25)
-#define   G_00000D_FORCE_PB(x)                         (((x) >> 25) & 0x1)
-#define   C_00000D_FORCE_PB                            0xFDFFFFFF
+#define   S_00000D_FORCE_SR(x)                         (((x) & 0x1) << 25)
+#define   G_00000D_FORCE_SR(x)                         (((x) >> 25) & 0x1)
+#define   C_00000D_FORCE_SR                            0xFDFFFFFF
 #define   S_00000D_FORCE_PX(x)                         (((x) & 0x1) << 26)
 #define   G_00000D_FORCE_PX(x)                         (((x) >> 26) & 0x1)
 #define   C_00000D_FORCE_PX                            0xFBFFFFFF
 #define   S_00000D_FORCE_TX(x)                         (((x) & 0x1) << 27)
 #define   G_00000D_FORCE_TX(x)                         (((x) >> 27) & 0x1)
 #define   C_00000D_FORCE_TX                            0xF7FFFFFF
-#define   S_00000D_FORCE_RB(x)                         (((x) & 0x1) << 28)
-#define   G_00000D_FORCE_RB(x)                         (((x) >> 28) & 0x1)
-#define   C_00000D_FORCE_RB                            0xEFFFFFFF
+#define   S_00000D_FORCE_US(x)                         (((x) & 0x1) << 28)
+#define   G_00000D_FORCE_US(x)                         (((x) >> 28) & 0x1)
+#define   C_00000D_FORCE_US                            0xEFFFFFFF
 #define   S_00000D_FORCE_TV_SCLK(x)                    (((x) & 0x1) << 29)
 #define   G_00000D_FORCE_TV_SCLK(x)                    (((x) >> 29) & 0x1)
 #define   C_00000D_FORCE_TV_SCLK                       0xDFFFFFFF
-#define   S_00000D_FORCE_SUBPIC(x)                     (((x) & 0x1) << 30)
-#define   G_00000D_FORCE_SUBPIC(x)                     (((x) >> 30) & 0x1)
-#define   C_00000D_FORCE_SUBPIC                        0xBFFFFFFF
+#define   S_00000D_FORCE_SU(x)                         (((x) & 0x1) << 30)
+#define   G_00000D_FORCE_SU(x)                         (((x) >> 30) & 0x1)
+#define   C_00000D_FORCE_SU                            0xBFFFFFFF
 #define   S_00000D_FORCE_OV0(x)                        (((x) & 0x1) << 31)
 #define   G_00000D_FORCE_OV0(x)                        (((x) >> 31) & 0x1)
 #define   C_00000D_FORCE_OV0                           0x7FFFFFFF
index 0bf13fc..a555b7b 100644 (file)
@@ -186,7 +186,7 @@ static int r520_startup(struct radeon_device *rdev)
        }
        /* Enable IRQ */
        rdev->irq.sw_int = true;
-       r100_irq_set(rdev);
+       rs600_irq_set(rdev);
        /* 1M ring buffer */
        r = r100_cp_init(rdev, 1024 * 1024);
        if (r) {
@@ -228,7 +228,6 @@ int r520_init(struct radeon_device *rdev)
 {
        int r;
 
-       rdev->new_init_path = true;
        /* Initialize scratch registers */
        radeon_scratch_init(rdev);
        /* Initialize surface registers */
index 2e4e60e..6097194 100644 (file)
@@ -65,16 +65,11 @@ MODULE_FIRMWARE("radeon/RV710_me.bin");
 
 int r600_debugfs_mc_info_init(struct radeon_device *rdev);
 
-/* This files gather functions specifics to:
- * r600,rv610,rv630,rv620,rv635,rv670
- *
- * Some of these functions might be used by newer ASICs.
- */
+/* r600,rv610,rv630,rv620,rv635,rv670 */
 int r600_mc_wait_for_idle(struct radeon_device *rdev);
 void r600_gpu_init(struct radeon_device *rdev);
 void r600_fini(struct radeon_device *rdev);
 
-
 /*
  * R600 PCIE GART
  */
@@ -168,7 +163,7 @@ int r600_pcie_gart_enable(struct radeon_device *rdev)
        WREG32(MC_VM_L1_TLB_MCB_RD_SEM_CNTL, tmp | ENABLE_SEMAPHORE_MODE);
        WREG32(MC_VM_L1_TLB_MCB_WR_SEM_CNTL, tmp | ENABLE_SEMAPHORE_MODE);
        WREG32(VM_CONTEXT0_PAGE_TABLE_START_ADDR, rdev->mc.gtt_start >> 12);
-       WREG32(VM_CONTEXT0_PAGE_TABLE_END_ADDR, (rdev->mc.gtt_end - 1) >> 12);
+       WREG32(VM_CONTEXT0_PAGE_TABLE_END_ADDR, rdev->mc.gtt_end >> 12);
        WREG32(VM_CONTEXT0_PAGE_TABLE_BASE_ADDR, rdev->gart.table_addr >> 12);
        WREG32(VM_CONTEXT0_CNTL, ENABLE_CONTEXT | PAGE_TABLE_DEPTH(0) |
                                RANGE_PROTECTION_FAULT_ENABLE_DEFAULT);
@@ -225,6 +220,40 @@ void r600_pcie_gart_fini(struct radeon_device *rdev)
        radeon_gart_fini(rdev);
 }
 
+void r600_agp_enable(struct radeon_device *rdev)
+{
+       u32 tmp;
+       int i;
+
+       /* Setup L2 cache */
+       WREG32(VM_L2_CNTL, ENABLE_L2_CACHE | ENABLE_L2_FRAGMENT_PROCESSING |
+                               ENABLE_L2_PTE_CACHE_LRU_UPDATE_BY_WRITE |
+                               EFFECTIVE_L2_QUEUE_SIZE(7));
+       WREG32(VM_L2_CNTL2, 0);
+       WREG32(VM_L2_CNTL3, BANK_SELECT_0(0) | BANK_SELECT_1(1));
+       /* Setup TLB control */
+       tmp = ENABLE_L1_TLB | ENABLE_L1_FRAGMENT_PROCESSING |
+               SYSTEM_ACCESS_MODE_NOT_IN_SYS |
+               EFFECTIVE_L1_TLB_SIZE(5) | EFFECTIVE_L1_QUEUE_SIZE(5) |
+               ENABLE_WAIT_L2_QUERY;
+       WREG32(MC_VM_L1_TLB_MCB_RD_SYS_CNTL, tmp);
+       WREG32(MC_VM_L1_TLB_MCB_WR_SYS_CNTL, tmp);
+       WREG32(MC_VM_L1_TLB_MCB_RD_HDP_CNTL, tmp | ENABLE_L1_STRICT_ORDERING);
+       WREG32(MC_VM_L1_TLB_MCB_WR_HDP_CNTL, tmp);
+       WREG32(MC_VM_L1_TLB_MCD_RD_A_CNTL, tmp);
+       WREG32(MC_VM_L1_TLB_MCD_WR_A_CNTL, tmp);
+       WREG32(MC_VM_L1_TLB_MCD_RD_B_CNTL, tmp);
+       WREG32(MC_VM_L1_TLB_MCD_WR_B_CNTL, tmp);
+       WREG32(MC_VM_L1_TLB_MCB_RD_GFX_CNTL, tmp);
+       WREG32(MC_VM_L1_TLB_MCB_WR_GFX_CNTL, tmp);
+       WREG32(MC_VM_L1_TLB_MCB_RD_PDMA_CNTL, tmp);
+       WREG32(MC_VM_L1_TLB_MCB_WR_PDMA_CNTL, tmp);
+       WREG32(MC_VM_L1_TLB_MCB_RD_SEM_CNTL, tmp | ENABLE_SEMAPHORE_MODE);
+       WREG32(MC_VM_L1_TLB_MCB_WR_SEM_CNTL, tmp | ENABLE_SEMAPHORE_MODE);
+       for (i = 0; i < 7; i++)
+               WREG32(VM_CONTEXT0_CNTL + (i * 4), 0);
+}
+
 int r600_mc_wait_for_idle(struct radeon_device *rdev)
 {
        unsigned i;
@@ -240,14 +269,9 @@ int r600_mc_wait_for_idle(struct radeon_device *rdev)
        return -1;
 }
 
-static void r600_mc_resume(struct radeon_device *rdev)
+static void r600_mc_program(struct radeon_device *rdev)
 {
-       u32 d1vga_control, d2vga_control;
-       u32 vga_render_control, vga_hdp_control;
-       u32 d1crtc_control, d2crtc_control;
-       u32 new_d1grph_primary, new_d1grph_secondary;
-       u32 new_d2grph_primary, new_d2grph_secondary;
-       u64 old_vram_start;
+       struct rv515_mc_save save;
        u32 tmp;
        int i, j;
 
@@ -261,85 +285,51 @@ static void r600_mc_resume(struct radeon_device *rdev)
        }
        WREG32(HDP_REG_COHERENCY_FLUSH_CNTL, 0);
 
-       d1vga_control = RREG32(D1VGA_CONTROL);
-       d2vga_control = RREG32(D2VGA_CONTROL);
-       vga_render_control = RREG32(VGA_RENDER_CONTROL);
-       vga_hdp_control = RREG32(VGA_HDP_CONTROL);
-       d1crtc_control = RREG32(D1CRTC_CONTROL);
-       d2crtc_control = RREG32(D2CRTC_CONTROL);
-       old_vram_start = (u64)(RREG32(MC_VM_FB_LOCATION) & 0xFFFF) << 24;
-       new_d1grph_primary = RREG32(D1GRPH_PRIMARY_SURFACE_ADDRESS);
-       new_d1grph_secondary = RREG32(D1GRPH_SECONDARY_SURFACE_ADDRESS);
-       new_d1grph_primary += rdev->mc.vram_start - old_vram_start;
-       new_d1grph_secondary += rdev->mc.vram_start - old_vram_start;
-       new_d2grph_primary = RREG32(D2GRPH_PRIMARY_SURFACE_ADDRESS);
-       new_d2grph_secondary = RREG32(D2GRPH_SECONDARY_SURFACE_ADDRESS);
-       new_d2grph_primary += rdev->mc.vram_start - old_vram_start;
-       new_d2grph_secondary += rdev->mc.vram_start - old_vram_start;
-
-       /* Stop all video */
-       WREG32(D1VGA_CONTROL, 0);
-       WREG32(D2VGA_CONTROL, 0);
-       WREG32(VGA_RENDER_CONTROL, 0);
-       WREG32(D1CRTC_UPDATE_LOCK, 1);
-       WREG32(D2CRTC_UPDATE_LOCK, 1);
-       WREG32(D1CRTC_CONTROL, 0);
-       WREG32(D2CRTC_CONTROL, 0);
-       WREG32(D1CRTC_UPDATE_LOCK, 0);
-       WREG32(D2CRTC_UPDATE_LOCK, 0);
-
-       mdelay(1);
+       rv515_mc_stop(rdev, &save);
        if (r600_mc_wait_for_idle(rdev)) {
-               printk(KERN_WARNING "[drm] MC not idle !\n");
+               dev_warn(rdev->dev, "Wait for MC idle timedout !\n");
        }
-
-       /* Lockout access through VGA aperture*/
+       /* Lockout access through VGA aperture (doesn't exist before R600) */
        WREG32(VGA_HDP_CONTROL, VGA_MEMORY_DISABLE);
-
        /* Update configuration */
-       WREG32(MC_VM_SYSTEM_APERTURE_LOW_ADDR, rdev->mc.vram_start >> 12);
-       WREG32(MC_VM_SYSTEM_APERTURE_HIGH_ADDR, (rdev->mc.vram_end - 1) >> 12);
+       if (rdev->flags & RADEON_IS_AGP) {
+               if (rdev->mc.vram_start < rdev->mc.gtt_start) {
+                       /* VRAM before AGP */
+                       WREG32(MC_VM_SYSTEM_APERTURE_LOW_ADDR,
+                               rdev->mc.vram_start >> 12);
+                       WREG32(MC_VM_SYSTEM_APERTURE_HIGH_ADDR,
+                               rdev->mc.gtt_end >> 12);
+               } else {
+                       /* VRAM after AGP */
+                       WREG32(MC_VM_SYSTEM_APERTURE_LOW_ADDR,
+                               rdev->mc.gtt_start >> 12);
+                       WREG32(MC_VM_SYSTEM_APERTURE_HIGH_ADDR,
+                               rdev->mc.vram_end >> 12);
+               }
+       } else {
+               WREG32(MC_VM_SYSTEM_APERTURE_LOW_ADDR, rdev->mc.vram_start >> 12);
+               WREG32(MC_VM_SYSTEM_APERTURE_HIGH_ADDR, rdev->mc.vram_end >> 12);
+       }
        WREG32(MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR, 0);
-       tmp = (((rdev->mc.vram_end - 1) >> 24) & 0xFFFF) << 16;
+       tmp = ((rdev->mc.vram_end >> 24) & 0xFFFF) << 16;
        tmp |= ((rdev->mc.vram_start >> 24) & 0xFFFF);
        WREG32(MC_VM_FB_LOCATION, tmp);
        WREG32(HDP_NONSURFACE_BASE, (rdev->mc.vram_start >> 8));
        WREG32(HDP_NONSURFACE_INFO, (2 << 7));
-       WREG32(HDP_NONSURFACE_SIZE, (rdev->mc.mc_vram_size - 1) | 0x3FF);
+       WREG32(HDP_NONSURFACE_SIZE, rdev->mc.mc_vram_size | 0x3FF);
        if (rdev->flags & RADEON_IS_AGP) {
-               WREG32(MC_VM_AGP_TOP, (rdev->mc.gtt_end - 1) >> 16);
-               WREG32(MC_VM_AGP_BOT, rdev->mc.gtt_start >> 16);
+               WREG32(MC_VM_AGP_TOP, rdev->mc.gtt_end >> 22);
+               WREG32(MC_VM_AGP_BOT, rdev->mc.gtt_start >> 22);
                WREG32(MC_VM_AGP_BASE, rdev->mc.agp_base >> 22);
        } else {
                WREG32(MC_VM_AGP_BASE, 0);
                WREG32(MC_VM_AGP_TOP, 0x0FFFFFFF);
                WREG32(MC_VM_AGP_BOT, 0x0FFFFFFF);
        }
-       WREG32(D1GRPH_PRIMARY_SURFACE_ADDRESS, new_d1grph_primary);
-       WREG32(D1GRPH_SECONDARY_SURFACE_ADDRESS, new_d1grph_secondary);
-       WREG32(D2GRPH_PRIMARY_SURFACE_ADDRESS, new_d2grph_primary);
-       WREG32(D2GRPH_SECONDARY_SURFACE_ADDRESS, new_d2grph_secondary);
-       WREG32(VGA_MEMORY_BASE_ADDRESS, rdev->mc.vram_start);
-
-       /* Unlock host access */
-       WREG32(VGA_HDP_CONTROL, vga_hdp_control);
-
-       mdelay(1);
        if (r600_mc_wait_for_idle(rdev)) {
-               printk(KERN_WARNING "[drm] MC not idle !\n");
+               dev_warn(rdev->dev, "Wait for MC idle timedout !\n");
        }
-
-       /* Restore video state */
-       WREG32(D1CRTC_UPDATE_LOCK, 1);
-       WREG32(D2CRTC_UPDATE_LOCK, 1);
-       WREG32(D1CRTC_CONTROL, d1crtc_control);
-       WREG32(D2CRTC_CONTROL, d2crtc_control);
-       WREG32(D1CRTC_UPDATE_LOCK, 0);
-       WREG32(D2CRTC_UPDATE_LOCK, 0);
-       WREG32(D1VGA_CONTROL, d1vga_control);
-       WREG32(D2VGA_CONTROL, d2vga_control);
-       WREG32(VGA_RENDER_CONTROL, vga_render_control);
-
+       rv515_mc_resume(rdev, &save);
        /* we need to own VRAM, so turn off the VGA renderer here
         * to stop it overwriting our objects */
        rv515_vga_render_disable(rdev);
@@ -445,9 +435,9 @@ int r600_mc_init(struct radeon_device *rdev)
                }
        }
        rdev->mc.vram_start = rdev->mc.vram_location;
-       rdev->mc.vram_end = rdev->mc.vram_location + rdev->mc.mc_vram_size;
+       rdev->mc.vram_end = rdev->mc.vram_location + rdev->mc.mc_vram_size - 1;
        rdev->mc.gtt_start = rdev->mc.gtt_location;
-       rdev->mc.gtt_end = rdev->mc.gtt_location + rdev->mc.gtt_size;
+       rdev->mc.gtt_end = rdev->mc.gtt_location + rdev->mc.gtt_size - 1;
        /* FIXME: we should enforce default clock in case GPU is not in
         * default setup
         */
@@ -463,6 +453,7 @@ int r600_mc_init(struct radeon_device *rdev)
  */
 int r600_gpu_soft_reset(struct radeon_device *rdev)
 {
+       struct rv515_mc_save save;
        u32 grbm_busy_mask = S_008010_VC_BUSY(1) | S_008010_VGT_BUSY_NO_DMA(1) |
                                S_008010_VGT_BUSY(1) | S_008010_TA03_BUSY(1) |
                                S_008010_TC_BUSY(1) | S_008010_SX_BUSY(1) |
@@ -480,13 +471,25 @@ int r600_gpu_soft_reset(struct radeon_device *rdev)
                        S_008014_CB0_BUSY(1) | S_008014_CB1_BUSY(1) |
                        S_008014_CB2_BUSY(1) | S_008014_CB3_BUSY(1);
        u32 srbm_reset = 0;
+       u32 tmp;
 
+       dev_info(rdev->dev, "GPU softreset \n");
+       dev_info(rdev->dev, "  R_008010_GRBM_STATUS=0x%08X\n",
+               RREG32(R_008010_GRBM_STATUS));
+       dev_info(rdev->dev, "  R_008014_GRBM_STATUS2=0x%08X\n",
+               RREG32(R_008014_GRBM_STATUS2));
+       dev_info(rdev->dev, "  R_000E50_SRBM_STATUS=0x%08X\n",
+               RREG32(R_000E50_SRBM_STATUS));
+       rv515_mc_stop(rdev, &save);
+       if (r600_mc_wait_for_idle(rdev)) {
+               dev_warn(rdev->dev, "Wait for MC idle timedout !\n");
+       }
        /* Disable CP parsing/prefetching */
        WREG32(R_0086D8_CP_ME_CNTL, S_0086D8_CP_ME_HALT(0xff));
        /* Check if any of the rendering block is busy and reset it */
        if ((RREG32(R_008010_GRBM_STATUS) & grbm_busy_mask) ||
            (RREG32(R_008014_GRBM_STATUS2) & grbm2_busy_mask)) {
-               WREG32(R_008020_GRBM_SOFT_RESET, S_008020_SOFT_RESET_CR(1) |
+               tmp = S_008020_SOFT_RESET_CR(1) |
                        S_008020_SOFT_RESET_DB(1) |
                        S_008020_SOFT_RESET_CB(1) |
                        S_008020_SOFT_RESET_PA(1) |
@@ -498,14 +501,18 @@ int r600_gpu_soft_reset(struct radeon_device *rdev)
                        S_008020_SOFT_RESET_TC(1) |
                        S_008020_SOFT_RESET_TA(1) |
                        S_008020_SOFT_RESET_VC(1) |
-                       S_008020_SOFT_RESET_VGT(1));
+                       S_008020_SOFT_RESET_VGT(1);
+               dev_info(rdev->dev, "  R_008020_GRBM_SOFT_RESET=0x%08X\n", tmp);
+               WREG32(R_008020_GRBM_SOFT_RESET, tmp);
                (void)RREG32(R_008020_GRBM_SOFT_RESET);
                udelay(50);
                WREG32(R_008020_GRBM_SOFT_RESET, 0);
                (void)RREG32(R_008020_GRBM_SOFT_RESET);
        }
        /* Reset CP (we always reset CP) */
-       WREG32(R_008020_GRBM_SOFT_RESET, S_008020_SOFT_RESET_CP(1));
+       tmp = S_008020_SOFT_RESET_CP(1);
+       dev_info(rdev->dev, "R_008020_GRBM_SOFT_RESET=0x%08X\n", tmp);
+       WREG32(R_008020_GRBM_SOFT_RESET, tmp);
        (void)RREG32(R_008020_GRBM_SOFT_RESET);
        udelay(50);
        WREG32(R_008020_GRBM_SOFT_RESET, 0);
@@ -533,6 +540,14 @@ int r600_gpu_soft_reset(struct radeon_device *rdev)
                srbm_reset |= S_000E60_SOFT_RESET_RLC(1);
        if (G_000E50_SEM_BUSY(RREG32(R_000E50_SRBM_STATUS)))
                srbm_reset |= S_000E60_SOFT_RESET_SEM(1);
+       if (G_000E50_BIF_BUSY(RREG32(R_000E50_SRBM_STATUS)))
+               srbm_reset |= S_000E60_SOFT_RESET_BIF(1);
+       dev_info(rdev->dev, "  R_000E60_SRBM_SOFT_RESET=0x%08X\n", srbm_reset);
+       WREG32(R_000E60_SRBM_SOFT_RESET, srbm_reset);
+       (void)RREG32(R_000E60_SRBM_SOFT_RESET);
+       udelay(50);
+       WREG32(R_000E60_SRBM_SOFT_RESET, 0);
+       (void)RREG32(R_000E60_SRBM_SOFT_RESET);
        WREG32(R_000E60_SRBM_SOFT_RESET, srbm_reset);
        (void)RREG32(R_000E60_SRBM_SOFT_RESET);
        udelay(50);
@@ -540,6 +555,17 @@ int r600_gpu_soft_reset(struct radeon_device *rdev)
        (void)RREG32(R_000E60_SRBM_SOFT_RESET);
        /* Wait a little for things to settle down */
        udelay(50);
+       dev_info(rdev->dev, "  R_008010_GRBM_STATUS=0x%08X\n",
+               RREG32(R_008010_GRBM_STATUS));
+       dev_info(rdev->dev, "  R_008014_GRBM_STATUS2=0x%08X\n",
+               RREG32(R_008014_GRBM_STATUS2));
+       dev_info(rdev->dev, "  R_000E50_SRBM_STATUS=0x%08X\n",
+               RREG32(R_000E50_SRBM_STATUS));
+       /* After reset we need to reinit the asic as GPU often endup in an
+        * incoherent state.
+        */
+       atom_asic_init(rdev->mode_info.atom_context);
+       rv515_mc_resume(rdev, &save);
        return 0;
 }
 
@@ -1350,32 +1376,47 @@ int r600_ring_test(struct radeon_device *rdev)
        return r;
 }
 
-/*
- * Writeback
- */
-int r600_wb_init(struct radeon_device *rdev)
+void r600_wb_disable(struct radeon_device *rdev)
+{
+       WREG32(SCRATCH_UMSK, 0);
+       if (rdev->wb.wb_obj) {
+               radeon_object_kunmap(rdev->wb.wb_obj);
+               radeon_object_unpin(rdev->wb.wb_obj);
+       }
+}
+
+void r600_wb_fini(struct radeon_device *rdev)
+{
+       r600_wb_disable(rdev);
+       if (rdev->wb.wb_obj) {
+               radeon_object_unref(&rdev->wb.wb_obj);
+               rdev->wb.wb = NULL;
+               rdev->wb.wb_obj = NULL;
+       }
+}
+
+int r600_wb_enable(struct radeon_device *rdev)
 {
        int r;
 
        if (rdev->wb.wb_obj == NULL) {
-               r = radeon_object_create(rdev, NULL, 4096,
-                                        true,
-                                        RADEON_GEM_DOMAIN_GTT,
-                                        false, &rdev->wb.wb_obj);
+               r = radeon_object_create(rdev, NULL, 4096, true,
+                               RADEON_GEM_DOMAIN_GTT, false, &rdev->wb.wb_obj);
                if (r) {
-                       DRM_ERROR("radeon: failed to create WB buffer (%d).\n", r);
+                       dev_warn(rdev->dev, "failed to create WB buffer (%d).\n", r);
                        return r;
                }
-               r = radeon_object_pin(rdev->wb.wb_obj,
-                                     RADEON_GEM_DOMAIN_GTT,
-                                     &rdev->wb.gpu_addr);
+               r = radeon_object_pin(rdev->wb.wb_obj, RADEON_GEM_DOMAIN_GTT,
+                               &rdev->wb.gpu_addr);
                if (r) {
-                       DRM_ERROR("radeon: failed to pin WB buffer (%d).\n", r);
+                       dev_warn(rdev->dev, "failed to pin WB buffer (%d).\n", r);
+                       r600_wb_fini(rdev);
                        return r;
                }
                r = radeon_object_kmap(rdev->wb.wb_obj, (void **)&rdev->wb.wb);
                if (r) {
-                       DRM_ERROR("radeon: failed to map WB buffer (%d).\n", r);
+                       dev_warn(rdev->dev, "failed to map WB buffer (%d).\n", r);
+                       r600_wb_fini(rdev);
                        return r;
                }
        }
@@ -1386,21 +1427,6 @@ int r600_wb_init(struct radeon_device *rdev)
        return 0;
 }
 
-void r600_wb_fini(struct radeon_device *rdev)
-{
-       if (rdev->wb.wb_obj) {
-               radeon_object_kunmap(rdev->wb.wb_obj);
-               radeon_object_unpin(rdev->wb.wb_obj);
-               radeon_object_unref(&rdev->wb.wb_obj);
-               rdev->wb.wb = NULL;
-               rdev->wb.wb_obj = NULL;
-       }
-}
-
-
-/*
- * CS
- */
 void r600_fence_ring_emit(struct radeon_device *rdev,
                          struct radeon_fence *fence)
 {
@@ -1477,11 +1503,14 @@ int r600_startup(struct radeon_device *rdev)
 {
        int r;
 
-       r600_gpu_reset(rdev);
-       r600_mc_resume(rdev);
-       r = r600_pcie_gart_enable(rdev);
-       if (r)
-               return r;
+       r600_mc_program(rdev);
+       if (rdev->flags & RADEON_IS_AGP) {
+               r600_agp_enable(rdev);
+       } else {
+               r = r600_pcie_gart_enable(rdev);
+               if (r)
+                       return r;
+       }
        r600_gpu_init(rdev);
 
        r = radeon_object_pin(rdev->r600_blit.shader_obj, RADEON_GEM_DOMAIN_VRAM,
@@ -1500,9 +1529,8 @@ int r600_startup(struct radeon_device *rdev)
        r = r600_cp_resume(rdev);
        if (r)
                return r;
-       r = r600_wb_init(rdev);
-       if (r)
-               return r;
+       /* write back buffer are not vital so don't worry about failure */
+       r600_wb_enable(rdev);
        return 0;
 }
 
@@ -1524,15 +1552,12 @@ int r600_resume(struct radeon_device *rdev)
 {
        int r;
 
-       if (radeon_gpu_reset(rdev)) {
-               /* FIXME: what do we want to do here ? */
-       }
+       /* Do not reset GPU before posting, on r600 hw unlike on r500 hw,
+        * posting will perform necessary task to bring back GPU into good
+        * shape.
+        */
        /* post card */
-       if (rdev->is_atom_bios) {
-               atom_asic_init(rdev->mode_info.atom_context);
-       } else {
-               radeon_combios_asic_init(rdev->ddev);
-       }
+       atom_asic_init(rdev->mode_info.atom_context);
        /* Initialize clocks */
        r = radeon_clocks_init(rdev);
        if (r) {
@@ -1545,7 +1570,7 @@ int r600_resume(struct radeon_device *rdev)
                return r;
        }
 
-       r = radeon_ib_test(rdev);
+       r = r600_ib_test(rdev);
        if (r) {
                DRM_ERROR("radeon: failled testing IB (%d).\n", r);
                return r;
@@ -1553,13 +1578,12 @@ int r600_resume(struct radeon_device *rdev)
        return r;
 }
 
-
 int r600_suspend(struct radeon_device *rdev)
 {
        /* FIXME: we should wait for ring to be empty */
        r600_cp_stop(rdev);
        rdev->cp.ready = false;
-
+       r600_wb_disable(rdev);
        r600_pcie_gart_disable(rdev);
        /* unpin shaders bo */
        radeon_object_unpin(rdev->r600_blit.shader_obj);
@@ -1576,7 +1600,6 @@ int r600_init(struct radeon_device *rdev)
 {
        int r;
 
-       rdev->new_init_path = true;
        r = radeon_dummy_page_init(rdev);
        if (r)
                return r;
@@ -1593,8 +1616,10 @@ int r600_init(struct radeon_device *rdev)
                        return -EINVAL;
        }
        /* Must be an ATOMBIOS */
-       if (!rdev->is_atom_bios)
+       if (!rdev->is_atom_bios) {
+               dev_err(rdev->dev, "Expecting atombios for R600 GPU\n");
                return -EINVAL;
+       }
        r = radeon_atombios_init(rdev);
        if (r)
                return r;
@@ -1616,15 +1641,8 @@ int r600_init(struct radeon_device *rdev)
        if (r)
                return r;
        r = r600_mc_init(rdev);
-       if (r) {
-               if (rdev->flags & RADEON_IS_AGP) {
-                       /* Retry with disabling AGP */
-                       r600_fini(rdev);
-                       rdev->flags &= ~RADEON_IS_AGP;
-                       return r600_init(rdev);
-               }
+       if (r)
                return r;
-       }
        /* Memory manager */
        r = radeon_object_init(rdev);
        if (r)
@@ -1653,12 +1671,10 @@ int r600_init(struct radeon_device *rdev)
 
        r = r600_startup(rdev);
        if (r) {
-               if (rdev->flags & RADEON_IS_AGP) {
-                       /* Retry with disabling AGP */
-                       r600_fini(rdev);
-                       rdev->flags &= ~RADEON_IS_AGP;
-                       return r600_init(rdev);
-               }
+               r600_suspend(rdev);
+               r600_wb_fini(rdev);
+               radeon_ring_fini(rdev);
+               r600_pcie_gart_fini(rdev);
                rdev->accel_working = false;
        }
        if (rdev->accel_working) {
@@ -1667,7 +1683,7 @@ int r600_init(struct radeon_device *rdev)
                        DRM_ERROR("radeon: failled initializing IB pool (%d).\n", r);
                        rdev->accel_working = false;
                }
-               r = radeon_ib_test(rdev);
+               r = r600_ib_test(rdev);
                if (r) {
                        DRM_ERROR("radeon: failled testing IB (%d).\n", r);
                        rdev->accel_working = false;
@@ -1683,19 +1699,15 @@ void r600_fini(struct radeon_device *rdev)
 
        r600_blit_fini(rdev);
        radeon_ring_fini(rdev);
+       r600_wb_fini(rdev);
        r600_pcie_gart_fini(rdev);
        radeon_gem_fini(rdev);
        radeon_fence_driver_fini(rdev);
        radeon_clocks_fini(rdev);
-#if __OS_HAS_AGP
        if (rdev->flags & RADEON_IS_AGP)
                radeon_agp_fini(rdev);
-#endif
        radeon_object_fini(rdev);
-       if (rdev->is_atom_bios)
-               radeon_atombios_fini(rdev);
-       else
-               radeon_combios_fini(rdev);
+       radeon_atombios_fini(rdev);
        kfree(rdev->bios);
        rdev->bios = NULL;
        radeon_dummy_page_fini(rdev);
index d988eec..dec5010 100644 (file)
@@ -582,8 +582,6 @@ r600_blit_copy(struct drm_device *dev,
        u64 vb_addr;
        u32 *vb;
 
-       vb = r600_nomm_get_vb_ptr(dev);
-
        if ((size_bytes & 3) || (src_gpu_addr & 3) || (dst_gpu_addr & 3)) {
                max_bytes = 8192;
 
@@ -619,8 +617,8 @@ r600_blit_copy(struct drm_device *dev,
                                if (!dev_priv->blit_vb)
                                        return;
                                set_shaders(dev);
-                               vb = r600_nomm_get_vb_ptr(dev);
                        }
+                       vb = r600_nomm_get_vb_ptr(dev);
 
                        vb[0] = i2f(dst_x);
                        vb[1] = 0;
@@ -708,8 +706,8 @@ r600_blit_copy(struct drm_device *dev,
                                        return;
 
                                set_shaders(dev);
-                               vb = r600_nomm_get_vb_ptr(dev);
                        }
+                       vb = r600_nomm_get_vb_ptr(dev);
 
                        vb[0] = i2f(dst_x / 4);
                        vb[1] = 0;
@@ -777,8 +775,6 @@ r600_blit_swap(struct drm_device *dev,
        u64 vb_addr;
        u32 *vb;
 
-       vb = r600_nomm_get_vb_ptr(dev);
-
        if ((dev_priv->blit_vb->used + 48) > dev_priv->blit_vb->total) {
 
                r600_nomm_put_vb(dev);
@@ -787,8 +783,8 @@ r600_blit_swap(struct drm_device *dev,
                        return;
 
                set_shaders(dev);
-               vb = r600_nomm_get_vb_ptr(dev);
        }
+       vb = r600_nomm_get_vb_ptr(dev);
 
        if (cpp == 4) {
                cb_format = COLOR_8_8_8_8;
index acae33e..93108bb 100644 (file)
@@ -610,7 +610,6 @@ void r600_kms_blit_copy(struct radeon_device *rdev,
 
        DRM_DEBUG("emitting copy %16llx %16llx %d %d\n", src_gpu_addr, dst_gpu_addr,
                  size_bytes, rdev->r600_blit.vb_used);
-       vb = (u32 *)(rdev->r600_blit.vb_ib->ptr + rdev->r600_blit.vb_used);
        if ((size_bytes & 3) || (src_gpu_addr & 3) || (dst_gpu_addr & 3)) {
                max_bytes = 8192;
 
@@ -653,6 +652,7 @@ void r600_kms_blit_copy(struct radeon_device *rdev,
                                vb = r600_nomm_get_vb_ptr(dev);
 #endif
                        }
+                       vb = (u32 *)(rdev->r600_blit.vb_ib->ptr + rdev->r600_blit.vb_used);
 
                        vb[0] = i2f(dst_x);
                        vb[1] = 0;
@@ -747,6 +747,7 @@ void r600_kms_blit_copy(struct radeon_device *rdev,
                                vb = r600_nomm_get_vb_ptr(dev);
                        }
 #endif
+                       vb = (u32 *)(rdev->r600_blit.vb_ib->ptr + rdev->r600_blit.vb_used);
 
                        vb[0] = i2f(dst_x / 4);
                        vb[1] = 0;
index d28970d..17e4219 100644 (file)
@@ -252,7 +252,7 @@ static int r600_cs_packet_parse_vline(struct radeon_cs_parser *p)
 
        header = radeon_get_ib_value(p, h_idx);
        crtc_id = radeon_get_ib_value(p, h_idx + 2 + 7 + 1);
-       reg = header >> 2;
+       reg = CP_PACKET0_GET_REG(header);
        mutex_lock(&p->rdev->ddev->mode_config.mutex);
        obj = drm_mode_object_find(p->rdev->ddev, crtc_id, DRM_MODE_OBJECT_CRTC);
        if (!obj) {
index 4a9028a..9b64d47 100644 (file)
 #define                G_000E50_MCDW_BUSY(x)                   (((x) >> 13) & 1)
 #define                G_000E50_SEM_BUSY(x)                    (((x) >> 14) & 1)
 #define                G_000E50_RLC_BUSY(x)                    (((x) >> 15) & 1)
+#define                G_000E50_BIF_BUSY(x)                    (((x) >> 29) & 1)
 #define        R_000E60_SRBM_SOFT_RESET                        0x0E60
 #define                S_000E60_SOFT_RESET_BIF(x)              (((x) & 1) << 1)
 #define                S_000E60_SOFT_RESET_CG(x)               (((x) & 1) << 2)
index 950b346..5ab35b8 100644 (file)
@@ -590,18 +590,8 @@ struct radeon_asic {
        void (*fini)(struct radeon_device *rdev);
        int (*resume)(struct radeon_device *rdev);
        int (*suspend)(struct radeon_device *rdev);
-       void (*errata)(struct radeon_device *rdev);
-       void (*vram_info)(struct radeon_device *rdev);
        void (*vga_set_state)(struct radeon_device *rdev, bool state);
        int (*gpu_reset)(struct radeon_device *rdev);
-       int (*mc_init)(struct radeon_device *rdev);
-       void (*mc_fini)(struct radeon_device *rdev);
-       int (*wb_init)(struct radeon_device *rdev);
-       void (*wb_fini)(struct radeon_device *rdev);
-       int (*gart_init)(struct radeon_device *rdev);
-       void (*gart_fini)(struct radeon_device *rdev);
-       int (*gart_enable)(struct radeon_device *rdev);
-       void (*gart_disable)(struct radeon_device *rdev);
        void (*gart_tlb_flush)(struct radeon_device *rdev);
        int (*gart_set_page)(struct radeon_device *rdev, int i, uint64_t addr);
        int (*cp_init)(struct radeon_device *rdev, unsigned ring_size);
@@ -611,7 +601,6 @@ struct radeon_asic {
        void (*ring_start)(struct radeon_device *rdev);
        int (*ring_test)(struct radeon_device *rdev);
        void (*ring_ib_execute)(struct radeon_device *rdev, struct radeon_ib *ib);
-       int (*ib_test)(struct radeon_device *rdev);
        int (*irq_set)(struct radeon_device *rdev);
        int (*irq_process)(struct radeon_device *rdev);
        u32 (*get_vblank_counter)(struct radeon_device *rdev, int crtc);
@@ -789,7 +778,6 @@ struct radeon_device {
        bool                            shutdown;
        bool                            suspend;
        bool                            need_dma32;
-       bool                            new_init_path;
        bool                            accel_working;
        struct radeon_surface_reg surface_regs[RADEON_GEM_MAX_SURFACES];
        const struct firmware *me_fw;   /* all family ME firmware */
@@ -949,28 +937,14 @@ static inline void radeon_ring_write(struct radeon_device *rdev, uint32_t v)
 #define radeon_resume(rdev) (rdev)->asic->resume((rdev))
 #define radeon_suspend(rdev) (rdev)->asic->suspend((rdev))
 #define radeon_cs_parse(p) rdev->asic->cs_parse((p))
-#define radeon_errata(rdev) (rdev)->asic->errata((rdev))
-#define radeon_vram_info(rdev) (rdev)->asic->vram_info((rdev))
 #define radeon_vga_set_state(rdev, state) (rdev)->asic->vga_set_state((rdev), (state))
 #define radeon_gpu_reset(rdev) (rdev)->asic->gpu_reset((rdev))
-#define radeon_mc_init(rdev) (rdev)->asic->mc_init((rdev))
-#define radeon_mc_fini(rdev) (rdev)->asic->mc_fini((rdev))
-#define radeon_wb_init(rdev) (rdev)->asic->wb_init((rdev))
-#define radeon_wb_fini(rdev) (rdev)->asic->wb_fini((rdev))
-#define radeon_gpu_gart_init(rdev) (rdev)->asic->gart_init((rdev))
-#define radeon_gpu_gart_fini(rdev) (rdev)->asic->gart_fini((rdev))
-#define radeon_gart_enable(rdev) (rdev)->asic->gart_enable((rdev))
-#define radeon_gart_disable(rdev) (rdev)->asic->gart_disable((rdev))
 #define radeon_gart_tlb_flush(rdev) (rdev)->asic->gart_tlb_flush((rdev))
 #define radeon_gart_set_page(rdev, i, p) (rdev)->asic->gart_set_page((rdev), (i), (p))
-#define radeon_cp_init(rdev,rsize) (rdev)->asic->cp_init((rdev), (rsize))
-#define radeon_cp_fini(rdev) (rdev)->asic->cp_fini((rdev))
-#define radeon_cp_disable(rdev) (rdev)->asic->cp_disable((rdev))
 #define radeon_cp_commit(rdev) (rdev)->asic->cp_commit((rdev))
 #define radeon_ring_start(rdev) (rdev)->asic->ring_start((rdev))
 #define radeon_ring_test(rdev) (rdev)->asic->ring_test((rdev))
 #define radeon_ring_ib_execute(rdev, ib) (rdev)->asic->ring_ib_execute((rdev), (ib))
-#define radeon_ib_test(rdev) (rdev)->asic->ib_test((rdev))
 #define radeon_irq_set(rdev) (rdev)->asic->irq_set((rdev))
 #define radeon_irq_process(rdev) (rdev)->asic->irq_process((rdev))
 #define radeon_get_vblank_counter(rdev, crtc) (rdev)->asic->get_vblank_counter((rdev), (crtc))
@@ -996,6 +970,7 @@ extern void radeon_clocks_fini(struct radeon_device *rdev);
 extern void radeon_scratch_init(struct radeon_device *rdev);
 extern void radeon_surface_init(struct radeon_device *rdev);
 extern int radeon_cs_parser_init(struct radeon_cs_parser *p, void *data);
+extern void radeon_legacy_set_clock_gating(struct radeon_device *rdev, int enable);
 extern void radeon_atom_set_clock_gating(struct radeon_device *rdev, int enable);
 
 /* r100,rv100,rs100,rv200,rs200,r200,rv250,rs300,rv280 */
@@ -1031,11 +1006,27 @@ extern int r100_wb_init(struct radeon_device *rdev);
 extern void r100_hdp_reset(struct radeon_device *rdev);
 extern int r100_rb2d_reset(struct radeon_device *rdev);
 extern int r100_cp_reset(struct radeon_device *rdev);
+extern void r100_vga_render_disable(struct radeon_device *rdev);
+extern int r100_cs_track_check_pkt3_indx_buffer(struct radeon_cs_parser *p,
+                                               struct radeon_cs_packet *pkt,
+                                               struct radeon_object *robj);
+extern int r100_cs_parse_packet0(struct radeon_cs_parser *p,
+                               struct radeon_cs_packet *pkt,
+                               const unsigned *auth, unsigned n,
+                               radeon_packet0_check_t check);
+extern int r100_cs_packet_parse(struct radeon_cs_parser *p,
+                               struct radeon_cs_packet *pkt,
+                               unsigned idx);
+
+/* rv200,rv250,rv280 */
+extern void r200_set_safe_registers(struct radeon_device *rdev);
 
 /* r300,r350,rv350,rv370,rv380 */
 extern void r300_set_reg_safe(struct radeon_device *rdev);
 extern void r300_mc_program(struct radeon_device *rdev);
 extern void r300_vram_info(struct radeon_device *rdev);
+extern void r300_clock_startup(struct radeon_device *rdev);
+extern int r300_mc_wait_for_idle(struct radeon_device *rdev);
 extern int rv370_pcie_gart_init(struct radeon_device *rdev);
 extern void rv370_pcie_gart_fini(struct radeon_device *rdev);
 extern int rv370_pcie_gart_enable(struct radeon_device *rdev);
@@ -1066,6 +1057,18 @@ extern void rv515_clock_startup(struct radeon_device *rdev);
 extern void rv515_debugfs(struct radeon_device *rdev);
 extern int rv515_suspend(struct radeon_device *rdev);
 
+/* rs400 */
+extern int rs400_gart_init(struct radeon_device *rdev);
+extern int rs400_gart_enable(struct radeon_device *rdev);
+extern void rs400_gart_adjust_size(struct radeon_device *rdev);
+extern void rs400_gart_disable(struct radeon_device *rdev);
+extern void rs400_gart_fini(struct radeon_device *rdev);
+
+/* rs600 */
+extern void rs600_set_safe_registers(struct radeon_device *rdev);
+extern int rs600_irq_set(struct radeon_device *rdev);
+extern void rs600_irq_disable(struct radeon_device *rdev);
+
 /* rs690, rs740 */
 extern void rs690_line_buffer_adjust(struct radeon_device *rdev,
                                        struct drm_display_mode *mode1,
@@ -1083,8 +1086,9 @@ extern int r600_pcie_gart_init(struct radeon_device *rdev);
 extern void r600_pcie_gart_tlb_flush(struct radeon_device *rdev);
 extern int r600_ib_test(struct radeon_device *rdev);
 extern int r600_ring_test(struct radeon_device *rdev);
-extern int r600_wb_init(struct radeon_device *rdev);
 extern void r600_wb_fini(struct radeon_device *rdev);
+extern int r600_wb_enable(struct radeon_device *rdev);
+extern void r600_wb_disable(struct radeon_device *rdev);
 extern void r600_scratch_init(struct radeon_device *rdev);
 extern int r600_blit_init(struct radeon_device *rdev);
 extern void r600_blit_fini(struct radeon_device *rdev);
index c8a4e7b..c3532c7 100644 (file)
@@ -41,28 +41,17 @@ void radeon_atom_set_clock_gating(struct radeon_device *rdev, int enable);
 /*
  * r100,rv100,rs100,rv200,rs200,r200,rv250,rs300,rv280
  */
-int r100_init(struct radeon_device *rdev);
-int r200_init(struct radeon_device *rdev);
+extern int r100_init(struct radeon_device *rdev);
+extern void r100_fini(struct radeon_device *rdev);
+extern int r100_suspend(struct radeon_device *rdev);
+extern int r100_resume(struct radeon_device *rdev);
 uint32_t r100_mm_rreg(struct radeon_device *rdev, uint32_t reg);
 void r100_mm_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v);
-void r100_errata(struct radeon_device *rdev);
-void r100_vram_info(struct radeon_device *rdev);
 void r100_vga_set_state(struct radeon_device *rdev, bool state);
 int r100_gpu_reset(struct radeon_device *rdev);
-int r100_mc_init(struct radeon_device *rdev);
-void r100_mc_fini(struct radeon_device *rdev);
 u32 r100_get_vblank_counter(struct radeon_device *rdev, int crtc);
-int r100_wb_init(struct radeon_device *rdev);
-void r100_wb_fini(struct radeon_device *rdev);
-int r100_pci_gart_init(struct radeon_device *rdev);
-void r100_pci_gart_fini(struct radeon_device *rdev);
-int r100_pci_gart_enable(struct radeon_device *rdev);
-void r100_pci_gart_disable(struct radeon_device *rdev);
 void r100_pci_gart_tlb_flush(struct radeon_device *rdev);
 int r100_pci_gart_set_page(struct radeon_device *rdev, int i, uint64_t addr);
-int r100_cp_init(struct radeon_device *rdev, unsigned ring_size);
-void r100_cp_fini(struct radeon_device *rdev);
-void r100_cp_disable(struct radeon_device *rdev);
 void r100_cp_commit(struct radeon_device *rdev);
 void r100_ring_start(struct radeon_device *rdev);
 int r100_irq_set(struct radeon_device *rdev);
@@ -83,33 +72,21 @@ int r100_set_surface_reg(struct radeon_device *rdev, int reg,
 int r100_clear_surface_reg(struct radeon_device *rdev, int reg);
 void r100_bandwidth_update(struct radeon_device *rdev);
 void r100_ring_ib_execute(struct radeon_device *rdev, struct radeon_ib *ib);
-int r100_ib_test(struct radeon_device *rdev);
 int r100_ring_test(struct radeon_device *rdev);
 
 static struct radeon_asic r100_asic = {
        .init = &r100_init,
-       .errata = &r100_errata,
-       .vram_info = &r100_vram_info,
+       .fini = &r100_fini,
+       .suspend = &r100_suspend,
+       .resume = &r100_resume,
        .vga_set_state = &r100_vga_set_state,
        .gpu_reset = &r100_gpu_reset,
-       .mc_init = &r100_mc_init,
-       .mc_fini = &r100_mc_fini,
-       .wb_init = &r100_wb_init,
-       .wb_fini = &r100_wb_fini,
-       .gart_init = &r100_pci_gart_init,
-       .gart_fini = &r100_pci_gart_fini,
-       .gart_enable = &r100_pci_gart_enable,
-       .gart_disable = &r100_pci_gart_disable,
        .gart_tlb_flush = &r100_pci_gart_tlb_flush,
        .gart_set_page = &r100_pci_gart_set_page,
-       .cp_init = &r100_cp_init,
-       .cp_fini = &r100_cp_fini,
-       .cp_disable = &r100_cp_disable,
        .cp_commit = &r100_cp_commit,
        .ring_start = &r100_ring_start,
        .ring_test = &r100_ring_test,
        .ring_ib_execute = &r100_ring_ib_execute,
-       .ib_test = &r100_ib_test,
        .irq_set = &r100_irq_set,
        .irq_process = &r100_irq_process,
        .get_vblank_counter = &r100_get_vblank_counter,
@@ -131,55 +108,38 @@ static struct radeon_asic r100_asic = {
 /*
  * r300,r350,rv350,rv380
  */
-int r300_init(struct radeon_device *rdev);
-void r300_errata(struct radeon_device *rdev);
-void r300_vram_info(struct radeon_device *rdev);
-int r300_gpu_reset(struct radeon_device *rdev);
-int r300_mc_init(struct radeon_device *rdev);
-void r300_mc_fini(struct radeon_device *rdev);
-void r300_ring_start(struct radeon_device *rdev);
-void r300_fence_ring_emit(struct radeon_device *rdev,
-                         struct radeon_fence *fence);
-int r300_cs_parse(struct radeon_cs_parser *p);
-int rv370_pcie_gart_init(struct radeon_device *rdev);
-void rv370_pcie_gart_fini(struct radeon_device *rdev);
-int rv370_pcie_gart_enable(struct radeon_device *rdev);
-void rv370_pcie_gart_disable(struct radeon_device *rdev);
-void rv370_pcie_gart_tlb_flush(struct radeon_device *rdev);
-int rv370_pcie_gart_set_page(struct radeon_device *rdev, int i, uint64_t addr);
-uint32_t rv370_pcie_rreg(struct radeon_device *rdev, uint32_t reg);
-void rv370_pcie_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v);
-void rv370_set_pcie_lanes(struct radeon_device *rdev, int lanes);
-int r300_copy_dma(struct radeon_device *rdev,
-                 uint64_t src_offset,
-                 uint64_t dst_offset,
-                 unsigned num_pages,
-                 struct radeon_fence *fence);
-
+extern int r300_init(struct radeon_device *rdev);
+extern void r300_fini(struct radeon_device *rdev);
+extern int r300_suspend(struct radeon_device *rdev);
+extern int r300_resume(struct radeon_device *rdev);
+extern int r300_gpu_reset(struct radeon_device *rdev);
+extern void r300_ring_start(struct radeon_device *rdev);
+extern void r300_fence_ring_emit(struct radeon_device *rdev,
+                               struct radeon_fence *fence);
+extern int r300_cs_parse(struct radeon_cs_parser *p);
+extern void rv370_pcie_gart_tlb_flush(struct radeon_device *rdev);
+extern int rv370_pcie_gart_set_page(struct radeon_device *rdev, int i, uint64_t addr);
+extern uint32_t rv370_pcie_rreg(struct radeon_device *rdev, uint32_t reg);
+extern void rv370_pcie_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v);
+extern void rv370_set_pcie_lanes(struct radeon_device *rdev, int lanes);
+extern int r300_copy_dma(struct radeon_device *rdev,
+                       uint64_t src_offset,
+                       uint64_t dst_offset,
+                       unsigned num_pages,
+                       struct radeon_fence *fence);
 static struct radeon_asic r300_asic = {
        .init = &r300_init,
-       .errata = &r300_errata,
-       .vram_info = &r300_vram_info,
+       .fini = &r300_fini,
+       .suspend = &r300_suspend,
+       .resume = &r300_resume,
        .vga_set_state = &r100_vga_set_state,
        .gpu_reset = &r300_gpu_reset,
-       .mc_init = &r300_mc_init,
-       .mc_fini = &r300_mc_fini,
-       .wb_init = &r100_wb_init,
-       .wb_fini = &r100_wb_fini,
-       .gart_init = &r100_pci_gart_init,
-       .gart_fini = &r100_pci_gart_fini,
-       .gart_enable = &r100_pci_gart_enable,
-       .gart_disable = &r100_pci_gart_disable,
        .gart_tlb_flush = &r100_pci_gart_tlb_flush,
        .gart_set_page = &r100_pci_gart_set_page,
-       .cp_init = &r100_cp_init,
-       .cp_fini = &r100_cp_fini,
-       .cp_disable = &r100_cp_disable,
        .cp_commit = &r100_cp_commit,
        .ring_start = &r300_ring_start,
        .ring_test = &r100_ring_test,
        .ring_ib_execute = &r100_ring_ib_execute,
-       .ib_test = &r100_ib_test,
        .irq_set = &r100_irq_set,
        .irq_process = &r100_irq_process,
        .get_vblank_counter = &r100_get_vblank_counter,
@@ -209,26 +169,14 @@ static struct radeon_asic r420_asic = {
        .fini = &r420_fini,
        .suspend = &r420_suspend,
        .resume = &r420_resume,
-       .errata = NULL,
-       .vram_info = NULL,
        .vga_set_state = &r100_vga_set_state,
        .gpu_reset = &r300_gpu_reset,
-       .mc_init = NULL,
-       .mc_fini = NULL,
-       .wb_init = NULL,
-       .wb_fini = NULL,
-       .gart_enable = NULL,
-       .gart_disable = NULL,
        .gart_tlb_flush = &rv370_pcie_gart_tlb_flush,
        .gart_set_page = &rv370_pcie_gart_set_page,
-       .cp_init = NULL,
-       .cp_fini = NULL,
-       .cp_disable = NULL,
        .cp_commit = &r100_cp_commit,
        .ring_start = &r300_ring_start,
        .ring_test = &r100_ring_test,
        .ring_ib_execute = &r100_ring_ib_execute,
-       .ib_test = NULL,
        .irq_set = &r100_irq_set,
        .irq_process = &r100_irq_process,
        .get_vblank_counter = &r100_get_vblank_counter,
@@ -250,42 +198,27 @@ static struct radeon_asic r420_asic = {
 /*
  * rs400,rs480
  */
-void rs400_errata(struct radeon_device *rdev);
-void rs400_vram_info(struct radeon_device *rdev);
-int rs400_mc_init(struct radeon_device *rdev);
-void rs400_mc_fini(struct radeon_device *rdev);
-int rs400_gart_init(struct radeon_device *rdev);
-void rs400_gart_fini(struct radeon_device *rdev);
-int rs400_gart_enable(struct radeon_device *rdev);
-void rs400_gart_disable(struct radeon_device *rdev);
+extern int rs400_init(struct radeon_device *rdev);
+extern void rs400_fini(struct radeon_device *rdev);
+extern int rs400_suspend(struct radeon_device *rdev);
+extern int rs400_resume(struct radeon_device *rdev);
 void rs400_gart_tlb_flush(struct radeon_device *rdev);
 int rs400_gart_set_page(struct radeon_device *rdev, int i, uint64_t addr);
 uint32_t rs400_mc_rreg(struct radeon_device *rdev, uint32_t reg);
 void rs400_mc_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v);
 static struct radeon_asic rs400_asic = {
-       .init = &r300_init,
-       .errata = &rs400_errata,
-       .vram_info = &rs400_vram_info,
+       .init = &rs400_init,
+       .fini = &rs400_fini,
+       .suspend = &rs400_suspend,
+       .resume = &rs400_resume,
        .vga_set_state = &r100_vga_set_state,
        .gpu_reset = &r300_gpu_reset,
-       .mc_init = &rs400_mc_init,
-       .mc_fini = &rs400_mc_fini,
-       .wb_init = &r100_wb_init,
-       .wb_fini = &r100_wb_fini,
-       .gart_init = &rs400_gart_init,
-       .gart_fini = &rs400_gart_fini,
-       .gart_enable = &rs400_gart_enable,
-       .gart_disable = &rs400_gart_disable,
        .gart_tlb_flush = &rs400_gart_tlb_flush,
        .gart_set_page = &rs400_gart_set_page,
-       .cp_init = &r100_cp_init,
-       .cp_fini = &r100_cp_fini,
-       .cp_disable = &r100_cp_disable,
        .cp_commit = &r100_cp_commit,
        .ring_start = &r300_ring_start,
        .ring_test = &r100_ring_test,
        .ring_ib_execute = &r100_ring_ib_execute,
-       .ib_test = &r100_ib_test,
        .irq_set = &r100_irq_set,
        .irq_process = &r100_irq_process,
        .get_vblank_counter = &r100_get_vblank_counter,
@@ -307,18 +240,13 @@ static struct radeon_asic rs400_asic = {
 /*
  * rs600.
  */
-int rs600_init(struct radeon_device *rdev);
-void rs600_errata(struct radeon_device *rdev);
-void rs600_vram_info(struct radeon_device *rdev);
-int rs600_mc_init(struct radeon_device *rdev);
-void rs600_mc_fini(struct radeon_device *rdev);
+extern int rs600_init(struct radeon_device *rdev);
+extern void rs600_fini(struct radeon_device *rdev);
+extern int rs600_suspend(struct radeon_device *rdev);
+extern int rs600_resume(struct radeon_device *rdev);
 int rs600_irq_set(struct radeon_device *rdev);
 int rs600_irq_process(struct radeon_device *rdev);
 u32 rs600_get_vblank_counter(struct radeon_device *rdev, int crtc);
-int rs600_gart_init(struct radeon_device *rdev);
-void rs600_gart_fini(struct radeon_device *rdev);
-int rs600_gart_enable(struct radeon_device *rdev);
-void rs600_gart_disable(struct radeon_device *rdev);
 void rs600_gart_tlb_flush(struct radeon_device *rdev);
 int rs600_gart_set_page(struct radeon_device *rdev, int i, uint64_t addr);
 uint32_t rs600_mc_rreg(struct radeon_device *rdev, uint32_t reg);
@@ -326,28 +254,17 @@ void rs600_mc_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v);
 void rs600_bandwidth_update(struct radeon_device *rdev);
 static struct radeon_asic rs600_asic = {
        .init = &rs600_init,
-       .errata = &rs600_errata,
-       .vram_info = &rs600_vram_info,
+       .fini = &rs600_fini,
+       .suspend = &rs600_suspend,
+       .resume = &rs600_resume,
        .vga_set_state = &r100_vga_set_state,
        .gpu_reset = &r300_gpu_reset,
-       .mc_init = &rs600_mc_init,
-       .mc_fini = &rs600_mc_fini,
-       .wb_init = &r100_wb_init,
-       .wb_fini = &r100_wb_fini,
-       .gart_init = &rs600_gart_init,
-       .gart_fini = &rs600_gart_fini,
-       .gart_enable = &rs600_gart_enable,
-       .gart_disable = &rs600_gart_disable,
        .gart_tlb_flush = &rs600_gart_tlb_flush,
        .gart_set_page = &rs600_gart_set_page,
-       .cp_init = &r100_cp_init,
-       .cp_fini = &r100_cp_fini,
-       .cp_disable = &r100_cp_disable,
        .cp_commit = &r100_cp_commit,
        .ring_start = &r300_ring_start,
        .ring_test = &r100_ring_test,
        .ring_ib_execute = &r100_ring_ib_execute,
-       .ib_test = &r100_ib_test,
        .irq_set = &rs600_irq_set,
        .irq_process = &rs600_irq_process,
        .get_vblank_counter = &rs600_get_vblank_counter,
@@ -367,37 +284,26 @@ static struct radeon_asic rs600_asic = {
 /*
  * rs690,rs740
  */
-void rs690_errata(struct radeon_device *rdev);
-void rs690_vram_info(struct radeon_device *rdev);
-int rs690_mc_init(struct radeon_device *rdev);
-void rs690_mc_fini(struct radeon_device *rdev);
+int rs690_init(struct radeon_device *rdev);
+void rs690_fini(struct radeon_device *rdev);
+int rs690_resume(struct radeon_device *rdev);
+int rs690_suspend(struct radeon_device *rdev);
 uint32_t rs690_mc_rreg(struct radeon_device *rdev, uint32_t reg);
 void rs690_mc_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v);
 void rs690_bandwidth_update(struct radeon_device *rdev);
 static struct radeon_asic rs690_asic = {
-       .init = &rs600_init,
-       .errata = &rs690_errata,
-       .vram_info = &rs690_vram_info,
+       .init = &rs690_init,
+       .fini = &rs690_fini,
+       .suspend = &rs690_suspend,
+       .resume = &rs690_resume,
        .vga_set_state = &r100_vga_set_state,
        .gpu_reset = &r300_gpu_reset,
-       .mc_init = &rs690_mc_init,
-       .mc_fini = &rs690_mc_fini,
-       .wb_init = &r100_wb_init,
-       .wb_fini = &r100_wb_fini,
-       .gart_init = &rs400_gart_init,
-       .gart_fini = &rs400_gart_fini,
-       .gart_enable = &rs400_gart_enable,
-       .gart_disable = &rs400_gart_disable,
        .gart_tlb_flush = &rs400_gart_tlb_flush,
        .gart_set_page = &rs400_gart_set_page,
-       .cp_init = &r100_cp_init,
-       .cp_fini = &r100_cp_fini,
-       .cp_disable = &r100_cp_disable,
        .cp_commit = &r100_cp_commit,
        .ring_start = &r300_ring_start,
        .ring_test = &r100_ring_test,
        .ring_ib_execute = &r100_ring_ib_execute,
-       .ib_test = &r100_ib_test,
        .irq_set = &rs600_irq_set,
        .irq_process = &rs600_irq_process,
        .get_vblank_counter = &rs600_get_vblank_counter,
@@ -435,28 +341,14 @@ static struct radeon_asic rv515_asic = {
        .fini = &rv515_fini,
        .suspend = &rv515_suspend,
        .resume = &rv515_resume,
-       .errata = NULL,
-       .vram_info = NULL,
        .vga_set_state = &r100_vga_set_state,
        .gpu_reset = &rv515_gpu_reset,
-       .mc_init = NULL,
-       .mc_fini = NULL,
-       .wb_init = NULL,
-       .wb_fini = NULL,
-       .gart_init = &rv370_pcie_gart_init,
-       .gart_fini = &rv370_pcie_gart_fini,
-       .gart_enable = NULL,
-       .gart_disable = NULL,
        .gart_tlb_flush = &rv370_pcie_gart_tlb_flush,
        .gart_set_page = &rv370_pcie_gart_set_page,
-       .cp_init = NULL,
-       .cp_fini = NULL,
-       .cp_disable = NULL,
        .cp_commit = &r100_cp_commit,
        .ring_start = &rv515_ring_start,
        .ring_test = &r100_ring_test,
        .ring_ib_execute = &r100_ring_ib_execute,
-       .ib_test = NULL,
        .irq_set = &rs600_irq_set,
        .irq_process = &rs600_irq_process,
        .get_vblank_counter = &rs600_get_vblank_counter,
@@ -485,28 +377,14 @@ static struct radeon_asic r520_asic = {
        .fini = &rv515_fini,
        .suspend = &rv515_suspend,
        .resume = &r520_resume,
-       .errata = NULL,
-       .vram_info = NULL,
        .vga_set_state = &r100_vga_set_state,
        .gpu_reset = &rv515_gpu_reset,
-       .mc_init = NULL,
-       .mc_fini = NULL,
-       .wb_init = NULL,
-       .wb_fini = NULL,
-       .gart_init = NULL,
-       .gart_fini = NULL,
-       .gart_enable = NULL,
-       .gart_disable = NULL,
        .gart_tlb_flush = &rv370_pcie_gart_tlb_flush,
        .gart_set_page = &rv370_pcie_gart_set_page,
-       .cp_init = NULL,
-       .cp_fini = NULL,
-       .cp_disable = NULL,
        .cp_commit = &r100_cp_commit,
        .ring_start = &rv515_ring_start,
        .ring_test = &r100_ring_test,
        .ring_ib_execute = &r100_ring_ib_execute,
-       .ib_test = NULL,
        .irq_set = &rs600_irq_set,
        .irq_process = &rs600_irq_process,
        .get_vblank_counter = &rs600_get_vblank_counter,
@@ -554,37 +432,23 @@ int r600_set_surface_reg(struct radeon_device *rdev, int reg,
                         uint32_t offset, uint32_t obj_size);
 int r600_clear_surface_reg(struct radeon_device *rdev, int reg);
 void r600_ring_ib_execute(struct radeon_device *rdev, struct radeon_ib *ib);
-int r600_ib_test(struct radeon_device *rdev);
 int r600_ring_test(struct radeon_device *rdev);
 int r600_copy_blit(struct radeon_device *rdev,
                   uint64_t src_offset, uint64_t dst_offset,
                   unsigned num_pages, struct radeon_fence *fence);
 
 static struct radeon_asic r600_asic = {
-       .errata = NULL,
        .init = &r600_init,
        .fini = &r600_fini,
        .suspend = &r600_suspend,
        .resume = &r600_resume,
        .cp_commit = &r600_cp_commit,
-       .vram_info = NULL,
        .vga_set_state = &r600_vga_set_state,
        .gpu_reset = &r600_gpu_reset,
-       .mc_init = NULL,
-       .mc_fini = NULL,
-       .wb_init = &r600_wb_init,
-       .wb_fini = &r600_wb_fini,
-       .gart_enable = NULL,
-       .gart_disable = NULL,
        .gart_tlb_flush = &r600_pcie_gart_tlb_flush,
        .gart_set_page = &rs600_gart_set_page,
-       .cp_init = NULL,
-       .cp_fini = NULL,
-       .cp_disable = NULL,
-       .ring_start = NULL,
        .ring_test = &r600_ring_test,
        .ring_ib_execute = &r600_ring_ib_execute,
-       .ib_test = &r600_ib_test,
        .irq_set = &r600_irq_set,
        .irq_process = &r600_irq_process,
        .fence_ring_emit = &r600_fence_ring_emit,
@@ -611,30 +475,17 @@ int rv770_resume(struct radeon_device *rdev);
 int rv770_gpu_reset(struct radeon_device *rdev);
 
 static struct radeon_asic rv770_asic = {
-       .errata = NULL,
        .init = &rv770_init,
        .fini = &rv770_fini,
        .suspend = &rv770_suspend,
        .resume = &rv770_resume,
        .cp_commit = &r600_cp_commit,
-       .vram_info = NULL,
        .gpu_reset = &rv770_gpu_reset,
        .vga_set_state = &r600_vga_set_state,
-       .mc_init = NULL,
-       .mc_fini = NULL,
-       .wb_init = &r600_wb_init,
-       .wb_fini = &r600_wb_fini,
-       .gart_enable = NULL,
-       .gart_disable = NULL,
        .gart_tlb_flush = &r600_pcie_gart_tlb_flush,
        .gart_set_page = &rs600_gart_set_page,
-       .cp_init = NULL,
-       .cp_fini = NULL,
-       .cp_disable = NULL,
-       .ring_start = NULL,
        .ring_test = &r600_ring_test,
        .ring_ib_execute = &r600_ring_ib_execute,
-       .ib_test = &r600_ib_test,
        .irq_set = &r600_irq_set,
        .irq_process = &r600_irq_process,
        .fence_ring_emit = &r600_fence_ring_emit,
index 96e37a6..34a9b91 100644 (file)
 /*
  * BIOS.
  */
+
+/* If you boot an IGP board with a discrete card as the primary,
+ * the IGP rom is not accessible via the rom bar as the IGP rom is
+ * part of the system bios.  On boot, the system bios puts a
+ * copy of the igp rom at the start of vram if a discrete card is
+ * present.
+ */
+static bool igp_read_bios_from_vram(struct radeon_device *rdev)
+{
+       uint8_t __iomem *bios;
+       resource_size_t vram_base;
+       resource_size_t size = 256 * 1024; /* ??? */
+
+       rdev->bios = NULL;
+       vram_base = drm_get_resource_start(rdev->ddev, 0);
+       bios = ioremap(vram_base, size);
+       if (!bios) {
+               DRM_ERROR("Unable to mmap vram\n");
+               return false;
+       }
+
+       if (size == 0 || bios[0] != 0x55 || bios[1] != 0xaa) {
+               iounmap(bios);
+               DRM_ERROR("bad rom signature\n");
+               return false;
+       }
+       rdev->bios = kmalloc(size, GFP_KERNEL);
+       if (rdev->bios == NULL) {
+               iounmap(bios);
+               DRM_ERROR("kmalloc failed\n");
+               return false;
+       }
+       memcpy(rdev->bios, bios, size);
+       iounmap(bios);
+       return true;
+}
+
 static bool radeon_read_bios(struct radeon_device *rdev)
 {
        uint8_t __iomem *bios;
        size_t size;
 
        rdev->bios = NULL;
+       /* XXX: some cards may return 0 for rom size? ddx has a workaround */
        bios = pci_map_rom(rdev->pdev, &size);
        if (!bios) {
                return false;
@@ -341,7 +379,9 @@ static bool legacy_read_disabled_bios(struct radeon_device *rdev)
 
 static bool radeon_read_disabled_bios(struct radeon_device *rdev)
 {
-       if (rdev->family >= CHIP_RV770)
+       if (rdev->flags & RADEON_IS_IGP)
+               return igp_read_bios_from_vram(rdev);
+       else if (rdev->family >= CHIP_RV770)
                return r700_read_disabled_bios(rdev);
        else if (rdev->family >= CHIP_R600)
                return r600_read_disabled_bios(rdev);
@@ -356,7 +396,12 @@ bool radeon_get_bios(struct radeon_device *rdev)
        bool r;
        uint16_t tmp;
 
-       r = radeon_read_bios(rdev);
+       if (rdev->flags & RADEON_IS_IGP) {
+               r = igp_read_bios_from_vram(rdev);
+               if (r == false)
+                       r = radeon_read_bios(rdev);
+       } else
+               r = radeon_read_bios(rdev);
        if (r == false) {
                r = radeon_read_disabled_bios(rdev);
        }
index 152eef1..f5c32a7 100644 (file)
@@ -411,7 +411,7 @@ void radeon_legacy_set_clock_gating(struct radeon_device *rdev, int enable)
                                        R300_PIXCLK_TRANS_ALWAYS_ONb |
                                        R300_PIXCLK_TVO_ALWAYS_ONb |
                                        R300_P2G2CLK_ALWAYS_ONb |
-                                       R300_P2G2CLK_ALWAYS_ONb);
+                                       R300_P2G2CLK_DAC_ALWAYS_ONb);
                                WREG32_PLL(RADEON_PIXCLKS_CNTL, tmp);
                        } else if (rdev->family >= CHIP_RV350) {
                                tmp = RREG32_PLL(R300_SCLK_CNTL2);
@@ -464,7 +464,7 @@ void radeon_legacy_set_clock_gating(struct radeon_device *rdev, int enable)
                                        R300_PIXCLK_TRANS_ALWAYS_ONb |
                                        R300_PIXCLK_TVO_ALWAYS_ONb |
                                        R300_P2G2CLK_ALWAYS_ONb |
-                                       R300_P2G2CLK_ALWAYS_ONb);
+                                       R300_P2G2CLK_DAC_ALWAYS_ONb);
                                WREG32_PLL(RADEON_PIXCLKS_CNTL, tmp);
 
                                tmp = RREG32_PLL(RADEON_MCLK_MISC);
@@ -654,7 +654,7 @@ void radeon_legacy_set_clock_gating(struct radeon_device *rdev, int enable)
                                 R300_PIXCLK_TRANS_ALWAYS_ONb |
                                 R300_PIXCLK_TVO_ALWAYS_ONb |
                                 R300_P2G2CLK_ALWAYS_ONb |
-                                R300_P2G2CLK_ALWAYS_ONb |
+                                R300_P2G2CLK_DAC_ALWAYS_ONb |
                                 R300_DISP_DAC_PIXCLK_DAC2_BLANK_OFF);
                        WREG32_PLL(RADEON_PIXCLKS_CNTL, tmp);
                } else if (rdev->family >= CHIP_RV350) {
@@ -705,7 +705,7 @@ void radeon_legacy_set_clock_gating(struct radeon_device *rdev, int enable)
                                 R300_PIXCLK_TRANS_ALWAYS_ONb |
                                 R300_PIXCLK_TVO_ALWAYS_ONb |
                                 R300_P2G2CLK_ALWAYS_ONb |
-                                R300_P2G2CLK_ALWAYS_ONb |
+                                R300_P2G2CLK_DAC_ALWAYS_ONb |
                                 R300_DISP_DAC_PIXCLK_DAC2_BLANK_OFF);
                        WREG32_PLL(RADEON_PIXCLKS_CNTL, tmp);
                } else {
index ec835d5..df98814 100644 (file)
@@ -322,10 +322,6 @@ int radeon_asic_init(struct radeon_device *rdev)
        case CHIP_RV380:
                rdev->asic = &r300_asic;
                if (rdev->flags & RADEON_IS_PCIE) {
-                       rdev->asic->gart_init = &rv370_pcie_gart_init;
-                       rdev->asic->gart_fini = &rv370_pcie_gart_fini;
-                       rdev->asic->gart_enable = &rv370_pcie_gart_enable;
-                       rdev->asic->gart_disable = &rv370_pcie_gart_disable;
                        rdev->asic->gart_tlb_flush = &rv370_pcie_gart_tlb_flush;
                        rdev->asic->gart_set_page = &rv370_pcie_gart_set_page;
                }
@@ -485,7 +481,6 @@ void radeon_combios_fini(struct radeon_device *rdev)
 static unsigned int radeon_vga_set_decode(void *cookie, bool state)
 {
        struct radeon_device *rdev = cookie;
-
        radeon_vga_set_state(rdev, state);
        if (state)
                return VGA_RSRC_LEGACY_IO | VGA_RSRC_LEGACY_MEM |
@@ -493,6 +488,29 @@ static unsigned int radeon_vga_set_decode(void *cookie, bool state)
        else
                return VGA_RSRC_NORMAL_IO | VGA_RSRC_NORMAL_MEM;
 }
+
+void radeon_agp_disable(struct radeon_device *rdev)
+{
+       rdev->flags &= ~RADEON_IS_AGP;
+       if (rdev->family >= CHIP_R600) {
+               DRM_INFO("Forcing AGP to PCIE mode\n");
+               rdev->flags |= RADEON_IS_PCIE;
+       } else if (rdev->family >= CHIP_RV515 ||
+                       rdev->family == CHIP_RV380 ||
+                       rdev->family == CHIP_RV410 ||
+                       rdev->family == CHIP_R423) {
+               DRM_INFO("Forcing AGP to PCIE mode\n");
+               rdev->flags |= RADEON_IS_PCIE;
+               rdev->asic->gart_tlb_flush = &rv370_pcie_gart_tlb_flush;
+               rdev->asic->gart_set_page = &rv370_pcie_gart_set_page;
+       } else {
+               DRM_INFO("Forcing AGP to PCI mode\n");
+               rdev->flags |= RADEON_IS_PCI;
+               rdev->asic->gart_tlb_flush = &r100_pci_gart_tlb_flush;
+               rdev->asic->gart_set_page = &r100_pci_gart_set_page;
+       }
+}
+
 /*
  * Radeon device.
  */
@@ -531,32 +549,7 @@ int radeon_device_init(struct radeon_device *rdev,
        }
 
        if (radeon_agpmode == -1) {
-               rdev->flags &= ~RADEON_IS_AGP;
-               if (rdev->family >= CHIP_R600) {
-                       DRM_INFO("Forcing AGP to PCIE mode\n");
-                       rdev->flags |= RADEON_IS_PCIE;
-               } else if (rdev->family >= CHIP_RV515 ||
-                          rdev->family == CHIP_RV380 ||
-                          rdev->family == CHIP_RV410 ||
-                          rdev->family == CHIP_R423) {
-                       DRM_INFO("Forcing AGP to PCIE mode\n");
-                       rdev->flags |= RADEON_IS_PCIE;
-                       rdev->asic->gart_init = &rv370_pcie_gart_init;
-                       rdev->asic->gart_fini = &rv370_pcie_gart_fini;
-                       rdev->asic->gart_enable = &rv370_pcie_gart_enable;
-                       rdev->asic->gart_disable = &rv370_pcie_gart_disable;
-                       rdev->asic->gart_tlb_flush = &rv370_pcie_gart_tlb_flush;
-                       rdev->asic->gart_set_page = &rv370_pcie_gart_set_page;
-               } else {
-                       DRM_INFO("Forcing AGP to PCI mode\n");
-                       rdev->flags |= RADEON_IS_PCI;
-                       rdev->asic->gart_init = &r100_pci_gart_init;
-                       rdev->asic->gart_fini = &r100_pci_gart_fini;
-                       rdev->asic->gart_enable = &r100_pci_gart_enable;
-                       rdev->asic->gart_disable = &r100_pci_gart_disable;
-                       rdev->asic->gart_tlb_flush = &r100_pci_gart_tlb_flush;
-                       rdev->asic->gart_set_page = &r100_pci_gart_set_page;
-               }
+               radeon_agp_disable(rdev);
        }
 
        /* set DMA mask + need_dma32 flags.
@@ -588,111 +581,26 @@ int radeon_device_init(struct radeon_device *rdev,
        DRM_INFO("register mmio base: 0x%08X\n", (uint32_t)rdev->rmmio_base);
        DRM_INFO("register mmio size: %u\n", (unsigned)rdev->rmmio_size);
 
-       rdev->new_init_path = false;
-       r = radeon_init(rdev);
-       if (r) {
-               return r;
-       }
-
        /* if we have > 1 VGA cards, then disable the radeon VGA resources */
-       r = vga_client_register(rdev->pdev, rdev, NULL, radeon_vga_set_decode);
-       if (r) {
-               return -EINVAL;
-       }
-
-       if (!rdev->new_init_path) {
-               /* Setup errata flags */
-               radeon_errata(rdev);
-               /* Initialize scratch registers */
-               radeon_scratch_init(rdev);
-               /* Initialize surface registers */
-               radeon_surface_init(rdev);
+       /* this will fail for cards that aren't VGA class devices, just
+        * ignore it */
+       vga_client_register(rdev->pdev, rdev, NULL, radeon_vga_set_decode);
 
-               /* BIOS*/
-               if (!radeon_get_bios(rdev)) {
-                       if (ASIC_IS_AVIVO(rdev))
-                               return -EINVAL;
-               }
-               if (rdev->is_atom_bios) {
-                       r = radeon_atombios_init(rdev);
-                       if (r) {
-                               return r;
-                       }
-               } else {
-                       r = radeon_combios_init(rdev);
-                       if (r) {
-                               return r;
-                       }
-               }
-               /* Reset gpu before posting otherwise ATOM will enter infinite loop */
-               if (radeon_gpu_reset(rdev)) {
-                       /* FIXME: what do we want to do here ? */
-               }
-               /* check if cards are posted or not */
-               if (!radeon_card_posted(rdev) && rdev->bios) {
-                       DRM_INFO("GPU not posted. posting now...\n");
-                       if (rdev->is_atom_bios) {
-                               atom_asic_init(rdev->mode_info.atom_context);
-                       } else {
-                               radeon_combios_asic_init(rdev->ddev);
-                       }
-               }
-               /* Get clock & vram information */
-               radeon_get_clock_info(rdev->ddev);
-               radeon_vram_info(rdev);
-               /* Initialize clocks */
-               r = radeon_clocks_init(rdev);
-               if (r) {
-                       return r;
-               }
+       r = radeon_init(rdev);
+       if (r)
+               return r;
 
-               /* Initialize memory controller (also test AGP) */
-               r = radeon_mc_init(rdev);
-               if (r) {
-                       return r;
-               }
-               /* Fence driver */
-               r = radeon_fence_driver_init(rdev);
-               if (r) {
-                       return r;
-               }
-               r = radeon_irq_kms_init(rdev);
-               if (r) {
-                       return r;
-               }
-               /* Memory manager */
-               r = radeon_object_init(rdev);
-               if (r) {
-                       return r;
-               }
-               r = radeon_gpu_gart_init(rdev);
+       if (rdev->flags & RADEON_IS_AGP && !rdev->accel_working) {
+               /* Acceleration not working on AGP card try again
+                * with fallback to PCI or PCIE GART
+                */
+               radeon_gpu_reset(rdev);
+               radeon_fini(rdev);
+               radeon_agp_disable(rdev);
+               r = radeon_init(rdev);
                if (r)
                        return r;
-               /* Initialize GART (initialize after TTM so we can allocate
-                * memory through TTM but finalize after TTM) */
-               r = radeon_gart_enable(rdev);
-               if (r)
-                       return 0;
-                       r = radeon_gem_init(rdev);
-               if (r)
-                       return 0;
-
-               /* 1M ring buffer */
-               r = radeon_cp_init(rdev, 1024 * 1024);
-               if (r)
-                       return 0;
-               r = radeon_wb_init(rdev);
-               if (r)
-                       DRM_ERROR("radeon: failled initializing WB (%d).\n", r);
-               r = radeon_ib_pool_init(rdev);
-               if (r)
-                       return 0;
-               r = radeon_ib_test(rdev);
-               if (r)
-                       return 0;
-               rdev->accel_working = true;
        }
-       DRM_INFO("radeon: kernel modesetting successfully initialized.\n");
        if (radeon_testing) {
                radeon_test_moves(rdev);
        }
@@ -706,32 +614,8 @@ void radeon_device_fini(struct radeon_device *rdev)
 {
        DRM_INFO("radeon: finishing device.\n");
        rdev->shutdown = true;
-       /* Order matter so becarefull if you rearrange anythings */
-       if (!rdev->new_init_path) {
-               radeon_ib_pool_fini(rdev);
-               radeon_cp_fini(rdev);
-               radeon_wb_fini(rdev);
-               radeon_gpu_gart_fini(rdev);
-               radeon_gem_fini(rdev);
-               radeon_mc_fini(rdev);
-#if __OS_HAS_AGP
-               radeon_agp_fini(rdev);
-#endif
-               radeon_irq_kms_fini(rdev);
-               vga_client_register(rdev->pdev, NULL, NULL, NULL);
-               radeon_fence_driver_fini(rdev);
-               radeon_clocks_fini(rdev);
-               radeon_object_fini(rdev);
-               if (rdev->is_atom_bios) {
-                       radeon_atombios_fini(rdev);
-               } else {
-                       radeon_combios_fini(rdev);
-               }
-               kfree(rdev->bios);
-               rdev->bios = NULL;
-       } else {
-               radeon_fini(rdev);
-       }
+       radeon_fini(rdev);
+       vga_client_register(rdev->pdev, NULL, NULL, NULL);
        iounmap(rdev->rmmio);
        rdev->rmmio = NULL;
 }
@@ -771,14 +655,7 @@ int radeon_suspend_kms(struct drm_device *dev, pm_message_t state)
 
        radeon_save_bios_scratch_regs(rdev);
 
-       if (!rdev->new_init_path) {
-               radeon_cp_disable(rdev);
-               radeon_gart_disable(rdev);
-               rdev->irq.sw_int = false;
-               radeon_irq_set(rdev);
-       } else {
-               radeon_suspend(rdev);
-       }
+       radeon_suspend(rdev);
        /* evict remaining vram memory */
        radeon_object_evict_vram(rdev);
 
@@ -797,7 +674,6 @@ int radeon_suspend_kms(struct drm_device *dev, pm_message_t state)
 int radeon_resume_kms(struct drm_device *dev)
 {
        struct radeon_device *rdev = dev->dev_private;
-       int r;
 
        acquire_console_sem();
        pci_set_power_state(dev->pdev, PCI_D0);
@@ -807,43 +683,7 @@ int radeon_resume_kms(struct drm_device *dev)
                return -1;
        }
        pci_set_master(dev->pdev);
-       /* Reset gpu before posting otherwise ATOM will enter infinite loop */
-       if (!rdev->new_init_path) {
-               if (radeon_gpu_reset(rdev)) {
-                       /* FIXME: what do we want to do here ? */
-               }
-               /* post card */
-               if (rdev->is_atom_bios) {
-                       atom_asic_init(rdev->mode_info.atom_context);
-               } else {
-                       radeon_combios_asic_init(rdev->ddev);
-               }
-               /* Initialize clocks */
-               r = radeon_clocks_init(rdev);
-               if (r) {
-                       release_console_sem();
-                       return r;
-               }
-               /* Enable IRQ */
-               rdev->irq.sw_int = true;
-               radeon_irq_set(rdev);
-               /* Initialize GPU Memory Controller */
-               r = radeon_mc_init(rdev);
-               if (r) {
-                       goto out;
-               }
-               r = radeon_gart_enable(rdev);
-               if (r) {
-                       goto out;
-               }
-               r = radeon_cp_init(rdev, rdev->cp.ring_size);
-               if (r) {
-                       goto out;
-               }
-       } else {
-               radeon_resume(rdev);
-       }
-out:
+       radeon_resume(rdev);
        radeon_restore_bios_scratch_regs(rdev);
        fb_set_suspend(rdev->fbdev_info, 0);
        release_console_sem();
index 5d8141b..3655d91 100644 (file)
@@ -106,24 +106,33 @@ void radeon_crtc_load_lut(struct drm_crtc *crtc)
                legacy_crtc_load_lut(crtc);
 }
 
-/** Sets the color ramps on behalf of RandR */
+/** Sets the color ramps on behalf of fbcon */
 void radeon_crtc_fb_gamma_set(struct drm_crtc *crtc, u16 red, u16 green,
                              u16 blue, int regno)
 {
        struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
 
-       if (regno == 0)
-               DRM_DEBUG("gamma set %d\n", radeon_crtc->crtc_id);
        radeon_crtc->lut_r[regno] = red >> 6;
        radeon_crtc->lut_g[regno] = green >> 6;
        radeon_crtc->lut_b[regno] = blue >> 6;
 }
 
+/** Gets the color ramps on behalf of fbcon */
+void radeon_crtc_fb_gamma_get(struct drm_crtc *crtc, u16 *red, u16 *green,
+                             u16 *blue, int regno)
+{
+       struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
+
+       *red = radeon_crtc->lut_r[regno] << 6;
+       *green = radeon_crtc->lut_g[regno] << 6;
+       *blue = radeon_crtc->lut_b[regno] << 6;
+}
+
 static void radeon_crtc_gamma_set(struct drm_crtc *crtc, u16 *red, u16 *green,
                                  u16 *blue, uint32_t size)
 {
        struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
-       int i, j;
+       int i;
 
        if (size != 256) {
                return;
@@ -132,23 +141,11 @@ static void radeon_crtc_gamma_set(struct drm_crtc *crtc, u16 *red, u16 *green,
                return;
        }
 
-       if (crtc->fb->depth == 16) {
-               for (i = 0; i < 64; i++) {
-                       if (i <= 31) {
-                               for (j = 0; j < 8; j++) {
-                                       radeon_crtc->lut_r[i * 8 + j] = red[i] >> 6;
-                                       radeon_crtc->lut_b[i * 8 + j] = blue[i] >> 6;
-                               }
-                       }
-                       for (j = 0; j < 4; j++)
-                               radeon_crtc->lut_g[i * 4 + j] = green[i] >> 6;
-               }
-       } else {
-               for (i = 0; i < 256; i++) {
-                       radeon_crtc->lut_r[i] = red[i] >> 6;
-                       radeon_crtc->lut_g[i] = green[i] >> 6;
-                       radeon_crtc->lut_b[i] = blue[i] >> 6;
-               }
+       /* userspace palettes are always correct as is */
+       for (i = 0; i < 256; i++) {
+               radeon_crtc->lut_r[i] = red[i] >> 6;
+               radeon_crtc->lut_g[i] = green[i] >> 6;
+               radeon_crtc->lut_b[i] = blue[i] >> 6;
        }
 
        radeon_crtc_load_lut(crtc);
@@ -724,7 +721,11 @@ int radeon_modeset_init(struct radeon_device *rdev)
        if (ret) {
                return ret;
        }
-       /* allocate crtcs - TODO single crtc */
+
+       if (rdev->flags & RADEON_SINGLE_CRTC)
+               num_crtc = 1;
+
+       /* allocate crtcs */
        for (i = 0; i < num_crtc; i++) {
                radeon_crtc_init(rdev->ddev, i);
        }
index 6216467..a65ab1a 100644 (file)
@@ -1345,6 +1345,7 @@ radeon_atombios_set_dig_info(struct radeon_encoder *radeon_encoder)
 void
 radeon_add_atom_encoder(struct drm_device *dev, uint32_t encoder_id, uint32_t supported_device)
 {
+       struct radeon_device *rdev = dev->dev_private;
        struct drm_encoder *encoder;
        struct radeon_encoder *radeon_encoder;
 
@@ -1364,7 +1365,10 @@ radeon_add_atom_encoder(struct drm_device *dev, uint32_t encoder_id, uint32_t su
                return;
 
        encoder = &radeon_encoder->base;
-       encoder->possible_crtcs = 0x3;
+       if (rdev->flags & RADEON_SINGLE_CRTC)
+               encoder->possible_crtcs = 0x1;
+       else
+               encoder->possible_crtcs = 0x3;
        encoder->possible_clones = 0;
 
        radeon_encoder->enc_priv = NULL;
index 1ba704e..b38c4c8 100644 (file)
@@ -55,6 +55,7 @@ static struct fb_ops radeonfb_ops = {
        .fb_imageblit = cfb_imageblit,
        .fb_pan_display = drm_fb_helper_pan_display,
        .fb_blank = drm_fb_helper_blank,
+       .fb_setcmap = drm_fb_helper_setcmap,
 };
 
 /**
@@ -123,6 +124,7 @@ static int radeon_align_pitch(struct radeon_device *rdev, int width, int bpp, bo
 
 static struct drm_fb_helper_funcs radeon_fb_helper_funcs = {
        .gamma_set = radeon_crtc_fb_gamma_set,
+       .gamma_get = radeon_crtc_fb_gamma_get,
 };
 
 int radeonfb_create(struct drm_device *dev,
@@ -146,9 +148,15 @@ int radeonfb_create(struct drm_device *dev,
        unsigned long tmp;
        bool fb_tiled = false; /* useful for testing */
        u32 tiling_flags = 0;
+       int crtc_count;
 
        mode_cmd.width = surface_width;
        mode_cmd.height = surface_height;
+
+       /* avivo can't scanout real 24bpp */
+       if ((surface_bpp == 24) && ASIC_IS_AVIVO(rdev))
+               surface_bpp = 32;
+
        mode_cmd.bpp = surface_bpp;
        /* need to align pitch with crtc limits */
        mode_cmd.pitch = radeon_align_pitch(rdev, mode_cmd.width, mode_cmd.bpp, fb_tiled) * ((mode_cmd.bpp + 1) / 8);
@@ -217,7 +225,11 @@ int radeonfb_create(struct drm_device *dev,
        rfbdev = info->par;
        rfbdev->helper.funcs = &radeon_fb_helper_funcs;
        rfbdev->helper.dev = dev;
-       ret = drm_fb_helper_init_crtc_count(&rfbdev->helper, 2,
+       if (rdev->flags & RADEON_SINGLE_CRTC)
+               crtc_count = 1;
+       else
+               crtc_count = 2;
+       ret = drm_fb_helper_init_crtc_count(&rfbdev->helper, crtc_count,
                                            RADEONFB_CONN_LIMIT);
        if (ret)
                goto out_unref;
@@ -234,7 +246,7 @@ int radeonfb_create(struct drm_device *dev,
 
        strcpy(info->fix.id, "radeondrmfb");
 
-       drm_fb_helper_fill_fix(info, fb->pitch);
+       drm_fb_helper_fill_fix(info, fb->pitch, fb->depth);
 
        info->flags = FBINFO_DEFAULT;
        info->fbops = &radeonfb_ops;
@@ -309,7 +321,7 @@ int radeon_parse_options(char *options)
 
 int radeonfb_probe(struct drm_device *dev)
 {
-       return drm_fb_helper_single_fb_probe(dev, &radeonfb_create);
+       return drm_fb_helper_single_fb_probe(dev, 32, &radeonfb_create);
 }
 
 int radeonfb_remove(struct drm_device *dev, struct drm_framebuffer *fb)
index 1841145..8e0a875 100644 (file)
@@ -83,8 +83,12 @@ void radeon_driver_irq_uninstall_kms(struct drm_device *dev)
 int radeon_irq_kms_init(struct radeon_device *rdev)
 {
        int r = 0;
+       int num_crtc = 2;
 
-       r = drm_vblank_init(rdev->ddev, 2);
+       if (rdev->flags & RADEON_SINGLE_CRTC)
+               num_crtc = 1;
+
+       r = drm_vblank_init(rdev->ddev, num_crtc);
        if (r) {
                return r;
        }
index 2b997a1..36410f8 100644 (file)
@@ -1053,6 +1053,7 @@ static const struct drm_crtc_helper_funcs legacy_helper_funcs = {
        .mode_set_base = radeon_crtc_set_base,
        .prepare = radeon_crtc_prepare,
        .commit = radeon_crtc_commit,
+       .load_lut = radeon_crtc_load_lut,
 };
 
 
index b1547f7..6ceb958 100644 (file)
@@ -881,7 +881,7 @@ static void radeon_legacy_tv_dac_mode_set(struct drm_encoder *encoder,
                                        R420_TV_DAC_DACADJ_MASK |
                                        R420_TV_DAC_RDACPD |
                                        R420_TV_DAC_GDACPD |
-                                       R420_TV_DAC_GDACPD |
+                                       R420_TV_DAC_BDACPD |
                                        R420_TV_DAC_TVENABLE);
                } else {
                        tv_dac_cntl &= ~(RADEON_TV_DAC_STD_MASK |
@@ -889,7 +889,7 @@ static void radeon_legacy_tv_dac_mode_set(struct drm_encoder *encoder,
                                        RADEON_TV_DAC_DACADJ_MASK |
                                        RADEON_TV_DAC_RDACPD |
                                        RADEON_TV_DAC_GDACPD |
-                                       RADEON_TV_DAC_GDACPD);
+                                       RADEON_TV_DAC_BDACPD);
                }
 
                /*  FIXME TV */
@@ -1318,7 +1318,10 @@ radeon_add_legacy_encoder(struct drm_device *dev, uint32_t encoder_id, uint32_t
                return;
 
        encoder = &radeon_encoder->base;
-       encoder->possible_crtcs = 0x3;
+       if (rdev->flags & RADEON_SINGLE_CRTC)
+               encoder->possible_crtcs = 0x1;
+       else
+               encoder->possible_crtcs = 0x3;
        encoder->possible_clones = 0;
 
        radeon_encoder->enc_priv = NULL;
index 570a587..e612268 100644 (file)
@@ -407,6 +407,8 @@ extern void
 radeon_combios_encoder_dpms_scratch_regs(struct drm_encoder *encoder, bool on);
 extern void radeon_crtc_fb_gamma_set(struct drm_crtc *crtc, u16 red, u16 green,
                                     u16 blue, int regno);
+extern void radeon_crtc_fb_gamma_get(struct drm_crtc *crtc, u16 *red, u16 *green,
+                                    u16 *blue, int regno);
 struct drm_framebuffer *radeon_framebuffer_create(struct drm_device *dev,
                                                  struct drm_mode_fb_cmd *mode_cmd,
                                                  struct drm_gem_object *obj);
index 73af463..1f056da 100644 (file)
@@ -400,11 +400,9 @@ void radeon_object_list_add_object(struct radeon_object_list *lobj,
 int radeon_object_list_reserve(struct list_head *head)
 {
        struct radeon_object_list *lobj;
-       struct list_head *i;
        int r;
 
-       list_for_each(i, head) {
-               lobj = list_entry(i, struct radeon_object_list, list);
+       list_for_each_entry(lobj, head, list){
                if (!lobj->robj->pin_count) {
                        r = radeon_object_reserve(lobj->robj, true);
                        if (unlikely(r != 0)) {
@@ -420,13 +418,10 @@ int radeon_object_list_reserve(struct list_head *head)
 void radeon_object_list_unreserve(struct list_head *head)
 {
        struct radeon_object_list *lobj;
-       struct list_head *i;
 
-       list_for_each(i, head) {
-               lobj = list_entry(i, struct radeon_object_list, list);
+       list_for_each_entry(lobj, head, list) {
                if (!lobj->robj->pin_count) {
                        radeon_object_unreserve(lobj->robj);
-               } else {
                }
        }
 }
@@ -436,7 +431,6 @@ int radeon_object_list_validate(struct list_head *head, void *fence)
        struct radeon_object_list *lobj;
        struct radeon_object *robj;
        struct radeon_fence *old_fence = NULL;
-       struct list_head *i;
        int r;
 
        r = radeon_object_list_reserve(head);
@@ -444,8 +438,7 @@ int radeon_object_list_validate(struct list_head *head, void *fence)
                radeon_object_list_unreserve(head);
                return r;
        }
-       list_for_each(i, head) {
-               lobj = list_entry(i, struct radeon_object_list, list);
+       list_for_each_entry(lobj, head, list) {
                robj = lobj->robj;
                if (!robj->pin_count) {
                        if (lobj->wdomain) {
@@ -482,10 +475,8 @@ void radeon_object_list_unvalidate(struct list_head *head)
 {
        struct radeon_object_list *lobj;
        struct radeon_fence *old_fence = NULL;
-       struct list_head *i;
 
-       list_for_each(i, head) {
-               lobj = list_entry(i, struct radeon_object_list, list);
+       list_for_each_entry(lobj, head, list) {
                old_fence = (struct radeon_fence *)lobj->robj->tobj.sync_obj;
                lobj->robj->tobj.sync_obj = NULL;
                if (old_fence) {
diff --git a/drivers/gpu/drm/radeon/rs100d.h b/drivers/gpu/drm/radeon/rs100d.h
new file mode 100644 (file)
index 0000000..48a913a
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2008 Advanced Micro Devices, Inc.
+ * Copyright 2008 Red Hat Inc.
+ * Copyright 2009 Jerome Glisse.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: Dave Airlie
+ *          Alex Deucher
+ *          Jerome Glisse
+ */
+#ifndef __RS100D_H__
+#define __RS100D_H__
+
+/* Registers */
+#define R_00015C_NB_TOM                              0x00015C
+#define   S_00015C_MC_FB_START(x)                      (((x) & 0xFFFF) << 0)
+#define   G_00015C_MC_FB_START(x)                      (((x) >> 0) & 0xFFFF)
+#define   C_00015C_MC_FB_START                         0xFFFF0000
+#define   S_00015C_MC_FB_TOP(x)                        (((x) & 0xFFFF) << 16)
+#define   G_00015C_MC_FB_TOP(x)                        (((x) >> 16) & 0xFFFF)
+#define   C_00015C_MC_FB_TOP                           0x0000FFFF
+
+#endif
index a3fbdad..a769c29 100644 (file)
  */
 #include <linux/seq_file.h>
 #include <drm/drmP.h>
-#include "radeon_reg.h"
 #include "radeon.h"
+#include "rs400d.h"
 
-/* rs400,rs480 depends on : */
-void r100_hdp_reset(struct radeon_device *rdev);
-void r100_mc_disable_clients(struct radeon_device *rdev);
-int r300_mc_wait_for_idle(struct radeon_device *rdev);
-void r420_pipes_init(struct radeon_device *rdev);
+/* This files gather functions specifics to : rs400,rs480 */
+static int rs400_debugfs_pcie_gart_info_init(struct radeon_device *rdev);
 
-/* This files gather functions specifics to :
- * rs400,rs480
- *
- * Some of these functions might be used by newer ASICs.
- */
-void rs400_gpu_init(struct radeon_device *rdev);
-int rs400_debugfs_pcie_gart_info_init(struct radeon_device *rdev);
-
-
-/*
- * GART functions.
- */
 void rs400_gart_adjust_size(struct radeon_device *rdev)
 {
        /* Check gart size */
@@ -238,61 +223,6 @@ int rs400_gart_set_page(struct radeon_device *rdev, int i, uint64_t addr)
        return 0;
 }
 
-
-/*
- * MC functions.
- */
-int rs400_mc_init(struct radeon_device *rdev)
-{
-       uint32_t tmp;
-       int r;
-
-       if (r100_debugfs_rbbm_init(rdev)) {
-               DRM_ERROR("Failed to register debugfs file for RBBM !\n");
-       }
-
-       rs400_gpu_init(rdev);
-       rs400_gart_disable(rdev);
-       rdev->mc.gtt_location = rdev->mc.mc_vram_size;
-       rdev->mc.gtt_location += (rdev->mc.gtt_size - 1);
-       rdev->mc.gtt_location &= ~(rdev->mc.gtt_size - 1);
-       r = radeon_mc_setup(rdev);
-       if (r) {
-               return r;
-       }
-
-       r100_mc_disable_clients(rdev);
-       if (r300_mc_wait_for_idle(rdev)) {
-               printk(KERN_WARNING "Failed to wait MC idle while "
-                      "programming pipes. Bad things might happen.\n");
-       }
-
-       tmp = rdev->mc.vram_location + rdev->mc.mc_vram_size - 1;
-       tmp = REG_SET(RADEON_MC_FB_TOP, tmp >> 16);
-       tmp |= REG_SET(RADEON_MC_FB_START, rdev->mc.vram_location >> 16);
-       WREG32(RADEON_MC_FB_LOCATION, tmp);
-       tmp = RREG32(RADEON_HOST_PATH_CNTL) | RADEON_HP_LIN_RD_CACHE_DIS;
-       WREG32(RADEON_HOST_PATH_CNTL, tmp | RADEON_HDP_SOFT_RESET | RADEON_HDP_READ_BUFFER_INVALIDATE);
-       (void)RREG32(RADEON_HOST_PATH_CNTL);
-       WREG32(RADEON_HOST_PATH_CNTL, tmp);
-       (void)RREG32(RADEON_HOST_PATH_CNTL);
-
-       return 0;
-}
-
-void rs400_mc_fini(struct radeon_device *rdev)
-{
-}
-
-
-/*
- * Global GPU functions
- */
-void rs400_errata(struct radeon_device *rdev)
-{
-       rdev->pll_errata = 0;
-}
-
 void rs400_gpu_init(struct radeon_device *rdev)
 {
        /* FIXME: HDP same place on rs400 ? */
@@ -305,10 +235,6 @@ void rs400_gpu_init(struct radeon_device *rdev)
        }
 }
 
-
-/*
- * VRAM info.
- */
 void rs400_vram_info(struct radeon_device *rdev)
 {
        rs400_gart_adjust_size(rdev);
@@ -319,10 +245,6 @@ void rs400_vram_info(struct radeon_device *rdev)
        r100_vram_init_sizes(rdev);
 }
 
-
-/*
- * Indirect registers accessor
- */
 uint32_t rs400_mc_rreg(struct radeon_device *rdev, uint32_t reg)
 {
        uint32_t r;
@@ -340,10 +262,6 @@ void rs400_mc_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v)
        WREG32(RS480_NB_MC_INDEX, 0xff);
 }
 
-
-/*
- * Debugfs info
- */
 #if defined(CONFIG_DEBUG_FS)
 static int rs400_debugfs_gart_info(struct seq_file *m, void *data)
 {
@@ -419,7 +337,7 @@ static struct drm_info_list rs400_gart_info_list[] = {
 };
 #endif
 
-int rs400_debugfs_pcie_gart_info_init(struct radeon_device *rdev)
+static int rs400_debugfs_pcie_gart_info_init(struct radeon_device *rdev)
 {
 #if defined(CONFIG_DEBUG_FS)
        return radeon_debugfs_add_files(rdev, rs400_gart_info_list, 1);
@@ -427,3 +345,188 @@ int rs400_debugfs_pcie_gart_info_init(struct radeon_device *rdev)
        return 0;
 #endif
 }
+
+static int rs400_mc_init(struct radeon_device *rdev)
+{
+       int r;
+       u32 tmp;
+
+       /* Setup GPU memory space */
+       tmp = G_00015C_MC_FB_START(RREG32(R_00015C_NB_TOM));
+       rdev->mc.vram_location = G_00015C_MC_FB_START(tmp) << 16;
+       rdev->mc.gtt_location = 0xFFFFFFFFUL;
+       r = radeon_mc_setup(rdev);
+       if (r)
+               return r;
+       return 0;
+}
+
+void rs400_mc_program(struct radeon_device *rdev)
+{
+       struct r100_mc_save save;
+
+       /* Stops all mc clients */
+       r100_mc_stop(rdev, &save);
+
+       /* Wait for mc idle */
+       if (r300_mc_wait_for_idle(rdev))
+               dev_warn(rdev->dev, "Wait MC idle timeout before updating MC.\n");
+       WREG32(R_000148_MC_FB_LOCATION,
+               S_000148_MC_FB_START(rdev->mc.vram_start >> 16) |
+               S_000148_MC_FB_TOP(rdev->mc.vram_end >> 16));
+
+       r100_mc_resume(rdev, &save);
+}
+
+static int rs400_startup(struct radeon_device *rdev)
+{
+       int r;
+
+       rs400_mc_program(rdev);
+       /* Resume clock */
+       r300_clock_startup(rdev);
+       /* Initialize GPU configuration (# pipes, ...) */
+       rs400_gpu_init(rdev);
+       /* Initialize GART (initialize after TTM so we can allocate
+        * memory through TTM but finalize after TTM) */
+       r = rs400_gart_enable(rdev);
+       if (r)
+               return r;
+       /* Enable IRQ */
+       rdev->irq.sw_int = true;
+       r100_irq_set(rdev);
+       /* 1M ring buffer */
+       r = r100_cp_init(rdev, 1024 * 1024);
+       if (r) {
+               dev_err(rdev->dev, "failled initializing CP (%d).\n", r);
+               return r;
+       }
+       r = r100_wb_init(rdev);
+       if (r)
+               dev_err(rdev->dev, "failled initializing WB (%d).\n", r);
+       r = r100_ib_init(rdev);
+       if (r) {
+               dev_err(rdev->dev, "failled initializing IB (%d).\n", r);
+               return r;
+       }
+       return 0;
+}
+
+int rs400_resume(struct radeon_device *rdev)
+{
+       /* Make sur GART are not working */
+       rs400_gart_disable(rdev);
+       /* Resume clock before doing reset */
+       r300_clock_startup(rdev);
+       /* Reset gpu before posting otherwise ATOM will enter infinite loop */
+       if (radeon_gpu_reset(rdev)) {
+               dev_warn(rdev->dev, "GPU reset failed ! (0xE40=0x%08X, 0x7C0=0x%08X)\n",
+                       RREG32(R_000E40_RBBM_STATUS),
+                       RREG32(R_0007C0_CP_STAT));
+       }
+       /* post */
+       radeon_combios_asic_init(rdev->ddev);
+       /* Resume clock after posting */
+       r300_clock_startup(rdev);
+       return rs400_startup(rdev);
+}
+
+int rs400_suspend(struct radeon_device *rdev)
+{
+       r100_cp_disable(rdev);
+       r100_wb_disable(rdev);
+       r100_irq_disable(rdev);
+       rs400_gart_disable(rdev);
+       return 0;
+}
+
+void rs400_fini(struct radeon_device *rdev)
+{
+       rs400_suspend(rdev);
+       r100_cp_fini(rdev);
+       r100_wb_fini(rdev);
+       r100_ib_fini(rdev);
+       radeon_gem_fini(rdev);
+       rs400_gart_fini(rdev);
+       radeon_irq_kms_fini(rdev);
+       radeon_fence_driver_fini(rdev);
+       radeon_object_fini(rdev);
+       radeon_atombios_fini(rdev);
+       kfree(rdev->bios);
+       rdev->bios = NULL;
+}
+
+int rs400_init(struct radeon_device *rdev)
+{
+       int r;
+
+       /* Disable VGA */
+       r100_vga_render_disable(rdev);
+       /* Initialize scratch registers */
+       radeon_scratch_init(rdev);
+       /* Initialize surface registers */
+       radeon_surface_init(rdev);
+       /* TODO: disable VGA need to use VGA request */
+       /* BIOS*/
+       if (!radeon_get_bios(rdev)) {
+               if (ASIC_IS_AVIVO(rdev))
+                       return -EINVAL;
+       }
+       if (rdev->is_atom_bios) {
+               dev_err(rdev->dev, "Expecting combios for RS400/RS480 GPU\n");
+               return -EINVAL;
+       } else {
+               r = radeon_combios_init(rdev);
+               if (r)
+                       return r;
+       }
+       /* Reset gpu before posting otherwise ATOM will enter infinite loop */
+       if (radeon_gpu_reset(rdev)) {
+               dev_warn(rdev->dev,
+                       "GPU reset failed ! (0xE40=0x%08X, 0x7C0=0x%08X)\n",
+                       RREG32(R_000E40_RBBM_STATUS),
+                       RREG32(R_0007C0_CP_STAT));
+       }
+       /* check if cards are posted or not */
+       if (!radeon_card_posted(rdev) && rdev->bios) {
+               DRM_INFO("GPU not posted. posting now...\n");
+               radeon_combios_asic_init(rdev->ddev);
+       }
+       /* Initialize clocks */
+       radeon_get_clock_info(rdev->ddev);
+       /* Get vram informations */
+       rs400_vram_info(rdev);
+       /* Initialize memory controller (also test AGP) */
+       r = rs400_mc_init(rdev);
+       if (r)
+               return r;
+       /* Fence driver */
+       r = radeon_fence_driver_init(rdev);
+       if (r)
+               return r;
+       r = radeon_irq_kms_init(rdev);
+       if (r)
+               return r;
+       /* Memory manager */
+       r = radeon_object_init(rdev);
+       if (r)
+               return r;
+       r = rs400_gart_init(rdev);
+       if (r)
+               return r;
+       r300_set_reg_safe(rdev);
+       rdev->accel_working = true;
+       r = rs400_startup(rdev);
+       if (r) {
+               /* Somethings want wront with the accel init stop accel */
+               dev_err(rdev->dev, "Disabling GPU acceleration\n");
+               rs400_suspend(rdev);
+               r100_cp_fini(rdev);
+               r100_wb_fini(rdev);
+               r100_ib_fini(rdev);
+               rs400_gart_fini(rdev);
+               radeon_irq_kms_fini(rdev);
+               rdev->accel_working = false;
+       }
+       return 0;
+}
diff --git a/drivers/gpu/drm/radeon/rs400d.h b/drivers/gpu/drm/radeon/rs400d.h
new file mode 100644 (file)
index 0000000..6d8bac5
--- /dev/null
@@ -0,0 +1,160 @@
+/*
+ * Copyright 2008 Advanced Micro Devices, Inc.
+ * Copyright 2008 Red Hat Inc.
+ * Copyright 2009 Jerome Glisse.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: Dave Airlie
+ *          Alex Deucher
+ *          Jerome Glisse
+ */
+#ifndef __RS400D_H__
+#define __RS400D_H__
+
+/* Registers */
+#define R_000148_MC_FB_LOCATION                      0x000148
+#define   S_000148_MC_FB_START(x)                      (((x) & 0xFFFF) << 0)
+#define   G_000148_MC_FB_START(x)                      (((x) >> 0) & 0xFFFF)
+#define   C_000148_MC_FB_START                         0xFFFF0000
+#define   S_000148_MC_FB_TOP(x)                        (((x) & 0xFFFF) << 16)
+#define   G_000148_MC_FB_TOP(x)                        (((x) >> 16) & 0xFFFF)
+#define   C_000148_MC_FB_TOP                           0x0000FFFF
+#define R_00015C_NB_TOM                              0x00015C
+#define   S_00015C_MC_FB_START(x)                      (((x) & 0xFFFF) << 0)
+#define   G_00015C_MC_FB_START(x)                      (((x) >> 0) & 0xFFFF)
+#define   C_00015C_MC_FB_START                         0xFFFF0000
+#define   S_00015C_MC_FB_TOP(x)                        (((x) & 0xFFFF) << 16)
+#define   G_00015C_MC_FB_TOP(x)                        (((x) >> 16) & 0xFFFF)
+#define   C_00015C_MC_FB_TOP                           0x0000FFFF
+#define R_0007C0_CP_STAT                             0x0007C0
+#define   S_0007C0_MRU_BUSY(x)                         (((x) & 0x1) << 0)
+#define   G_0007C0_MRU_BUSY(x)                         (((x) >> 0) & 0x1)
+#define   C_0007C0_MRU_BUSY                            0xFFFFFFFE
+#define   S_0007C0_MWU_BUSY(x)                         (((x) & 0x1) << 1)
+#define   G_0007C0_MWU_BUSY(x)                         (((x) >> 1) & 0x1)
+#define   C_0007C0_MWU_BUSY                            0xFFFFFFFD
+#define   S_0007C0_RSIU_BUSY(x)                        (((x) & 0x1) << 2)
+#define   G_0007C0_RSIU_BUSY(x)                        (((x) >> 2) & 0x1)
+#define   C_0007C0_RSIU_BUSY                           0xFFFFFFFB
+#define   S_0007C0_RCIU_BUSY(x)                        (((x) & 0x1) << 3)
+#define   G_0007C0_RCIU_BUSY(x)                        (((x) >> 3) & 0x1)
+#define   C_0007C0_RCIU_BUSY                           0xFFFFFFF7
+#define   S_0007C0_CSF_PRIMARY_BUSY(x)                 (((x) & 0x1) << 9)
+#define   G_0007C0_CSF_PRIMARY_BUSY(x)                 (((x) >> 9) & 0x1)
+#define   C_0007C0_CSF_PRIMARY_BUSY                    0xFFFFFDFF
+#define   S_0007C0_CSF_INDIRECT_BUSY(x)                (((x) & 0x1) << 10)
+#define   G_0007C0_CSF_INDIRECT_BUSY(x)                (((x) >> 10) & 0x1)
+#define   C_0007C0_CSF_INDIRECT_BUSY                   0xFFFFFBFF
+#define   S_0007C0_CSQ_PRIMARY_BUSY(x)                 (((x) & 0x1) << 11)
+#define   G_0007C0_CSQ_PRIMARY_BUSY(x)                 (((x) >> 11) & 0x1)
+#define   C_0007C0_CSQ_PRIMARY_BUSY                    0xFFFFF7FF
+#define   S_0007C0_CSQ_INDIRECT_BUSY(x)                (((x) & 0x1) << 12)
+#define   G_0007C0_CSQ_INDIRECT_BUSY(x)                (((x) >> 12) & 0x1)
+#define   C_0007C0_CSQ_INDIRECT_BUSY                   0xFFFFEFFF
+#define   S_0007C0_CSI_BUSY(x)                         (((x) & 0x1) << 13)
+#define   G_0007C0_CSI_BUSY(x)                         (((x) >> 13) & 0x1)
+#define   C_0007C0_CSI_BUSY                            0xFFFFDFFF
+#define   S_0007C0_CSF_INDIRECT2_BUSY(x)               (((x) & 0x1) << 14)
+#define   G_0007C0_CSF_INDIRECT2_BUSY(x)               (((x) >> 14) & 0x1)
+#define   C_0007C0_CSF_INDIRECT2_BUSY                  0xFFFFBFFF
+#define   S_0007C0_CSQ_INDIRECT2_BUSY(x)               (((x) & 0x1) << 15)
+#define   G_0007C0_CSQ_INDIRECT2_BUSY(x)               (((x) >> 15) & 0x1)
+#define   C_0007C0_CSQ_INDIRECT2_BUSY                  0xFFFF7FFF
+#define   S_0007C0_GUIDMA_BUSY(x)                      (((x) & 0x1) << 28)
+#define   G_0007C0_GUIDMA_BUSY(x)                      (((x) >> 28) & 0x1)
+#define   C_0007C0_GUIDMA_BUSY                         0xEFFFFFFF
+#define   S_0007C0_VIDDMA_BUSY(x)                      (((x) & 0x1) << 29)
+#define   G_0007C0_VIDDMA_BUSY(x)                      (((x) >> 29) & 0x1)
+#define   C_0007C0_VIDDMA_BUSY                         0xDFFFFFFF
+#define   S_0007C0_CMDSTRM_BUSY(x)                     (((x) & 0x1) << 30)
+#define   G_0007C0_CMDSTRM_BUSY(x)                     (((x) >> 30) & 0x1)
+#define   C_0007C0_CMDSTRM_BUSY                        0xBFFFFFFF
+#define   S_0007C0_CP_BUSY(x)                          (((x) & 0x1) << 31)
+#define   G_0007C0_CP_BUSY(x)                          (((x) >> 31) & 0x1)
+#define   C_0007C0_CP_BUSY                             0x7FFFFFFF
+#define R_000E40_RBBM_STATUS                         0x000E40
+#define   S_000E40_CMDFIFO_AVAIL(x)                    (((x) & 0x7F) << 0)
+#define   G_000E40_CMDFIFO_AVAIL(x)                    (((x) >> 0) & 0x7F)
+#define   C_000E40_CMDFIFO_AVAIL                       0xFFFFFF80
+#define   S_000E40_HIRQ_ON_RBB(x)                      (((x) & 0x1) << 8)
+#define   G_000E40_HIRQ_ON_RBB(x)                      (((x) >> 8) & 0x1)
+#define   C_000E40_HIRQ_ON_RBB                         0xFFFFFEFF
+#define   S_000E40_CPRQ_ON_RBB(x)                      (((x) & 0x1) << 9)
+#define   G_000E40_CPRQ_ON_RBB(x)                      (((x) >> 9) & 0x1)
+#define   C_000E40_CPRQ_ON_RBB                         0xFFFFFDFF
+#define   S_000E40_CFRQ_ON_RBB(x)                      (((x) & 0x1) << 10)
+#define   G_000E40_CFRQ_ON_RBB(x)                      (((x) >> 10) & 0x1)
+#define   C_000E40_CFRQ_ON_RBB                         0xFFFFFBFF
+#define   S_000E40_HIRQ_IN_RTBUF(x)                    (((x) & 0x1) << 11)
+#define   G_000E40_HIRQ_IN_RTBUF(x)                    (((x) >> 11) & 0x1)
+#define   C_000E40_HIRQ_IN_RTBUF                       0xFFFFF7FF
+#define   S_000E40_CPRQ_IN_RTBUF(x)                    (((x) & 0x1) << 12)
+#define   G_000E40_CPRQ_IN_RTBUF(x)                    (((x) >> 12) & 0x1)
+#define   C_000E40_CPRQ_IN_RTBUF                       0xFFFFEFFF
+#define   S_000E40_CFRQ_IN_RTBUF(x)                    (((x) & 0x1) << 13)
+#define   G_000E40_CFRQ_IN_RTBUF(x)                    (((x) >> 13) & 0x1)
+#define   C_000E40_CFRQ_IN_RTBUF                       0xFFFFDFFF
+#define   S_000E40_CF_PIPE_BUSY(x)                     (((x) & 0x1) << 14)
+#define   G_000E40_CF_PIPE_BUSY(x)                     (((x) >> 14) & 0x1)
+#define   C_000E40_CF_PIPE_BUSY                        0xFFFFBFFF
+#define   S_000E40_ENG_EV_BUSY(x)                      (((x) & 0x1) << 15)
+#define   G_000E40_ENG_EV_BUSY(x)                      (((x) >> 15) & 0x1)
+#define   C_000E40_ENG_EV_BUSY                         0xFFFF7FFF
+#define   S_000E40_CP_CMDSTRM_BUSY(x)                  (((x) & 0x1) << 16)
+#define   G_000E40_CP_CMDSTRM_BUSY(x)                  (((x) >> 16) & 0x1)
+#define   C_000E40_CP_CMDSTRM_BUSY                     0xFFFEFFFF
+#define   S_000E40_E2_BUSY(x)                          (((x) & 0x1) << 17)
+#define   G_000E40_E2_BUSY(x)                          (((x) >> 17) & 0x1)
+#define   C_000E40_E2_BUSY                             0xFFFDFFFF
+#define   S_000E40_RB2D_BUSY(x)                        (((x) & 0x1) << 18)
+#define   G_000E40_RB2D_BUSY(x)                        (((x) >> 18) & 0x1)
+#define   C_000E40_RB2D_BUSY                           0xFFFBFFFF
+#define   S_000E40_RB3D_BUSY(x)                        (((x) & 0x1) << 19)
+#define   G_000E40_RB3D_BUSY(x)                        (((x) >> 19) & 0x1)
+#define   C_000E40_RB3D_BUSY                           0xFFF7FFFF
+#define   S_000E40_VAP_BUSY(x)                         (((x) & 0x1) << 20)
+#define   G_000E40_VAP_BUSY(x)                         (((x) >> 20) & 0x1)
+#define   C_000E40_VAP_BUSY                            0xFFEFFFFF
+#define   S_000E40_RE_BUSY(x)                          (((x) & 0x1) << 21)
+#define   G_000E40_RE_BUSY(x)                          (((x) >> 21) & 0x1)
+#define   C_000E40_RE_BUSY                             0xFFDFFFFF
+#define   S_000E40_TAM_BUSY(x)                         (((x) & 0x1) << 22)
+#define   G_000E40_TAM_BUSY(x)                         (((x) >> 22) & 0x1)
+#define   C_000E40_TAM_BUSY                            0xFFBFFFFF
+#define   S_000E40_TDM_BUSY(x)                         (((x) & 0x1) << 23)
+#define   G_000E40_TDM_BUSY(x)                         (((x) >> 23) & 0x1)
+#define   C_000E40_TDM_BUSY                            0xFF7FFFFF
+#define   S_000E40_PB_BUSY(x)                          (((x) & 0x1) << 24)
+#define   G_000E40_PB_BUSY(x)                          (((x) >> 24) & 0x1)
+#define   C_000E40_PB_BUSY                             0xFEFFFFFF
+#define   S_000E40_TIM_BUSY(x)                         (((x) & 0x1) << 25)
+#define   G_000E40_TIM_BUSY(x)                         (((x) >> 25) & 0x1)
+#define   C_000E40_TIM_BUSY                            0xFDFFFFFF
+#define   S_000E40_GA_BUSY(x)                          (((x) & 0x1) << 26)
+#define   G_000E40_GA_BUSY(x)                          (((x) >> 26) & 0x1)
+#define   C_000E40_GA_BUSY                             0xFBFFFFFF
+#define   S_000E40_CBA2D_BUSY(x)                       (((x) & 0x1) << 27)
+#define   G_000E40_CBA2D_BUSY(x)                       (((x) >> 27) & 0x1)
+#define   C_000E40_CBA2D_BUSY                          0xF7FFFFFF
+#define   S_000E40_GUI_ACTIVE(x)                       (((x) & 0x1) << 31)
+#define   G_000E40_GUI_ACTIVE(x)                       (((x) >> 31) & 0x1)
+#define   C_000E40_GUI_ACTIVE                          0x7FFFFFFF
+
+#endif
index 4a4fe1c..10dfa78 100644 (file)
  *          Alex Deucher
  *          Jerome Glisse
  */
+/* RS600 / Radeon X1250/X1270 integrated GPU
+ *
+ * This file gather function specific to RS600 which is the IGP of
+ * the X1250/X1270 family supporting intel CPU (while RS690/RS740
+ * is the X1250/X1270 supporting AMD CPU). The display engine are
+ * the avivo one, bios is an atombios, 3D block are the one of the
+ * R4XX family. The GART is different from the RS400 one and is very
+ * close to the one of the R600 family (R600 likely being an evolution
+ * of the RS600 GART block).
+ */
 #include "drmP.h"
-#include "radeon_reg.h"
 #include "radeon.h"
+#include "atom.h"
+#include "rs600d.h"
 
 #include "rs600_reg_safe.h"
 
-/* rs600 depends on : */
-void r100_hdp_reset(struct radeon_device *rdev);
-int r100_gui_wait_for_idle(struct radeon_device *rdev);
-int r300_mc_wait_for_idle(struct radeon_device *rdev);
-void r420_pipes_init(struct radeon_device *rdev);
-
-/* This files gather functions specifics to :
- * rs600
- *
- * Some of these functions might be used by newer ASICs.
- */
 void rs600_gpu_init(struct radeon_device *rdev);
 int rs600_mc_wait_for_idle(struct radeon_device *rdev);
 
-
 /*
  * GART.
  */
@@ -53,18 +52,18 @@ void rs600_gart_tlb_flush(struct radeon_device *rdev)
 {
        uint32_t tmp;
 
-       tmp = RREG32_MC(RS600_MC_PT0_CNTL);
-       tmp &= ~(RS600_INVALIDATE_ALL_L1_TLBS | RS600_INVALIDATE_L2_CACHE);
-       WREG32_MC(RS600_MC_PT0_CNTL, tmp);
+       tmp = RREG32_MC(R_000100_MC_PT0_CNTL);
+       tmp &= C_000100_INVALIDATE_ALL_L1_TLBS & C_000100_INVALIDATE_L2_CACHE;
+       WREG32_MC(R_000100_MC_PT0_CNTL, tmp);
 
-       tmp = RREG32_MC(RS600_MC_PT0_CNTL);
-       tmp |= RS600_INVALIDATE_ALL_L1_TLBS | RS600_INVALIDATE_L2_CACHE;
-       WREG32_MC(RS600_MC_PT0_CNTL, tmp);
+       tmp = RREG32_MC(R_000100_MC_PT0_CNTL);
+       tmp |= S_000100_INVALIDATE_ALL_L1_TLBS(1) & S_000100_INVALIDATE_L2_CACHE(1);
+       WREG32_MC(R_000100_MC_PT0_CNTL, tmp);
 
-       tmp = RREG32_MC(RS600_MC_PT0_CNTL);
-       tmp &= ~(RS600_INVALIDATE_ALL_L1_TLBS | RS600_INVALIDATE_L2_CACHE);
-       WREG32_MC(RS600_MC_PT0_CNTL, tmp);
-       tmp = RREG32_MC(RS600_MC_PT0_CNTL);
+       tmp = RREG32_MC(R_000100_MC_PT0_CNTL);
+       tmp &= C_000100_INVALIDATE_ALL_L1_TLBS & C_000100_INVALIDATE_L2_CACHE;
+       WREG32_MC(R_000100_MC_PT0_CNTL, tmp);
+       tmp = RREG32_MC(R_000100_MC_PT0_CNTL);
 }
 
 int rs600_gart_init(struct radeon_device *rdev)
@@ -86,7 +85,7 @@ int rs600_gart_init(struct radeon_device *rdev)
 
 int rs600_gart_enable(struct radeon_device *rdev)
 {
-       uint32_t tmp;
+       u32 tmp;
        int r, i;
 
        if (rdev->gart.table.vram.robj == NULL) {
@@ -96,46 +95,50 @@ int rs600_gart_enable(struct radeon_device *rdev)
        r = radeon_gart_table_vram_pin(rdev);
        if (r)
                return r;
+       /* Enable bus master */
+       tmp = RREG32(R_00004C_BUS_CNTL) & C_00004C_BUS_MASTER_DIS;
+       WREG32(R_00004C_BUS_CNTL, tmp);
        /* FIXME: setup default page */
-       WREG32_MC(RS600_MC_PT0_CNTL,
-                (RS600_EFFECTIVE_L2_CACHE_SIZE(6) |
-                 RS600_EFFECTIVE_L2_QUEUE_SIZE(6)));
+       WREG32_MC(R_000100_MC_PT0_CNTL,
+                (S_000100_EFFECTIVE_L2_CACHE_SIZE(6) |
+                 S_000100_EFFECTIVE_L2_QUEUE_SIZE(6)));
        for (i = 0; i < 19; i++) {
-               WREG32_MC(RS600_MC_PT0_CLIENT0_CNTL + i,
-                        (RS600_ENABLE_TRANSLATION_MODE_OVERRIDE |
-                         RS600_SYSTEM_ACCESS_MODE_IN_SYS |
-                         RS600_SYSTEM_APERTURE_UNMAPPED_ACCESS_DEFAULT_PAGE |
-                         RS600_EFFECTIVE_L1_CACHE_SIZE(3) |
-                         RS600_ENABLE_FRAGMENT_PROCESSING |
-                         RS600_EFFECTIVE_L1_QUEUE_SIZE(3)));
+               WREG32_MC(R_00016C_MC_PT0_CLIENT0_CNTL + i,
+                       S_00016C_ENABLE_TRANSLATION_MODE_OVERRIDE(1) |
+                       S_00016C_SYSTEM_ACCESS_MODE_MASK(
+                               V_00016C_SYSTEM_ACCESS_MODE_IN_SYS) |
+                       S_00016C_SYSTEM_APERTURE_UNMAPPED_ACCESS(
+                               V_00016C_SYSTEM_APERTURE_UNMAPPED_DEFAULT_PAGE) |
+                       S_00016C_EFFECTIVE_L1_CACHE_SIZE(1) |
+                       S_00016C_ENABLE_FRAGMENT_PROCESSING(1) |
+                       S_00016C_EFFECTIVE_L1_QUEUE_SIZE(1));
        }
 
        /* System context map to GART space */
-       WREG32_MC(RS600_MC_PT0_SYSTEM_APERTURE_LOW_ADDR, rdev->mc.gtt_location);
-       tmp = rdev->mc.gtt_location + rdev->mc.gtt_size - 1;
-       WREG32_MC(RS600_MC_PT0_SYSTEM_APERTURE_HIGH_ADDR, tmp);
+       WREG32_MC(R_000112_MC_PT0_SYSTEM_APERTURE_LOW_ADDR, rdev->mc.gtt_start);
+       WREG32_MC(R_000114_MC_PT0_SYSTEM_APERTURE_HIGH_ADDR, rdev->mc.gtt_end);
 
        /* enable first context */
-       WREG32_MC(RS600_MC_PT0_CONTEXT0_FLAT_START_ADDR, rdev->mc.gtt_location);
-       tmp = rdev->mc.gtt_location + rdev->mc.gtt_size - 1;
-       WREG32_MC(RS600_MC_PT0_CONTEXT0_FLAT_END_ADDR, tmp);
-       WREG32_MC(RS600_MC_PT0_CONTEXT0_CNTL,
-                (RS600_ENABLE_PAGE_TABLE | RS600_PAGE_TABLE_TYPE_FLAT));
+       WREG32_MC(R_00013C_MC_PT0_CONTEXT0_FLAT_START_ADDR, rdev->mc.gtt_start);
+       WREG32_MC(R_00014C_MC_PT0_CONTEXT0_FLAT_END_ADDR, rdev->mc.gtt_end);
+       WREG32_MC(R_000102_MC_PT0_CONTEXT0_CNTL,
+                       S_000102_ENABLE_PAGE_TABLE(1) |
+                       S_000102_PAGE_TABLE_DEPTH(V_000102_PAGE_TABLE_FLAT));
        /* disable all other contexts */
        for (i = 1; i < 8; i++) {
-               WREG32_MC(RS600_MC_PT0_CONTEXT0_CNTL + i, 0);
+               WREG32_MC(R_000102_MC_PT0_CONTEXT0_CNTL + i, 0);
        }
 
        /* setup the page table */
-       WREG32_MC(RS600_MC_PT0_CONTEXT0_FLAT_BASE_ADDR,
-                rdev->gart.table_addr);
-       WREG32_MC(RS600_MC_PT0_CONTEXT0_DEFAULT_READ_ADDR, 0);
+       WREG32_MC(R_00012C_MC_PT0_CONTEXT0_FLAT_BASE_ADDR,
+                       rdev->gart.table_addr);
+       WREG32_MC(R_00011C_MC_PT0_CONTEXT0_DEFAULT_READ_ADDR, 0);
 
        /* enable page tables */
-       tmp = RREG32_MC(RS600_MC_PT0_CNTL);
-       WREG32_MC(RS600_MC_PT0_CNTL, (tmp | RS600_ENABLE_PT));
-       tmp = RREG32_MC(RS600_MC_CNTL1);
-       WREG32_MC(RS600_MC_CNTL1, (tmp | RS600_ENABLE_PAGE_TABLES));
+       tmp = RREG32_MC(R_000100_MC_PT0_CNTL);
+       WREG32_MC(R_000100_MC_PT0_CNTL, (tmp | S_000100_ENABLE_PT(1)));
+       tmp = RREG32_MC(R_000009_MC_CNTL1);
+       WREG32_MC(R_000009_MC_CNTL1, (tmp | S_000009_ENABLE_PAGE_TABLES(1)));
        rs600_gart_tlb_flush(rdev);
        rdev->gart.ready = true;
        return 0;
@@ -146,10 +149,9 @@ void rs600_gart_disable(struct radeon_device *rdev)
        uint32_t tmp;
 
        /* FIXME: disable out of gart access */
-       WREG32_MC(RS600_MC_PT0_CNTL, 0);
-       tmp = RREG32_MC(RS600_MC_CNTL1);
-       tmp &= ~RS600_ENABLE_PAGE_TABLES;
-       WREG32_MC(RS600_MC_CNTL1, tmp);
+       WREG32_MC(R_000100_MC_PT0_CNTL, 0);
+       tmp = RREG32_MC(R_000009_MC_CNTL1);
+       WREG32_MC(R_000009_MC_CNTL1, tmp & C_000009_ENABLE_PAGE_TABLES);
        if (rdev->gart.table.vram.robj) {
                radeon_object_kunmap(rdev->gart.table.vram.robj);
                radeon_object_unpin(rdev->gart.table.vram.robj);
@@ -183,129 +185,61 @@ int rs600_gart_set_page(struct radeon_device *rdev, int i, uint64_t addr)
        return 0;
 }
 
-
-/*
- * MC.
- */
-void rs600_mc_disable_clients(struct radeon_device *rdev)
-{
-       unsigned tmp;
-
-       if (r100_gui_wait_for_idle(rdev)) {
-               printk(KERN_WARNING "Failed to wait GUI idle while "
-                      "programming pipes. Bad things might happen.\n");
-       }
-
-       rv515_vga_render_disable(rdev);
-
-       tmp = RREG32(AVIVO_D1VGA_CONTROL);
-       WREG32(AVIVO_D1VGA_CONTROL, tmp & ~AVIVO_DVGA_CONTROL_MODE_ENABLE);
-       tmp = RREG32(AVIVO_D2VGA_CONTROL);
-       WREG32(AVIVO_D2VGA_CONTROL, tmp & ~AVIVO_DVGA_CONTROL_MODE_ENABLE);
-
-       tmp = RREG32(AVIVO_D1CRTC_CONTROL);
-       WREG32(AVIVO_D1CRTC_CONTROL, tmp & ~AVIVO_CRTC_EN);
-       tmp = RREG32(AVIVO_D2CRTC_CONTROL);
-       WREG32(AVIVO_D2CRTC_CONTROL, tmp & ~AVIVO_CRTC_EN);
-
-       /* make sure all previous write got through */
-       tmp = RREG32(AVIVO_D2CRTC_CONTROL);
-
-       mdelay(1);
-}
-
-int rs600_mc_init(struct radeon_device *rdev)
-{
-       uint32_t tmp;
-       int r;
-
-       if (r100_debugfs_rbbm_init(rdev)) {
-               DRM_ERROR("Failed to register debugfs file for RBBM !\n");
-       }
-
-       rs600_gpu_init(rdev);
-       rs600_gart_disable(rdev);
-
-       /* Setup GPU memory space */
-       rdev->mc.vram_location = 0xFFFFFFFFUL;
-       rdev->mc.gtt_location = 0xFFFFFFFFUL;
-       r = radeon_mc_setup(rdev);
-       if (r) {
-               return r;
-       }
-
-       /* Program GPU memory space */
-       /* Enable bus master */
-       tmp = RREG32(RADEON_BUS_CNTL) & ~RS600_BUS_MASTER_DIS;
-       WREG32(RADEON_BUS_CNTL, tmp);
-       /* FIXME: What does AGP means for such chipset ? */
-       WREG32_MC(RS600_MC_AGP_LOCATION, 0x0FFFFFFF);
-       /* FIXME: are this AGP reg in indirect MC range ? */
-       WREG32_MC(RS600_MC_AGP_BASE, 0);
-       WREG32_MC(RS600_MC_AGP_BASE_2, 0);
-       rs600_mc_disable_clients(rdev);
-       if (rs600_mc_wait_for_idle(rdev)) {
-               printk(KERN_WARNING "Failed to wait MC idle while "
-                      "programming pipes. Bad things might happen.\n");
-       }
-       tmp = rdev->mc.vram_location + rdev->mc.mc_vram_size - 1;
-       tmp = REG_SET(RS600_MC_FB_TOP, tmp >> 16);
-       tmp |= REG_SET(RS600_MC_FB_START, rdev->mc.vram_location >> 16);
-       WREG32_MC(RS600_MC_FB_LOCATION, tmp);
-       WREG32(RS690_HDP_FB_LOCATION, rdev->mc.vram_location >> 16);
-       return 0;
-}
-
-void rs600_mc_fini(struct radeon_device *rdev)
-{
-}
-
-
-/*
- * Interrupts
- */
 int rs600_irq_set(struct radeon_device *rdev)
 {
        uint32_t tmp = 0;
        uint32_t mode_int = 0;
 
        if (rdev->irq.sw_int) {
-               tmp |= RADEON_SW_INT_ENABLE;
+               tmp |= S_000040_SW_INT_EN(1);
        }
        if (rdev->irq.crtc_vblank_int[0]) {
-               mode_int |= AVIVO_D1MODE_INT_MASK;
+               mode_int |= S_006540_D1MODE_VBLANK_INT_MASK(1);
        }
        if (rdev->irq.crtc_vblank_int[1]) {
-               mode_int |= AVIVO_D2MODE_INT_MASK;
+               mode_int |= S_006540_D2MODE_VBLANK_INT_MASK(1);
        }
-       WREG32(RADEON_GEN_INT_CNTL, tmp);
-       WREG32(AVIVO_DxMODE_INT_MASK, mode_int);
+       WREG32(R_000040_GEN_INT_CNTL, tmp);
+       WREG32(R_006540_DxMODE_INT_MASK, mode_int);
        return 0;
 }
 
 static inline uint32_t rs600_irq_ack(struct radeon_device *rdev, u32 *r500_disp_int)
 {
-       uint32_t irqs = RREG32(RADEON_GEN_INT_STATUS);
-       uint32_t irq_mask = RADEON_SW_INT_TEST;
-
-       if (irqs & AVIVO_DISPLAY_INT_STATUS) {
-               *r500_disp_int = RREG32(AVIVO_DISP_INTERRUPT_STATUS);
-               if (*r500_disp_int & AVIVO_D1_VBLANK_INTERRUPT) {
-                       WREG32(AVIVO_D1MODE_VBLANK_STATUS, AVIVO_VBLANK_ACK);
+       uint32_t irqs = RREG32(R_000044_GEN_INT_STATUS);
+       uint32_t irq_mask = ~C_000044_SW_INT;
+
+       if (G_000044_DISPLAY_INT_STAT(irqs)) {
+               *r500_disp_int = RREG32(R_007EDC_DISP_INTERRUPT_STATUS);
+               if (G_007EDC_LB_D1_VBLANK_INTERRUPT(*r500_disp_int)) {
+                       WREG32(R_006534_D1MODE_VBLANK_STATUS,
+                               S_006534_D1MODE_VBLANK_ACK(1));
                }
-               if (*r500_disp_int & AVIVO_D2_VBLANK_INTERRUPT) {
-                       WREG32(AVIVO_D2MODE_VBLANK_STATUS, AVIVO_VBLANK_ACK);
+               if (G_007EDC_LB_D2_VBLANK_INTERRUPT(*r500_disp_int)) {
+                       WREG32(R_006D34_D2MODE_VBLANK_STATUS,
+                               S_006D34_D2MODE_VBLANK_ACK(1));
                }
        } else {
                *r500_disp_int = 0;
        }
 
        if (irqs) {
-               WREG32(RADEON_GEN_INT_STATUS, irqs);
+               WREG32(R_000044_GEN_INT_STATUS, irqs);
        }
        return irqs & irq_mask;
 }
 
+void rs600_irq_disable(struct radeon_device *rdev)
+{
+       u32 tmp;
+
+       WREG32(R_000040_GEN_INT_CNTL, 0);
+       WREG32(R_006540_DxMODE_INT_MASK, 0);
+       /* Wait and acknowledge irq */
+       mdelay(1);
+       rs600_irq_ack(rdev, &tmp);
+}
+
 int rs600_irq_process(struct radeon_device *rdev)
 {
        uint32_t status;
@@ -317,16 +251,13 @@ int rs600_irq_process(struct radeon_device *rdev)
        }
        while (status || r500_disp_int) {
                /* SW interrupt */
-               if (status & RADEON_SW_INT_TEST) {
+               if (G_000040_SW_INT_EN(status))
                        radeon_fence_process(rdev);
-               }
                /* Vertical blank interrupts */
-               if (r500_disp_int & AVIVO_D1_VBLANK_INTERRUPT) {
+               if (G_007EDC_LB_D1_VBLANK_INTERRUPT(r500_disp_int))
                        drm_handle_vblank(rdev->ddev, 0);
-               }
-               if (r500_disp_int & AVIVO_D2_VBLANK_INTERRUPT) {
+               if (G_007EDC_LB_D2_VBLANK_INTERRUPT(r500_disp_int))
                        drm_handle_vblank(rdev->ddev, 1);
-               }
                status = rs600_irq_ack(rdev, &r500_disp_int);
        }
        return IRQ_HANDLED;
@@ -335,53 +266,34 @@ int rs600_irq_process(struct radeon_device *rdev)
 u32 rs600_get_vblank_counter(struct radeon_device *rdev, int crtc)
 {
        if (crtc == 0)
-               return RREG32(AVIVO_D1CRTC_FRAME_COUNT);
+               return RREG32(R_0060A4_D1CRTC_STATUS_FRAME_COUNT);
        else
-               return RREG32(AVIVO_D2CRTC_FRAME_COUNT);
+               return RREG32(R_0068A4_D2CRTC_STATUS_FRAME_COUNT);
 }
 
-
-/*
- * Global GPU functions
- */
 int rs600_mc_wait_for_idle(struct radeon_device *rdev)
 {
        unsigned i;
-       uint32_t tmp;
 
        for (i = 0; i < rdev->usec_timeout; i++) {
-               /* read MC_STATUS */
-               tmp = RREG32_MC(RS600_MC_STATUS);
-               if (tmp & RS600_MC_STATUS_IDLE) {
+               if (G_000000_MC_IDLE(RREG32_MC(R_000000_MC_STATUS)))
                        return 0;
-               }
-               DRM_UDELAY(1);
+               udelay(1);
        }
        return -1;
 }
 
-void rs600_errata(struct radeon_device *rdev)
-{
-       rdev->pll_errata = 0;
-}
-
 void rs600_gpu_init(struct radeon_device *rdev)
 {
        /* FIXME: HDP same place on rs600 ? */
        r100_hdp_reset(rdev);
-       rv515_vga_render_disable(rdev);
        /* FIXME: is this correct ? */
        r420_pipes_init(rdev);
-       if (rs600_mc_wait_for_idle(rdev)) {
-               printk(KERN_WARNING "Failed to wait MC idle while "
-                      "programming pipes. Bad things might happen.\n");
-       }
+       /* Wait for mc idle */
+       if (rs600_mc_wait_for_idle(rdev))
+               dev_warn(rdev->dev, "Wait MC idle timeout before updating MC.\n");
 }
 
-
-/*
- * VRAM info.
- */
 void rs600_vram_info(struct radeon_device *rdev)
 {
        /* FIXME: to do or is these values sane ? */
@@ -394,31 +306,206 @@ void rs600_bandwidth_update(struct radeon_device *rdev)
        /* FIXME: implement, should this be like rs690 ? */
 }
 
-
-/*
- * Indirect registers accessor
- */
 uint32_t rs600_mc_rreg(struct radeon_device *rdev, uint32_t reg)
 {
-       uint32_t r;
-
-       WREG32(RS600_MC_INDEX,
-              ((reg & RS600_MC_ADDR_MASK) | RS600_MC_IND_CITF_ARB0));
-       r = RREG32(RS600_MC_DATA);
-       return r;
+       WREG32(R_000070_MC_IND_INDEX, S_000070_MC_IND_ADDR(reg) |
+               S_000070_MC_IND_CITF_ARB0(1));
+       return RREG32(R_000074_MC_IND_DATA);
 }
 
 void rs600_mc_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v)
 {
-       WREG32(RS600_MC_INDEX,
-               RS600_MC_IND_WR_EN | RS600_MC_IND_CITF_ARB0 |
-               ((reg) & RS600_MC_ADDR_MASK));
-       WREG32(RS600_MC_DATA, v);
+       WREG32(R_000070_MC_IND_INDEX, S_000070_MC_IND_ADDR(reg) |
+               S_000070_MC_IND_CITF_ARB0(1) | S_000070_MC_IND_WR_EN(1));
+       WREG32(R_000074_MC_IND_DATA, v);
 }
 
-int rs600_init(struct radeon_device *rdev)
+void rs600_debugfs(struct radeon_device *rdev)
+{
+       if (r100_debugfs_rbbm_init(rdev))
+               DRM_ERROR("Failed to register debugfs file for RBBM !\n");
+}
+
+void rs600_set_safe_registers(struct radeon_device *rdev)
 {
        rdev->config.r300.reg_safe_bm = rs600_reg_safe_bm;
        rdev->config.r300.reg_safe_bm_size = ARRAY_SIZE(rs600_reg_safe_bm);
+}
+
+static void rs600_mc_program(struct radeon_device *rdev)
+{
+       struct rv515_mc_save save;
+
+       /* Stops all mc clients */
+       rv515_mc_stop(rdev, &save);
+
+       /* Wait for mc idle */
+       if (rs600_mc_wait_for_idle(rdev))
+               dev_warn(rdev->dev, "Wait MC idle timeout before updating MC.\n");
+
+       /* FIXME: What does AGP means for such chipset ? */
+       WREG32_MC(R_000005_MC_AGP_LOCATION, 0x0FFFFFFF);
+       WREG32_MC(R_000006_AGP_BASE, 0);
+       WREG32_MC(R_000007_AGP_BASE_2, 0);
+       /* Program MC */
+       WREG32_MC(R_000004_MC_FB_LOCATION,
+                       S_000004_MC_FB_START(rdev->mc.vram_start >> 16) |
+                       S_000004_MC_FB_TOP(rdev->mc.vram_end >> 16));
+       WREG32(R_000134_HDP_FB_LOCATION,
+               S_000134_HDP_FB_START(rdev->mc.vram_start >> 16));
+
+       rv515_mc_resume(rdev, &save);
+}
+
+static int rs600_startup(struct radeon_device *rdev)
+{
+       int r;
+
+       rs600_mc_program(rdev);
+       /* Resume clock */
+       rv515_clock_startup(rdev);
+       /* Initialize GPU configuration (# pipes, ...) */
+       rs600_gpu_init(rdev);
+       /* Initialize GART (initialize after TTM so we can allocate
+        * memory through TTM but finalize after TTM) */
+       r = rs600_gart_enable(rdev);
+       if (r)
+               return r;
+       /* Enable IRQ */
+       rdev->irq.sw_int = true;
+       rs600_irq_set(rdev);
+       /* 1M ring buffer */
+       r = r100_cp_init(rdev, 1024 * 1024);
+       if (r) {
+               dev_err(rdev->dev, "failled initializing CP (%d).\n", r);
+               return r;
+       }
+       r = r100_wb_init(rdev);
+       if (r)
+               dev_err(rdev->dev, "failled initializing WB (%d).\n", r);
+       r = r100_ib_init(rdev);
+       if (r) {
+               dev_err(rdev->dev, "failled initializing IB (%d).\n", r);
+               return r;
+       }
+       return 0;
+}
+
+int rs600_resume(struct radeon_device *rdev)
+{
+       /* Make sur GART are not working */
+       rs600_gart_disable(rdev);
+       /* Resume clock before doing reset */
+       rv515_clock_startup(rdev);
+       /* Reset gpu before posting otherwise ATOM will enter infinite loop */
+       if (radeon_gpu_reset(rdev)) {
+               dev_warn(rdev->dev, "GPU reset failed ! (0xE40=0x%08X, 0x7C0=0x%08X)\n",
+                       RREG32(R_000E40_RBBM_STATUS),
+                       RREG32(R_0007C0_CP_STAT));
+       }
+       /* post */
+       atom_asic_init(rdev->mode_info.atom_context);
+       /* Resume clock after posting */
+       rv515_clock_startup(rdev);
+       return rs600_startup(rdev);
+}
+
+int rs600_suspend(struct radeon_device *rdev)
+{
+       r100_cp_disable(rdev);
+       r100_wb_disable(rdev);
+       rs600_irq_disable(rdev);
+       rs600_gart_disable(rdev);
+       return 0;
+}
+
+void rs600_fini(struct radeon_device *rdev)
+{
+       rs600_suspend(rdev);
+       r100_cp_fini(rdev);
+       r100_wb_fini(rdev);
+       r100_ib_fini(rdev);
+       radeon_gem_fini(rdev);
+       rs600_gart_fini(rdev);
+       radeon_irq_kms_fini(rdev);
+       radeon_fence_driver_fini(rdev);
+       radeon_object_fini(rdev);
+       radeon_atombios_fini(rdev);
+       kfree(rdev->bios);
+       rdev->bios = NULL;
+}
+
+int rs600_init(struct radeon_device *rdev)
+{
+       int r;
+
+       /* Disable VGA */
+       rv515_vga_render_disable(rdev);
+       /* Initialize scratch registers */
+       radeon_scratch_init(rdev);
+       /* Initialize surface registers */
+       radeon_surface_init(rdev);
+       /* BIOS */
+       if (!radeon_get_bios(rdev)) {
+               if (ASIC_IS_AVIVO(rdev))
+                       return -EINVAL;
+       }
+       if (rdev->is_atom_bios) {
+               r = radeon_atombios_init(rdev);
+               if (r)
+                       return r;
+       } else {
+               dev_err(rdev->dev, "Expecting atombios for RS600 GPU\n");
+               return -EINVAL;
+       }
+       /* Reset gpu before posting otherwise ATOM will enter infinite loop */
+       if (radeon_gpu_reset(rdev)) {
+               dev_warn(rdev->dev,
+                       "GPU reset failed ! (0xE40=0x%08X, 0x7C0=0x%08X)\n",
+                       RREG32(R_000E40_RBBM_STATUS),
+                       RREG32(R_0007C0_CP_STAT));
+       }
+       /* check if cards are posted or not */
+       if (!radeon_card_posted(rdev) && rdev->bios) {
+               DRM_INFO("GPU not posted. posting now...\n");
+               atom_asic_init(rdev->mode_info.atom_context);
+       }
+       /* Initialize clocks */
+       radeon_get_clock_info(rdev->ddev);
+       /* Get vram informations */
+       rs600_vram_info(rdev);
+       /* Initialize memory controller (also test AGP) */
+       r = r420_mc_init(rdev);
+       if (r)
+               return r;
+       rs600_debugfs(rdev);
+       /* Fence driver */
+       r = radeon_fence_driver_init(rdev);
+       if (r)
+               return r;
+       r = radeon_irq_kms_init(rdev);
+       if (r)
+               return r;
+       /* Memory manager */
+       r = radeon_object_init(rdev);
+       if (r)
+               return r;
+       r = rs600_gart_init(rdev);
+       if (r)
+               return r;
+       rs600_set_safe_registers(rdev);
+       rdev->accel_working = true;
+       r = rs600_startup(rdev);
+       if (r) {
+               /* Somethings want wront with the accel init stop accel */
+               dev_err(rdev->dev, "Disabling GPU acceleration\n");
+               rs600_suspend(rdev);
+               r100_cp_fini(rdev);
+               r100_wb_fini(rdev);
+               r100_ib_fini(rdev);
+               rs600_gart_fini(rdev);
+               radeon_irq_kms_fini(rdev);
+               rdev->accel_working = false;
+       }
        return 0;
 }
diff --git a/drivers/gpu/drm/radeon/rs600d.h b/drivers/gpu/drm/radeon/rs600d.h
new file mode 100644 (file)
index 0000000..8130892
--- /dev/null
@@ -0,0 +1,470 @@
+/*
+ * Copyright 2008 Advanced Micro Devices, Inc.
+ * Copyright 2008 Red Hat Inc.
+ * Copyright 2009 Jerome Glisse.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: Dave Airlie
+ *          Alex Deucher
+ *          Jerome Glisse
+ */
+#ifndef __RS600D_H__
+#define __RS600D_H__
+
+/* Registers */
+#define R_000040_GEN_INT_CNTL                        0x000040
+#define   S_000040_DISPLAY_INT_STATUS(x)               (((x) & 0x1) << 0)
+#define   G_000040_DISPLAY_INT_STATUS(x)               (((x) >> 0) & 0x1)
+#define   C_000040_DISPLAY_INT_STATUS                  0xFFFFFFFE
+#define   S_000040_DMA_VIPH0_INT_EN(x)                 (((x) & 0x1) << 12)
+#define   G_000040_DMA_VIPH0_INT_EN(x)                 (((x) >> 12) & 0x1)
+#define   C_000040_DMA_VIPH0_INT_EN                    0xFFFFEFFF
+#define   S_000040_CRTC2_VSYNC(x)                      (((x) & 0x1) << 6)
+#define   G_000040_CRTC2_VSYNC(x)                      (((x) >> 6) & 0x1)
+#define   C_000040_CRTC2_VSYNC                         0xFFFFFFBF
+#define   S_000040_SNAPSHOT2(x)                        (((x) & 0x1) << 7)
+#define   G_000040_SNAPSHOT2(x)                        (((x) >> 7) & 0x1)
+#define   C_000040_SNAPSHOT2                           0xFFFFFF7F
+#define   S_000040_CRTC2_VBLANK(x)                     (((x) & 0x1) << 9)
+#define   G_000040_CRTC2_VBLANK(x)                     (((x) >> 9) & 0x1)
+#define   C_000040_CRTC2_VBLANK                        0xFFFFFDFF
+#define   S_000040_FP2_DETECT(x)                       (((x) & 0x1) << 10)
+#define   G_000040_FP2_DETECT(x)                       (((x) >> 10) & 0x1)
+#define   C_000040_FP2_DETECT                          0xFFFFFBFF
+#define   S_000040_VSYNC_DIFF_OVER_LIMIT(x)            (((x) & 0x1) << 11)
+#define   G_000040_VSYNC_DIFF_OVER_LIMIT(x)            (((x) >> 11) & 0x1)
+#define   C_000040_VSYNC_DIFF_OVER_LIMIT               0xFFFFF7FF
+#define   S_000040_DMA_VIPH1_INT_EN(x)                 (((x) & 0x1) << 13)
+#define   G_000040_DMA_VIPH1_INT_EN(x)                 (((x) >> 13) & 0x1)
+#define   C_000040_DMA_VIPH1_INT_EN                    0xFFFFDFFF
+#define   S_000040_DMA_VIPH2_INT_EN(x)                 (((x) & 0x1) << 14)
+#define   G_000040_DMA_VIPH2_INT_EN(x)                 (((x) >> 14) & 0x1)
+#define   C_000040_DMA_VIPH2_INT_EN                    0xFFFFBFFF
+#define   S_000040_DMA_VIPH3_INT_EN(x)                 (((x) & 0x1) << 15)
+#define   G_000040_DMA_VIPH3_INT_EN(x)                 (((x) >> 15) & 0x1)
+#define   C_000040_DMA_VIPH3_INT_EN                    0xFFFF7FFF
+#define   S_000040_I2C_INT_EN(x)                       (((x) & 0x1) << 17)
+#define   G_000040_I2C_INT_EN(x)                       (((x) >> 17) & 0x1)
+#define   C_000040_I2C_INT_EN                          0xFFFDFFFF
+#define   S_000040_GUI_IDLE(x)                         (((x) & 0x1) << 19)
+#define   G_000040_GUI_IDLE(x)                         (((x) >> 19) & 0x1)
+#define   C_000040_GUI_IDLE                            0xFFF7FFFF
+#define   S_000040_VIPH_INT_EN(x)                      (((x) & 0x1) << 24)
+#define   G_000040_VIPH_INT_EN(x)                      (((x) >> 24) & 0x1)
+#define   C_000040_VIPH_INT_EN                         0xFEFFFFFF
+#define   S_000040_SW_INT_EN(x)                        (((x) & 0x1) << 25)
+#define   G_000040_SW_INT_EN(x)                        (((x) >> 25) & 0x1)
+#define   C_000040_SW_INT_EN                           0xFDFFFFFF
+#define   S_000040_GEYSERVILLE(x)                      (((x) & 0x1) << 27)
+#define   G_000040_GEYSERVILLE(x)                      (((x) >> 27) & 0x1)
+#define   C_000040_GEYSERVILLE                         0xF7FFFFFF
+#define   S_000040_HDCP_AUTHORIZED_INT(x)              (((x) & 0x1) << 28)
+#define   G_000040_HDCP_AUTHORIZED_INT(x)              (((x) >> 28) & 0x1)
+#define   C_000040_HDCP_AUTHORIZED_INT                 0xEFFFFFFF
+#define   S_000040_DVI_I2C_INT(x)                      (((x) & 0x1) << 29)
+#define   G_000040_DVI_I2C_INT(x)                      (((x) >> 29) & 0x1)
+#define   C_000040_DVI_I2C_INT                         0xDFFFFFFF
+#define   S_000040_GUIDMA(x)                           (((x) & 0x1) << 30)
+#define   G_000040_GUIDMA(x)                           (((x) >> 30) & 0x1)
+#define   C_000040_GUIDMA                              0xBFFFFFFF
+#define   S_000040_VIDDMA(x)                           (((x) & 0x1) << 31)
+#define   G_000040_VIDDMA(x)                           (((x) >> 31) & 0x1)
+#define   C_000040_VIDDMA                              0x7FFFFFFF
+#define R_000044_GEN_INT_STATUS                      0x000044
+#define   S_000044_DISPLAY_INT_STAT(x)                 (((x) & 0x1) << 0)
+#define   G_000044_DISPLAY_INT_STAT(x)                 (((x) >> 0) & 0x1)
+#define   C_000044_DISPLAY_INT_STAT                    0xFFFFFFFE
+#define   S_000044_VGA_INT_STAT(x)                     (((x) & 0x1) << 1)
+#define   G_000044_VGA_INT_STAT(x)                     (((x) >> 1) & 0x1)
+#define   C_000044_VGA_INT_STAT                        0xFFFFFFFD
+#define   S_000044_CAP0_INT_ACTIVE(x)                  (((x) & 0x1) << 8)
+#define   G_000044_CAP0_INT_ACTIVE(x)                  (((x) >> 8) & 0x1)
+#define   C_000044_CAP0_INT_ACTIVE                     0xFFFFFEFF
+#define   S_000044_DMA_VIPH0_INT(x)                    (((x) & 0x1) << 12)
+#define   G_000044_DMA_VIPH0_INT(x)                    (((x) >> 12) & 0x1)
+#define   C_000044_DMA_VIPH0_INT                       0xFFFFEFFF
+#define   S_000044_DMA_VIPH1_INT(x)                    (((x) & 0x1) << 13)
+#define   G_000044_DMA_VIPH1_INT(x)                    (((x) >> 13) & 0x1)
+#define   C_000044_DMA_VIPH1_INT                       0xFFFFDFFF
+#define   S_000044_DMA_VIPH2_INT(x)                    (((x) & 0x1) << 14)
+#define   G_000044_DMA_VIPH2_INT(x)                    (((x) >> 14) & 0x1)
+#define   C_000044_DMA_VIPH2_INT                       0xFFFFBFFF
+#define   S_000044_DMA_VIPH3_INT(x)                    (((x) & 0x1) << 15)
+#define   G_000044_DMA_VIPH3_INT(x)                    (((x) >> 15) & 0x1)
+#define   C_000044_DMA_VIPH3_INT                       0xFFFF7FFF
+#define   S_000044_MC_PROBE_FAULT_STAT(x)              (((x) & 0x1) << 16)
+#define   G_000044_MC_PROBE_FAULT_STAT(x)              (((x) >> 16) & 0x1)
+#define   C_000044_MC_PROBE_FAULT_STAT                 0xFFFEFFFF
+#define   S_000044_I2C_INT(x)                          (((x) & 0x1) << 17)
+#define   G_000044_I2C_INT(x)                          (((x) >> 17) & 0x1)
+#define   C_000044_I2C_INT                             0xFFFDFFFF
+#define   S_000044_SCRATCH_INT_STAT(x)                 (((x) & 0x1) << 18)
+#define   G_000044_SCRATCH_INT_STAT(x)                 (((x) >> 18) & 0x1)
+#define   C_000044_SCRATCH_INT_STAT                    0xFFFBFFFF
+#define   S_000044_GUI_IDLE_STAT(x)                    (((x) & 0x1) << 19)
+#define   G_000044_GUI_IDLE_STAT(x)                    (((x) >> 19) & 0x1)
+#define   C_000044_GUI_IDLE_STAT                       0xFFF7FFFF
+#define   S_000044_ATI_OVERDRIVE_INT_STAT(x)           (((x) & 0x1) << 20)
+#define   G_000044_ATI_OVERDRIVE_INT_STAT(x)           (((x) >> 20) & 0x1)
+#define   C_000044_ATI_OVERDRIVE_INT_STAT              0xFFEFFFFF
+#define   S_000044_MC_PROTECTION_FAULT_STAT(x)         (((x) & 0x1) << 21)
+#define   G_000044_MC_PROTECTION_FAULT_STAT(x)         (((x) >> 21) & 0x1)
+#define   C_000044_MC_PROTECTION_FAULT_STAT            0xFFDFFFFF
+#define   S_000044_RBBM_READ_INT_STAT(x)               (((x) & 0x1) << 22)
+#define   G_000044_RBBM_READ_INT_STAT(x)               (((x) >> 22) & 0x1)
+#define   C_000044_RBBM_READ_INT_STAT                  0xFFBFFFFF
+#define   S_000044_CB_CONTEXT_SWITCH_STAT(x)           (((x) & 0x1) << 23)
+#define   G_000044_CB_CONTEXT_SWITCH_STAT(x)           (((x) >> 23) & 0x1)
+#define   C_000044_CB_CONTEXT_SWITCH_STAT              0xFF7FFFFF
+#define   S_000044_VIPH_INT(x)                         (((x) & 0x1) << 24)
+#define   G_000044_VIPH_INT(x)                         (((x) >> 24) & 0x1)
+#define   C_000044_VIPH_INT                            0xFEFFFFFF
+#define   S_000044_SW_INT(x)                           (((x) & 0x1) << 25)
+#define   G_000044_SW_INT(x)                           (((x) >> 25) & 0x1)
+#define   C_000044_SW_INT                              0xFDFFFFFF
+#define   S_000044_SW_INT_SET(x)                       (((x) & 0x1) << 26)
+#define   G_000044_SW_INT_SET(x)                       (((x) >> 26) & 0x1)
+#define   C_000044_SW_INT_SET                          0xFBFFFFFF
+#define   S_000044_IDCT_INT_STAT(x)                    (((x) & 0x1) << 27)
+#define   G_000044_IDCT_INT_STAT(x)                    (((x) >> 27) & 0x1)
+#define   C_000044_IDCT_INT_STAT                       0xF7FFFFFF
+#define   S_000044_GUIDMA_STAT(x)                      (((x) & 0x1) << 30)
+#define   G_000044_GUIDMA_STAT(x)                      (((x) >> 30) & 0x1)
+#define   C_000044_GUIDMA_STAT                         0xBFFFFFFF
+#define   S_000044_VIDDMA_STAT(x)                      (((x) & 0x1) << 31)
+#define   G_000044_VIDDMA_STAT(x)                      (((x) >> 31) & 0x1)
+#define   C_000044_VIDDMA_STAT                         0x7FFFFFFF
+#define R_00004C_BUS_CNTL                            0x00004C
+#define   S_00004C_BUS_MASTER_DIS(x)                   (((x) & 0x1) << 14)
+#define   G_00004C_BUS_MASTER_DIS(x)                   (((x) >> 14) & 0x1)
+#define   C_00004C_BUS_MASTER_DIS                      0xFFFFBFFF
+#define   S_00004C_BUS_MSI_REARM(x)                    (((x) & 0x1) << 20)
+#define   G_00004C_BUS_MSI_REARM(x)                    (((x) >> 20) & 0x1)
+#define   C_00004C_BUS_MSI_REARM                       0xFFEFFFFF
+#define R_000070_MC_IND_INDEX                        0x000070
+#define   S_000070_MC_IND_ADDR(x)                      (((x) & 0xFFFF) << 0)
+#define   G_000070_MC_IND_ADDR(x)                      (((x) >> 0) & 0xFFFF)
+#define   C_000070_MC_IND_ADDR                         0xFFFF0000
+#define   S_000070_MC_IND_SEQ_RBS_0(x)                 (((x) & 0x1) << 16)
+#define   G_000070_MC_IND_SEQ_RBS_0(x)                 (((x) >> 16) & 0x1)
+#define   C_000070_MC_IND_SEQ_RBS_0                    0xFFFEFFFF
+#define   S_000070_MC_IND_SEQ_RBS_1(x)                 (((x) & 0x1) << 17)
+#define   G_000070_MC_IND_SEQ_RBS_1(x)                 (((x) >> 17) & 0x1)
+#define   C_000070_MC_IND_SEQ_RBS_1                    0xFFFDFFFF
+#define   S_000070_MC_IND_SEQ_RBS_2(x)                 (((x) & 0x1) << 18)
+#define   G_000070_MC_IND_SEQ_RBS_2(x)                 (((x) >> 18) & 0x1)
+#define   C_000070_MC_IND_SEQ_RBS_2                    0xFFFBFFFF
+#define   S_000070_MC_IND_SEQ_RBS_3(x)                 (((x) & 0x1) << 19)
+#define   G_000070_MC_IND_SEQ_RBS_3(x)                 (((x) >> 19) & 0x1)
+#define   C_000070_MC_IND_SEQ_RBS_3                    0xFFF7FFFF
+#define   S_000070_MC_IND_AIC_RBS(x)                   (((x) & 0x1) << 20)
+#define   G_000070_MC_IND_AIC_RBS(x)                   (((x) >> 20) & 0x1)
+#define   C_000070_MC_IND_AIC_RBS                      0xFFEFFFFF
+#define   S_000070_MC_IND_CITF_ARB0(x)                 (((x) & 0x1) << 21)
+#define   G_000070_MC_IND_CITF_ARB0(x)                 (((x) >> 21) & 0x1)
+#define   C_000070_MC_IND_CITF_ARB0                    0xFFDFFFFF
+#define   S_000070_MC_IND_CITF_ARB1(x)                 (((x) & 0x1) << 22)
+#define   G_000070_MC_IND_CITF_ARB1(x)                 (((x) >> 22) & 0x1)
+#define   C_000070_MC_IND_CITF_ARB1                    0xFFBFFFFF
+#define   S_000070_MC_IND_WR_EN(x)                     (((x) & 0x1) << 23)
+#define   G_000070_MC_IND_WR_EN(x)                     (((x) >> 23) & 0x1)
+#define   C_000070_MC_IND_WR_EN                        0xFF7FFFFF
+#define   S_000070_MC_IND_RD_INV(x)                    (((x) & 0x1) << 24)
+#define   G_000070_MC_IND_RD_INV(x)                    (((x) >> 24) & 0x1)
+#define   C_000070_MC_IND_RD_INV                       0xFEFFFFFF
+#define R_000074_MC_IND_DATA                         0x000074
+#define   S_000074_MC_IND_DATA(x)                      (((x) & 0xFFFFFFFF) << 0)
+#define   G_000074_MC_IND_DATA(x)                      (((x) >> 0) & 0xFFFFFFFF)
+#define   C_000074_MC_IND_DATA                         0x00000000
+#define R_000134_HDP_FB_LOCATION                     0x000134
+#define   S_000134_HDP_FB_START(x)                     (((x) & 0xFFFF) << 0)
+#define   G_000134_HDP_FB_START(x)                     (((x) >> 0) & 0xFFFF)
+#define   C_000134_HDP_FB_START                        0xFFFF0000
+#define R_0007C0_CP_STAT                             0x0007C0
+#define   S_0007C0_MRU_BUSY(x)                         (((x) & 0x1) << 0)
+#define   G_0007C0_MRU_BUSY(x)                         (((x) >> 0) & 0x1)
+#define   C_0007C0_MRU_BUSY                            0xFFFFFFFE
+#define   S_0007C0_MWU_BUSY(x)                         (((x) & 0x1) << 1)
+#define   G_0007C0_MWU_BUSY(x)                         (((x) >> 1) & 0x1)
+#define   C_0007C0_MWU_BUSY                            0xFFFFFFFD
+#define   S_0007C0_RSIU_BUSY(x)                        (((x) & 0x1) << 2)
+#define   G_0007C0_RSIU_BUSY(x)                        (((x) >> 2) & 0x1)
+#define   C_0007C0_RSIU_BUSY                           0xFFFFFFFB
+#define   S_0007C0_RCIU_BUSY(x)                        (((x) & 0x1) << 3)
+#define   G_0007C0_RCIU_BUSY(x)                        (((x) >> 3) & 0x1)
+#define   C_0007C0_RCIU_BUSY                           0xFFFFFFF7
+#define   S_0007C0_CSF_PRIMARY_BUSY(x)                 (((x) & 0x1) << 9)
+#define   G_0007C0_CSF_PRIMARY_BUSY(x)                 (((x) >> 9) & 0x1)
+#define   C_0007C0_CSF_PRIMARY_BUSY                    0xFFFFFDFF
+#define   S_0007C0_CSF_INDIRECT_BUSY(x)                (((x) & 0x1) << 10)
+#define   G_0007C0_CSF_INDIRECT_BUSY(x)                (((x) >> 10) & 0x1)
+#define   C_0007C0_CSF_INDIRECT_BUSY                   0xFFFFFBFF
+#define   S_0007C0_CSQ_PRIMARY_BUSY(x)                 (((x) & 0x1) << 11)
+#define   G_0007C0_CSQ_PRIMARY_BUSY(x)                 (((x) >> 11) & 0x1)
+#define   C_0007C0_CSQ_PRIMARY_BUSY                    0xFFFFF7FF
+#define   S_0007C0_CSQ_INDIRECT_BUSY(x)                (((x) & 0x1) << 12)
+#define   G_0007C0_CSQ_INDIRECT_BUSY(x)                (((x) >> 12) & 0x1)
+#define   C_0007C0_CSQ_INDIRECT_BUSY                   0xFFFFEFFF
+#define   S_0007C0_CSI_BUSY(x)                         (((x) & 0x1) << 13)
+#define   G_0007C0_CSI_BUSY(x)                         (((x) >> 13) & 0x1)
+#define   C_0007C0_CSI_BUSY                            0xFFFFDFFF
+#define   S_0007C0_CSF_INDIRECT2_BUSY(x)               (((x) & 0x1) << 14)
+#define   G_0007C0_CSF_INDIRECT2_BUSY(x)               (((x) >> 14) & 0x1)
+#define   C_0007C0_CSF_INDIRECT2_BUSY                  0xFFFFBFFF
+#define   S_0007C0_CSQ_INDIRECT2_BUSY(x)               (((x) & 0x1) << 15)
+#define   G_0007C0_CSQ_INDIRECT2_BUSY(x)               (((x) >> 15) & 0x1)
+#define   C_0007C0_CSQ_INDIRECT2_BUSY                  0xFFFF7FFF
+#define   S_0007C0_GUIDMA_BUSY(x)                      (((x) & 0x1) << 28)
+#define   G_0007C0_GUIDMA_BUSY(x)                      (((x) >> 28) & 0x1)
+#define   C_0007C0_GUIDMA_BUSY                         0xEFFFFFFF
+#define   S_0007C0_VIDDMA_BUSY(x)                      (((x) & 0x1) << 29)
+#define   G_0007C0_VIDDMA_BUSY(x)                      (((x) >> 29) & 0x1)
+#define   C_0007C0_VIDDMA_BUSY                         0xDFFFFFFF
+#define   S_0007C0_CMDSTRM_BUSY(x)                     (((x) & 0x1) << 30)
+#define   G_0007C0_CMDSTRM_BUSY(x)                     (((x) >> 30) & 0x1)
+#define   C_0007C0_CMDSTRM_BUSY                        0xBFFFFFFF
+#define   S_0007C0_CP_BUSY(x)                          (((x) & 0x1) << 31)
+#define   G_0007C0_CP_BUSY(x)                          (((x) >> 31) & 0x1)
+#define   C_0007C0_CP_BUSY                             0x7FFFFFFF
+#define R_000E40_RBBM_STATUS                         0x000E40
+#define   S_000E40_CMDFIFO_AVAIL(x)                    (((x) & 0x7F) << 0)
+#define   G_000E40_CMDFIFO_AVAIL(x)                    (((x) >> 0) & 0x7F)
+#define   C_000E40_CMDFIFO_AVAIL                       0xFFFFFF80
+#define   S_000E40_HIRQ_ON_RBB(x)                      (((x) & 0x1) << 8)
+#define   G_000E40_HIRQ_ON_RBB(x)                      (((x) >> 8) & 0x1)
+#define   C_000E40_HIRQ_ON_RBB                         0xFFFFFEFF
+#define   S_000E40_CPRQ_ON_RBB(x)                      (((x) & 0x1) << 9)
+#define   G_000E40_CPRQ_ON_RBB(x)                      (((x) >> 9) & 0x1)
+#define   C_000E40_CPRQ_ON_RBB                         0xFFFFFDFF
+#define   S_000E40_CFRQ_ON_RBB(x)                      (((x) & 0x1) << 10)
+#define   G_000E40_CFRQ_ON_RBB(x)                      (((x) >> 10) & 0x1)
+#define   C_000E40_CFRQ_ON_RBB                         0xFFFFFBFF
+#define   S_000E40_HIRQ_IN_RTBUF(x)                    (((x) & 0x1) << 11)
+#define   G_000E40_HIRQ_IN_RTBUF(x)                    (((x) >> 11) & 0x1)
+#define   C_000E40_HIRQ_IN_RTBUF                       0xFFFFF7FF
+#define   S_000E40_CPRQ_IN_RTBUF(x)                    (((x) & 0x1) << 12)
+#define   G_000E40_CPRQ_IN_RTBUF(x)                    (((x) >> 12) & 0x1)
+#define   C_000E40_CPRQ_IN_RTBUF                       0xFFFFEFFF
+#define   S_000E40_CFRQ_IN_RTBUF(x)                    (((x) & 0x1) << 13)
+#define   G_000E40_CFRQ_IN_RTBUF(x)                    (((x) >> 13) & 0x1)
+#define   C_000E40_CFRQ_IN_RTBUF                       0xFFFFDFFF
+#define   S_000E40_CF_PIPE_BUSY(x)                     (((x) & 0x1) << 14)
+#define   G_000E40_CF_PIPE_BUSY(x)                     (((x) >> 14) & 0x1)
+#define   C_000E40_CF_PIPE_BUSY                        0xFFFFBFFF
+#define   S_000E40_ENG_EV_BUSY(x)                      (((x) & 0x1) << 15)
+#define   G_000E40_ENG_EV_BUSY(x)                      (((x) >> 15) & 0x1)
+#define   C_000E40_ENG_EV_BUSY                         0xFFFF7FFF
+#define   S_000E40_CP_CMDSTRM_BUSY(x)                  (((x) & 0x1) << 16)
+#define   G_000E40_CP_CMDSTRM_BUSY(x)                  (((x) >> 16) & 0x1)
+#define   C_000E40_CP_CMDSTRM_BUSY                     0xFFFEFFFF
+#define   S_000E40_E2_BUSY(x)                          (((x) & 0x1) << 17)
+#define   G_000E40_E2_BUSY(x)                          (((x) >> 17) & 0x1)
+#define   C_000E40_E2_BUSY                             0xFFFDFFFF
+#define   S_000E40_RB2D_BUSY(x)                        (((x) & 0x1) << 18)
+#define   G_000E40_RB2D_BUSY(x)                        (((x) >> 18) & 0x1)
+#define   C_000E40_RB2D_BUSY                           0xFFFBFFFF
+#define   S_000E40_RB3D_BUSY(x)                        (((x) & 0x1) << 19)
+#define   G_000E40_RB3D_BUSY(x)                        (((x) >> 19) & 0x1)
+#define   C_000E40_RB3D_BUSY                           0xFFF7FFFF
+#define   S_000E40_VAP_BUSY(x)                         (((x) & 0x1) << 20)
+#define   G_000E40_VAP_BUSY(x)                         (((x) >> 20) & 0x1)
+#define   C_000E40_VAP_BUSY                            0xFFEFFFFF
+#define   S_000E40_RE_BUSY(x)                          (((x) & 0x1) << 21)
+#define   G_000E40_RE_BUSY(x)                          (((x) >> 21) & 0x1)
+#define   C_000E40_RE_BUSY                             0xFFDFFFFF
+#define   S_000E40_TAM_BUSY(x)                         (((x) & 0x1) << 22)
+#define   G_000E40_TAM_BUSY(x)                         (((x) >> 22) & 0x1)
+#define   C_000E40_TAM_BUSY                            0xFFBFFFFF
+#define   S_000E40_TDM_BUSY(x)                         (((x) & 0x1) << 23)
+#define   G_000E40_TDM_BUSY(x)                         (((x) >> 23) & 0x1)
+#define   C_000E40_TDM_BUSY                            0xFF7FFFFF
+#define   S_000E40_PB_BUSY(x)                          (((x) & 0x1) << 24)
+#define   G_000E40_PB_BUSY(x)                          (((x) >> 24) & 0x1)
+#define   C_000E40_PB_BUSY                             0xFEFFFFFF
+#define   S_000E40_TIM_BUSY(x)                         (((x) & 0x1) << 25)
+#define   G_000E40_TIM_BUSY(x)                         (((x) >> 25) & 0x1)
+#define   C_000E40_TIM_BUSY                            0xFDFFFFFF
+#define   S_000E40_GA_BUSY(x)                          (((x) & 0x1) << 26)
+#define   G_000E40_GA_BUSY(x)                          (((x) >> 26) & 0x1)
+#define   C_000E40_GA_BUSY                             0xFBFFFFFF
+#define   S_000E40_CBA2D_BUSY(x)                       (((x) & 0x1) << 27)
+#define   G_000E40_CBA2D_BUSY(x)                       (((x) >> 27) & 0x1)
+#define   C_000E40_CBA2D_BUSY                          0xF7FFFFFF
+#define   S_000E40_GUI_ACTIVE(x)                       (((x) & 0x1) << 31)
+#define   G_000E40_GUI_ACTIVE(x)                       (((x) >> 31) & 0x1)
+#define   C_000E40_GUI_ACTIVE                          0x7FFFFFFF
+#define R_0060A4_D1CRTC_STATUS_FRAME_COUNT           0x0060A4
+#define   S_0060A4_D1CRTC_FRAME_COUNT(x)               (((x) & 0xFFFFFF) << 0)
+#define   G_0060A4_D1CRTC_FRAME_COUNT(x)               (((x) >> 0) & 0xFFFFFF)
+#define   C_0060A4_D1CRTC_FRAME_COUNT                  0xFF000000
+#define R_006534_D1MODE_VBLANK_STATUS                0x006534
+#define   S_006534_D1MODE_VBLANK_OCCURRED(x)           (((x) & 0x1) << 0)
+#define   G_006534_D1MODE_VBLANK_OCCURRED(x)           (((x) >> 0) & 0x1)
+#define   C_006534_D1MODE_VBLANK_OCCURRED              0xFFFFFFFE
+#define   S_006534_D1MODE_VBLANK_ACK(x)                (((x) & 0x1) << 4)
+#define   G_006534_D1MODE_VBLANK_ACK(x)                (((x) >> 4) & 0x1)
+#define   C_006534_D1MODE_VBLANK_ACK                   0xFFFFFFEF
+#define   S_006534_D1MODE_VBLANK_STAT(x)               (((x) & 0x1) << 12)
+#define   G_006534_D1MODE_VBLANK_STAT(x)               (((x) >> 12) & 0x1)
+#define   C_006534_D1MODE_VBLANK_STAT                  0xFFFFEFFF
+#define   S_006534_D1MODE_VBLANK_INTERRUPT(x)          (((x) & 0x1) << 16)
+#define   G_006534_D1MODE_VBLANK_INTERRUPT(x)          (((x) >> 16) & 0x1)
+#define   C_006534_D1MODE_VBLANK_INTERRUPT             0xFFFEFFFF
+#define R_006540_DxMODE_INT_MASK                     0x006540
+#define   S_006540_D1MODE_VBLANK_INT_MASK(x)           (((x) & 0x1) << 0)
+#define   G_006540_D1MODE_VBLANK_INT_MASK(x)           (((x) >> 0) & 0x1)
+#define   C_006540_D1MODE_VBLANK_INT_MASK              0xFFFFFFFE
+#define   S_006540_D1MODE_VLINE_INT_MASK(x)            (((x) & 0x1) << 4)
+#define   G_006540_D1MODE_VLINE_INT_MASK(x)            (((x) >> 4) & 0x1)
+#define   C_006540_D1MODE_VLINE_INT_MASK               0xFFFFFFEF
+#define   S_006540_D2MODE_VBLANK_INT_MASK(x)           (((x) & 0x1) << 8)
+#define   G_006540_D2MODE_VBLANK_INT_MASK(x)           (((x) >> 8) & 0x1)
+#define   C_006540_D2MODE_VBLANK_INT_MASK              0xFFFFFEFF
+#define   S_006540_D2MODE_VLINE_INT_MASK(x)            (((x) & 0x1) << 12)
+#define   G_006540_D2MODE_VLINE_INT_MASK(x)            (((x) >> 12) & 0x1)
+#define   C_006540_D2MODE_VLINE_INT_MASK               0xFFFFEFFF
+#define   S_006540_D1MODE_VBLANK_CP_SEL(x)             (((x) & 0x1) << 30)
+#define   G_006540_D1MODE_VBLANK_CP_SEL(x)             (((x) >> 30) & 0x1)
+#define   C_006540_D1MODE_VBLANK_CP_SEL                0xBFFFFFFF
+#define   S_006540_D2MODE_VBLANK_CP_SEL(x)             (((x) & 0x1) << 31)
+#define   G_006540_D2MODE_VBLANK_CP_SEL(x)             (((x) >> 31) & 0x1)
+#define   C_006540_D2MODE_VBLANK_CP_SEL                0x7FFFFFFF
+#define R_0068A4_D2CRTC_STATUS_FRAME_COUNT           0x0068A4
+#define   S_0068A4_D2CRTC_FRAME_COUNT(x)               (((x) & 0xFFFFFF) << 0)
+#define   G_0068A4_D2CRTC_FRAME_COUNT(x)               (((x) >> 0) & 0xFFFFFF)
+#define   C_0068A4_D2CRTC_FRAME_COUNT                  0xFF000000
+#define R_006D34_D2MODE_VBLANK_STATUS                0x006D34
+#define   S_006D34_D2MODE_VBLANK_OCCURRED(x)           (((x) & 0x1) << 0)
+#define   G_006D34_D2MODE_VBLANK_OCCURRED(x)           (((x) >> 0) & 0x1)
+#define   C_006D34_D2MODE_VBLANK_OCCURRED              0xFFFFFFFE
+#define   S_006D34_D2MODE_VBLANK_ACK(x)                (((x) & 0x1) << 4)
+#define   G_006D34_D2MODE_VBLANK_ACK(x)                (((x) >> 4) & 0x1)
+#define   C_006D34_D2MODE_VBLANK_ACK                   0xFFFFFFEF
+#define   S_006D34_D2MODE_VBLANK_STAT(x)               (((x) & 0x1) << 12)
+#define   G_006D34_D2MODE_VBLANK_STAT(x)               (((x) >> 12) & 0x1)
+#define   C_006D34_D2MODE_VBLANK_STAT                  0xFFFFEFFF
+#define   S_006D34_D2MODE_VBLANK_INTERRUPT(x)          (((x) & 0x1) << 16)
+#define   G_006D34_D2MODE_VBLANK_INTERRUPT(x)          (((x) >> 16) & 0x1)
+#define   C_006D34_D2MODE_VBLANK_INTERRUPT             0xFFFEFFFF
+#define R_007EDC_DISP_INTERRUPT_STATUS               0x007EDC
+#define   S_007EDC_LB_D1_VBLANK_INTERRUPT(x)           (((x) & 0x1) << 4)
+#define   G_007EDC_LB_D1_VBLANK_INTERRUPT(x)           (((x) >> 4) & 0x1)
+#define   C_007EDC_LB_D1_VBLANK_INTERRUPT              0xFFFFFFEF
+#define   S_007EDC_LB_D2_VBLANK_INTERRUPT(x)           (((x) & 0x1) << 5)
+#define   G_007EDC_LB_D2_VBLANK_INTERRUPT(x)           (((x) >> 5) & 0x1)
+#define   C_007EDC_LB_D2_VBLANK_INTERRUPT              0xFFFFFFDF
+
+
+/* MC registers */
+#define R_000000_MC_STATUS                           0x000000
+#define   S_000000_MC_IDLE(x)                          (((x) & 0x1) << 0)
+#define   G_000000_MC_IDLE(x)                          (((x) >> 0) & 0x1)
+#define   C_000000_MC_IDLE                             0xFFFFFFFE
+#define R_000004_MC_FB_LOCATION                      0x000004
+#define   S_000004_MC_FB_START(x)                      (((x) & 0xFFFF) << 0)
+#define   G_000004_MC_FB_START(x)                      (((x) >> 0) & 0xFFFF)
+#define   C_000004_MC_FB_START                         0xFFFF0000
+#define   S_000004_MC_FB_TOP(x)                        (((x) & 0xFFFF) << 16)
+#define   G_000004_MC_FB_TOP(x)                        (((x) >> 16) & 0xFFFF)
+#define   C_000004_MC_FB_TOP                           0x0000FFFF
+#define R_000005_MC_AGP_LOCATION                     0x000005
+#define   S_000005_MC_AGP_START(x)                     (((x) & 0xFFFF) << 0)
+#define   G_000005_MC_AGP_START(x)                     (((x) >> 0) & 0xFFFF)
+#define   C_000005_MC_AGP_START                        0xFFFF0000
+#define   S_000005_MC_AGP_TOP(x)                       (((x) & 0xFFFF) << 16)
+#define   G_000005_MC_AGP_TOP(x)                       (((x) >> 16) & 0xFFFF)
+#define   C_000005_MC_AGP_TOP                          0x0000FFFF
+#define R_000006_AGP_BASE                            0x000006
+#define   S_000006_AGP_BASE_ADDR(x)                    (((x) & 0xFFFFFFFF) << 0)
+#define   G_000006_AGP_BASE_ADDR(x)                    (((x) >> 0) & 0xFFFFFFFF)
+#define   C_000006_AGP_BASE_ADDR                       0x00000000
+#define R_000007_AGP_BASE_2                          0x000007
+#define   S_000007_AGP_BASE_ADDR_2(x)                  (((x) & 0xF) << 0)
+#define   G_000007_AGP_BASE_ADDR_2(x)                  (((x) >> 0) & 0xF)
+#define   C_000007_AGP_BASE_ADDR_2                     0xFFFFFFF0
+#define R_000009_MC_CNTL1                            0x000009
+#define   S_000009_ENABLE_PAGE_TABLES(x)               (((x) & 0x1) << 26)
+#define   G_000009_ENABLE_PAGE_TABLES(x)               (((x) >> 26) & 0x1)
+#define   C_000009_ENABLE_PAGE_TABLES                  0xFBFFFFFF
+/* FIXME don't know the various field size need feedback from AMD */
+#define R_000100_MC_PT0_CNTL                         0x000100
+#define   S_000100_ENABLE_PT(x)                        (((x) & 0x1) << 0)
+#define   G_000100_ENABLE_PT(x)                        (((x) >> 0) & 0x1)
+#define   C_000100_ENABLE_PT                           0xFFFFFFFE
+#define   S_000100_EFFECTIVE_L2_CACHE_SIZE(x)          (((x) & 0x7) << 15)
+#define   G_000100_EFFECTIVE_L2_CACHE_SIZE(x)          (((x) >> 15) & 0x7)
+#define   C_000100_EFFECTIVE_L2_CACHE_SIZE             0xFFFC7FFF
+#define   S_000100_EFFECTIVE_L2_QUEUE_SIZE(x)          (((x) & 0x7) << 21)
+#define   G_000100_EFFECTIVE_L2_QUEUE_SIZE(x)          (((x) >> 21) & 0x7)
+#define   C_000100_EFFECTIVE_L2_QUEUE_SIZE             0xFF1FFFFF
+#define   S_000100_INVALIDATE_ALL_L1_TLBS(x)           (((x) & 0x1) << 28)
+#define   G_000100_INVALIDATE_ALL_L1_TLBS(x)           (((x) >> 28) & 0x1)
+#define   C_000100_INVALIDATE_ALL_L1_TLBS              0xEFFFFFFF
+#define   S_000100_INVALIDATE_L2_CACHE(x)              (((x) & 0x1) << 29)
+#define   G_000100_INVALIDATE_L2_CACHE(x)              (((x) >> 29) & 0x1)
+#define   C_000100_INVALIDATE_L2_CACHE                 0xDFFFFFFF
+#define R_000102_MC_PT0_CONTEXT0_CNTL                0x000102
+#define   S_000102_ENABLE_PAGE_TABLE(x)                (((x) & 0x1) << 0)
+#define   G_000102_ENABLE_PAGE_TABLE(x)                (((x) >> 0) & 0x1)
+#define   C_000102_ENABLE_PAGE_TABLE                   0xFFFFFFFE
+#define   S_000102_PAGE_TABLE_DEPTH(x)                 (((x) & 0x3) << 1)
+#define   G_000102_PAGE_TABLE_DEPTH(x)                 (((x) >> 1) & 0x3)
+#define   C_000102_PAGE_TABLE_DEPTH                    0xFFFFFFF9
+#define   V_000102_PAGE_TABLE_FLAT                     0
+/* R600 documentation suggest that this should be a number of pages */
+#define R_000112_MC_PT0_SYSTEM_APERTURE_LOW_ADDR     0x000112
+#define R_000114_MC_PT0_SYSTEM_APERTURE_HIGH_ADDR    0x000114
+#define R_00011C_MC_PT0_CONTEXT0_DEFAULT_READ_ADDR   0x00011C
+#define R_00012C_MC_PT0_CONTEXT0_FLAT_BASE_ADDR      0x00012C
+#define R_00013C_MC_PT0_CONTEXT0_FLAT_START_ADDR     0x00013C
+#define R_00014C_MC_PT0_CONTEXT0_FLAT_END_ADDR       0x00014C
+#define R_00016C_MC_PT0_CLIENT0_CNTL                 0x00016C
+#define   S_00016C_ENABLE_TRANSLATION_MODE_OVERRIDE(x) (((x) & 0x1) << 0)
+#define   G_00016C_ENABLE_TRANSLATION_MODE_OVERRIDE(x) (((x) >> 0) & 0x1)
+#define   C_00016C_ENABLE_TRANSLATION_MODE_OVERRIDE    0xFFFFFFFE
+#define   S_00016C_TRANSLATION_MODE_OVERRIDE(x)        (((x) & 0x1) << 1)
+#define   G_00016C_TRANSLATION_MODE_OVERRIDE(x)        (((x) >> 1) & 0x1)
+#define   C_00016C_TRANSLATION_MODE_OVERRIDE           0xFFFFFFFD
+#define   S_00016C_SYSTEM_ACCESS_MODE_MASK(x)          (((x) & 0x3) << 8)
+#define   G_00016C_SYSTEM_ACCESS_MODE_MASK(x)          (((x) >> 8) & 0x3)
+#define   C_00016C_SYSTEM_ACCESS_MODE_MASK             0xFFFFFCFF
+#define   V_00016C_SYSTEM_ACCESS_MODE_PA_ONLY          0
+#define   V_00016C_SYSTEM_ACCESS_MODE_USE_SYS_MAP      1
+#define   V_00016C_SYSTEM_ACCESS_MODE_IN_SYS           2
+#define   V_00016C_SYSTEM_ACCESS_MODE_NOT_IN_SYS       3
+#define   S_00016C_SYSTEM_APERTURE_UNMAPPED_ACCESS(x)  (((x) & 0x1) << 10)
+#define   G_00016C_SYSTEM_APERTURE_UNMAPPED_ACCESS(x)  (((x) >> 10) & 0x1)
+#define   C_00016C_SYSTEM_APERTURE_UNMAPPED_ACCESS     0xFFFFFBFF
+#define   V_00016C_SYSTEM_APERTURE_UNMAPPED_PASSTHROUGH  0
+#define   V_00016C_SYSTEM_APERTURE_UNMAPPED_DEFAULT_PAGE 1
+#define   S_00016C_EFFECTIVE_L1_CACHE_SIZE(x)          (((x) & 0x7) << 11)
+#define   G_00016C_EFFECTIVE_L1_CACHE_SIZE(x)          (((x) >> 11) & 0x7)
+#define   C_00016C_EFFECTIVE_L1_CACHE_SIZE             0xFFFFC7FF
+#define   S_00016C_ENABLE_FRAGMENT_PROCESSING(x)       (((x) & 0x1) << 14)
+#define   G_00016C_ENABLE_FRAGMENT_PROCESSING(x)       (((x) >> 14) & 0x1)
+#define   C_00016C_ENABLE_FRAGMENT_PROCESSING          0xFFFFBFFF
+#define   S_00016C_EFFECTIVE_L1_QUEUE_SIZE(x)          (((x) & 0x7) << 15)
+#define   G_00016C_EFFECTIVE_L1_QUEUE_SIZE(x)          (((x) >> 15) & 0x7)
+#define   C_00016C_EFFECTIVE_L1_QUEUE_SIZE             0xFFFC7FFF
+#define   S_00016C_INVALIDATE_L1_TLB(x)                (((x) & 0x1) << 20)
+#define   G_00016C_INVALIDATE_L1_TLB(x)                (((x) >> 20) & 0x1)
+#define   C_00016C_INVALIDATE_L1_TLB                   0xFFEFFFFF
+
+#endif
index 7a0098d..025e322 100644 (file)
  *          Jerome Glisse
  */
 #include "drmP.h"
-#include "radeon_reg.h"
 #include "radeon.h"
-#include "rs690r.h"
 #include "atom.h"
-#include "atom-bits.h"
-
-/* rs690,rs740 depends on : */
-void r100_hdp_reset(struct radeon_device *rdev);
-int r300_mc_wait_for_idle(struct radeon_device *rdev);
-void r420_pipes_init(struct radeon_device *rdev);
-void rs400_gart_disable(struct radeon_device *rdev);
-int rs400_gart_enable(struct radeon_device *rdev);
-void rs400_gart_adjust_size(struct radeon_device *rdev);
-void rs600_mc_disable_clients(struct radeon_device *rdev);
-
-/* This files gather functions specifics to :
- * rs690,rs740
- *
- * Some of these functions might be used by newer ASICs.
- */
-void rs690_gpu_init(struct radeon_device *rdev);
-int rs690_mc_wait_for_idle(struct radeon_device *rdev);
-
-
-/*
- * MC functions.
- */
-int rs690_mc_init(struct radeon_device *rdev)
-{
-       uint32_t tmp;
-       int r;
-
-       if (r100_debugfs_rbbm_init(rdev)) {
-               DRM_ERROR("Failed to register debugfs file for RBBM !\n");
-       }
-
-       rs690_gpu_init(rdev);
-       rs400_gart_disable(rdev);
-
-       /* Setup GPU memory space */
-       rdev->mc.gtt_location = rdev->mc.mc_vram_size;
-       rdev->mc.gtt_location += (rdev->mc.gtt_size - 1);
-       rdev->mc.gtt_location &= ~(rdev->mc.gtt_size - 1);
-       rdev->mc.vram_location = 0xFFFFFFFFUL;
-       r = radeon_mc_setup(rdev);
-       if (r) {
-               return r;
-       }
-
-       /* Program GPU memory space */
-       rs600_mc_disable_clients(rdev);
-       if (rs690_mc_wait_for_idle(rdev)) {
-               printk(KERN_WARNING "Failed to wait MC idle while "
-                      "programming pipes. Bad things might happen.\n");
-       }
-       tmp = rdev->mc.vram_location + rdev->mc.mc_vram_size - 1;
-       tmp = REG_SET(RS690_MC_FB_TOP, tmp >> 16);
-       tmp |= REG_SET(RS690_MC_FB_START, rdev->mc.vram_location >> 16);
-       WREG32_MC(RS690_MCCFG_FB_LOCATION, tmp);
-       /* FIXME: Does this reg exist on RS480,RS740 ? */
-       WREG32(0x310, rdev->mc.vram_location);
-       WREG32(RS690_HDP_FB_LOCATION, rdev->mc.vram_location >> 16);
-       return 0;
-}
-
-void rs690_mc_fini(struct radeon_device *rdev)
-{
-}
-
+#include "rs690d.h"
 
-/*
- * Global GPU functions
- */
-int rs690_mc_wait_for_idle(struct radeon_device *rdev)
+static int rs690_mc_wait_for_idle(struct radeon_device *rdev)
 {
        unsigned i;
        uint32_t tmp;
 
        for (i = 0; i < rdev->usec_timeout; i++) {
                /* read MC_STATUS */
-               tmp = RREG32_MC(RS690_MC_STATUS);
-               if (tmp & RS690_MC_STATUS_IDLE) {
+               tmp = RREG32_MC(R_000090_MC_SYSTEM_STATUS);
+               if (G_000090_MC_SYSTEM_IDLE(tmp))
                        return 0;
-               }
-               DRM_UDELAY(1);
+               udelay(1);
        }
        return -1;
 }
 
-void rs690_errata(struct radeon_device *rdev)
-{
-       rdev->pll_errata = 0;
-}
-
-void rs690_gpu_init(struct radeon_device *rdev)
+static void rs690_gpu_init(struct radeon_device *rdev)
 {
        /* FIXME: HDP same place on rs690 ? */
        r100_hdp_reset(rdev);
-       rv515_vga_render_disable(rdev);
        /* FIXME: is this correct ? */
        r420_pipes_init(rdev);
        if (rs690_mc_wait_for_idle(rdev)) {
@@ -133,10 +57,6 @@ void rs690_gpu_init(struct radeon_device *rdev)
        }
 }
 
-
-/*
- * VRAM info.
- */
 void rs690_pm_info(struct radeon_device *rdev)
 {
        int index = GetIndexIntoMasterTable(DATA, IntegratedSystemInfo);
@@ -250,39 +170,39 @@ void rs690_line_buffer_adjust(struct radeon_device *rdev,
        /*
         * Line Buffer Setup
         * There is a single line buffer shared by both display controllers.
-        * DC_LB_MEMORY_SPLIT controls how that line buffer is shared between
+        * R_006520_DC_LB_MEMORY_SPLIT controls how that line buffer is shared between
         * the display controllers.  The paritioning can either be done
         * manually or via one of four preset allocations specified in bits 1:0:
         *  0 - line buffer is divided in half and shared between crtc
         *  1 - D1 gets 3/4 of the line buffer, D2 gets 1/4
         *  2 - D1 gets the whole buffer
         *  3 - D1 gets 1/4 of the line buffer, D2 gets 3/4
-        * Setting bit 2 of DC_LB_MEMORY_SPLIT controls switches to manual
+        * Setting bit 2 of R_006520_DC_LB_MEMORY_SPLIT controls switches to manual
         * allocation mode. In manual allocation mode, D1 always starts at 0,
         * D1 end/2 is specified in bits 14:4; D2 allocation follows D1.
         */
-       tmp = RREG32(DC_LB_MEMORY_SPLIT) & ~DC_LB_MEMORY_SPLIT_MASK;
-       tmp &= ~DC_LB_MEMORY_SPLIT_SHIFT_MODE;
+       tmp = RREG32(R_006520_DC_LB_MEMORY_SPLIT) & C_006520_DC_LB_MEMORY_SPLIT;
+       tmp &= ~C_006520_DC_LB_MEMORY_SPLIT_MODE;
        /* auto */
        if (mode1 && mode2) {
                if (mode1->hdisplay > mode2->hdisplay) {
                        if (mode1->hdisplay > 2560)
-                               tmp |= DC_LB_MEMORY_SPLIT_D1_3Q_D2_1Q;
+                               tmp |= V_006520_DC_LB_MEMORY_SPLIT_D1_3Q_D2_1Q;
                        else
-                               tmp |= DC_LB_MEMORY_SPLIT_D1HALF_D2HALF;
+                               tmp |= V_006520_DC_LB_MEMORY_SPLIT_D1HALF_D2HALF;
                } else if (mode2->hdisplay > mode1->hdisplay) {
                        if (mode2->hdisplay > 2560)
-                               tmp |= DC_LB_MEMORY_SPLIT_D1_1Q_D2_3Q;
+                               tmp |= V_006520_DC_LB_MEMORY_SPLIT_D1_1Q_D2_3Q;
                        else
-                               tmp |= DC_LB_MEMORY_SPLIT_D1HALF_D2HALF;
+                               tmp |= V_006520_DC_LB_MEMORY_SPLIT_D1HALF_D2HALF;
                } else
-                       tmp |= AVIVO_DC_LB_MEMORY_SPLIT_D1HALF_D2HALF;
+                       tmp |= V_006520_DC_LB_MEMORY_SPLIT_D1HALF_D2HALF;
        } else if (mode1) {
-               tmp |= DC_LB_MEMORY_SPLIT_D1_ONLY;
+               tmp |= V_006520_DC_LB_MEMORY_SPLIT_D1_ONLY;
        } else if (mode2) {
-               tmp |= DC_LB_MEMORY_SPLIT_D1_1Q_D2_3Q;
+               tmp |= V_006520_DC_LB_MEMORY_SPLIT_D1_1Q_D2_3Q;
        }
-       WREG32(DC_LB_MEMORY_SPLIT, tmp);
+       WREG32(R_006520_DC_LB_MEMORY_SPLIT, tmp);
 }
 
 struct rs690_watermark {
@@ -487,28 +407,28 @@ void rs690_bandwidth_update(struct radeon_device *rdev)
         * option.
         */
        if (rdev->disp_priority == 2) {
-               tmp = RREG32_MC(MC_INIT_MISC_LAT_TIMER);
-               tmp &= ~MC_DISP1R_INIT_LAT_MASK;
-               tmp &= ~MC_DISP0R_INIT_LAT_MASK;
-               if (mode1)
-                       tmp |= (1 << MC_DISP1R_INIT_LAT_SHIFT);
+               tmp = RREG32_MC(R_000104_MC_INIT_MISC_LAT_TIMER);
+               tmp &= C_000104_MC_DISP0R_INIT_LAT;
+               tmp &= C_000104_MC_DISP1R_INIT_LAT;
                if (mode0)
-                       tmp |= (1 << MC_DISP0R_INIT_LAT_SHIFT);
-               WREG32_MC(MC_INIT_MISC_LAT_TIMER, tmp);
+                       tmp |= S_000104_MC_DISP0R_INIT_LAT(1);
+               if (mode1)
+                       tmp |= S_000104_MC_DISP1R_INIT_LAT(1);
+               WREG32_MC(R_000104_MC_INIT_MISC_LAT_TIMER, tmp);
        }
        rs690_line_buffer_adjust(rdev, mode0, mode1);
 
        if ((rdev->family == CHIP_RS690) || (rdev->family == CHIP_RS740))
-               WREG32(DCP_CONTROL, 0);
+               WREG32(R_006C9C_DCP_CONTROL, 0);
        if ((rdev->family == CHIP_RS780) || (rdev->family == CHIP_RS880))
-               WREG32(DCP_CONTROL, 2);
+               WREG32(R_006C9C_DCP_CONTROL, 2);
 
        rs690_crtc_bandwidth_compute(rdev, rdev->mode_info.crtcs[0], &wm0);
        rs690_crtc_bandwidth_compute(rdev, rdev->mode_info.crtcs[1], &wm1);
 
        tmp = (wm0.lb_request_fifo_depth - 1);
        tmp |= (wm1.lb_request_fifo_depth - 1) << 16;
-       WREG32(LB_MAX_REQ_OUTSTANDING, tmp);
+       WREG32(R_006D58_LB_MAX_REQ_OUTSTANDING, tmp);
 
        if (mode0 && mode1) {
                if (rfixed_trunc(wm0.dbpp) > 64)
@@ -561,10 +481,10 @@ void rs690_bandwidth_update(struct radeon_device *rdev)
                        priority_mark12.full = 0;
                if (wm1.priority_mark_max.full > priority_mark12.full)
                        priority_mark12.full = wm1.priority_mark_max.full;
-               WREG32(D1MODE_PRIORITY_A_CNT, rfixed_trunc(priority_mark02));
-               WREG32(D1MODE_PRIORITY_B_CNT, rfixed_trunc(priority_mark02));
-               WREG32(D2MODE_PRIORITY_A_CNT, rfixed_trunc(priority_mark12));
-               WREG32(D2MODE_PRIORITY_B_CNT, rfixed_trunc(priority_mark12));
+               WREG32(R_006548_D1MODE_PRIORITY_A_CNT, rfixed_trunc(priority_mark02));
+               WREG32(R_00654C_D1MODE_PRIORITY_B_CNT, rfixed_trunc(priority_mark02));
+               WREG32(R_006D48_D2MODE_PRIORITY_A_CNT, rfixed_trunc(priority_mark12));
+               WREG32(R_006D4C_D2MODE_PRIORITY_B_CNT, rfixed_trunc(priority_mark12));
        } else if (mode0) {
                if (rfixed_trunc(wm0.dbpp) > 64)
                        a.full = rfixed_mul(wm0.dbpp, wm0.num_line_pair);
@@ -591,10 +511,12 @@ void rs690_bandwidth_update(struct radeon_device *rdev)
                        priority_mark02.full = 0;
                if (wm0.priority_mark_max.full > priority_mark02.full)
                        priority_mark02.full = wm0.priority_mark_max.full;
-               WREG32(D1MODE_PRIORITY_A_CNT, rfixed_trunc(priority_mark02));
-               WREG32(D1MODE_PRIORITY_B_CNT, rfixed_trunc(priority_mark02));
-               WREG32(D2MODE_PRIORITY_A_CNT, MODE_PRIORITY_OFF);
-               WREG32(D2MODE_PRIORITY_B_CNT, MODE_PRIORITY_OFF);
+               WREG32(R_006548_D1MODE_PRIORITY_A_CNT, rfixed_trunc(priority_mark02));
+               WREG32(R_00654C_D1MODE_PRIORITY_B_CNT, rfixed_trunc(priority_mark02));
+               WREG32(R_006D48_D2MODE_PRIORITY_A_CNT,
+                       S_006D48_D2MODE_PRIORITY_A_OFF(1));
+               WREG32(R_006D4C_D2MODE_PRIORITY_B_CNT,
+                       S_006D4C_D2MODE_PRIORITY_B_OFF(1));
        } else {
                if (rfixed_trunc(wm1.dbpp) > 64)
                        a.full = rfixed_mul(wm1.dbpp, wm1.num_line_pair);
@@ -621,30 +543,203 @@ void rs690_bandwidth_update(struct radeon_device *rdev)
                        priority_mark12.full = 0;
                if (wm1.priority_mark_max.full > priority_mark12.full)
                        priority_mark12.full = wm1.priority_mark_max.full;
-               WREG32(D1MODE_PRIORITY_A_CNT, MODE_PRIORITY_OFF);
-               WREG32(D1MODE_PRIORITY_B_CNT, MODE_PRIORITY_OFF);
-               WREG32(D2MODE_PRIORITY_A_CNT, rfixed_trunc(priority_mark12));
-               WREG32(D2MODE_PRIORITY_B_CNT, rfixed_trunc(priority_mark12));
+               WREG32(R_006548_D1MODE_PRIORITY_A_CNT,
+                       S_006548_D1MODE_PRIORITY_A_OFF(1));
+               WREG32(R_00654C_D1MODE_PRIORITY_B_CNT,
+                       S_00654C_D1MODE_PRIORITY_B_OFF(1));
+               WREG32(R_006D48_D2MODE_PRIORITY_A_CNT, rfixed_trunc(priority_mark12));
+               WREG32(R_006D4C_D2MODE_PRIORITY_B_CNT, rfixed_trunc(priority_mark12));
        }
 }
 
-/*
- * Indirect registers accessor
- */
 uint32_t rs690_mc_rreg(struct radeon_device *rdev, uint32_t reg)
 {
        uint32_t r;
 
-       WREG32(RS690_MC_INDEX, (reg & RS690_MC_INDEX_MASK));
-       r = RREG32(RS690_MC_DATA);
-       WREG32(RS690_MC_INDEX, RS690_MC_INDEX_MASK);
+       WREG32(R_000078_MC_INDEX, S_000078_MC_IND_ADDR(reg));
+       r = RREG32(R_00007C_MC_DATA);
+       WREG32(R_000078_MC_INDEX, ~C_000078_MC_IND_ADDR);
        return r;
 }
 
 void rs690_mc_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v)
 {
-       WREG32(RS690_MC_INDEX,
-              RS690_MC_INDEX_WR_EN | ((reg) & RS690_MC_INDEX_MASK));
-       WREG32(RS690_MC_DATA, v);
-       WREG32(RS690_MC_INDEX, RS690_MC_INDEX_WR_ACK);
+       WREG32(R_000078_MC_INDEX, S_000078_MC_IND_ADDR(reg) |
+               S_000078_MC_IND_WR_EN(1));
+       WREG32(R_00007C_MC_DATA, v);
+       WREG32(R_000078_MC_INDEX, 0x7F);
+}
+
+void rs690_mc_program(struct radeon_device *rdev)
+{
+       struct rv515_mc_save save;
+
+       /* Stops all mc clients */
+       rv515_mc_stop(rdev, &save);
+
+       /* Wait for mc idle */
+       if (rs690_mc_wait_for_idle(rdev))
+               dev_warn(rdev->dev, "Wait MC idle timeout before updating MC.\n");
+       /* Program MC, should be a 32bits limited address space */
+       WREG32_MC(R_000100_MCCFG_FB_LOCATION,
+                       S_000100_MC_FB_START(rdev->mc.vram_start >> 16) |
+                       S_000100_MC_FB_TOP(rdev->mc.vram_end >> 16));
+       WREG32(R_000134_HDP_FB_LOCATION,
+               S_000134_HDP_FB_START(rdev->mc.vram_start >> 16));
+
+       rv515_mc_resume(rdev, &save);
+}
+
+static int rs690_startup(struct radeon_device *rdev)
+{
+       int r;
+
+       rs690_mc_program(rdev);
+       /* Resume clock */
+       rv515_clock_startup(rdev);
+       /* Initialize GPU configuration (# pipes, ...) */
+       rs690_gpu_init(rdev);
+       /* Initialize GART (initialize after TTM so we can allocate
+        * memory through TTM but finalize after TTM) */
+       r = rs400_gart_enable(rdev);
+       if (r)
+               return r;
+       /* Enable IRQ */
+       rdev->irq.sw_int = true;
+       rs600_irq_set(rdev);
+       /* 1M ring buffer */
+       r = r100_cp_init(rdev, 1024 * 1024);
+       if (r) {
+               dev_err(rdev->dev, "failled initializing CP (%d).\n", r);
+               return r;
+       }
+       r = r100_wb_init(rdev);
+       if (r)
+               dev_err(rdev->dev, "failled initializing WB (%d).\n", r);
+       r = r100_ib_init(rdev);
+       if (r) {
+               dev_err(rdev->dev, "failled initializing IB (%d).\n", r);
+               return r;
+       }
+       return 0;
+}
+
+int rs690_resume(struct radeon_device *rdev)
+{
+       /* Make sur GART are not working */
+       rs400_gart_disable(rdev);
+       /* Resume clock before doing reset */
+       rv515_clock_startup(rdev);
+       /* Reset gpu before posting otherwise ATOM will enter infinite loop */
+       if (radeon_gpu_reset(rdev)) {
+               dev_warn(rdev->dev, "GPU reset failed ! (0xE40=0x%08X, 0x7C0=0x%08X)\n",
+                       RREG32(R_000E40_RBBM_STATUS),
+                       RREG32(R_0007C0_CP_STAT));
+       }
+       /* post */
+       atom_asic_init(rdev->mode_info.atom_context);
+       /* Resume clock after posting */
+       rv515_clock_startup(rdev);
+       return rs690_startup(rdev);
+}
+
+int rs690_suspend(struct radeon_device *rdev)
+{
+       r100_cp_disable(rdev);
+       r100_wb_disable(rdev);
+       rs600_irq_disable(rdev);
+       rs400_gart_disable(rdev);
+       return 0;
+}
+
+void rs690_fini(struct radeon_device *rdev)
+{
+       rs690_suspend(rdev);
+       r100_cp_fini(rdev);
+       r100_wb_fini(rdev);
+       r100_ib_fini(rdev);
+       radeon_gem_fini(rdev);
+       rs400_gart_fini(rdev);
+       radeon_irq_kms_fini(rdev);
+       radeon_fence_driver_fini(rdev);
+       radeon_object_fini(rdev);
+       radeon_atombios_fini(rdev);
+       kfree(rdev->bios);
+       rdev->bios = NULL;
+}
+
+int rs690_init(struct radeon_device *rdev)
+{
+       int r;
+
+       /* Disable VGA */
+       rv515_vga_render_disable(rdev);
+       /* Initialize scratch registers */
+       radeon_scratch_init(rdev);
+       /* Initialize surface registers */
+       radeon_surface_init(rdev);
+       /* TODO: disable VGA need to use VGA request */
+       /* BIOS*/
+       if (!radeon_get_bios(rdev)) {
+               if (ASIC_IS_AVIVO(rdev))
+                       return -EINVAL;
+       }
+       if (rdev->is_atom_bios) {
+               r = radeon_atombios_init(rdev);
+               if (r)
+                       return r;
+       } else {
+               dev_err(rdev->dev, "Expecting atombios for RV515 GPU\n");
+               return -EINVAL;
+       }
+       /* Reset gpu before posting otherwise ATOM will enter infinite loop */
+       if (radeon_gpu_reset(rdev)) {
+               dev_warn(rdev->dev,
+                       "GPU reset failed ! (0xE40=0x%08X, 0x7C0=0x%08X)\n",
+                       RREG32(R_000E40_RBBM_STATUS),
+                       RREG32(R_0007C0_CP_STAT));
+       }
+       /* check if cards are posted or not */
+       if (!radeon_card_posted(rdev) && rdev->bios) {
+               DRM_INFO("GPU not posted. posting now...\n");
+               atom_asic_init(rdev->mode_info.atom_context);
+       }
+       /* Initialize clocks */
+       radeon_get_clock_info(rdev->ddev);
+       /* Get vram informations */
+       rs690_vram_info(rdev);
+       /* Initialize memory controller (also test AGP) */
+       r = r420_mc_init(rdev);
+       if (r)
+               return r;
+       rv515_debugfs(rdev);
+       /* Fence driver */
+       r = radeon_fence_driver_init(rdev);
+       if (r)
+               return r;
+       r = radeon_irq_kms_init(rdev);
+       if (r)
+               return r;
+       /* Memory manager */
+       r = radeon_object_init(rdev);
+       if (r)
+               return r;
+       r = rs400_gart_init(rdev);
+       if (r)
+               return r;
+       rs600_set_safe_registers(rdev);
+       rdev->accel_working = true;
+       r = rs690_startup(rdev);
+       if (r) {
+               /* Somethings want wront with the accel init stop accel */
+               dev_err(rdev->dev, "Disabling GPU acceleration\n");
+               rs690_suspend(rdev);
+               r100_cp_fini(rdev);
+               r100_wb_fini(rdev);
+               r100_ib_fini(rdev);
+               rs400_gart_fini(rdev);
+               radeon_irq_kms_fini(rdev);
+               rdev->accel_working = false;
+       }
+       return 0;
 }
diff --git a/drivers/gpu/drm/radeon/rs690d.h b/drivers/gpu/drm/radeon/rs690d.h
new file mode 100644 (file)
index 0000000..62d31e7
--- /dev/null
@@ -0,0 +1,307 @@
+/*
+ * Copyright 2008 Advanced Micro Devices, Inc.
+ * Copyright 2008 Red Hat Inc.
+ * Copyright 2009 Jerome Glisse.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: Dave Airlie
+ *          Alex Deucher
+ *          Jerome Glisse
+ */
+#ifndef __RS690D_H__
+#define __RS690D_H__
+
+/* Registers */
+#define R_000078_MC_INDEX                            0x000078
+#define   S_000078_MC_IND_ADDR(x)                      (((x) & 0x1FF) << 0)
+#define   G_000078_MC_IND_ADDR(x)                      (((x) >> 0) & 0x1FF)
+#define   C_000078_MC_IND_ADDR                         0xFFFFFE00
+#define   S_000078_MC_IND_WR_EN(x)                     (((x) & 0x1) << 9)
+#define   G_000078_MC_IND_WR_EN(x)                     (((x) >> 9) & 0x1)
+#define   C_000078_MC_IND_WR_EN                        0xFFFFFDFF
+#define R_00007C_MC_DATA                             0x00007C
+#define   S_00007C_MC_DATA(x)                          (((x) & 0xFFFFFFFF) << 0)
+#define   G_00007C_MC_DATA(x)                          (((x) >> 0) & 0xFFFFFFFF)
+#define   C_00007C_MC_DATA                             0x00000000
+#define R_0000F8_CONFIG_MEMSIZE                      0x0000F8
+#define   S_0000F8_CONFIG_MEMSIZE(x)                   (((x) & 0xFFFFFFFF) << 0)
+#define   G_0000F8_CONFIG_MEMSIZE(x)                   (((x) >> 0) & 0xFFFFFFFF)
+#define   C_0000F8_CONFIG_MEMSIZE                      0x00000000
+#define R_000134_HDP_FB_LOCATION                     0x000134
+#define   S_000134_HDP_FB_START(x)                     (((x) & 0xFFFF) << 0)
+#define   G_000134_HDP_FB_START(x)                     (((x) >> 0) & 0xFFFF)
+#define   C_000134_HDP_FB_START                        0xFFFF0000
+#define R_0007C0_CP_STAT                             0x0007C0
+#define   S_0007C0_MRU_BUSY(x)                         (((x) & 0x1) << 0)
+#define   G_0007C0_MRU_BUSY(x)                         (((x) >> 0) & 0x1)
+#define   C_0007C0_MRU_BUSY                            0xFFFFFFFE
+#define   S_0007C0_MWU_BUSY(x)                         (((x) & 0x1) << 1)
+#define   G_0007C0_MWU_BUSY(x)                         (((x) >> 1) & 0x1)
+#define   C_0007C0_MWU_BUSY                            0xFFFFFFFD
+#define   S_0007C0_RSIU_BUSY(x)                        (((x) & 0x1) << 2)
+#define   G_0007C0_RSIU_BUSY(x)                        (((x) >> 2) & 0x1)
+#define   C_0007C0_RSIU_BUSY                           0xFFFFFFFB
+#define   S_0007C0_RCIU_BUSY(x)                        (((x) & 0x1) << 3)
+#define   G_0007C0_RCIU_BUSY(x)                        (((x) >> 3) & 0x1)
+#define   C_0007C0_RCIU_BUSY                           0xFFFFFFF7
+#define   S_0007C0_CSF_PRIMARY_BUSY(x)                 (((x) & 0x1) << 9)
+#define   G_0007C0_CSF_PRIMARY_BUSY(x)                 (((x) >> 9) & 0x1)
+#define   C_0007C0_CSF_PRIMARY_BUSY                    0xFFFFFDFF
+#define   S_0007C0_CSF_INDIRECT_BUSY(x)                (((x) & 0x1) << 10)
+#define   G_0007C0_CSF_INDIRECT_BUSY(x)                (((x) >> 10) & 0x1)
+#define   C_0007C0_CSF_INDIRECT_BUSY                   0xFFFFFBFF
+#define   S_0007C0_CSQ_PRIMARY_BUSY(x)                 (((x) & 0x1) << 11)
+#define   G_0007C0_CSQ_PRIMARY_BUSY(x)                 (((x) >> 11) & 0x1)
+#define   C_0007C0_CSQ_PRIMARY_BUSY                    0xFFFFF7FF
+#define   S_0007C0_CSQ_INDIRECT_BUSY(x)                (((x) & 0x1) << 12)
+#define   G_0007C0_CSQ_INDIRECT_BUSY(x)                (((x) >> 12) & 0x1)
+#define   C_0007C0_CSQ_INDIRECT_BUSY                   0xFFFFEFFF
+#define   S_0007C0_CSI_BUSY(x)                         (((x) & 0x1) << 13)
+#define   G_0007C0_CSI_BUSY(x)                         (((x) >> 13) & 0x1)
+#define   C_0007C0_CSI_BUSY                            0xFFFFDFFF
+#define   S_0007C0_CSF_INDIRECT2_BUSY(x)               (((x) & 0x1) << 14)
+#define   G_0007C0_CSF_INDIRECT2_BUSY(x)               (((x) >> 14) & 0x1)
+#define   C_0007C0_CSF_INDIRECT2_BUSY                  0xFFFFBFFF
+#define   S_0007C0_CSQ_INDIRECT2_BUSY(x)               (((x) & 0x1) << 15)
+#define   G_0007C0_CSQ_INDIRECT2_BUSY(x)               (((x) >> 15) & 0x1)
+#define   C_0007C0_CSQ_INDIRECT2_BUSY                  0xFFFF7FFF
+#define   S_0007C0_GUIDMA_BUSY(x)                      (((x) & 0x1) << 28)
+#define   G_0007C0_GUIDMA_BUSY(x)                      (((x) >> 28) & 0x1)
+#define   C_0007C0_GUIDMA_BUSY                         0xEFFFFFFF
+#define   S_0007C0_VIDDMA_BUSY(x)                      (((x) & 0x1) << 29)
+#define   G_0007C0_VIDDMA_BUSY(x)                      (((x) >> 29) & 0x1)
+#define   C_0007C0_VIDDMA_BUSY                         0xDFFFFFFF
+#define   S_0007C0_CMDSTRM_BUSY(x)                     (((x) & 0x1) << 30)
+#define   G_0007C0_CMDSTRM_BUSY(x)                     (((x) >> 30) & 0x1)
+#define   C_0007C0_CMDSTRM_BUSY                        0xBFFFFFFF
+#define   S_0007C0_CP_BUSY(x)                          (((x) & 0x1) << 31)
+#define   G_0007C0_CP_BUSY(x)                          (((x) >> 31) & 0x1)
+#define   C_0007C0_CP_BUSY                             0x7FFFFFFF
+#define R_000E40_RBBM_STATUS                         0x000E40
+#define   S_000E40_CMDFIFO_AVAIL(x)                    (((x) & 0x7F) << 0)
+#define   G_000E40_CMDFIFO_AVAIL(x)                    (((x) >> 0) & 0x7F)
+#define   C_000E40_CMDFIFO_AVAIL                       0xFFFFFF80
+#define   S_000E40_HIRQ_ON_RBB(x)                      (((x) & 0x1) << 8)
+#define   G_000E40_HIRQ_ON_RBB(x)                      (((x) >> 8) & 0x1)
+#define   C_000E40_HIRQ_ON_RBB                         0xFFFFFEFF
+#define   S_000E40_CPRQ_ON_RBB(x)                      (((x) & 0x1) << 9)
+#define   G_000E40_CPRQ_ON_RBB(x)                      (((x) >> 9) & 0x1)
+#define   C_000E40_CPRQ_ON_RBB                         0xFFFFFDFF
+#define   S_000E40_CFRQ_ON_RBB(x)                      (((x) & 0x1) << 10)
+#define   G_000E40_CFRQ_ON_RBB(x)                      (((x) >> 10) & 0x1)
+#define   C_000E40_CFRQ_ON_RBB                         0xFFFFFBFF
+#define   S_000E40_HIRQ_IN_RTBUF(x)                    (((x) & 0x1) << 11)
+#define   G_000E40_HIRQ_IN_RTBUF(x)                    (((x) >> 11) & 0x1)
+#define   C_000E40_HIRQ_IN_RTBUF                       0xFFFFF7FF
+#define   S_000E40_CPRQ_IN_RTBUF(x)                    (((x) & 0x1) << 12)
+#define   G_000E40_CPRQ_IN_RTBUF(x)                    (((x) >> 12) & 0x1)
+#define   C_000E40_CPRQ_IN_RTBUF                       0xFFFFEFFF
+#define   S_000E40_CFRQ_IN_RTBUF(x)                    (((x) & 0x1) << 13)
+#define   G_000E40_CFRQ_IN_RTBUF(x)                    (((x) >> 13) & 0x1)
+#define   C_000E40_CFRQ_IN_RTBUF                       0xFFFFDFFF
+#define   S_000E40_CF_PIPE_BUSY(x)                     (((x) & 0x1) << 14)
+#define   G_000E40_CF_PIPE_BUSY(x)                     (((x) >> 14) & 0x1)
+#define   C_000E40_CF_PIPE_BUSY                        0xFFFFBFFF
+#define   S_000E40_ENG_EV_BUSY(x)                      (((x) & 0x1) << 15)
+#define   G_000E40_ENG_EV_BUSY(x)                      (((x) >> 15) & 0x1)
+#define   C_000E40_ENG_EV_BUSY                         0xFFFF7FFF
+#define   S_000E40_CP_CMDSTRM_BUSY(x)                  (((x) & 0x1) << 16)
+#define   G_000E40_CP_CMDSTRM_BUSY(x)                  (((x) >> 16) & 0x1)
+#define   C_000E40_CP_CMDSTRM_BUSY                     0xFFFEFFFF
+#define   S_000E40_E2_BUSY(x)                          (((x) & 0x1) << 17)
+#define   G_000E40_E2_BUSY(x)                          (((x) >> 17) & 0x1)
+#define   C_000E40_E2_BUSY                             0xFFFDFFFF
+#define   S_000E40_RB2D_BUSY(x)                        (((x) & 0x1) << 18)
+#define   G_000E40_RB2D_BUSY(x)                        (((x) >> 18) & 0x1)
+#define   C_000E40_RB2D_BUSY                           0xFFFBFFFF
+#define   S_000E40_RB3D_BUSY(x)                        (((x) & 0x1) << 19)
+#define   G_000E40_RB3D_BUSY(x)                        (((x) >> 19) & 0x1)
+#define   C_000E40_RB3D_BUSY                           0xFFF7FFFF
+#define   S_000E40_VAP_BUSY(x)                         (((x) & 0x1) << 20)
+#define   G_000E40_VAP_BUSY(x)                         (((x) >> 20) & 0x1)
+#define   C_000E40_VAP_BUSY                            0xFFEFFFFF
+#define   S_000E40_RE_BUSY(x)                          (((x) & 0x1) << 21)
+#define   G_000E40_RE_BUSY(x)                          (((x) >> 21) & 0x1)
+#define   C_000E40_RE_BUSY                             0xFFDFFFFF
+#define   S_000E40_TAM_BUSY(x)                         (((x) & 0x1) << 22)
+#define   G_000E40_TAM_BUSY(x)                         (((x) >> 22) & 0x1)
+#define   C_000E40_TAM_BUSY                            0xFFBFFFFF
+#define   S_000E40_TDM_BUSY(x)                         (((x) & 0x1) << 23)
+#define   G_000E40_TDM_BUSY(x)                         (((x) >> 23) & 0x1)
+#define   C_000E40_TDM_BUSY                            0xFF7FFFFF
+#define   S_000E40_PB_BUSY(x)                          (((x) & 0x1) << 24)
+#define   G_000E40_PB_BUSY(x)                          (((x) >> 24) & 0x1)
+#define   C_000E40_PB_BUSY                             0xFEFFFFFF
+#define   S_000E40_TIM_BUSY(x)                         (((x) & 0x1) << 25)
+#define   G_000E40_TIM_BUSY(x)                         (((x) >> 25) & 0x1)
+#define   C_000E40_TIM_BUSY                            0xFDFFFFFF
+#define   S_000E40_GA_BUSY(x)                          (((x) & 0x1) << 26)
+#define   G_000E40_GA_BUSY(x)                          (((x) >> 26) & 0x1)
+#define   C_000E40_GA_BUSY                             0xFBFFFFFF
+#define   S_000E40_CBA2D_BUSY(x)                       (((x) & 0x1) << 27)
+#define   G_000E40_CBA2D_BUSY(x)                       (((x) >> 27) & 0x1)
+#define   C_000E40_CBA2D_BUSY                          0xF7FFFFFF
+#define   S_000E40_GUI_ACTIVE(x)                       (((x) & 0x1) << 31)
+#define   G_000E40_GUI_ACTIVE(x)                       (((x) >> 31) & 0x1)
+#define   C_000E40_GUI_ACTIVE                          0x7FFFFFFF
+#define R_006520_DC_LB_MEMORY_SPLIT                  0x006520
+#define   S_006520_DC_LB_MEMORY_SPLIT(x)               (((x) & 0x3) << 0)
+#define   G_006520_DC_LB_MEMORY_SPLIT(x)               (((x) >> 0) & 0x3)
+#define   C_006520_DC_LB_MEMORY_SPLIT                  0xFFFFFFFC
+#define   S_006520_DC_LB_MEMORY_SPLIT_MODE(x)          (((x) & 0x1) << 2)
+#define   G_006520_DC_LB_MEMORY_SPLIT_MODE(x)          (((x) >> 2) & 0x1)
+#define   C_006520_DC_LB_MEMORY_SPLIT_MODE             0xFFFFFFFB
+#define   V_006520_DC_LB_MEMORY_SPLIT_D1HALF_D2HALF    0
+#define   V_006520_DC_LB_MEMORY_SPLIT_D1_3Q_D2_1Q      1
+#define   V_006520_DC_LB_MEMORY_SPLIT_D1_ONLY          2
+#define   V_006520_DC_LB_MEMORY_SPLIT_D1_1Q_D2_3Q      3
+#define   S_006520_DC_LB_DISP1_END_ADR(x)              (((x) & 0x7FF) << 4)
+#define   G_006520_DC_LB_DISP1_END_ADR(x)              (((x) >> 4) & 0x7FF)
+#define   C_006520_DC_LB_DISP1_END_ADR                 0xFFFF800F
+#define R_006548_D1MODE_PRIORITY_A_CNT               0x006548
+#define   S_006548_D1MODE_PRIORITY_MARK_A(x)           (((x) & 0x7FFF) << 0)
+#define   G_006548_D1MODE_PRIORITY_MARK_A(x)           (((x) >> 0) & 0x7FFF)
+#define   C_006548_D1MODE_PRIORITY_MARK_A              0xFFFF8000
+#define   S_006548_D1MODE_PRIORITY_A_OFF(x)            (((x) & 0x1) << 16)
+#define   G_006548_D1MODE_PRIORITY_A_OFF(x)            (((x) >> 16) & 0x1)
+#define   C_006548_D1MODE_PRIORITY_A_OFF               0xFFFEFFFF
+#define   S_006548_D1MODE_PRIORITY_A_FORCE_MASK(x)     (((x) & 0x1) << 24)
+#define   G_006548_D1MODE_PRIORITY_A_FORCE_MASK(x)     (((x) >> 24) & 0x1)
+#define   C_006548_D1MODE_PRIORITY_A_FORCE_MASK        0xFEFFFFFF
+#define R_00654C_D1MODE_PRIORITY_B_CNT               0x00654C
+#define   S_00654C_D1MODE_PRIORITY_MARK_B(x)           (((x) & 0x7FFF) << 0)
+#define   G_00654C_D1MODE_PRIORITY_MARK_B(x)           (((x) >> 0) & 0x7FFF)
+#define   C_00654C_D1MODE_PRIORITY_MARK_B              0xFFFF8000
+#define   S_00654C_D1MODE_PRIORITY_B_OFF(x)            (((x) & 0x1) << 16)
+#define   G_00654C_D1MODE_PRIORITY_B_OFF(x)            (((x) >> 16) & 0x1)
+#define   C_00654C_D1MODE_PRIORITY_B_OFF               0xFFFEFFFF
+#define   S_00654C_D1MODE_PRIORITY_B_ALWAYS_ON(x)      (((x) & 0x1) << 20)
+#define   G_00654C_D1MODE_PRIORITY_B_ALWAYS_ON(x)      (((x) >> 20) & 0x1)
+#define   C_00654C_D1MODE_PRIORITY_B_ALWAYS_ON         0xFFEFFFFF
+#define   S_00654C_D1MODE_PRIORITY_B_FORCE_MASK(x)     (((x) & 0x1) << 24)
+#define   G_00654C_D1MODE_PRIORITY_B_FORCE_MASK(x)     (((x) >> 24) & 0x1)
+#define   C_00654C_D1MODE_PRIORITY_B_FORCE_MASK        0xFEFFFFFF
+#define R_006C9C_DCP_CONTROL                         0x006C9C
+#define R_006D48_D2MODE_PRIORITY_A_CNT               0x006D48
+#define   S_006D48_D2MODE_PRIORITY_MARK_A(x)           (((x) & 0x7FFF) << 0)
+#define   G_006D48_D2MODE_PRIORITY_MARK_A(x)           (((x) >> 0) & 0x7FFF)
+#define   C_006D48_D2MODE_PRIORITY_MARK_A              0xFFFF8000
+#define   S_006D48_D2MODE_PRIORITY_A_OFF(x)            (((x) & 0x1) << 16)
+#define   G_006D48_D2MODE_PRIORITY_A_OFF(x)            (((x) >> 16) & 0x1)
+#define   C_006D48_D2MODE_PRIORITY_A_OFF               0xFFFEFFFF
+#define   S_006D48_D2MODE_PRIORITY_A_ALWAYS_ON(x)      (((x) & 0x1) << 20)
+#define   G_006D48_D2MODE_PRIORITY_A_ALWAYS_ON(x)      (((x) >> 20) & 0x1)
+#define   C_006D48_D2MODE_PRIORITY_A_ALWAYS_ON         0xFFEFFFFF
+#define   S_006D48_D2MODE_PRIORITY_A_FORCE_MASK(x)     (((x) & 0x1) << 24)
+#define   G_006D48_D2MODE_PRIORITY_A_FORCE_MASK(x)     (((x) >> 24) & 0x1)
+#define   C_006D48_D2MODE_PRIORITY_A_FORCE_MASK        0xFEFFFFFF
+#define R_006D4C_D2MODE_PRIORITY_B_CNT               0x006D4C
+#define   S_006D4C_D2MODE_PRIORITY_MARK_B(x)           (((x) & 0x7FFF) << 0)
+#define   G_006D4C_D2MODE_PRIORITY_MARK_B(x)           (((x) >> 0) & 0x7FFF)
+#define   C_006D4C_D2MODE_PRIORITY_MARK_B              0xFFFF8000
+#define   S_006D4C_D2MODE_PRIORITY_B_OFF(x)            (((x) & 0x1) << 16)
+#define   G_006D4C_D2MODE_PRIORITY_B_OFF(x)            (((x) >> 16) & 0x1)
+#define   C_006D4C_D2MODE_PRIORITY_B_OFF               0xFFFEFFFF
+#define   S_006D4C_D2MODE_PRIORITY_B_ALWAYS_ON(x)      (((x) & 0x1) << 20)
+#define   G_006D4C_D2MODE_PRIORITY_B_ALWAYS_ON(x)      (((x) >> 20) & 0x1)
+#define   C_006D4C_D2MODE_PRIORITY_B_ALWAYS_ON         0xFFEFFFFF
+#define   S_006D4C_D2MODE_PRIORITY_B_FORCE_MASK(x)     (((x) & 0x1) << 24)
+#define   G_006D4C_D2MODE_PRIORITY_B_FORCE_MASK(x)     (((x) >> 24) & 0x1)
+#define   C_006D4C_D2MODE_PRIORITY_B_FORCE_MASK        0xFEFFFFFF
+#define R_006D58_LB_MAX_REQ_OUTSTANDING              0x006D58
+#define   S_006D58_LB_D1_MAX_REQ_OUTSTANDING(x)        (((x) & 0xF) << 0)
+#define   G_006D58_LB_D1_MAX_REQ_OUTSTANDING(x)        (((x) >> 0) & 0xF)
+#define   C_006D58_LB_D1_MAX_REQ_OUTSTANDING           0xFFFFFFF0
+#define   S_006D58_LB_D2_MAX_REQ_OUTSTANDING(x)        (((x) & 0xF) << 16)
+#define   G_006D58_LB_D2_MAX_REQ_OUTSTANDING(x)        (((x) >> 16) & 0xF)
+#define   C_006D58_LB_D2_MAX_REQ_OUTSTANDING           0xFFF0FFFF
+
+
+#define R_000090_MC_SYSTEM_STATUS                    0x000090
+#define   S_000090_MC_SYSTEM_IDLE(x)                   (((x) & 0x1) << 0)
+#define   G_000090_MC_SYSTEM_IDLE(x)                   (((x) >> 0) & 0x1)
+#define   C_000090_MC_SYSTEM_IDLE                      0xFFFFFFFE
+#define   S_000090_MC_SEQUENCER_IDLE(x)                (((x) & 0x1) << 1)
+#define   G_000090_MC_SEQUENCER_IDLE(x)                (((x) >> 1) & 0x1)
+#define   C_000090_MC_SEQUENCER_IDLE                   0xFFFFFFFD
+#define   S_000090_MC_ARBITER_IDLE(x)                  (((x) & 0x1) << 2)
+#define   G_000090_MC_ARBITER_IDLE(x)                  (((x) >> 2) & 0x1)
+#define   C_000090_MC_ARBITER_IDLE                     0xFFFFFFFB
+#define   S_000090_MC_SELECT_PM(x)                     (((x) & 0x1) << 3)
+#define   G_000090_MC_SELECT_PM(x)                     (((x) >> 3) & 0x1)
+#define   C_000090_MC_SELECT_PM                        0xFFFFFFF7
+#define   S_000090_RESERVED4(x)                        (((x) & 0xF) << 4)
+#define   G_000090_RESERVED4(x)                        (((x) >> 4) & 0xF)
+#define   C_000090_RESERVED4                           0xFFFFFF0F
+#define   S_000090_RESERVED8(x)                        (((x) & 0xF) << 8)
+#define   G_000090_RESERVED8(x)                        (((x) >> 8) & 0xF)
+#define   C_000090_RESERVED8                           0xFFFFF0FF
+#define   S_000090_RESERVED12(x)                       (((x) & 0xF) << 12)
+#define   G_000090_RESERVED12(x)                       (((x) >> 12) & 0xF)
+#define   C_000090_RESERVED12                          0xFFFF0FFF
+#define   S_000090_MCA_INIT_EXECUTED(x)                (((x) & 0x1) << 16)
+#define   G_000090_MCA_INIT_EXECUTED(x)                (((x) >> 16) & 0x1)
+#define   C_000090_MCA_INIT_EXECUTED                   0xFFFEFFFF
+#define   S_000090_MCA_IDLE(x)                         (((x) & 0x1) << 17)
+#define   G_000090_MCA_IDLE(x)                         (((x) >> 17) & 0x1)
+#define   C_000090_MCA_IDLE                            0xFFFDFFFF
+#define   S_000090_MCA_SEQ_IDLE(x)                     (((x) & 0x1) << 18)
+#define   G_000090_MCA_SEQ_IDLE(x)                     (((x) >> 18) & 0x1)
+#define   C_000090_MCA_SEQ_IDLE                        0xFFFBFFFF
+#define   S_000090_MCA_ARB_IDLE(x)                     (((x) & 0x1) << 19)
+#define   G_000090_MCA_ARB_IDLE(x)                     (((x) >> 19) & 0x1)
+#define   C_000090_MCA_ARB_IDLE                        0xFFF7FFFF
+#define   S_000090_RESERVED20(x)                       (((x) & 0xFFF) << 20)
+#define   G_000090_RESERVED20(x)                       (((x) >> 20) & 0xFFF)
+#define   C_000090_RESERVED20                          0x000FFFFF
+#define R_000100_MCCFG_FB_LOCATION                   0x000100
+#define   S_000100_MC_FB_START(x)                      (((x) & 0xFFFF) << 0)
+#define   G_000100_MC_FB_START(x)                      (((x) >> 0) & 0xFFFF)
+#define   C_000100_MC_FB_START                         0xFFFF0000
+#define   S_000100_MC_FB_TOP(x)                        (((x) & 0xFFFF) << 16)
+#define   G_000100_MC_FB_TOP(x)                        (((x) >> 16) & 0xFFFF)
+#define   C_000100_MC_FB_TOP                           0x0000FFFF
+#define R_000104_MC_INIT_MISC_LAT_TIMER              0x000104
+#define   S_000104_MC_CPR_INIT_LAT(x)                  (((x) & 0xF) << 0)
+#define   G_000104_MC_CPR_INIT_LAT(x)                  (((x) >> 0) & 0xF)
+#define   C_000104_MC_CPR_INIT_LAT                     0xFFFFFFF0
+#define   S_000104_MC_VF_INIT_LAT(x)                   (((x) & 0xF) << 4)
+#define   G_000104_MC_VF_INIT_LAT(x)                   (((x) >> 4) & 0xF)
+#define   C_000104_MC_VF_INIT_LAT                      0xFFFFFF0F
+#define   S_000104_MC_DISP0R_INIT_LAT(x)               (((x) & 0xF) << 8)
+#define   G_000104_MC_DISP0R_INIT_LAT(x)               (((x) >> 8) & 0xF)
+#define   C_000104_MC_DISP0R_INIT_LAT                  0xFFFFF0FF
+#define   S_000104_MC_DISP1R_INIT_LAT(x)               (((x) & 0xF) << 12)
+#define   G_000104_MC_DISP1R_INIT_LAT(x)               (((x) >> 12) & 0xF)
+#define   C_000104_MC_DISP1R_INIT_LAT                  0xFFFF0FFF
+#define   S_000104_MC_FIXED_INIT_LAT(x)                (((x) & 0xF) << 16)
+#define   G_000104_MC_FIXED_INIT_LAT(x)                (((x) >> 16) & 0xF)
+#define   C_000104_MC_FIXED_INIT_LAT                   0xFFF0FFFF
+#define   S_000104_MC_E2R_INIT_LAT(x)                  (((x) & 0xF) << 20)
+#define   G_000104_MC_E2R_INIT_LAT(x)                  (((x) >> 20) & 0xF)
+#define   C_000104_MC_E2R_INIT_LAT                     0xFF0FFFFF
+#define   S_000104_SAME_PAGE_PRIO(x)                   (((x) & 0xF) << 24)
+#define   G_000104_SAME_PAGE_PRIO(x)                   (((x) >> 24) & 0xF)
+#define   C_000104_SAME_PAGE_PRIO                      0xF0FFFFFF
+#define   S_000104_MC_GLOBW_INIT_LAT(x)                (((x) & 0xF) << 28)
+#define   G_000104_MC_GLOBW_INIT_LAT(x)                (((x) >> 28) & 0xF)
+#define   C_000104_MC_GLOBW_INIT_LAT                   0x0FFFFFFF
+
+#endif
diff --git a/drivers/gpu/drm/radeon/rs690r.h b/drivers/gpu/drm/radeon/rs690r.h
deleted file mode 100644 (file)
index c0d9faa..0000000
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- * Copyright 2008 Advanced Micro Devices, Inc.
- * Copyright 2008 Red Hat Inc.
- * Copyright 2009 Jerome Glisse.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- *
- * Authors: Dave Airlie
- *          Alex Deucher
- *          Jerome Glisse
- */
-#ifndef RS690R_H
-#define RS690R_H
-
-/* RS690/RS740 registers */
-#define MC_INDEX                       0x0078
-#      define MC_INDEX_MASK                    0x1FF
-#      define MC_INDEX_WR_EN                   (1 << 9)
-#      define MC_INDEX_WR_ACK                  0x7F
-#define MC_DATA                                0x007C
-#define HDP_FB_LOCATION                        0x0134
-#define DC_LB_MEMORY_SPLIT             0x6520
-#define                DC_LB_MEMORY_SPLIT_MASK                 0x00000003
-#define                DC_LB_MEMORY_SPLIT_SHIFT                0
-#define                DC_LB_MEMORY_SPLIT_D1HALF_D2HALF        0
-#define                DC_LB_MEMORY_SPLIT_D1_3Q_D2_1Q          1
-#define                DC_LB_MEMORY_SPLIT_D1_ONLY              2
-#define                DC_LB_MEMORY_SPLIT_D1_1Q_D2_3Q          3
-#define                DC_LB_MEMORY_SPLIT_SHIFT_MODE           (1 << 2)
-#define                DC_LB_DISP1_END_ADR_SHIFT               4
-#define                DC_LB_DISP1_END_ADR_MASK                0x00007FF0
-#define D1MODE_PRIORITY_A_CNT          0x6548
-#define                MODE_PRIORITY_MARK_MASK                 0x00007FFF
-#define                MODE_PRIORITY_OFF                       (1 << 16)
-#define                MODE_PRIORITY_ALWAYS_ON                 (1 << 20)
-#define                MODE_PRIORITY_FORCE_MASK                (1 << 24)
-#define D1MODE_PRIORITY_B_CNT          0x654C
-#define LB_MAX_REQ_OUTSTANDING         0x6D58
-#define                LB_D1_MAX_REQ_OUTSTANDING_MASK          0x0000000F
-#define                LB_D1_MAX_REQ_OUTSTANDING_SHIFT         0
-#define                LB_D2_MAX_REQ_OUTSTANDING_MASK          0x000F0000
-#define                LB_D2_MAX_REQ_OUTSTANDING_SHIFT         16
-#define DCP_CONTROL                    0x6C9C
-#define D2MODE_PRIORITY_A_CNT          0x6D48
-#define D2MODE_PRIORITY_B_CNT          0x6D4C
-
-/* MC indirect registers */
-#define MC_STATUS_IDLE                         (1 << 0)
-#define MC_MISC_CNTL                   0x18
-#define                DISABLE_GTW                     (1 << 1)
-#define                GART_INDEX_REG_EN               (1 << 12)
-#define                BLOCK_GFX_D3_EN                 (1 << 14)
-#define GART_FEATURE_ID                        0x2B
-#define                HANG_EN                         (1 << 11)
-#define                TLB_ENABLE                      (1 << 18)
-#define                P2P_ENABLE                      (1 << 19)
-#define                GTW_LAC_EN                      (1 << 25)
-#define                LEVEL2_GART                     (0 << 30)
-#define                LEVEL1_GART                     (1 << 30)
-#define                PDC_EN                          (1 << 31)
-#define GART_BASE                      0x2C
-#define GART_CACHE_CNTRL               0x2E
-#      define GART_CACHE_INVALIDATE            (1 << 0)
-#define MC_STATUS                      0x90
-#define MCCFG_FB_LOCATION              0x100
-#define                MC_FB_START_MASK                0x0000FFFF
-#define                MC_FB_START_SHIFT               0
-#define                MC_FB_TOP_MASK                  0xFFFF0000
-#define                MC_FB_TOP_SHIFT                 16
-#define MCCFG_AGP_LOCATION             0x101
-#define                MC_AGP_START_MASK               0x0000FFFF
-#define                MC_AGP_START_SHIFT              0
-#define                MC_AGP_TOP_MASK                 0xFFFF0000
-#define                MC_AGP_TOP_SHIFT                16
-#define MCCFG_AGP_BASE                 0x102
-#define MCCFG_AGP_BASE_2               0x103
-#define MC_INIT_MISC_LAT_TIMER         0x104
-#define                MC_DISP0R_INIT_LAT_SHIFT        8
-#define                MC_DISP0R_INIT_LAT_MASK         0x00000F00
-#define                MC_DISP1R_INIT_LAT_SHIFT        12
-#define                MC_DISP1R_INIT_LAT_MASK         0x0000F000
-
-#endif
diff --git a/drivers/gpu/drm/radeon/rv200d.h b/drivers/gpu/drm/radeon/rv200d.h
new file mode 100644 (file)
index 0000000..c5b3983
--- /dev/null
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2008 Advanced Micro Devices, Inc.
+ * Copyright 2008 Red Hat Inc.
+ * Copyright 2009 Jerome Glisse.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: Dave Airlie
+ *          Alex Deucher
+ *          Jerome Glisse
+ */
+#ifndef __RV200D_H__
+#define __RV200D_H__
+
+#define R_00015C_AGP_BASE_2                          0x00015C
+#define   S_00015C_AGP_BASE_ADDR_2(x)                  (((x) & 0xF) << 0)
+#define   G_00015C_AGP_BASE_ADDR_2(x)                  (((x) >> 0) & 0xF)
+#define   C_00015C_AGP_BASE_ADDR_2                     0xFFFFFFF0
+
+#endif
diff --git a/drivers/gpu/drm/radeon/rv250d.h b/drivers/gpu/drm/radeon/rv250d.h
new file mode 100644 (file)
index 0000000..e5a70b0
--- /dev/null
@@ -0,0 +1,123 @@
+/*
+ * Copyright 2008 Advanced Micro Devices, Inc.
+ * Copyright 2008 Red Hat Inc.
+ * Copyright 2009 Jerome Glisse.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: Dave Airlie
+ *          Alex Deucher
+ *          Jerome Glisse
+ */
+#ifndef __RV250D_H__
+#define __RV250D_H__
+
+#define R_00000D_SCLK_CNTL_M6                        0x00000D
+#define   S_00000D_SCLK_SRC_SEL(x)                     (((x) & 0x7) << 0)
+#define   G_00000D_SCLK_SRC_SEL(x)                     (((x) >> 0) & 0x7)
+#define   C_00000D_SCLK_SRC_SEL                        0xFFFFFFF8
+#define   S_00000D_CP_MAX_DYN_STOP_LAT(x)              (((x) & 0x1) << 3)
+#define   G_00000D_CP_MAX_DYN_STOP_LAT(x)              (((x) >> 3) & 0x1)
+#define   C_00000D_CP_MAX_DYN_STOP_LAT                 0xFFFFFFF7
+#define   S_00000D_HDP_MAX_DYN_STOP_LAT(x)             (((x) & 0x1) << 4)
+#define   G_00000D_HDP_MAX_DYN_STOP_LAT(x)             (((x) >> 4) & 0x1)
+#define   C_00000D_HDP_MAX_DYN_STOP_LAT                0xFFFFFFEF
+#define   S_00000D_TV_MAX_DYN_STOP_LAT(x)              (((x) & 0x1) << 5)
+#define   G_00000D_TV_MAX_DYN_STOP_LAT(x)              (((x) >> 5) & 0x1)
+#define   C_00000D_TV_MAX_DYN_STOP_LAT                 0xFFFFFFDF
+#define   S_00000D_E2_MAX_DYN_STOP_LAT(x)              (((x) & 0x1) << 6)
+#define   G_00000D_E2_MAX_DYN_STOP_LAT(x)              (((x) >> 6) & 0x1)
+#define   C_00000D_E2_MAX_DYN_STOP_LAT                 0xFFFFFFBF
+#define   S_00000D_SE_MAX_DYN_STOP_LAT(x)              (((x) & 0x1) << 7)
+#define   G_00000D_SE_MAX_DYN_STOP_LAT(x)              (((x) >> 7) & 0x1)
+#define   C_00000D_SE_MAX_DYN_STOP_LAT                 0xFFFFFF7F
+#define   S_00000D_IDCT_MAX_DYN_STOP_LAT(x)            (((x) & 0x1) << 8)
+#define   G_00000D_IDCT_MAX_DYN_STOP_LAT(x)            (((x) >> 8) & 0x1)
+#define   C_00000D_IDCT_MAX_DYN_STOP_LAT               0xFFFFFEFF
+#define   S_00000D_VIP_MAX_DYN_STOP_LAT(x)             (((x) & 0x1) << 9)
+#define   G_00000D_VIP_MAX_DYN_STOP_LAT(x)             (((x) >> 9) & 0x1)
+#define   C_00000D_VIP_MAX_DYN_STOP_LAT                0xFFFFFDFF
+#define   S_00000D_RE_MAX_DYN_STOP_LAT(x)              (((x) & 0x1) << 10)
+#define   G_00000D_RE_MAX_DYN_STOP_LAT(x)              (((x) >> 10) & 0x1)
+#define   C_00000D_RE_MAX_DYN_STOP_LAT                 0xFFFFFBFF
+#define   S_00000D_PB_MAX_DYN_STOP_LAT(x)              (((x) & 0x1) << 11)
+#define   G_00000D_PB_MAX_DYN_STOP_LAT(x)              (((x) >> 11) & 0x1)
+#define   C_00000D_PB_MAX_DYN_STOP_LAT                 0xFFFFF7FF
+#define   S_00000D_TAM_MAX_DYN_STOP_LAT(x)             (((x) & 0x1) << 12)
+#define   G_00000D_TAM_MAX_DYN_STOP_LAT(x)             (((x) >> 12) & 0x1)
+#define   C_00000D_TAM_MAX_DYN_STOP_LAT                0xFFFFEFFF
+#define   S_00000D_TDM_MAX_DYN_STOP_LAT(x)             (((x) & 0x1) << 13)
+#define   G_00000D_TDM_MAX_DYN_STOP_LAT(x)             (((x) >> 13) & 0x1)
+#define   C_00000D_TDM_MAX_DYN_STOP_LAT                0xFFFFDFFF
+#define   S_00000D_RB_MAX_DYN_STOP_LAT(x)              (((x) & 0x1) << 14)
+#define   G_00000D_RB_MAX_DYN_STOP_LAT(x)              (((x) >> 14) & 0x1)
+#define   C_00000D_RB_MAX_DYN_STOP_LAT                 0xFFFFBFFF
+#define   S_00000D_FORCE_DISP2(x)                      (((x) & 0x1) << 15)
+#define   G_00000D_FORCE_DISP2(x)                      (((x) >> 15) & 0x1)
+#define   C_00000D_FORCE_DISP2                         0xFFFF7FFF
+#define   S_00000D_FORCE_CP(x)                         (((x) & 0x1) << 16)
+#define   G_00000D_FORCE_CP(x)                         (((x) >> 16) & 0x1)
+#define   C_00000D_FORCE_CP                            0xFFFEFFFF
+#define   S_00000D_FORCE_HDP(x)                        (((x) & 0x1) << 17)
+#define   G_00000D_FORCE_HDP(x)                        (((x) >> 17) & 0x1)
+#define   C_00000D_FORCE_HDP                           0xFFFDFFFF
+#define   S_00000D_FORCE_DISP1(x)                      (((x) & 0x1) << 18)
+#define   G_00000D_FORCE_DISP1(x)                      (((x) >> 18) & 0x1)
+#define   C_00000D_FORCE_DISP1                         0xFFFBFFFF
+#define   S_00000D_FORCE_TOP(x)                        (((x) & 0x1) << 19)
+#define   G_00000D_FORCE_TOP(x)                        (((x) >> 19) & 0x1)
+#define   C_00000D_FORCE_TOP                           0xFFF7FFFF
+#define   S_00000D_FORCE_E2(x)                         (((x) & 0x1) << 20)
+#define   G_00000D_FORCE_E2(x)                         (((x) >> 20) & 0x1)
+#define   C_00000D_FORCE_E2                            0xFFEFFFFF
+#define   S_00000D_FORCE_SE(x)                         (((x) & 0x1) << 21)
+#define   G_00000D_FORCE_SE(x)                         (((x) >> 21) & 0x1)
+#define   C_00000D_FORCE_SE                            0xFFDFFFFF
+#define   S_00000D_FORCE_IDCT(x)                       (((x) & 0x1) << 22)
+#define   G_00000D_FORCE_IDCT(x)                       (((x) >> 22) & 0x1)
+#define   C_00000D_FORCE_IDCT                          0xFFBFFFFF
+#define   S_00000D_FORCE_VIP(x)                        (((x) & 0x1) << 23)
+#define   G_00000D_FORCE_VIP(x)                        (((x) >> 23) & 0x1)
+#define   C_00000D_FORCE_VIP                           0xFF7FFFFF
+#define   S_00000D_FORCE_RE(x)                         (((x) & 0x1) << 24)
+#define   G_00000D_FORCE_RE(x)                         (((x) >> 24) & 0x1)
+#define   C_00000D_FORCE_RE                            0xFEFFFFFF
+#define   S_00000D_FORCE_PB(x)                         (((x) & 0x1) << 25)
+#define   G_00000D_FORCE_PB(x)                         (((x) >> 25) & 0x1)
+#define   C_00000D_FORCE_PB                            0xFDFFFFFF
+#define   S_00000D_FORCE_TAM(x)                        (((x) & 0x1) << 26)
+#define   G_00000D_FORCE_TAM(x)                        (((x) >> 26) & 0x1)
+#define   C_00000D_FORCE_TAM                           0xFBFFFFFF
+#define   S_00000D_FORCE_TDM(x)                        (((x) & 0x1) << 27)
+#define   G_00000D_FORCE_TDM(x)                        (((x) >> 27) & 0x1)
+#define   C_00000D_FORCE_TDM                           0xF7FFFFFF
+#define   S_00000D_FORCE_RB(x)                         (((x) & 0x1) << 28)
+#define   G_00000D_FORCE_RB(x)                         (((x) >> 28) & 0x1)
+#define   C_00000D_FORCE_RB                            0xEFFFFFFF
+#define   S_00000D_FORCE_TV_SCLK(x)                    (((x) & 0x1) << 29)
+#define   G_00000D_FORCE_TV_SCLK(x)                    (((x) >> 29) & 0x1)
+#define   C_00000D_FORCE_TV_SCLK                       0xDFFFFFFF
+#define   S_00000D_FORCE_SUBPIC(x)                     (((x) & 0x1) << 30)
+#define   G_00000D_FORCE_SUBPIC(x)                     (((x) >> 30) & 0x1)
+#define   C_00000D_FORCE_SUBPIC                        0xBFFFFFFF
+#define   S_00000D_FORCE_OV0(x)                        (((x) & 0x1) << 31)
+#define   G_00000D_FORCE_OV0(x)                        (((x) >> 31) & 0x1)
+#define   C_00000D_FORCE_OV0                           0x7FFFFFFF
+
+#endif
diff --git a/drivers/gpu/drm/radeon/rv350d.h b/drivers/gpu/drm/radeon/rv350d.h
new file mode 100644 (file)
index 0000000..c75c5ed
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2008 Advanced Micro Devices, Inc.
+ * Copyright 2008 Red Hat Inc.
+ * Copyright 2009 Jerome Glisse.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: Dave Airlie
+ *          Alex Deucher
+ *          Jerome Glisse
+ */
+#ifndef __RV350D_H__
+#define __RV350D_H__
+
+/* RV350, RV380 registers */
+/* #define R_00000D_SCLK_CNTL                           0x00000D */
+#define   S_00000D_FORCE_VAP(x)                        (((x) & 0x1) << 21)
+#define   G_00000D_FORCE_VAP(x)                        (((x) >> 21) & 0x1)
+#define   C_00000D_FORCE_VAP                           0xFFDFFFFF
+#define   S_00000D_FORCE_SR(x)                         (((x) & 0x1) << 25)
+#define   G_00000D_FORCE_SR(x)                         (((x) >> 25) & 0x1)
+#define   C_00000D_FORCE_SR                            0xFDFFFFFF
+#define   S_00000D_FORCE_PX(x)                         (((x) & 0x1) << 26)
+#define   G_00000D_FORCE_PX(x)                         (((x) >> 26) & 0x1)
+#define   C_00000D_FORCE_PX                            0xFBFFFFFF
+#define   S_00000D_FORCE_TX(x)                         (((x) & 0x1) << 27)
+#define   G_00000D_FORCE_TX(x)                         (((x) >> 27) & 0x1)
+#define   C_00000D_FORCE_TX                            0xF7FFFFFF
+#define   S_00000D_FORCE_US(x)                         (((x) & 0x1) << 28)
+#define   G_00000D_FORCE_US(x)                         (((x) >> 28) & 0x1)
+#define   C_00000D_FORCE_US                            0xEFFFFFFF
+#define   S_00000D_FORCE_SU(x)                         (((x) & 0x1) << 30)
+#define   G_00000D_FORCE_SU(x)                         (((x) >> 30) & 0x1)
+#define   C_00000D_FORCE_SU                            0xBFFFFFFF
+
+#endif
index e53b5ca..41a34c2 100644 (file)
@@ -478,7 +478,7 @@ static int rv515_startup(struct radeon_device *rdev)
        }
        /* Enable IRQ */
        rdev->irq.sw_int = true;
-       r100_irq_set(rdev);
+       rs600_irq_set(rdev);
        /* 1M ring buffer */
        r = r100_cp_init(rdev, 1024 * 1024);
        if (r) {
@@ -520,7 +520,7 @@ int rv515_suspend(struct radeon_device *rdev)
 {
        r100_cp_disable(rdev);
        r100_wb_disable(rdev);
-       r100_irq_disable(rdev);
+       rs600_irq_disable(rdev);
        if (rdev->flags & RADEON_IS_PCIE)
                rv370_pcie_gart_disable(rdev);
        return 0;
@@ -553,7 +553,6 @@ int rv515_init(struct radeon_device *rdev)
 {
        int r;
 
-       rdev->new_init_path = true;
        /* Initialize scratch registers */
        radeon_scratch_init(rdev);
        /* Initialize surface registers */
index e0b97d1..595ac63 100644 (file)
@@ -75,7 +75,7 @@ int rv770_pcie_gart_enable(struct radeon_device *rdev)
        WREG32(MC_VM_MB_L1_TLB2_CNTL, tmp);
        WREG32(MC_VM_MB_L1_TLB3_CNTL, tmp);
        WREG32(VM_CONTEXT0_PAGE_TABLE_START_ADDR, rdev->mc.gtt_start >> 12);
-       WREG32(VM_CONTEXT0_PAGE_TABLE_END_ADDR, (rdev->mc.gtt_end - 1) >> 12);
+       WREG32(VM_CONTEXT0_PAGE_TABLE_END_ADDR, rdev->mc.gtt_end >> 12);
        WREG32(VM_CONTEXT0_PAGE_TABLE_BASE_ADDR, rdev->gart.table_addr >> 12);
        WREG32(VM_CONTEXT0_CNTL, ENABLE_CONTEXT | PAGE_TABLE_DEPTH(0) |
                                RANGE_PROTECTION_FAULT_ENABLE_DEFAULT);
@@ -126,17 +126,36 @@ void rv770_pcie_gart_fini(struct radeon_device *rdev)
 }
 
 
-/*
- * MC
- */
-static void rv770_mc_resume(struct radeon_device *rdev)
+void rv770_agp_enable(struct radeon_device *rdev)
 {
-       u32 d1vga_control, d2vga_control;
-       u32 vga_render_control, vga_hdp_control;
-       u32 d1crtc_control, d2crtc_control;
-       u32 new_d1grph_primary, new_d1grph_secondary;
-       u32 new_d2grph_primary, new_d2grph_secondary;
-       u64 old_vram_start;
+       u32 tmp;
+       int i;
+
+       /* Setup L2 cache */
+       WREG32(VM_L2_CNTL, ENABLE_L2_CACHE | ENABLE_L2_FRAGMENT_PROCESSING |
+                               ENABLE_L2_PTE_CACHE_LRU_UPDATE_BY_WRITE |
+                               EFFECTIVE_L2_QUEUE_SIZE(7));
+       WREG32(VM_L2_CNTL2, 0);
+       WREG32(VM_L2_CNTL3, BANK_SELECT(0) | CACHE_UPDATE_MODE(2));
+       /* Setup TLB control */
+       tmp = ENABLE_L1_TLB | ENABLE_L1_FRAGMENT_PROCESSING |
+               SYSTEM_ACCESS_MODE_NOT_IN_SYS |
+               SYSTEM_APERTURE_UNMAPPED_ACCESS_PASS_THRU |
+               EFFECTIVE_L1_TLB_SIZE(5) | EFFECTIVE_L1_QUEUE_SIZE(5);
+       WREG32(MC_VM_MD_L1_TLB0_CNTL, tmp);
+       WREG32(MC_VM_MD_L1_TLB1_CNTL, tmp);
+       WREG32(MC_VM_MD_L1_TLB2_CNTL, tmp);
+       WREG32(MC_VM_MB_L1_TLB0_CNTL, tmp);
+       WREG32(MC_VM_MB_L1_TLB1_CNTL, tmp);
+       WREG32(MC_VM_MB_L1_TLB2_CNTL, tmp);
+       WREG32(MC_VM_MB_L1_TLB3_CNTL, tmp);
+       for (i = 0; i < 7; i++)
+               WREG32(VM_CONTEXT0_CNTL + (i * 4), 0);
+}
+
+static void rv770_mc_program(struct radeon_device *rdev)
+{
+       struct rv515_mc_save save;
        u32 tmp;
        int i, j;
 
@@ -150,53 +169,42 @@ static void rv770_mc_resume(struct radeon_device *rdev)
        }
        WREG32(HDP_REG_COHERENCY_FLUSH_CNTL, 0);
 
-       d1vga_control = RREG32(D1VGA_CONTROL);
-       d2vga_control = RREG32(D2VGA_CONTROL);
-       vga_render_control = RREG32(VGA_RENDER_CONTROL);
-       vga_hdp_control = RREG32(VGA_HDP_CONTROL);
-       d1crtc_control = RREG32(D1CRTC_CONTROL);
-       d2crtc_control = RREG32(D2CRTC_CONTROL);
-       old_vram_start = (u64)(RREG32(MC_VM_FB_LOCATION) & 0xFFFF) << 24;
-       new_d1grph_primary = RREG32(D1GRPH_PRIMARY_SURFACE_ADDRESS);
-       new_d1grph_secondary = RREG32(D1GRPH_SECONDARY_SURFACE_ADDRESS);
-       new_d1grph_primary += rdev->mc.vram_start - old_vram_start;
-       new_d1grph_secondary += rdev->mc.vram_start - old_vram_start;
-       new_d2grph_primary = RREG32(D2GRPH_PRIMARY_SURFACE_ADDRESS);
-       new_d2grph_secondary = RREG32(D2GRPH_SECONDARY_SURFACE_ADDRESS);
-       new_d2grph_primary += rdev->mc.vram_start - old_vram_start;
-       new_d2grph_secondary += rdev->mc.vram_start - old_vram_start;
-
-       /* Stop all video */
-       WREG32(D1VGA_CONTROL, 0);
-       WREG32(D2VGA_CONTROL, 0);
-       WREG32(VGA_RENDER_CONTROL, 0);
-       WREG32(D1CRTC_UPDATE_LOCK, 1);
-       WREG32(D2CRTC_UPDATE_LOCK, 1);
-       WREG32(D1CRTC_CONTROL, 0);
-       WREG32(D2CRTC_CONTROL, 0);
-       WREG32(D1CRTC_UPDATE_LOCK, 0);
-       WREG32(D2CRTC_UPDATE_LOCK, 0);
-
-       mdelay(1);
+       rv515_mc_stop(rdev, &save);
        if (r600_mc_wait_for_idle(rdev)) {
-               printk(KERN_WARNING "[drm] MC not idle !\n");
+               dev_warn(rdev->dev, "Wait for MC idle timedout !\n");
        }
-
        /* Lockout access through VGA aperture*/
        WREG32(VGA_HDP_CONTROL, VGA_MEMORY_DISABLE);
-
        /* Update configuration */
-       WREG32(MC_VM_SYSTEM_APERTURE_LOW_ADDR, rdev->mc.vram_start >> 12);
-       WREG32(MC_VM_SYSTEM_APERTURE_HIGH_ADDR, (rdev->mc.vram_end - 1) >> 12);
+       if (rdev->flags & RADEON_IS_AGP) {
+               if (rdev->mc.vram_start < rdev->mc.gtt_start) {
+                       /* VRAM before AGP */
+                       WREG32(MC_VM_SYSTEM_APERTURE_LOW_ADDR,
+                               rdev->mc.vram_start >> 12);
+                       WREG32(MC_VM_SYSTEM_APERTURE_HIGH_ADDR,
+                               rdev->mc.gtt_end >> 12);
+               } else {
+                       /* VRAM after AGP */
+                       WREG32(MC_VM_SYSTEM_APERTURE_LOW_ADDR,
+                               rdev->mc.gtt_start >> 12);
+                       WREG32(MC_VM_SYSTEM_APERTURE_HIGH_ADDR,
+                               rdev->mc.vram_end >> 12);
+               }
+       } else {
+               WREG32(MC_VM_SYSTEM_APERTURE_LOW_ADDR,
+                       rdev->mc.vram_start >> 12);
+               WREG32(MC_VM_SYSTEM_APERTURE_HIGH_ADDR,
+                       rdev->mc.vram_end >> 12);
+       }
        WREG32(MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR, 0);
-       tmp = (((rdev->mc.vram_end - 1) >> 24) & 0xFFFF) << 16;
+       tmp = ((rdev->mc.vram_end >> 24) & 0xFFFF) << 16;
        tmp |= ((rdev->mc.vram_start >> 24) & 0xFFFF);
        WREG32(MC_VM_FB_LOCATION, tmp);
        WREG32(HDP_NONSURFACE_BASE, (rdev->mc.vram_start >> 8));
        WREG32(HDP_NONSURFACE_INFO, (2 << 7));
        WREG32(HDP_NONSURFACE_SIZE, (rdev->mc.mc_vram_size - 1) | 0x3FF);
        if (rdev->flags & RADEON_IS_AGP) {
-               WREG32(MC_VM_AGP_TOP, (rdev->mc.gtt_end - 1) >> 16);
+               WREG32(MC_VM_AGP_TOP, rdev->mc.gtt_end >> 16);
                WREG32(MC_VM_AGP_BOT, rdev->mc.gtt_start >> 16);
                WREG32(MC_VM_AGP_BASE, rdev->mc.agp_base >> 22);
        } else {
@@ -204,31 +212,10 @@ static void rv770_mc_resume(struct radeon_device *rdev)
                WREG32(MC_VM_AGP_TOP, 0x0FFFFFFF);
                WREG32(MC_VM_AGP_BOT, 0x0FFFFFFF);
        }
-       WREG32(D1GRPH_PRIMARY_SURFACE_ADDRESS, new_d1grph_primary);
-       WREG32(D1GRPH_SECONDARY_SURFACE_ADDRESS, new_d1grph_secondary);
-       WREG32(D2GRPH_PRIMARY_SURFACE_ADDRESS, new_d2grph_primary);
-       WREG32(D2GRPH_SECONDARY_SURFACE_ADDRESS, new_d2grph_secondary);
-       WREG32(VGA_MEMORY_BASE_ADDRESS, rdev->mc.vram_start);
-
-       /* Unlock host access */
-       WREG32(VGA_HDP_CONTROL, vga_hdp_control);
-
-       mdelay(1);
        if (r600_mc_wait_for_idle(rdev)) {
-               printk(KERN_WARNING "[drm] MC not idle !\n");
+               dev_warn(rdev->dev, "Wait for MC idle timedout !\n");
        }
-
-       /* Restore video state */
-       WREG32(D1CRTC_UPDATE_LOCK, 1);
-       WREG32(D2CRTC_UPDATE_LOCK, 1);
-       WREG32(D1CRTC_CONTROL, d1crtc_control);
-       WREG32(D2CRTC_CONTROL, d2crtc_control);
-       WREG32(D1CRTC_UPDATE_LOCK, 0);
-       WREG32(D2CRTC_UPDATE_LOCK, 0);
-       WREG32(D1VGA_CONTROL, d1vga_control);
-       WREG32(D2VGA_CONTROL, d2vga_control);
-       WREG32(VGA_RENDER_CONTROL, vga_render_control);
-
+       rv515_mc_resume(rdev, &save);
        /* we need to own VRAM, so turn off the VGA renderer here
         * to stop it overwriting our objects */
        rv515_vga_render_disable(rdev);
@@ -840,9 +827,9 @@ int rv770_mc_init(struct radeon_device *rdev)
                rdev->mc.gtt_size = radeon_gart_size * 1024 * 1024;
        }
        rdev->mc.vram_start = rdev->mc.vram_location;
-       rdev->mc.vram_end = rdev->mc.vram_location + rdev->mc.mc_vram_size;
+       rdev->mc.vram_end = rdev->mc.vram_location + rdev->mc.mc_vram_size - 1;
        rdev->mc.gtt_start = rdev->mc.gtt_location;
-       rdev->mc.gtt_end = rdev->mc.gtt_location + rdev->mc.gtt_size;
+       rdev->mc.gtt_end = rdev->mc.gtt_location + rdev->mc.gtt_size - 1;
        /* FIXME: we should enforce default clock in case GPU is not in
         * default setup
         */
@@ -861,11 +848,14 @@ static int rv770_startup(struct radeon_device *rdev)
 {
        int r;
 
-       radeon_gpu_reset(rdev);
-       rv770_mc_resume(rdev);
-       r = rv770_pcie_gart_enable(rdev);
-       if (r)
-               return r;
+       rv770_mc_program(rdev);
+       if (rdev->flags & RADEON_IS_AGP) {
+               rv770_agp_enable(rdev);
+       } else {
+               r = rv770_pcie_gart_enable(rdev);
+               if (r)
+                       return r;
+       }
        rv770_gpu_init(rdev);
 
        r = radeon_object_pin(rdev->r600_blit.shader_obj, RADEON_GEM_DOMAIN_VRAM,
@@ -884,9 +874,8 @@ static int rv770_startup(struct radeon_device *rdev)
        r = r600_cp_resume(rdev);
        if (r)
                return r;
-       r = r600_wb_init(rdev);
-       if (r)
-               return r;
+       /* write back buffer are not vital so don't worry about failure */
+       r600_wb_enable(rdev);
        return 0;
 }
 
@@ -894,15 +883,12 @@ int rv770_resume(struct radeon_device *rdev)
 {
        int r;
 
-       if (radeon_gpu_reset(rdev)) {
-               /* FIXME: what do we want to do here ? */
-       }
+       /* Do not reset GPU before posting, on rv770 hw unlike on r500 hw,
+        * posting will perform necessary task to bring back GPU into good
+        * shape.
+        */
        /* post card */
-       if (rdev->is_atom_bios) {
-               atom_asic_init(rdev->mode_info.atom_context);
-       } else {
-               radeon_combios_asic_init(rdev->ddev);
-       }
+       atom_asic_init(rdev->mode_info.atom_context);
        /* Initialize clocks */
        r = radeon_clocks_init(rdev);
        if (r) {
@@ -915,7 +901,7 @@ int rv770_resume(struct radeon_device *rdev)
                return r;
        }
 
-       r = radeon_ib_test(rdev);
+       r = r600_ib_test(rdev);
        if (r) {
                DRM_ERROR("radeon: failled testing IB (%d).\n", r);
                return r;
@@ -929,8 +915,8 @@ int rv770_suspend(struct radeon_device *rdev)
        /* FIXME: we should wait for ring to be empty */
        r700_cp_stop(rdev);
        rdev->cp.ready = false;
+       r600_wb_disable(rdev);
        rv770_pcie_gart_disable(rdev);
-
        /* unpin shaders bo */
         radeon_object_unpin(rdev->r600_blit.shader_obj);
        return 0;
@@ -946,7 +932,6 @@ int rv770_init(struct radeon_device *rdev)
 {
        int r;
 
-       rdev->new_init_path = true;
        r = radeon_dummy_page_init(rdev);
        if (r)
                return r;
@@ -960,8 +945,10 @@ int rv770_init(struct radeon_device *rdev)
                        return -EINVAL;
        }
        /* Must be an ATOMBIOS */
-       if (!rdev->is_atom_bios)
+       if (!rdev->is_atom_bios) {
+               dev_err(rdev->dev, "Expecting atombios for R600 GPU\n");
                return -EINVAL;
+       }
        r = radeon_atombios_init(rdev);
        if (r)
                return r;
@@ -983,15 +970,8 @@ int rv770_init(struct radeon_device *rdev)
        if (r)
                return r;
        r = rv770_mc_init(rdev);
-       if (r) {
-               if (rdev->flags & RADEON_IS_AGP) {
-                       /* Retry with disabling AGP */
-                       rv770_fini(rdev);
-                       rdev->flags &= ~RADEON_IS_AGP;
-                       return rv770_init(rdev);
-               }
+       if (r)
                return r;
-       }
        /* Memory manager */
        r = radeon_object_init(rdev);
        if (r)
@@ -1020,12 +1000,10 @@ int rv770_init(struct radeon_device *rdev)
 
        r = rv770_startup(rdev);
        if (r) {
-               if (rdev->flags & RADEON_IS_AGP) {
-                       /* Retry with disabling AGP */
-                       rv770_fini(rdev);
-                       rdev->flags &= ~RADEON_IS_AGP;
-                       return rv770_init(rdev);
-               }
+               rv770_suspend(rdev);
+               r600_wb_fini(rdev);
+               radeon_ring_fini(rdev);
+               rv770_pcie_gart_fini(rdev);
                rdev->accel_working = false;
        }
        if (rdev->accel_working) {
@@ -1034,7 +1012,7 @@ int rv770_init(struct radeon_device *rdev)
                        DRM_ERROR("radeon: failled initializing IB pool (%d).\n", r);
                        rdev->accel_working = false;
                }
-               r = radeon_ib_test(rdev);
+               r = r600_ib_test(rdev);
                if (r) {
                        DRM_ERROR("radeon: failled testing IB (%d).\n", r);
                        rdev->accel_working = false;
@@ -1049,20 +1027,15 @@ void rv770_fini(struct radeon_device *rdev)
 
        r600_blit_fini(rdev);
        radeon_ring_fini(rdev);
+       r600_wb_fini(rdev);
        rv770_pcie_gart_fini(rdev);
        radeon_gem_fini(rdev);
        radeon_fence_driver_fini(rdev);
        radeon_clocks_fini(rdev);
-#if __OS_HAS_AGP
        if (rdev->flags & RADEON_IS_AGP)
                radeon_agp_fini(rdev);
-#endif
        radeon_object_fini(rdev);
-       if (rdev->is_atom_bios) {
-               radeon_atombios_fini(rdev);
-       } else {
-               radeon_combios_fini(rdev);
-       }
+       radeon_atombios_fini(rdev);
        kfree(rdev->bios);
        rdev->bios = NULL;
        radeon_dummy_page_fini(rdev);
index 541744d..b170071 100644 (file)
@@ -82,8 +82,8 @@ int ttm_global_item_ref(struct ttm_global_reference *ref)
                if (unlikely(ret != 0))
                        goto out_err;
 
-               ++item->refcount;
        }
+       ++item->refcount;
        ref->object = item->object;
        object = item->object;
        mutex_unlock(&item->mutex);
index be34d32..7d05c4b 100644 (file)
@@ -1066,7 +1066,7 @@ EXPORT_SYMBOL_GPL(hid_report_raw_event);
  * @type: HID report type (HID_*_REPORT)
  * @data: report contents
  * @size: size of data parameter
- * @interrupt: called from atomic?
+ * @interrupt: distinguish between interrupt and control transfers
  *
  * This is data entry for lower layers.
  */
index b05f602..c40afc5 100644 (file)
@@ -132,12 +132,12 @@ static struct hid_driver twinhan_driver = {
        .input_mapping = twinhan_input_mapping,
 };
 
-static int twinhan_init(void)
+static int __init twinhan_init(void)
 {
        return hid_register_driver(&twinhan_driver);
 }
 
-static void twinhan_exit(void)
+static void __exit twinhan_exit(void)
 {
        hid_unregister_driver(&twinhan_driver);
 }
index ba05275..cdd1369 100644 (file)
@@ -48,10 +48,9 @@ static ssize_t hidraw_read(struct file *file, char __user *buffer, size_t count,
        char *report;
        DECLARE_WAITQUEUE(wait, current);
 
-       while (ret == 0) {
-
-               mutex_lock(&list->read_mutex);
+       mutex_lock(&list->read_mutex);
 
+       while (ret == 0) {
                if (list->head == list->tail) {
                        add_wait_queue(&list->hidraw->wait, &wait);
                        set_current_state(TASK_INTERRUPTIBLE);
index 6857560..700e93a 100644 (file)
@@ -675,7 +675,7 @@ config SENSORS_SHT15
 
 config SENSORS_S3C
        tristate "S3C24XX/S3C64XX Inbuilt ADC"
-       depends on ARCH_S3C2410 || ARCH_S3C64XX
+       depends on ARCH_S3C2410
        help
          If you say yes here you get support for the on-board ADCs of
          the Samsung S3C24XX or S3C64XX series of SoC
index fe4fa29..5a3ee00 100644 (file)
 #define METHOD_OLD_ENUM_FAN    "FSIF"
 
 #define ATK_MUX_HWMON          0x00000006ULL
+#define ATK_MUX_MGMT           0x00000011ULL
 
 #define ATK_CLASS_MASK         0xff000000ULL
 #define ATK_CLASS_FREQ_CTL     0x03000000ULL
 #define ATK_CLASS_FAN_CTL      0x04000000ULL
 #define ATK_CLASS_HWMON                0x06000000ULL
+#define ATK_CLASS_MGMT         0x11000000ULL
 
 #define ATK_TYPE_MASK          0x00ff0000ULL
 #define HWMON_TYPE_VOLT                0x00020000ULL
 #define HWMON_TYPE_TEMP                0x00030000ULL
 #define HWMON_TYPE_FAN         0x00040000ULL
 
-#define HWMON_SENSOR_ID_MASK   0x0000ffffULL
+#define ATK_ELEMENT_ID_MASK    0x0000ffffULL
+
+#define ATK_EC_ID              0x11060004ULL
 
 enum atk_pack_member {
        HWMON_PACK_FLAGS,
@@ -89,6 +93,9 @@ struct atk_data {
        /* new inteface */
        acpi_handle enumerate_handle;
        acpi_handle read_handle;
+       acpi_handle write_handle;
+
+       bool disable_ec;
 
        int voltage_count;
        int temperature_count;
@@ -129,9 +136,22 @@ struct atk_sensor_data {
        char const *acpi_name;
 };
 
-struct atk_acpi_buffer_u64 {
-       union acpi_object buf;
-       u64 value;
+/* Return buffer format:
+ * [0-3] "value" is valid flag
+ * [4-7] value
+ * [8- ] unknown stuff on newer mobos
+ */
+struct atk_acpi_ret_buffer {
+       u32 flags;
+       u32 value;
+       u8 data[];
+};
+
+/* Input buffer used for GITM and SITM methods */
+struct atk_acpi_input_buf {
+       u32 id;
+       u32 param1;
+       u32 param2;
 };
 
 static int atk_add(struct acpi_device *device);
@@ -439,52 +459,147 @@ static int atk_read_value_old(struct atk_sensor_data *sensor, u64 *value)
        return 0;
 }
 
-static int atk_read_value_new(struct atk_sensor_data *sensor, u64 *value)
+static union acpi_object *atk_ggrp(struct atk_data *data, u16 mux)
 {
-       struct atk_data *data = sensor->data;
        struct device *dev = &data->acpi_dev->dev;
+       struct acpi_buffer buf;
+       acpi_status ret;
        struct acpi_object_list params;
-       struct acpi_buffer ret;
        union acpi_object id;
-       struct atk_acpi_buffer_u64 tmp;
-       acpi_status status;
+       union acpi_object *pack;
 
        id.type = ACPI_TYPE_INTEGER;
-       id.integer.value = sensor->id;
-
+       id.integer.value = mux;
        params.count = 1;
        params.pointer = &id;
 
-       tmp.buf.type = ACPI_TYPE_BUFFER;
-       tmp.buf.buffer.pointer = (u8 *)&tmp.value;
-       tmp.buf.buffer.length = sizeof(u64);
-       ret.length = sizeof(tmp);
-       ret.pointer = &tmp;
+       buf.length = ACPI_ALLOCATE_BUFFER;
+       ret = acpi_evaluate_object(data->enumerate_handle, NULL, &params, &buf);
+       if (ret != AE_OK) {
+               dev_err(dev, "GGRP[%#x] ACPI exception: %s\n", mux,
+                               acpi_format_exception(ret));
+               return ERR_PTR(-EIO);
+       }
+       pack = buf.pointer;
+       if (pack->type != ACPI_TYPE_PACKAGE) {
+               /* Execution was successful, but the id was not found */
+               ACPI_FREE(pack);
+               return ERR_PTR(-ENOENT);
+       }
+
+       if (pack->package.count < 1) {
+               dev_err(dev, "GGRP[%#x] package is too small\n", mux);
+               ACPI_FREE(pack);
+               return ERR_PTR(-EIO);
+       }
+       return pack;
+}
+
+static union acpi_object *atk_gitm(struct atk_data *data, u64 id)
+{
+       struct device *dev = &data->acpi_dev->dev;
+       struct atk_acpi_input_buf buf;
+       union acpi_object tmp;
+       struct acpi_object_list params;
+       struct acpi_buffer ret;
+       union acpi_object *obj;
+       acpi_status status;
+
+       buf.id = id;
+       buf.param1 = 0;
+       buf.param2 = 0;
 
+       tmp.type = ACPI_TYPE_BUFFER;
+       tmp.buffer.pointer = (u8 *)&buf;
+       tmp.buffer.length = sizeof(buf);
+
+       params.count = 1;
+       params.pointer = (void *)&tmp;
+
+       ret.length = ACPI_ALLOCATE_BUFFER;
        status = acpi_evaluate_object_typed(data->read_handle, NULL, &params,
                        &ret, ACPI_TYPE_BUFFER);
        if (status != AE_OK) {
-               dev_warn(dev, "%s: ACPI exception: %s\n", __func__,
+               dev_warn(dev, "GITM[%#llx] ACPI exception: %s\n", id,
                                acpi_format_exception(status));
-               return -EIO;
+               return ERR_PTR(-EIO);
+       }
+       obj = ret.pointer;
+
+       /* Sanity check */
+       if (obj->buffer.length < 8) {
+               dev_warn(dev, "Unexpected ASBF length: %u\n",
+                               obj->buffer.length);
+               ACPI_FREE(obj);
+               return ERR_PTR(-EIO);
        }
+       return obj;
+}
 
-       /* Return buffer format:
-        * [0-3] "value" is valid flag
-        * [4-7] value
-        */
-       if (!(tmp.value & 0xffffffff)) {
+static union acpi_object *atk_sitm(struct atk_data *data,
+               struct atk_acpi_input_buf *buf)
+{
+       struct device *dev = &data->acpi_dev->dev;
+       struct acpi_object_list params;
+       union acpi_object tmp;
+       struct acpi_buffer ret;
+       union acpi_object *obj;
+       acpi_status status;
+
+       tmp.type = ACPI_TYPE_BUFFER;
+       tmp.buffer.pointer = (u8 *)buf;
+       tmp.buffer.length = sizeof(*buf);
+
+       params.count = 1;
+       params.pointer = &tmp;
+
+       ret.length = ACPI_ALLOCATE_BUFFER;
+       status = acpi_evaluate_object_typed(data->write_handle, NULL, &params,
+                       &ret, ACPI_TYPE_BUFFER);
+       if (status != AE_OK) {
+               dev_warn(dev, "SITM[%#x] ACPI exception: %s\n", buf->id,
+                               acpi_format_exception(status));
+               return ERR_PTR(-EIO);
+       }
+       obj = ret.pointer;
+
+       /* Sanity check */
+       if (obj->buffer.length < 8) {
+               dev_warn(dev, "Unexpected ASBF length: %u\n",
+                               obj->buffer.length);
+               ACPI_FREE(obj);
+               return ERR_PTR(-EIO);
+       }
+       return obj;
+}
+
+static int atk_read_value_new(struct atk_sensor_data *sensor, u64 *value)
+{
+       struct atk_data *data = sensor->data;
+       struct device *dev = &data->acpi_dev->dev;
+       union acpi_object *obj;
+       struct atk_acpi_ret_buffer *buf;
+       int err = 0;
+
+       obj = atk_gitm(data, sensor->id);
+       if (IS_ERR(obj))
+               return PTR_ERR(obj);
+
+       buf = (struct atk_acpi_ret_buffer *)obj->buffer.pointer;
+       if (buf->flags == 0) {
                /* The reading is not valid, possible causes:
                 * - sensor failure
                 * - enumeration was FUBAR (and we didn't notice)
                 */
-               dev_info(dev, "Failure: %#llx\n", tmp.value);
-               return -EIO;
+               dev_warn(dev, "Read failed, sensor = %#llx\n", sensor->id);
+               err = -EIO;
+               goto out;
        }
 
-       *value = (tmp.value & 0xffffffff00000000ULL) >> 32;
-
-       return 0;
+       *value = buf->value;
+out:
+       ACPI_FREE(obj);
+       return err;
 }
 
 static int atk_read_value(struct atk_sensor_data *sensor, u64 *value)
@@ -713,43 +828,141 @@ cleanup:
        return ret;
 }
 
-static int atk_enumerate_new_hwmon(struct atk_data *data)
+static int atk_ec_present(struct atk_data *data)
 {
        struct device *dev = &data->acpi_dev->dev;
-       struct acpi_buffer buf;
-       acpi_status ret;
-       struct acpi_object_list params;
-       union acpi_object id;
        union acpi_object *pack;
-       int err;
+       union acpi_object *ec;
+       int ret;
        int i;
 
-       dev_dbg(dev, "Enumerating hwmon sensors\n");
+       pack = atk_ggrp(data, ATK_MUX_MGMT);
+       if (IS_ERR(pack)) {
+               if (PTR_ERR(pack) == -ENOENT) {
+                       /* The MGMT class does not exists - that's ok */
+                       dev_dbg(dev, "Class %#llx not found\n", ATK_MUX_MGMT);
+                       return 0;
+               }
+               return PTR_ERR(pack);
+       }
 
-       id.type = ACPI_TYPE_INTEGER;
-       id.integer.value = ATK_MUX_HWMON;
-       params.count = 1;
-       params.pointer = &id;
+       /* Search the EC */
+       ec = NULL;
+       for (i = 0; i < pack->package.count; i++) {
+               union acpi_object *obj = &pack->package.elements[i];
+               union acpi_object *id;
 
-       buf.length = ACPI_ALLOCATE_BUFFER;
-       ret = acpi_evaluate_object_typed(data->enumerate_handle, NULL, &params,
-                       &buf, ACPI_TYPE_PACKAGE);
-       if (ret != AE_OK) {
-               dev_warn(dev, METHOD_ENUMERATE ": ACPI exception: %s\n",
-                               acpi_format_exception(ret));
-               return -ENODEV;
+               if (obj->type != ACPI_TYPE_PACKAGE)
+                       continue;
+
+               id = &obj->package.elements[0];
+               if (id->type != ACPI_TYPE_INTEGER)
+                       continue;
+
+               if (id->integer.value == ATK_EC_ID) {
+                       ec = obj;
+                       break;
+               }
        }
 
-       /* Result must be a package */
-       pack = buf.pointer;
+       ret = (ec != NULL);
+       if (!ret)
+               /* The system has no EC */
+               dev_dbg(dev, "EC not found\n");
 
-       if (pack->package.count < 1) {
-               dev_dbg(dev, "%s: hwmon package is too small: %d\n", __func__,
-                               pack->package.count);
-               err = -EINVAL;
-               goto out;
+       ACPI_FREE(pack);
+       return ret;
+}
+
+static int atk_ec_enabled(struct atk_data *data)
+{
+       struct device *dev = &data->acpi_dev->dev;
+       union acpi_object *obj;
+       struct atk_acpi_ret_buffer *buf;
+       int err;
+
+       obj = atk_gitm(data, ATK_EC_ID);
+       if (IS_ERR(obj)) {
+               dev_err(dev, "Unable to query EC status\n");
+               return PTR_ERR(obj);
+       }
+       buf = (struct atk_acpi_ret_buffer *)obj->buffer.pointer;
+
+       if (buf->flags == 0) {
+               dev_err(dev, "Unable to query EC status\n");
+               err = -EIO;
+       } else {
+               err = (buf->value != 0);
+               dev_dbg(dev, "EC is %sabled\n",
+                               err ? "en" : "dis");
+       }
+
+       ACPI_FREE(obj);
+       return err;
+}
+
+static int atk_ec_ctl(struct atk_data *data, int enable)
+{
+       struct device *dev = &data->acpi_dev->dev;
+       union acpi_object *obj;
+       struct atk_acpi_input_buf sitm;
+       struct atk_acpi_ret_buffer *ec_ret;
+       int err = 0;
+
+       sitm.id = ATK_EC_ID;
+       sitm.param1 = enable;
+       sitm.param2 = 0;
+
+       obj = atk_sitm(data, &sitm);
+       if (IS_ERR(obj)) {
+               dev_err(dev, "Failed to %sable the EC\n",
+                               enable ? "en" : "dis");
+               return PTR_ERR(obj);
+       }
+       ec_ret = (struct atk_acpi_ret_buffer *)obj->buffer.pointer;
+       if (ec_ret->flags == 0) {
+               dev_err(dev, "Failed to %sable the EC\n",
+                               enable ? "en" : "dis");
+               err = -EIO;
+       } else {
+               dev_info(dev, "EC %sabled\n",
+                               enable ? "en" : "dis");
+       }
+
+       ACPI_FREE(obj);
+       return err;
+}
+
+static int atk_enumerate_new_hwmon(struct atk_data *data)
+{
+       struct device *dev = &data->acpi_dev->dev;
+       union acpi_object *pack;
+       int err;
+       int i;
+
+       err = atk_ec_present(data);
+       if (err < 0)
+               return err;
+       if (err) {
+               err = atk_ec_enabled(data);
+               if (err < 0)
+                       return err;
+               /* If the EC was disabled we will disable it again on unload */
+               data->disable_ec = err;
+
+               err = atk_ec_ctl(data, 1);
+               if (err) {
+                       data->disable_ec = false;
+                       return err;
+               }
        }
 
+       dev_dbg(dev, "Enumerating hwmon sensors\n");
+
+       pack = atk_ggrp(data, ATK_MUX_HWMON);
+       if (IS_ERR(pack))
+               return PTR_ERR(pack);
+
        for (i = 0; i < pack->package.count; i++) {
                union acpi_object *obj = &pack->package.elements[i];
 
@@ -758,8 +971,7 @@ static int atk_enumerate_new_hwmon(struct atk_data *data)
 
        err = data->voltage_count + data->temperature_count + data->fan_count;
 
-out:
-       ACPI_FREE(buf.pointer);
+       ACPI_FREE(pack);
        return err;
 }
 
@@ -895,6 +1107,15 @@ static int atk_check_new_if(struct atk_data *data)
        }
        data->read_handle = ret;
 
+       /* De-multiplexer (write) */
+       status = acpi_get_handle(data->atk_handle, METHOD_WRITE, &ret);
+       if (status != AE_OK) {
+               dev_dbg(dev, "method " METHOD_READ " not found: %s\n",
+                                acpi_format_exception(status));
+               return -ENODEV;
+       }
+       data->write_handle = ret;
+
        return 0;
 }
 
@@ -915,6 +1136,7 @@ static int atk_add(struct acpi_device *device)
        data->acpi_dev = device;
        data->atk_handle = device->handle;
        INIT_LIST_HEAD(&data->sensor_list);
+       data->disable_ec = false;
 
        buf.length = ACPI_ALLOCATE_BUFFER;
        ret = acpi_evaluate_object_typed(data->atk_handle, BOARD_ID, NULL,
@@ -973,6 +1195,8 @@ static int atk_add(struct acpi_device *device)
 cleanup:
        atk_free_sensors(data);
 out:
+       if (data->disable_ec)
+               atk_ec_ctl(data, 0);
        kfree(data);
        return err;
 }
@@ -988,6 +1212,11 @@ static int atk_remove(struct acpi_device *device, int type)
        atk_free_sensors(data);
        hwmon_device_unregister(data->hwmon_dev);
 
+       if (data->disable_ec) {
+               if (atk_ec_ctl(data, 0))
+                       dev_err(&device->dev, "Failed to disable EC\n");
+       }
+
        kfree(data);
 
        return 0;
index 2c2cb1e..27d6257 100644 (file)
@@ -572,7 +572,7 @@ static struct dme1737_data *dme1737_update_device(struct device *dev)
 
        /* Sample register contents every 1 sec */
        if (time_after(jiffies, data->last_update + HZ) || !data->valid) {
-               if (data->type != sch5027) {
+               if (data->type == dme1737) {
                        data->vid = dme1737_read(data, DME1737_REG_VID) &
                                0x3f;
                }
@@ -1621,9 +1621,6 @@ static struct attribute *dme1737_misc_attr[] = {
        &sensor_dev_attr_zone1_auto_point1_temp_hyst.dev_attr.attr,
        &sensor_dev_attr_zone2_auto_point1_temp_hyst.dev_attr.attr,
        &sensor_dev_attr_zone3_auto_point1_temp_hyst.dev_attr.attr,
-       /* Misc */
-       &dev_attr_vrm.attr,
-       &dev_attr_cpu0_vid.attr,
        NULL
 };
 
@@ -1631,6 +1628,18 @@ static const struct attribute_group dme1737_misc_group = {
        .attrs = dme1737_misc_attr,
 };
 
+/* The following struct holds VID-related attributes. Their creation
+   depends on the chip type which is determined during module load. */
+static struct attribute *dme1737_vid_attr[] = {
+       &dev_attr_vrm.attr,
+       &dev_attr_cpu0_vid.attr,
+       NULL
+};
+
+static const struct attribute_group dme1737_vid_group = {
+       .attrs = dme1737_vid_attr,
+};
+
 /* The following structs hold the PWM attributes, some of which are optional.
  * Their creation depends on the chip configuration which is determined during
  * module load. */
@@ -1902,6 +1911,9 @@ static void dme1737_remove_files(struct device *dev)
        if (data->type != sch5027) {
                sysfs_remove_group(&dev->kobj, &dme1737_misc_group);
        }
+       if (data->type == dme1737) {
+               sysfs_remove_group(&dev->kobj, &dme1737_vid_group);
+       }
 
        sysfs_remove_group(&dev->kobj, &dme1737_group);
 
@@ -1933,6 +1945,13 @@ static int dme1737_create_files(struct device *dev)
                goto exit_remove;
        }
 
+       /* Create VID-related sysfs attributes */
+       if ((data->type == dme1737) &&
+           (err = sysfs_create_group(&dev->kobj,
+                                     &dme1737_vid_group))) {
+               goto exit_remove;
+       }
+
        /* Create fan sysfs attributes */
        for (ix = 0; ix < ARRAY_SIZE(dme1737_fan_group); ix++) {
                if (data->has_fan & (1 << ix)) {
@@ -2127,7 +2146,7 @@ static int dme1737_init_device(struct device *dev)
        data->pwm_acz[2] = 4;   /* pwm3 -> zone3 */
 
        /* Set VRM */
-       if (data->type != sch5027) {
+       if (data->type == dme1737) {
                data->vrm = vid_which_vrm();
        }
 
index 2a7a85a..da1b1f9 100644 (file)
@@ -819,7 +819,7 @@ static int watchdog_release(struct inode *inode, struct file *filp)
 static ssize_t watchdog_write(struct file *filp, const char __user *buf,
        size_t count, loff_t *offset)
 {
-       size_t ret;
+       int ret;
        struct fschmd_data *data = filp->private_data;
 
        if (count) {
index 6679854..be475e8 100644 (file)
@@ -197,11 +197,13 @@ static struct dmi_system_id lis3lv02d_dmi_ids[] = {
        AXIS_DMI_MATCH("HP2133", "HP 2133", xy_rotated_left),
        AXIS_DMI_MATCH("HP2140", "HP 2140", xy_swap_inverted),
        AXIS_DMI_MATCH("NC653x", "HP Compaq 653", xy_rotated_left_usd),
-       AXIS_DMI_MATCH("NC673x", "HP Compaq 673", xy_rotated_left_usd),
+       AXIS_DMI_MATCH("NC6730b", "HP Compaq 6730b", xy_rotated_left_usd),
+       AXIS_DMI_MATCH("NC6730s", "HP Compaq 6730s", xy_swap),
        AXIS_DMI_MATCH("NC651xx", "HP Compaq 651", xy_rotated_right),
        AXIS_DMI_MATCH("NC6710x", "HP Compaq 6710", xy_swap_yz_inverted),
        AXIS_DMI_MATCH("NC6715x", "HP Compaq 6715", y_inverted),
        AXIS_DMI_MATCH("NC693xx", "HP EliteBook 693", xy_rotated_right),
+       AXIS_DMI_MATCH("NC693xx", "HP EliteBook 853", xy_swap),
        /* Intel-based HP Pavilion dv5 */
        AXIS_DMI_MATCH2("HPDV5_I",
                        PRODUCT_NAME, "HP Pavilion dv5",
@@ -214,6 +216,7 @@ static struct dmi_system_id lis3lv02d_dmi_ids[] = {
                        y_inverted),
        AXIS_DMI_MATCH("DV7", "HP Pavilion dv7", x_inverted),
        AXIS_DMI_MATCH("HP8710", "HP Compaq 8710", y_inverted),
+       AXIS_DMI_MATCH("HDX18", "HP HDX 18", x_inverted),
        { NULL, }
 /* Laptop models without axis info (yet):
  * "NC6910" "HP Compaq 6910"
index ffeb2a1..a3749cb 100644 (file)
@@ -1028,12 +1028,11 @@ static int __init it87_find(unsigned short *address,
                chip_type, *address, sio_data->revision);
 
        /* Read GPIO config and VID value from LDN 7 (GPIO) */
-       if (chip_type != IT8705F_DEVID) {
+       if (sio_data->type != it87) {
                int reg;
 
                superio_select(GPIO);
-               if ((chip_type == it8718) ||
-                   (chip_type == it8720))
+               if (sio_data->type == it8718 || sio_data->type == it8720)
                        sio_data->vid_value = superio_inb(IT87_SIO_VID_REG);
 
                reg = superio_inb(IT87_SIO_PINX2_REG);
index ecd7395..82b1680 100644 (file)
@@ -83,7 +83,8 @@ static int __devexit lis302dl_spi_remove(struct spi_device *spi)
        struct lis3lv02d *lis3 = spi_get_drvdata(spi);
        lis3lv02d_joystick_disable();
        lis3lv02d_poweroff(lis3);
-       return 0;
+
+       return lis3lv02d_remove_fs(&lis3_dev);
 }
 
 #ifdef CONFIG_PM
index 303c026..ebe38b6 100644 (file)
@@ -30,6 +30,7 @@
 #include <linux/hwmon-sysfs.h>
 #include <linux/mutex.h>
 #include <linux/platform_device.h>
+#include <linux/sched.h>
 #include <linux/delay.h>
 #include <linux/jiffies.h>
 #include <linux/err.h>
@@ -622,7 +623,12 @@ static int __devexit sht15_remove(struct platform_device *pdev)
 }
 
 
-static struct platform_driver sht_drivers[] = {
+/*
+ * sht_drivers simultaneously refers to __devinit and __devexit function
+ * which causes spurious section mismatch warning. So use __refdata to
+ * get rid from this.
+ */
+static struct platform_driver __refdata sht_drivers[] = {
        {
                .driver = {
                        .name = "sht10",
index 4afba3e..e3654d6 100644 (file)
@@ -120,19 +120,26 @@ struct imx_i2c_struct {
        wait_queue_head_t       queue;
        unsigned long           i2csr;
        unsigned int            disable_delay;
+       int                     stopped;
+       unsigned int            ifdr; /* IMX_I2C_IFDR */
 };
 
 /** Functions for IMX I2C adapter driver ***************************************
 *******************************************************************************/
 
-static int i2c_imx_bus_busy(struct imx_i2c_struct *i2c_imx)
+static int i2c_imx_bus_busy(struct imx_i2c_struct *i2c_imx, int for_busy)
 {
        unsigned long orig_jiffies = jiffies;
+       unsigned int temp;
 
        dev_dbg(&i2c_imx->adapter.dev, "<%s>\n", __func__);
 
-       /* wait for bus not busy */
-       while (readb(i2c_imx->base + IMX_I2C_I2SR) & I2SR_IBB) {
+       while (1) {
+               temp = readb(i2c_imx->base + IMX_I2C_I2SR);
+               if (for_busy && (temp & I2SR_IBB))
+                       break;
+               if (!for_busy && !(temp & I2SR_IBB))
+                       break;
                if (signal_pending(current)) {
                        dev_dbg(&i2c_imx->adapter.dev,
                                "<%s> I2C Interrupted\n", __func__);
@@ -179,41 +186,62 @@ static int i2c_imx_acked(struct imx_i2c_struct *i2c_imx)
        return 0;
 }
 
-static void i2c_imx_start(struct imx_i2c_struct *i2c_imx)
+static int i2c_imx_start(struct imx_i2c_struct *i2c_imx)
 {
        unsigned int temp = 0;
+       int result;
 
        dev_dbg(&i2c_imx->adapter.dev, "<%s>\n", __func__);
 
+       clk_enable(i2c_imx->clk);
+       writeb(i2c_imx->ifdr, i2c_imx->base + IMX_I2C_IFDR);
        /* Enable I2C controller */
+       writeb(0, i2c_imx->base + IMX_I2C_I2SR);
        writeb(I2CR_IEN, i2c_imx->base + IMX_I2C_I2CR);
+
+       /* Wait controller to be stable */
+       udelay(50);
+
        /* Start I2C transaction */
        temp = readb(i2c_imx->base + IMX_I2C_I2CR);
        temp |= I2CR_MSTA;
        writeb(temp, i2c_imx->base + IMX_I2C_I2CR);
+       result = i2c_imx_bus_busy(i2c_imx, 1);
+       if (result)
+               return result;
+       i2c_imx->stopped = 0;
+
        temp |= I2CR_IIEN | I2CR_MTX | I2CR_TXAK;
        writeb(temp, i2c_imx->base + IMX_I2C_I2CR);
+       return result;
 }
 
 static void i2c_imx_stop(struct imx_i2c_struct *i2c_imx)
 {
        unsigned int temp = 0;
 
-       /* Stop I2C transaction */
-       dev_dbg(&i2c_imx->adapter.dev, "<%s>\n", __func__);
-       temp = readb(i2c_imx->base + IMX_I2C_I2CR);
-       temp &= ~I2CR_MSTA;
-       writeb(temp, i2c_imx->base + IMX_I2C_I2CR);
-       /* setup chip registers to defaults */
-       writeb(I2CR_IEN, i2c_imx->base + IMX_I2C_I2CR);
-       writeb(0, i2c_imx->base + IMX_I2C_I2SR);
-       /*
-        * This delay caused by an i.MXL hardware bug.
-        * If no (or too short) delay, no "STOP" bit will be generated.
-        */
-       udelay(i2c_imx->disable_delay);
+       if (!i2c_imx->stopped) {
+               /* Stop I2C transaction */
+               dev_dbg(&i2c_imx->adapter.dev, "<%s>\n", __func__);
+               temp = readb(i2c_imx->base + IMX_I2C_I2CR);
+               temp &= ~(I2CR_MSTA | I2CR_MTX);
+               writeb(temp, i2c_imx->base + IMX_I2C_I2CR);
+               i2c_imx->stopped = 1;
+       }
+       if (cpu_is_mx1()) {
+               /*
+                * This delay caused by an i.MXL hardware bug.
+                * If no (or too short) delay, no "STOP" bit will be generated.
+                */
+               udelay(i2c_imx->disable_delay);
+       }
+
+       if (!i2c_imx->stopped)
+               i2c_imx_bus_busy(i2c_imx, 0);
+
        /* Disable I2C controller */
        writeb(0, i2c_imx->base + IMX_I2C_I2CR);
+       clk_disable(i2c_imx->clk);
 }
 
 static void __init i2c_imx_set_clk(struct imx_i2c_struct *i2c_imx,
@@ -233,8 +261,8 @@ static void __init i2c_imx_set_clk(struct imx_i2c_struct *i2c_imx,
        else
                for (i = 0; i2c_clk_div[i][0] < div; i++);
 
-       /* Write divider value to register */
-       writeb(i2c_clk_div[i][1], i2c_imx->base + IMX_I2C_IFDR);
+       /* Store divider value */
+       i2c_imx->ifdr = i2c_clk_div[i][1];
 
        /*
         * There dummy delay is calculated.
@@ -341,11 +369,15 @@ static int i2c_imx_read(struct imx_i2c_struct *i2c_imx, struct i2c_msg *msgs)
                if (result)
                        return result;
                if (i == (msgs->len - 1)) {
+                       /* It must generate STOP before read I2DR to prevent
+                          controller from generating another clock cycle */
                        dev_dbg(&i2c_imx->adapter.dev,
                                "<%s> clear MSTA\n", __func__);
                        temp = readb(i2c_imx->base + IMX_I2C_I2CR);
-                       temp &= ~I2CR_MSTA;
+                       temp &= ~(I2CR_MSTA | I2CR_MTX);
                        writeb(temp, i2c_imx->base + IMX_I2C_I2CR);
+                       i2c_imx_bus_busy(i2c_imx, 0);
+                       i2c_imx->stopped = 1;
                } else if (i == (msgs->len - 2)) {
                        dev_dbg(&i2c_imx->adapter.dev,
                                "<%s> set TXAK\n", __func__);
@@ -370,14 +402,11 @@ static int i2c_imx_xfer(struct i2c_adapter *adapter,
 
        dev_dbg(&i2c_imx->adapter.dev, "<%s>\n", __func__);
 
-       /* Check if i2c bus is not busy */
-       result = i2c_imx_bus_busy(i2c_imx);
+       /* Start I2C transfer */
+       result = i2c_imx_start(i2c_imx);
        if (result)
                goto fail0;
 
-       /* Start I2C transfer */
-       i2c_imx_start(i2c_imx);
-
        /* read/write data */
        for (i = 0; i < num; i++) {
                if (i) {
@@ -386,6 +415,9 @@ static int i2c_imx_xfer(struct i2c_adapter *adapter,
                        temp = readb(i2c_imx->base + IMX_I2C_I2CR);
                        temp |= I2CR_RSTA;
                        writeb(temp, i2c_imx->base + IMX_I2C_I2CR);
+                       result =  i2c_imx_bus_busy(i2c_imx, 1);
+                       if (result)
+                               goto fail0;
                }
                dev_dbg(&i2c_imx->adapter.dev,
                        "<%s> transfer message: %d\n", __func__, i);
@@ -500,7 +532,6 @@ static int __init i2c_imx_probe(struct platform_device *pdev)
                dev_err(&pdev->dev, "can't get I2C clock\n");
                goto fail3;
        }
-       clk_enable(i2c_imx->clk);
 
        /* Request IRQ */
        ret = request_irq(i2c_imx->irq, i2c_imx_isr, 0, pdev->name, i2c_imx);
@@ -549,7 +580,6 @@ static int __init i2c_imx_probe(struct platform_device *pdev)
 fail5:
        free_irq(i2c_imx->irq, i2c_imx);
 fail4:
-       clk_disable(i2c_imx->clk);
        clk_put(i2c_imx->clk);
 fail3:
        release_mem_region(i2c_imx->res->start, resource_size(res));
@@ -586,8 +616,6 @@ static int __exit i2c_imx_remove(struct platform_device *pdev)
        if (pdata && pdata->exit)
                pdata->exit(&pdev->dev);
 
-       /* Disable I2C clock */
-       clk_disable(i2c_imx->clk);
        clk_put(i2c_imx->clk);
 
        release_mem_region(i2c_imx->res->start, resource_size(i2c_imx->res));
index d325e86..f627001 100644 (file)
@@ -365,9 +365,6 @@ static int mpc_write(struct mpc_i2c *i2c, int target,
        unsigned timeout = i2c->adap.timeout;
        u32 flags = restart ? CCR_RSTA : 0;
 
-       /* Start with MEN */
-       if (!restart)
-               writeccr(i2c, CCR_MEN);
        /* Start as master */
        writeccr(i2c, CCR_MIEN | CCR_MEN | CCR_MSTA | CCR_MTX | flags);
        /* Write target byte */
@@ -396,9 +393,6 @@ static int mpc_read(struct mpc_i2c *i2c, int target,
        int i, result;
        u32 flags = restart ? CCR_RSTA : 0;
 
-       /* Start with MEN */
-       if (!restart)
-               writeccr(i2c, CCR_MEN);
        /* Switch to read - restart */
        writeccr(i2c, CCR_MIEN | CCR_MEN | CCR_MSTA | CCR_MTX | flags);
        /* Write target address byte - this time with the read flag set */
@@ -425,9 +419,9 @@ static int mpc_read(struct mpc_i2c *i2c, int target,
                /* Generate txack on next to last byte */
                if (i == length - 2)
                        writeccr(i2c, CCR_MIEN | CCR_MEN | CCR_MSTA | CCR_TXAK);
-               /* Generate stop on last byte */
+               /* Do not generate stop on last byte */
                if (i == length - 1)
-                       writeccr(i2c, CCR_MIEN | CCR_MEN | CCR_TXAK);
+                       writeccr(i2c, CCR_MIEN | CCR_MEN | CCR_MSTA | CCR_MTX);
                data[i] = readb(i2c->base + MPC_I2C_DR);
        }
 
index 6396c3a..837322b 100644 (file)
@@ -177,7 +177,7 @@ static const struct pci_device_id atiixp_pci_tbl[] = {
        { PCI_VDEVICE(ATI, PCI_DEVICE_ID_ATI_IXP400_IDE), 0 },
        { PCI_VDEVICE(ATI, PCI_DEVICE_ID_ATI_IXP600_IDE), 1 },
        { PCI_VDEVICE(ATI, PCI_DEVICE_ID_ATI_IXP700_IDE), 0 },
-       { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_SB900_IDE), 0 },
+       { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_HUDSON2_IDE), 0 },
        { 0, },
 };
 MODULE_DEVICE_TABLE(pci, atiixp_pci_tbl);
index 680e597..ca0c46f 100644 (file)
@@ -379,7 +379,8 @@ static const struct ide_port_info cmd64x_chipsets[] __devinitdata = {
                .enablebits     = {{0x00,0x00,0x00}, {0x51,0x08,0x08}},
                .port_ops       = &cmd64x_port_ops,
                .host_flags     = IDE_HFLAG_CLEAR_SIMPLEX |
-                                 IDE_HFLAG_ABUSE_PREFETCH,
+                                 IDE_HFLAG_ABUSE_PREFETCH |
+                                 IDE_HFLAG_SERIALIZE,
                .pio_mask       = ATA_PIO5,
                .mwdma_mask     = ATA_MWDMA2,
                .udma_mask      = 0x00, /* no udma */
@@ -389,7 +390,8 @@ static const struct ide_port_info cmd64x_chipsets[] __devinitdata = {
                .init_chipset   = init_chipset_cmd64x,
                .enablebits     = {{0x51,0x04,0x04}, {0x51,0x08,0x08}},
                .port_ops       = &cmd648_port_ops,
-               .host_flags     = IDE_HFLAG_ABUSE_PREFETCH,
+               .host_flags     = IDE_HFLAG_ABUSE_PREFETCH |
+                                 IDE_HFLAG_SERIALIZE,
                .pio_mask       = ATA_PIO5,
                .mwdma_mask     = ATA_MWDMA2,
                .udma_mask      = ATA_UDMA2,
index 28d09a5..017c095 100644 (file)
@@ -273,14 +273,8 @@ static const struct ide_proc_devset ide_generic_settings[] = {
 
 static void proc_ide_settings_warn(void)
 {
-       static int warned;
-
-       if (warned)
-               return;
-
-       printk(KERN_WARNING "Warning: /proc/ide/hd?/settings interface is "
+       printk_once(KERN_WARNING "Warning: /proc/ide/hd?/settings interface is "
                            "obsolete, and will be removed soon!\n");
-       warned = 1;
 }
 
 static int ide_settings_proc_show(struct seq_file *m, void *v)
index afca22b..3b88eba 100644 (file)
@@ -2,7 +2,7 @@
  * Copyright (C) 1999-2000     Andre Hedrick <andre@linux-ide.org>
  * Copyright (C) 2002          Lionel Bouton <Lionel.Bouton@inet6.fr>, Maintainer
  * Copyright (C) 2003          Vojtech Pavlik <vojtech@suse.cz>
- * Copyright (C) 2007          Bartlomiej Zolnierkiewicz
+ * Copyright (C) 2007-2009     Bartlomiej Zolnierkiewicz
  *
  * May be copied or modified under the terms of the GNU General Public License
  *
@@ -281,11 +281,13 @@ static void config_drive_art_rwp(ide_drive_t *drive)
 
        pci_read_config_byte(dev, 0x4b, &reg4bh);
 
+       rw_prefetch = reg4bh & ~(0x11 << drive->dn);
+
        if (drive->media == ide_disk)
-               rw_prefetch = 0x11 << drive->dn;
+               rw_prefetch |= 0x11 << drive->dn;
 
-       if ((reg4bh & (0x11 << drive->dn)) != rw_prefetch)
-               pci_write_config_byte(dev, 0x4b, reg4bh|rw_prefetch);
+       if (reg4bh != rw_prefetch)
+               pci_write_config_byte(dev, 0x4b, rw_prefetch);
 }
 
 static void sis_set_pio_mode(ide_drive_t *drive, const u8 pio)
index 0bc3d78..8aa56ac 100644 (file)
@@ -29,6 +29,7 @@
 
 #include <linux/kernel.h>
 #include <linux/list.h>
+#include <linux/sched.h>
 #include <linux/string.h>
 #include <linux/slab.h>
 #include <linux/fs.h>
index d287ba7..949064a 100644 (file)
@@ -30,6 +30,7 @@
  */
 #include <linux/kernel.h>
 #include <linux/list.h>
+#include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/interrupt.h>
 #include <linux/wait.h>
index 5be1bd4..bd07803 100644 (file)
@@ -393,7 +393,7 @@ static int addr_resolve_local(struct sockaddr *src_in,
 
                for_each_netdev(&init_net, dev)
                        if (ipv6_chk_addr(&init_net,
-                                         &((struct sockaddr_in6 *) addr)->sin6_addr,
+                                         &((struct sockaddr_in6 *) dst_in)->sin6_addr,
                                          dev, 1))
                                break;
 
index 55d093a..0f89909 100644 (file)
@@ -40,6 +40,7 @@
 #include <linux/idr.h>
 #include <linux/interrupt.h>
 #include <linux/rbtree.h>
+#include <linux/sched.h>
 #include <linux/spinlock.h>
 #include <linux/workqueue.h>
 #include <linux/completion.h>
@@ -362,7 +363,9 @@ static void destroy_cm_id(struct iw_cm_id *cm_id)
                 * In either case, must tell the provider to reject.
                 */
                cm_id_priv->state = IW_CM_STATE_DESTROYING;
+               spin_unlock_irqrestore(&cm_id_priv->lock, flags);
                cm_id->device->iwcm->reject(cm_id, NULL, 0);
+               spin_lock_irqsave(&cm_id_priv->lock, flags);
                break;
        case IW_CM_STATE_CONN_SENT:
        case IW_CM_STATE_DESTROYING:
index 4346a24..bb96d3c 100644 (file)
@@ -34,6 +34,7 @@
 #include <linux/file.h>
 #include <linux/mutex.h>
 #include <linux/poll.h>
+#include <linux/sched.h>
 #include <linux/idr.h>
 #include <linux/in.h>
 #include <linux/in6.h>
index 6895523..ed71755 100644 (file)
@@ -37,6 +37,7 @@
 #include <linux/delay.h>
 #include <linux/errno.h>
 #include <linux/list.h>
+#include <linux/sched.h>
 #include <linux/spinlock.h>
 #include <linux/ethtool.h>
 #include <linux/rtnetlink.h>
@@ -1199,11 +1200,14 @@ static int iwch_query_port(struct ib_device *ibdev,
                props->state = IB_PORT_DOWN;
        else {
                inetdev = in_dev_get(netdev);
-               if (inetdev->ifa_list)
-                       props->state = IB_PORT_ACTIVE;
-               else
+               if (inetdev) {
+                       if (inetdev->ifa_list)
+                               props->state = IB_PORT_ACTIVE;
+                       else
+                               props->state = IB_PORT_INIT;
+                       in_dev_put(inetdev);
+               } else
                        props->state = IB_PORT_INIT;
-               in_dev_put(inetdev);
        }
 
        props->port_cap_flags =
index 6e86534..1cecf98 100644 (file)
@@ -29,6 +29,7 @@
  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  * SOFTWARE.
  */
+#include <linux/sched.h>
 #include "iwch_provider.h"
 #include "iwch.h"
 #include "iwch_cm.h"
index 04e88b6..013d138 100644 (file)
@@ -31,6 +31,7 @@
  * SOFTWARE.
  */
 
+#include <linux/sched.h>
 #include <linux/spinlock.h>
 #include <linux/idr.h>
 #include <linux/pci.h>
index b2a9d4c..a805402 100644 (file)
@@ -37,6 +37,7 @@
 
 #include <linux/interrupt.h>
 #include <linux/pci.h>
+#include <linux/sched.h>
 #include <linux/delay.h>
 #include <linux/io.h>
 #include <rdma/ib_verbs.h>
index 6c21b4b..c0a03ac 100644 (file)
@@ -33,6 +33,7 @@
 
 #include <linux/pci.h>
 #include <linux/delay.h>
+#include <linux/sched.h>
 
 #include "ipath_kernel.h"
 #include "ipath_verbs.h"
index 3a5a89b..cb2d3ef 100644 (file)
@@ -32,6 +32,7 @@
  */
 
 #include <linux/err.h>
+#include <linux/sched.h>
 #include <linux/vmalloc.h>
 
 #include "ipath_verbs.h"
index 2296832..1f95bba 100644 (file)
@@ -31,6 +31,7 @@
  * SOFTWARE.
  */
 
+#include <linux/sched.h>
 #include <linux/spinlock.h>
 
 #include "ipath_verbs.h"
index 6076cb6..7420715 100644 (file)
@@ -31,6 +31,7 @@
  * SOFTWARE.
  */
 
+#include <linux/sched.h>
 #include <rdma/ib_smi.h>
 
 #include "ipath_verbs.h"
index 855911e..82878e3 100644 (file)
@@ -33,6 +33,7 @@
 
 #include <linux/mm.h>
 #include <linux/device.h>
+#include <linux/sched.h>
 
 #include "ipath_kernel.h"
 
index 7bff4b9..be78f66 100644 (file)
@@ -33,6 +33,7 @@
 #include <linux/types.h>
 #include <linux/device.h>
 #include <linux/dmapool.h>
+#include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/list.h>
 #include <linux/highmem.h>
index d73e322..6923e1d 100644 (file)
@@ -32,6 +32,7 @@
  */
 
 #include <linux/rculist.h>
+#include <linux/sched.h>
 
 #include "ipath_verbs.h"
 
index 0ba6ec8..add9188 100644 (file)
@@ -426,7 +426,7 @@ iscsi_iser_session_create(struct iscsi_endpoint *ep,
         * because we preallocate so many resources
         */
        cls_session = iscsi_session_setup(&iscsi_iser_transport, shost,
-                                         ISCSI_DEF_XMIT_CMDS_MAX,
+                                         ISCSI_DEF_XMIT_CMDS_MAX, 0,
                                          sizeof(struct iscsi_iser_task),
                                          initial_cmdsn, 0);
        if (!cls_session)
index c6f88eb..cc763c9 100644 (file)
@@ -782,10 +782,29 @@ static unsigned int input_proc_devices_poll(struct file *file, poll_table *wait)
        return 0;
 }
 
+union input_seq_state {
+       struct {
+               unsigned short pos;
+               bool mutex_acquired;
+       };
+       void *p;
+};
+
 static void *input_devices_seq_start(struct seq_file *seq, loff_t *pos)
 {
-       if (mutex_lock_interruptible(&input_mutex))
-               return NULL;
+       union input_seq_state *state = (union input_seq_state *)&seq->private;
+       int error;
+
+       /* We need to fit into seq->private pointer */
+       BUILD_BUG_ON(sizeof(union input_seq_state) != sizeof(seq->private));
+
+       error = mutex_lock_interruptible(&input_mutex);
+       if (error) {
+               state->mutex_acquired = false;
+               return ERR_PTR(error);
+       }
+
+       state->mutex_acquired = true;
 
        return seq_list_start(&input_dev_list, *pos);
 }
@@ -795,9 +814,12 @@ static void *input_devices_seq_next(struct seq_file *seq, void *v, loff_t *pos)
        return seq_list_next(v, &input_dev_list, pos);
 }
 
-static void input_devices_seq_stop(struct seq_file *seq, void *v)
+static void input_seq_stop(struct seq_file *seq, void *v)
 {
-       mutex_unlock(&input_mutex);
+       union input_seq_state *state = (union input_seq_state *)&seq->private;
+
+       if (state->mutex_acquired)
+               mutex_unlock(&input_mutex);
 }
 
 static void input_seq_print_bitmap(struct seq_file *seq, const char *name,
@@ -861,7 +883,7 @@ static int input_devices_seq_show(struct seq_file *seq, void *v)
 static const struct seq_operations input_devices_seq_ops = {
        .start  = input_devices_seq_start,
        .next   = input_devices_seq_next,
-       .stop   = input_devices_seq_stop,
+       .stop   = input_seq_stop,
        .show   = input_devices_seq_show,
 };
 
@@ -881,40 +903,49 @@ static const struct file_operations input_devices_fileops = {
 
 static void *input_handlers_seq_start(struct seq_file *seq, loff_t *pos)
 {
-       if (mutex_lock_interruptible(&input_mutex))
-               return NULL;
+       union input_seq_state *state = (union input_seq_state *)&seq->private;
+       int error;
+
+       /* We need to fit into seq->private pointer */
+       BUILD_BUG_ON(sizeof(union input_seq_state) != sizeof(seq->private));
+
+       error = mutex_lock_interruptible(&input_mutex);
+       if (error) {
+               state->mutex_acquired = false;
+               return ERR_PTR(error);
+       }
+
+       state->mutex_acquired = true;
+       state->pos = *pos;
 
-       seq->private = (void *)(unsigned long)*pos;
        return seq_list_start(&input_handler_list, *pos);
 }
 
 static void *input_handlers_seq_next(struct seq_file *seq, void *v, loff_t *pos)
 {
-       seq->private = (void *)(unsigned long)(*pos + 1);
-       return seq_list_next(v, &input_handler_list, pos);
-}
+       union input_seq_state *state = (union input_seq_state *)&seq->private;
 
-static void input_handlers_seq_stop(struct seq_file *seq, void *v)
-{
-       mutex_unlock(&input_mutex);
+       state->pos = *pos + 1;
+       return seq_list_next(v, &input_handler_list, pos);
 }
 
 static int input_handlers_seq_show(struct seq_file *seq, void *v)
 {
        struct input_handler *handler = container_of(v, struct input_handler, node);
+       union input_seq_state *state = (union input_seq_state *)&seq->private;
 
-       seq_printf(seq, "N: Number=%ld Name=%s",
-                  (unsigned long)seq->private, handler->name);
+       seq_printf(seq, "N: Number=%u Name=%s", state->pos, handler->name);
        if (handler->fops)
                seq_printf(seq, " Minor=%d", handler->minor);
        seq_putc(seq, '\n');
 
        return 0;
 }
+
 static const struct seq_operations input_handlers_seq_ops = {
        .start  = input_handlers_seq_start,
        .next   = input_handlers_seq_next,
-       .stop   = input_handlers_seq_stop,
+       .stop   = input_seq_stop,
        .show   = input_handlers_seq_show,
 };
 
index 2388cf5..79e3edc 100644 (file)
@@ -143,6 +143,7 @@ static const struct xpad_device {
        { 0x12ab, 0x8809, "Xbox DDR dancepad", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX },
        { 0x1430, 0x4748, "RedOctane Guitar Hero X-plorer", MAP_DPAD_TO_AXES, XTYPE_XBOX360 },
        { 0x1430, 0x8888, "TX6500+ Dance Pad (first generation)", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX },
+       { 0x146b, 0x0601, "BigBen Interactive XBOX 360 Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX360 },
        { 0x045e, 0x028e, "Microsoft X-Box 360 pad", MAP_DPAD_TO_AXES, XTYPE_XBOX360 },
        { 0x1bad, 0x0003, "Harmonix Rock Band Drumkit", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX360 },
        { 0xffff, 0xffff, "Chinese-made Xbox Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX },
@@ -209,6 +210,7 @@ static struct usb_device_id xpad_table [] = {
        XPAD_XBOX360_VENDOR(0x0738),            /* Mad Catz X-Box 360 controllers */
        XPAD_XBOX360_VENDOR(0x0e6f),            /* 0x0e6f X-Box 360 controllers */
        XPAD_XBOX360_VENDOR(0x1430),            /* RedOctane X-Box 360 controllers */
+       XPAD_XBOX360_VENDOR(0x146b),            /* BigBen Interactive Controllers */
        XPAD_XBOX360_VENDOR(0x1bad),            /* Rock Band Drums */
        { }
 };
index 4709e15..4452eab 100644 (file)
@@ -233,6 +233,7 @@ struct atkbd {
  */
 static void (*atkbd_platform_fixup)(struct atkbd *, const void *data);
 static void *atkbd_platform_fixup_data;
+static unsigned int (*atkbd_platform_scancode_fixup)(struct atkbd *, unsigned int);
 
 static ssize_t atkbd_attr_show_helper(struct device *dev, char *buf,
                                ssize_t (*handler)(struct atkbd *, char *));
@@ -393,6 +394,9 @@ static irqreturn_t atkbd_interrupt(struct serio *serio, unsigned char data,
 
        input_event(dev, EV_MSC, MSC_RAW, code);
 
+       if (atkbd_platform_scancode_fixup)
+               code = atkbd_platform_scancode_fixup(atkbd, code);
+
        if (atkbd->translated) {
 
                if (atkbd->emul || atkbd_need_xlate(atkbd->xl_bit, code)) {
@@ -574,11 +578,22 @@ static void atkbd_event_work(struct work_struct *work)
 
        mutex_lock(&atkbd->event_mutex);
 
-       if (test_and_clear_bit(ATKBD_LED_EVENT_BIT, &atkbd->event_mask))
-               atkbd_set_leds(atkbd);
+       if (!atkbd->enabled) {
+               /*
+                * Serio ports are resumed asynchronously so while driver core
+                * thinks that device is already fully operational in reality
+                * it may not be ready yet. In this case we need to keep
+                * rescheduling till reconnect completes.
+                */
+               schedule_delayed_work(&atkbd->event_work,
+                                       msecs_to_jiffies(100));
+       } else {
+               if (test_and_clear_bit(ATKBD_LED_EVENT_BIT, &atkbd->event_mask))
+                       atkbd_set_leds(atkbd);
 
-       if (test_and_clear_bit(ATKBD_REP_EVENT_BIT, &atkbd->event_mask))
-               atkbd_set_repeat_rate(atkbd);
+               if (test_and_clear_bit(ATKBD_REP_EVENT_BIT, &atkbd->event_mask))
+                       atkbd_set_repeat_rate(atkbd);
+       }
 
        mutex_unlock(&atkbd->event_mutex);
 }
@@ -770,6 +785,30 @@ static int atkbd_select_set(struct atkbd *atkbd, int target_set, int allow_extra
        return 3;
 }
 
+static int atkbd_reset_state(struct atkbd *atkbd)
+{
+        struct ps2dev *ps2dev = &atkbd->ps2dev;
+       unsigned char param[1];
+
+/*
+ * Set the LEDs to a predefined state (all off).
+ */
+
+       param[0] = 0;
+       if (ps2_command(ps2dev, param, ATKBD_CMD_SETLEDS))
+               return -1;
+
+/*
+ * Set autorepeat to fastest possible.
+ */
+
+       param[0] = 0;
+       if (ps2_command(ps2dev, param, ATKBD_CMD_SETREP))
+               return -1;
+
+       return 0;
+}
+
 static int atkbd_activate(struct atkbd *atkbd)
 {
        struct ps2dev *ps2dev = &atkbd->ps2dev;
@@ -852,29 +891,6 @@ static unsigned int atkbd_hp_forced_release_keys[] = {
 };
 
 /*
- * Inventec system with broken key release on volume keys
- */
-static unsigned int atkbd_inventec_forced_release_keys[] = {
-       0xae, 0xb0, -1U
-};
-
-/*
- * Perform fixup for HP Pavilion ZV6100 laptop that doesn't generate release
- * for its volume buttons
- */
-static unsigned int atkbd_hp_zv6100_forced_release_keys[] = {
-       0xae, 0xb0, -1U
-};
-
-/*
- * Perform fixup for HP (Compaq) Presario R4000 R4100 R4200 that don't generate
- * release for their volume buttons
- */
-static unsigned int atkbd_hp_r4000_forced_release_keys[] = {
-       0xae, 0xb0, -1U
-};
-
-/*
  * Samsung NC10,NC20 with Fn+F? key release not working
  */
 static unsigned int atkbd_samsung_forced_release_keys[] = {
@@ -882,14 +898,6 @@ static unsigned int atkbd_samsung_forced_release_keys[] = {
 };
 
 /*
- * The volume up and volume down special keys on a Fujitsu Amilo PA 1510 laptop
- * do not generate release events so we have to do it ourselves.
- */
-static unsigned int atkbd_amilo_pa1510_forced_release_keys[] = {
-       0xb0, 0xae, -1U
-};
-
-/*
  * Amilo Pi 3525 key release for Fn+Volume keys not working
  */
 static unsigned int atkbd_amilo_pi3525_forced_release_keys[] = {
@@ -911,6 +919,30 @@ static unsigned int atkdb_soltech_ta12_forced_release_keys[] = {
 };
 
 /*
+ * Many notebooks don't send key release event for volume up/down
+ * keys, with key list below common among them
+ */
+static unsigned int atkbd_volume_forced_release_keys[] = {
+       0xae, 0xb0, -1U
+};
+
+/*
+ * OQO 01+ multimedia keys (64--66) generate e0 6x upon release whereas
+ * they should be generating e4-e6 (0x80 | code).
+ */
+static unsigned int atkbd_oqo_01plus_scancode_fixup(struct atkbd *atkbd,
+                                                   unsigned int code)
+{
+       if (atkbd->translated && atkbd->emul == 1 &&
+           (code == 0x64 || code == 0x65 || code == 0x66)) {
+               atkbd->emul = 0;
+               code |= 0x80;
+       }
+
+       return code;
+}
+
+/*
  * atkbd_set_keycode_table() initializes keyboard's keycode table
  * according to the selected scancode set
  */
@@ -1087,6 +1119,7 @@ static int atkbd_connect(struct serio *serio, struct serio_driver *drv)
                }
 
                atkbd->set = atkbd_select_set(atkbd, atkbd_set, atkbd_extra);
+               atkbd_reset_state(atkbd);
                atkbd_activate(atkbd);
 
        } else {
@@ -1267,6 +1300,7 @@ static ssize_t atkbd_set_extra(struct atkbd *atkbd, const char *buf, size_t coun
 
                atkbd->dev = new_dev;
                atkbd->set = atkbd_select_set(atkbd, atkbd->set, value);
+               atkbd_reset_state(atkbd);
                atkbd_activate(atkbd);
                atkbd_set_keycode_table(atkbd);
                atkbd_set_device_attrs(atkbd);
@@ -1513,6 +1547,13 @@ static int __init atkbd_setup_forced_release(const struct dmi_system_id *id)
        return 0;
 }
 
+static int __init atkbd_setup_scancode_fixup(const struct dmi_system_id *id)
+{
+       atkbd_platform_scancode_fixup = id->driver_data;
+
+       return 0;
+}
+
 static struct dmi_system_id atkbd_dmi_quirk_table[] __initdata = {
        {
                .ident = "Dell Laptop",
@@ -1548,7 +1589,7 @@ static struct dmi_system_id atkbd_dmi_quirk_table[] __initdata = {
                        DMI_MATCH(DMI_PRODUCT_NAME, "Pavilion ZV6100"),
                },
                .callback = atkbd_setup_forced_release,
-               .driver_data = atkbd_hp_zv6100_forced_release_keys,
+               .driver_data = atkbd_volume_forced_release_keys,
        },
        {
                .ident = "HP Presario R4000",
@@ -1557,7 +1598,7 @@ static struct dmi_system_id atkbd_dmi_quirk_table[] __initdata = {
                        DMI_MATCH(DMI_PRODUCT_NAME, "Presario R4000"),
                },
                .callback = atkbd_setup_forced_release,
-               .driver_data = atkbd_hp_r4000_forced_release_keys,
+               .driver_data = atkbd_volume_forced_release_keys,
        },
        {
                .ident = "HP Presario R4100",
@@ -1566,7 +1607,7 @@ static struct dmi_system_id atkbd_dmi_quirk_table[] __initdata = {
                        DMI_MATCH(DMI_PRODUCT_NAME, "Presario R4100"),
                },
                .callback = atkbd_setup_forced_release,
-               .driver_data = atkbd_hp_r4000_forced_release_keys,
+               .driver_data = atkbd_volume_forced_release_keys,
        },
        {
                .ident = "HP Presario R4200",
@@ -1575,7 +1616,7 @@ static struct dmi_system_id atkbd_dmi_quirk_table[] __initdata = {
                        DMI_MATCH(DMI_PRODUCT_NAME, "Presario R4200"),
                },
                .callback = atkbd_setup_forced_release,
-               .driver_data = atkbd_hp_r4000_forced_release_keys,
+               .driver_data = atkbd_volume_forced_release_keys,
        },
        {
                .ident = "Inventec Symphony",
@@ -1584,7 +1625,7 @@ static struct dmi_system_id atkbd_dmi_quirk_table[] __initdata = {
                        DMI_MATCH(DMI_PRODUCT_NAME, "SYMPHONY 6.0/7.0"),
                },
                .callback = atkbd_setup_forced_release,
-               .driver_data = atkbd_inventec_forced_release_keys,
+               .driver_data = atkbd_volume_forced_release_keys,
        },
        {
                .ident = "Samsung NC10",
@@ -1620,7 +1661,7 @@ static struct dmi_system_id atkbd_dmi_quirk_table[] __initdata = {
                        DMI_MATCH(DMI_PRODUCT_NAME, "AMILO Pa 1510"),
                },
                .callback = atkbd_setup_forced_release,
-               .driver_data = atkbd_amilo_pa1510_forced_release_keys,
+               .driver_data = atkbd_volume_forced_release_keys,
        },
        {
                .ident = "Fujitsu Amilo Pi 3525",
@@ -1649,6 +1690,15 @@ static struct dmi_system_id atkbd_dmi_quirk_table[] __initdata = {
                .callback = atkbd_setup_forced_release,
                .driver_data = atkdb_soltech_ta12_forced_release_keys,
        },
+       {
+               .ident = "OQO Model 01+",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "OQO"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "ZEPTO"),
+               },
+               .callback = atkbd_setup_scancode_fixup,
+               .driver_data = atkbd_oqo_01plus_scancode_fixup,
+       },
        { }
 };
 
index a88aff3..77d1309 100644 (file)
@@ -147,6 +147,7 @@ static int __devinit gpio_keys_probe(struct platform_device *pdev)
                }
 
                error = request_irq(irq, gpio_keys_isr,
+                                   IRQF_SHARED |
                                    IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
                                    button->desc ? button->desc : "gpio_keys",
                                    bdata);
index e9d639e..5f72440 100644 (file)
@@ -24,6 +24,7 @@
 #include <linux/interrupt.h>
 #include <linux/hil.h>
 #include <linux/io.h>
+#include <linux/sched.h>
 #include <linux/spinlock.h>
 #include <asm/irq.h>
 #ifdef CONFIG_HP300
index 472b566..a99a04b 100644 (file)
@@ -27,6 +27,7 @@
  */
 
 #include <linux/delay.h>
+#include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/module.h>
 #include <linux/interrupt.h>
index 02f4f8f..a9bb254 100644 (file)
@@ -227,6 +227,7 @@ config INPUT_WINBOND_CIR
        depends on X86 && PNP
        select NEW_LEDS
        select LEDS_CLASS
+       select LEDS_TRIGGERS
        select BITREVERSE
        help
          Say Y here if you want to use the IR remote functionality found
index 216a559..ea821b5 100644 (file)
@@ -209,7 +209,7 @@ static inline int hp_sdc_rtc_read_rt(struct timeval *res) {
 
 /* Read the i8042 fast handshake timer */
 static inline int hp_sdc_rtc_read_fhs(struct timeval *res) {
-       uint64_t raw;
+       int64_t raw;
        unsigned int tenms;
 
        raw = hp_sdc_rtc_read_i8042timer(HP_SDC_CMD_LOAD_FHS, 2);
index c806fbf..3b9f588 100644 (file)
@@ -106,8 +106,8 @@ static int __devinit rotary_encoder_probe(struct platform_device *pdev)
        struct input_dev *input;
        int err;
 
-       if (!pdata || !pdata->steps) {
-               dev_err(&pdev->dev, "invalid platform data\n");
+       if (!pdata) {
+               dev_err(&pdev->dev, "missing platform data\n");
                return -ENOENT;
        }
 
index c4f4231..b064419 100644 (file)
@@ -230,7 +230,7 @@ out_err:
        return err;
 }
 
-static int bbc_remove(struct of_device *op)
+static int __devexit bbc_remove(struct of_device *op)
 {
        struct sparcspkr_state *state = dev_get_drvdata(&op->dev);
        struct input_dev *input_dev = state->input_dev;
@@ -308,7 +308,7 @@ out_err:
        return err;
 }
 
-static int grover_remove(struct of_device *op)
+static int __devexit grover_remove(struct of_device *op)
 {
        struct sparcspkr_state *state = dev_get_drvdata(&op->dev);
        struct grover_beep_info *info = &state->u.grover;
index 11fd038..a932179 100644 (file)
@@ -936,6 +936,15 @@ static struct dmi_system_id dmi_ids[] __initdata = {
        },
        {
                .callback = dmi_matched,
+               .ident = "Medion MD 42200",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "Medion"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "WIM 2030"),
+               },
+               .driver_data = keymap_fs_amilo_pro_v2000
+       },
+       {
+               .callback = dmi_matched,
                .ident = "Medion MD 96500",
                .matches = {
                        DMI_MATCH(DMI_SYS_VENDOR, "MEDIONPC"),
index de745d7..ab5dc5f 100644 (file)
@@ -219,7 +219,7 @@ static const struct ps2pp_info *get_model_info(unsigned char model)
                                PS2PP_WHEEL | PS2PP_SIDE_BTN | PS2PP_TASK_BTN |
                                PS2PP_EXTRA_BTN | PS2PP_NAV_BTN | PS2PP_HWHEEL },
                { 72,   PS2PP_KIND_TRACKMAN,    0 },                    /* T-CH11: TrackMan Marble */
-               { 73,   0,                      PS2PP_SIDE_BTN },
+               { 73,   PS2PP_KIND_TRACKMAN,    PS2PP_SIDE_BTN },       /* TrackMan FX */
                { 75,   PS2PP_KIND_WHEEL,       PS2PP_WHEEL },
                { 76,   PS2PP_KIND_WHEEL,       PS2PP_WHEEL },
                { 79,   PS2PP_KIND_TRACKMAN,    PS2PP_WHEEL },          /* TrackMan with wheel */
index b66ff1a..f4a6125 100644 (file)
@@ -652,6 +652,16 @@ static const struct dmi_system_id toshiba_dmi_table[] = {
                        DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
                        DMI_MATCH(DMI_PRODUCT_NAME, "PORTEGE M300"),
                },
+
+       },
+       {
+               .ident = "Toshiba Portege M300",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "Portable PC"),
+                       DMI_MATCH(DMI_PRODUCT_VERSION, "Version 1.0"),
+               },
+
        },
        { }
 };
index c4b3fbd..aa533ce 100644 (file)
@@ -4,7 +4,7 @@
 config SERIO
        tristate "Serial I/O support" if EMBEDDED || !X86
        default y
-       ---help---
+       help
          Say Yes here if you have any input device that uses serial I/O to
          communicate with the system. This includes the
                        * standard AT keyboard and PS/2 mouse *
@@ -22,7 +22,7 @@ config SERIO_I8042
        tristate "i8042 PC Keyboard controller" if EMBEDDED || !X86
        default y
        depends on !PARISC && (!ARM || ARCH_SHARK || FOOTBRIDGE_HOST) && !M68K && !BLACKFIN
-       ---help---
+       help
          i8042 is the chip over which the standard AT keyboard and PS/2
          mouse are connected to the computer. If you use these devices,
          you'll need to say Y here.
@@ -35,7 +35,7 @@ config SERIO_I8042
 config SERIO_SERPORT
        tristate "Serial port line discipline"
        default y
-       ---help---
+       help
          Say Y here if you plan to use an input device (mouse, joystick,
          tablet, 6dof) that communicates over the RS232 serial (COM) port.
 
@@ -49,7 +49,7 @@ config SERIO_SERPORT
 config SERIO_CT82C710
        tristate "ct82c710 Aux port controller"
        depends on X86
-       ---help---
+       help
          Say Y here if you have a Texas Instruments TravelMate notebook
          equipped with the ct82c710 chip and want to use a mouse connected
          to the "QuickPort".
@@ -66,7 +66,7 @@ config SERIO_Q40KBD
 config SERIO_PARKBD
        tristate "Parallel port keyboard adapter"
        depends on PARPORT
-       ---help---
+       help
          Say Y here if you built a simple parallel port adapter to attach
          an additional AT keyboard, XT keyboard or PS/2 mouse.
 
@@ -124,7 +124,7 @@ config HP_SDC
        tristate "HP System Device Controller i8042 Support"
        depends on (GSC || HP300) && SERIO
        default y
-       ---help---
+       help
          This option enables support for the "System Device
          Controller", an i8042 carrying microcode to manage a
          few miscellaneous devices on some Hewlett Packard systems.
@@ -168,6 +168,7 @@ config SERIO_MACEPS2
 
 config SERIO_LIBPS2
        tristate "PS/2 driver library" if EMBEDDED
+       depends on SERIO_I8042 || SERIO_I8042=n
        help
          Say Y here if you are using a driver for device connected
          to a PS/2 port, such as PS/2 mouse or standard AT keyboard.
index a39bc4e..a537925 100644 (file)
@@ -327,6 +327,17 @@ static struct dmi_system_id __initdata i8042_dmi_nomux_table[] = {
                },
        },
        {
+               /*
+                * Reset and GET ID commands issued via KBD port are
+                * sometimes being delivered to AUX3.
+                */
+               .ident = "Sony Vaio FZ-240E",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "VGN-FZ240E"),
+               },
+       },
+       {
                .ident = "Amoi M636/A737",
                .matches = {
                        DMI_MATCH(DMI_SYS_VENDOR, "Amoi Electronics CO.,LTD."),
@@ -661,7 +672,7 @@ static void i8042_pnp_exit(void)
 static int __init i8042_pnp_init(void)
 {
        char kbd_irq_str[4] = { 0 }, aux_irq_str[4] = { 0 };
-       int pnp_data_busted = false;
+       bool pnp_data_busted = false;
        int err;
 
 #ifdef CONFIG_X86
index bc56e52..1df02d2 100644 (file)
@@ -609,6 +609,8 @@ static irqreturn_t __init i8042_aux_test_irq(int irq, void *dev_id)
        str = i8042_read_status();
        if (str & I8042_STR_OBF) {
                data = i8042_read_data();
+               dbg("%02x <- i8042 (aux_test_irq, %s)",
+                       data, str & I8042_STR_AUXDATA ? "aux" : "kbd");
                if (i8042_irq_being_tested &&
                    data == 0xa5 && (str & I8042_STR_AUXDATA))
                        complete(&i8042_aux_irq_delivered);
@@ -750,6 +752,7 @@ static int __init i8042_check_aux(void)
  * AUX IRQ was never delivered so we need to flush the controller to
  * get rid of the byte we put there; otherwise keyboard may not work.
  */
+               dbg("     -- i8042 (aux irq test timeout)");
                i8042_flush();
                retval = -1;
        }
@@ -833,17 +836,32 @@ static int i8042_controller_selftest(void)
 static int i8042_controller_init(void)
 {
        unsigned long flags;
+       int n = 0;
+       unsigned char ctr[2];
 
 /*
- * Save the CTR for restoral on unload / reboot.
+ * Save the CTR for restore on unload / reboot.
  */
 
-       if (i8042_command(&i8042_ctr, I8042_CMD_CTL_RCTR)) {
-               printk(KERN_ERR "i8042.c: Can't read CTR while initializing i8042.\n");
-               return -EIO;
-       }
+       do {
+               if (n >= 10) {
+                       printk(KERN_ERR
+                               "i8042.c: Unable to get stable CTR read.\n");
+                       return -EIO;
+               }
+
+               if (n != 0)
+                       udelay(50);
+
+               if (i8042_command(&ctr[n++ % 2], I8042_CMD_CTL_RCTR)) {
+                       printk(KERN_ERR
+                               "i8042.c: Can't read CTR while initializing i8042.\n");
+                       return -EIO;
+               }
 
-       i8042_initial_ctr = i8042_ctr;
+       } while (n < 2 || ctr[0] != ctr[1]);
+
+       i8042_initial_ctr = i8042_ctr = ctr[0];
 
 /*
  * Disable the keyboard interface and interrupt.
@@ -892,6 +910,12 @@ static int i8042_controller_init(void)
                return -EIO;
        }
 
+/*
+ * Flush whatever accumulated while we were disabling keyboard port.
+ */
+
+       i8042_flush();
+
        return 0;
 }
 
@@ -911,7 +935,7 @@ static void i8042_controller_reset(void)
        i8042_ctr |= I8042_CTR_KBDDIS | I8042_CTR_AUXDIS;
        i8042_ctr &= ~(I8042_CTR_KBDINT | I8042_CTR_AUXINT);
 
-       if (i8042_command(&i8042_initial_ctr, I8042_CMD_CTL_WCTR))
+       if (i8042_command(&i8042_ctr, I8042_CMD_CTL_WCTR))
                printk(KERN_WARNING "i8042.c: Can't write CTR while resetting.\n");
 
 /*
index 769ba65..f3876ac 100644 (file)
@@ -13,6 +13,7 @@
 
 #include <linux/delay.h>
 #include <linux/module.h>
+#include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/interrupt.h>
 #include <linux/input.h>
index b03009b..27fdaaf 100644 (file)
@@ -9,6 +9,7 @@
  * the Free Software Foundation.
  */
 
+#include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/smp_lock.h>
 #include <linux/poll.h>
index b9694b6..6d34511 100644 (file)
@@ -15,6 +15,7 @@
 
 #include <asm/uaccess.h>
 #include <linux/kernel.h>
+#include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/module.h>
 #include <linux/init.h>
index f06332c..c21e6d3 100644 (file)
@@ -645,7 +645,7 @@ static int __devinit ad7879_probe(struct spi_device *spi)
                kfree(ts);
        }
 
-       return 0;
+       return error;
 }
 
 static int __devexit ad7879_remove(struct spi_device *spi)
@@ -732,7 +732,7 @@ static int __devinit ad7879_probe(struct i2c_client *client,
                kfree(ts);
        }
 
-       return 0;
+       return error;
 }
 
 static int __devexit ad7879_remove(struct i2c_client *client)
index 2d83524..65bf91e 100644 (file)
@@ -603,7 +603,7 @@ static void capi_recv_message(struct capi20_appl *ap, struct sk_buff *skb)
 
        if (CAPIMSG_CMD(skb->data) == CAPI_CONNECT_B3_CONF) {
                u16 info = CAPIMSG_U16(skb->data, 12); // Info field
-               if (info == 0) {
+               if ((info & 0xff00) == 0) {
                        mutex_lock(&cdev->ncci_list_mtx);
                        capincci_alloc(cdev, CAPIMSG_NCCI(skb->data));
                        mutex_unlock(&cdev->ncci_list_mtx);
index 6501202..3e6d17f 100644 (file)
@@ -40,7 +40,7 @@ static int debugmode = 0;
 MODULE_DESCRIPTION("CAPI4Linux: Interface to ISDN4Linux");
 MODULE_AUTHOR("Carsten Paeth");
 MODULE_LICENSE("GPL");
-module_param(debugmode, uint, 0);
+module_param(debugmode, uint, S_IRUGO|S_IWUSR);
 
 /* -------- type definitions ----------------------------------------- */
 
@@ -671,8 +671,8 @@ static void n0(capidrv_contr * card, capidrv_ncci * ncci)
                                 NULL,  /* Useruserdata */   /* $$$$ */
                                 NULL   /* Facilitydataarray */
        );
-       send_message(card, &cmsg);
        plci_change_state(card, ncci->plcip, EV_PLCI_DISCONNECT_REQ);
+       send_message(card, &cmsg);
 
        cmd.command = ISDN_STAT_BHUP;
        cmd.driver = card->myid;
@@ -924,8 +924,8 @@ static void handle_incoming_call(capidrv_contr * card, _cmsg * cmsg)
                 */
                capi_cmsg_answer(cmsg);
                cmsg->Reject = 1;       /* ignore */
-               send_message(card, cmsg);
                plci_change_state(card, plcip, EV_PLCI_CONNECT_REJECT);
+               send_message(card, cmsg);
                printk(KERN_INFO "capidrv-%d: incoming call %s,%d,%d,%s ignored\n",
                        card->contrnr,
                        cmd.parm.setup.phone,
@@ -974,8 +974,8 @@ static void handle_incoming_call(capidrv_contr * card, _cmsg * cmsg)
        case 2:         /* Call will be rejected. */
                capi_cmsg_answer(cmsg);
                cmsg->Reject = 2;       /* reject call, normal call clearing */
-               send_message(card, cmsg);
                plci_change_state(card, plcip, EV_PLCI_CONNECT_REJECT);
+               send_message(card, cmsg);
                break;
 
        default:
@@ -983,8 +983,8 @@ static void handle_incoming_call(capidrv_contr * card, _cmsg * cmsg)
                capi_cmsg_answer(cmsg);
                cmsg->Reject = 8;       /* reject call,
                                           destination out of order */
-               send_message(card, cmsg);
                plci_change_state(card, plcip, EV_PLCI_CONNECT_REJECT);
+               send_message(card, cmsg);
                break;
        }
        return;
@@ -1020,8 +1020,8 @@ static void handle_plci(_cmsg * cmsg)
                card->bchans[plcip->chan].disconnecting = 1;
                plci_change_state(card, plcip, EV_PLCI_DISCONNECT_IND);
                capi_cmsg_answer(cmsg);
-               send_message(card, cmsg);
                plci_change_state(card, plcip, EV_PLCI_DISCONNECT_RESP);
+               send_message(card, cmsg);
                break;
 
        case CAPI_DISCONNECT_CONF:      /* plci */
@@ -1078,8 +1078,8 @@ static void handle_plci(_cmsg * cmsg)
 
                if (card->bchans[plcip->chan].incoming) {
                        capi_cmsg_answer(cmsg);
-                       send_message(card, cmsg);
                        plci_change_state(card, plcip, EV_PLCI_CONNECT_ACTIVE_IND);
+                       send_message(card, cmsg);
                } else {
                        capidrv_ncci *nccip;
                        capi_cmsg_answer(cmsg);
@@ -1098,13 +1098,14 @@ static void handle_plci(_cmsg * cmsg)
                                                 NULL   /* NCPI */
                        );
                        nccip->msgid = cmsg->Messagenumber;
+                       plci_change_state(card, plcip,
+                                         EV_PLCI_CONNECT_ACTIVE_IND);
+                       ncci_change_state(card, nccip, EV_NCCI_CONNECT_B3_REQ);
                        send_message(card, cmsg);
                        cmd.command = ISDN_STAT_DCONN;
                        cmd.driver = card->myid;
                        cmd.arg = plcip->chan;
                        card->interface.statcallb(&cmd);
-                       plci_change_state(card, plcip, EV_PLCI_CONNECT_ACTIVE_IND);
-                       ncci_change_state(card, nccip, EV_NCCI_CONNECT_B3_REQ);
                }
                break;
 
@@ -1193,8 +1194,8 @@ static void handle_ncci(_cmsg * cmsg)
                        goto notfound;
 
                capi_cmsg_answer(cmsg);
-               send_message(card, cmsg);
                ncci_change_state(card, nccip, EV_NCCI_CONNECT_B3_ACTIVE_IND);
+               send_message(card, cmsg);
 
                cmd.command = ISDN_STAT_BCONN;
                cmd.driver = card->myid;
@@ -1222,8 +1223,8 @@ static void handle_ncci(_cmsg * cmsg)
                                                          0,    /* Reject */
                                                          NULL  /* NCPI */
                                );
-                               send_message(card, cmsg);
                                ncci_change_state(card, nccip, EV_NCCI_CONNECT_B3_RESP);
+                               send_message(card, cmsg);
                                break;
                        }
                        printk(KERN_ERR "capidrv-%d: no mem for ncci, sorry\n",                                                 card->contrnr);
@@ -1299,8 +1300,8 @@ static void handle_ncci(_cmsg * cmsg)
                card->bchans[nccip->chan].disconnecting = 1;
                ncci_change_state(card, nccip, EV_NCCI_DISCONNECT_B3_IND);
                capi_cmsg_answer(cmsg);
-               send_message(card, cmsg);
                ncci_change_state(card, nccip, EV_NCCI_DISCONNECT_B3_RESP);
+               send_message(card, cmsg);
                break;
 
        case CAPI_DISCONNECT_B3_CONF:   /* ncci */
@@ -2014,8 +2015,8 @@ static void send_listen(capidrv_contr *card)
                             card->cipmask,
                             card->cipmask2,
                             NULL, NULL);
-       send_message(card, &cmdcmsg);
        listen_change_state(card, EV_LISTEN_REQ);
+       send_message(card, &cmdcmsg);
 }
 
 static void listentimerfunc(unsigned long x)
index 57d2636..dc506ab 100644 (file)
@@ -18,6 +18,7 @@
 #include <linux/interrupt.h>
 #include <linux/ioport.h>
 #include <linux/proc_fs.h>
+#include <linux/sched.h>
 #include <linux/seq_file.h>
 #include <linux/skbuff.h>
 #include <linux/workqueue.h>
index 234cc5d..44a58e6 100644 (file)
@@ -334,7 +334,14 @@ static inline int iraw_loop(unsigned char c, unsigned char *src, int numbytes,
        return startbytes - numbytes;
 }
 
-/* process a block of data received from the device
+/**
+ * gigaset_m10x_input() - process a block of data received from the device
+ * @inbuf:     received data and device descriptor structure.
+ *
+ * Called by hardware module {ser,usb}_gigaset with a block of received
+ * bytes. Separates the bytes received over the serial data channel into
+ * user data and command replies (locked/unlocked) according to the
+ * current state of the interface.
  */
 void gigaset_m10x_input(struct inbuf_t *inbuf)
 {
@@ -543,16 +550,17 @@ static struct sk_buff *iraw_encode(struct sk_buff *skb, int head, int tail)
        return iraw_skb;
 }
 
-/* gigaset_send_skb
- * called by common.c to queue an skb for sending
- * and start transmission if necessary
- * parameters:
- *     B Channel control structure
- *     skb
+/**
+ * gigaset_m10x_send_skb() - queue an skb for sending
+ * @bcs:       B channel descriptor structure.
+ * @skb:       data to send.
+ *
+ * Called by i4l.c to encode and queue an skb for sending, and start
+ * transmission if necessary.
+ *
  * Return value:
- *     number of bytes accepted for sending
- *     (skb->len if ok, 0 if out of buffer space)
- *     or error code (< 0, eg. -EINVAL)
+ *     number of bytes accepted for sending (skb->len) if ok,
+ *     error code < 0 (eg. -ENOMEM) on error
  */
 int gigaset_m10x_send_skb(struct bc_state *bcs, struct sk_buff *skb)
 {
index 781c404..5ed1d99 100644 (file)
@@ -134,6 +134,7 @@ struct bas_cardstate {
 #define BS_ATRDPEND    0x040   /* urb_cmd_in in use */
 #define BS_ATWRPEND    0x080   /* urb_cmd_out in use */
 #define BS_SUSPEND     0x100   /* USB port suspended */
+#define BS_RESETTING   0x200   /* waiting for HD_RESET_INTERRUPT_PIPE_ACK */
 
 
 static struct gigaset_driver *driver = NULL;
@@ -319,6 +320,21 @@ static int gigaset_set_line_ctrl(struct cardstate *cs, unsigned cflag)
        return -EINVAL;
 }
 
+/* set/clear bits in base connection state, return previous state
+ */
+static inline int update_basstate(struct bas_cardstate *ucs,
+                                 int set, int clear)
+{
+       unsigned long flags;
+       int state;
+
+       spin_lock_irqsave(&ucs->lock, flags);
+       state = ucs->basstate;
+       ucs->basstate = (state & ~clear) | set;
+       spin_unlock_irqrestore(&ucs->lock, flags);
+       return state;
+}
+
 /* error_hangup
  * hang up any existing connection because of an unrecoverable error
  * This function may be called from any context and takes care of scheduling
@@ -350,12 +366,9 @@ static inline void error_hangup(struct bc_state *bcs)
  */
 static inline void error_reset(struct cardstate *cs)
 {
-       /* close AT command channel to recover (ignore errors) */
-       req_submit(cs->bcs, HD_CLOSE_ATCHANNEL, 0, BAS_TIMEOUT);
-
-       //FIXME try to recover without bothering the user
-       dev_err(cs->dev,
-           "unrecoverable error - please disconnect Gigaset base to reset\n");
+       /* reset interrupt pipe to recover (ignore errors) */
+       update_basstate(cs->hw.bas, BS_RESETTING, 0);
+       req_submit(cs->bcs, HD_RESET_INTERRUPT_PIPE, 0, BAS_TIMEOUT);
 }
 
 /* check_pending
@@ -398,8 +411,13 @@ static void check_pending(struct bas_cardstate *ucs)
        case HD_DEVICE_INIT_ACK:                /* no reply expected */
                ucs->pending = 0;
                break;
-       /* HD_READ_ATMESSAGE, HD_WRITE_ATMESSAGE, HD_RESET_INTERRUPTPIPE
-        * are handled separately and should never end up here
+       case HD_RESET_INTERRUPT_PIPE:
+               if (!(ucs->basstate & BS_RESETTING))
+                       ucs->pending = 0;
+               break;
+       /*
+        * HD_READ_ATMESSAGE and HD_WRITE_ATMESSAGE are handled separately
+        * and should never end up here
         */
        default:
                dev_warn(&ucs->interface->dev,
@@ -449,21 +467,6 @@ static void cmd_in_timeout(unsigned long data)
        error_reset(cs);
 }
 
-/* set/clear bits in base connection state, return previous state
- */
-inline static int update_basstate(struct bas_cardstate *ucs,
-                                 int set, int clear)
-{
-       unsigned long flags;
-       int state;
-
-       spin_lock_irqsave(&ucs->lock, flags);
-       state = ucs->basstate;
-       ucs->basstate = (state & ~clear) | set;
-       spin_unlock_irqrestore(&ucs->lock, flags);
-       return state;
-}
-
 /* read_ctrl_callback
  * USB completion handler for control pipe input
  * called by the USB subsystem in interrupt context
@@ -762,7 +765,8 @@ static void read_int_callback(struct urb *urb)
                break;
 
        case HD_RESET_INTERRUPT_PIPE_ACK:
-               gig_dbg(DEBUG_USBREQ, "HD_RESET_INTERRUPT_PIPE_ACK");
+               update_basstate(ucs, 0, BS_RESETTING);
+               dev_notice(cs->dev, "interrupt pipe reset\n");
                break;
 
        case HD_SUSPEND_END:
@@ -1331,28 +1335,24 @@ static void read_iso_tasklet(unsigned long data)
                rcvbuf = urb->transfer_buffer;
                totleft = urb->actual_length;
                for (frame = 0; totleft > 0 && frame < BAS_NUMFRAMES; frame++) {
-                       if (unlikely(urb->iso_frame_desc[frame].status)) {
+                       numbytes = urb->iso_frame_desc[frame].actual_length;
+                       if (unlikely(urb->iso_frame_desc[frame].status))
                                dev_warn(cs->dev,
-                                        "isochronous read: frame %d: %s\n",
-                                        frame,
+                                        "isochronous read: frame %d[%d]: %s\n",
+                                        frame, numbytes,
                                         get_usb_statmsg(
                                            urb->iso_frame_desc[frame].status));
-                               break;
-                       }
-                       numbytes = urb->iso_frame_desc[frame].actual_length;
-                       if (unlikely(numbytes > BAS_MAXFRAME)) {
+                       if (unlikely(numbytes > BAS_MAXFRAME))
                                dev_warn(cs->dev,
                                         "isochronous read: frame %d: "
                                         "numbytes (%d) > BAS_MAXFRAME\n",
                                         frame, numbytes);
-                               break;
-                       }
                        if (unlikely(numbytes > totleft)) {
                                dev_warn(cs->dev,
                                         "isochronous read: frame %d: "
                                         "numbytes (%d) > totleft (%d)\n",
                                         frame, numbytes, totleft);
-                               break;
+                               numbytes = totleft;
                        }
                        offset = urb->iso_frame_desc[frame].offset;
                        if (unlikely(offset + numbytes > BAS_INBUFSIZE)) {
@@ -1361,7 +1361,7 @@ static void read_iso_tasklet(unsigned long data)
                                         "offset (%d) + numbytes (%d) "
                                         "> BAS_INBUFSIZE\n",
                                         frame, offset, numbytes);
-                               break;
+                               numbytes = BAS_INBUFSIZE - offset;
                        }
                        gigaset_isoc_receive(rcvbuf + offset, numbytes, bcs);
                        totleft -= numbytes;
@@ -1433,6 +1433,7 @@ static void req_timeout(unsigned long data)
 
        case HD_CLOSE_ATCHANNEL:
                dev_err(bcs->cs->dev, "timeout closing AT channel\n");
+               error_reset(bcs->cs);
                break;
 
        case HD_CLOSE_B2CHANNEL:
@@ -1442,6 +1443,13 @@ static void req_timeout(unsigned long data)
                error_reset(bcs->cs);
                break;
 
+       case HD_RESET_INTERRUPT_PIPE:
+               /* error recovery escalation */
+               dev_err(bcs->cs->dev,
+                       "reset interrupt pipe timeout, attempting USB reset\n");
+               usb_queue_reset_device(bcs->cs->hw.bas->interface);
+               break;
+
        default:
                dev_warn(bcs->cs->dev, "request 0x%02x timed out, clearing\n",
                         pending);
@@ -1934,6 +1942,15 @@ static int gigaset_write_cmd(struct cardstate *cs,
                goto notqueued;
        }
 
+       /* translate "+++" escape sequence sent as a single separate command
+        * into "close AT channel" command for error recovery
+        * The next command will reopen the AT channel automatically.
+        */
+       if (len == 3 && !memcmp(buf, "+++", 3)) {
+               rc = req_submit(cs->bcs, HD_CLOSE_ATCHANNEL, 0, BAS_TIMEOUT);
+               goto notqueued;
+       }
+
        if (len > IF_WRITEBUF)
                len = IF_WRITEBUF;
        if (!(cb = kmalloc(sizeof(struct cmdbuf_t) + len, GFP_ATOMIC))) {
index e4141bf..33dcd8d 100644 (file)
 #define DRIVER_AUTHOR "Hansjoerg Lipp <hjlipp@web.de>, Tilman Schmidt <tilman@imap.cc>, Stefan Eilers"
 #define DRIVER_DESC "Driver for Gigaset 307x"
 
+#ifdef CONFIG_GIGASET_DEBUG
+#define DRIVER_DESC_DEBUG " (debug build)"
+#else
+#define DRIVER_DESC_DEBUG ""
+#endif
+
 /* Module parameters */
 int gigaset_debuglevel = DEBUG_DEFAULT;
 EXPORT_SYMBOL_GPL(gigaset_debuglevel);
@@ -32,6 +38,17 @@ MODULE_PARM_DESC(debug, "debug level");
 #define VALID_MINOR    0x01
 #define VALID_ID       0x02
 
+/**
+ * gigaset_dbg_buffer() - dump data in ASCII and hex for debugging
+ * @level:     debugging level.
+ * @msg:       message prefix.
+ * @len:       number of bytes to dump.
+ * @buf:       data to dump.
+ *
+ * If the current debugging level includes one of the bits set in @level,
+ * @len bytes starting at @buf are logged to dmesg at KERN_DEBUG prio,
+ * prefixed by the text @msg.
+ */
 void gigaset_dbg_buffer(enum debuglevel level, const unsigned char *msg,
                        size_t len, const unsigned char *buf)
 {
@@ -274,6 +291,20 @@ static void clear_events(struct cardstate *cs)
        spin_unlock_irqrestore(&cs->ev_lock, flags);
 }
 
+/**
+ * gigaset_add_event() - add event to device event queue
+ * @cs:                device descriptor structure.
+ * @at_state:  connection state structure.
+ * @type:      event type.
+ * @ptr:       pointer parameter for event.
+ * @parameter: integer parameter for event.
+ * @arg:       pointer parameter for event.
+ *
+ * Allocate an event queue entry from the device's event queue, and set it up
+ * with the parameters given.
+ *
+ * Return value: added event
+ */
 struct event_t *gigaset_add_event(struct cardstate *cs,
                                  struct at_state_t *at_state, int type,
                                  void *ptr, int parameter, void *arg)
@@ -398,6 +429,15 @@ static void make_invalid(struct cardstate *cs, unsigned mask)
        spin_unlock_irqrestore(&drv->lock, flags);
 }
 
+/**
+ * gigaset_freecs() - free all associated ressources of a device
+ * @cs:                device descriptor structure.
+ *
+ * Stops all tasklets and timers, unregisters the device from all
+ * subsystems it was registered to, deallocates the device structure
+ * @cs and all structures referenced from it.
+ * Operations on the device should be stopped before calling this.
+ */
 void gigaset_freecs(struct cardstate *cs)
 {
        int i;
@@ -506,7 +546,12 @@ static void gigaset_inbuf_init(struct inbuf_t *inbuf, struct bc_state *bcs,
        inbuf->inputstate = inputstate;
 }
 
-/* append received bytes to inbuf */
+/**
+ * gigaset_fill_inbuf() - append received data to input buffer
+ * @inbuf:     buffer structure.
+ * @src:       received data.
+ * @numbytes:  number of bytes received.
+ */
 int gigaset_fill_inbuf(struct inbuf_t *inbuf, const unsigned char *src,
                       unsigned numbytes)
 {
@@ -606,20 +651,22 @@ static struct bc_state *gigaset_initbcs(struct bc_state *bcs,
        return NULL;
 }
 
-/* gigaset_initcs
+/**
+ * gigaset_initcs() - initialize device structure
+ * @drv:       hardware driver the device belongs to
+ * @channels:  number of B channels supported by device
+ * @onechannel:        !=0 if B channel data and AT commands share one
+ *                 communication channel (M10x),
+ *             ==0 if B channels have separate communication channels (base)
+ * @ignoreframes:      number of frames to ignore after setting up B channel
+ * @cidmode:   !=0: start in CallID mode
+ * @modulename:        name of driver module for LL registration
+ *
  * Allocate and initialize cardstate structure for Gigaset driver
  * Calls hardware dependent gigaset_initcshw() function
  * Calls B channel initialization function gigaset_initbcs() for each B channel
- * parameters:
- *     drv             hardware driver the device belongs to
- *     channels        number of B channels supported by device
- *     onechannel      !=0: B channel data and AT commands share one
- *                          communication channel
- *                     ==0: B channels have separate communication channels
- *     ignoreframes    number of frames to ignore after setting up B channel
- *     cidmode         !=0: start in CallID mode
- *     modulename      name of driver module (used for I4L registration)
- * return value:
+ *
+ * Return value:
  *     pointer to cardstate structure
  */
 struct cardstate *gigaset_initcs(struct gigaset_driver *drv, int channels,
@@ -837,6 +884,17 @@ static void cleanup_cs(struct cardstate *cs)
 }
 
 
+/**
+ * gigaset_start() - start device operations
+ * @cs:                device descriptor structure.
+ *
+ * Prepares the device for use by setting up communication parameters,
+ * scheduling an EV_START event to initiate device initialization, and
+ * waiting for completion of the initialization.
+ *
+ * Return value:
+ *     1 - success, 0 - error
+ */
 int gigaset_start(struct cardstate *cs)
 {
        unsigned long flags;
@@ -879,9 +937,15 @@ error:
 }
 EXPORT_SYMBOL_GPL(gigaset_start);
 
-/* gigaset_shutdown
- * check if a device is associated to the cardstate structure and stop it
- * return value: 0 if ok, -1 if no device was associated
+/**
+ * gigaset_shutdown() - shut down device operations
+ * @cs:                device descriptor structure.
+ *
+ * Deactivates the device by scheduling an EV_SHUTDOWN event and
+ * waiting for completion of the shutdown.
+ *
+ * Return value:
+ *     0 - success, -1 - error (no device associated)
  */
 int gigaset_shutdown(struct cardstate *cs)
 {
@@ -912,6 +976,13 @@ exit:
 }
 EXPORT_SYMBOL_GPL(gigaset_shutdown);
 
+/**
+ * gigaset_stop() - stop device operations
+ * @cs:                device descriptor structure.
+ *
+ * Stops operations on the device by scheduling an EV_STOP event and
+ * waiting for completion of the shutdown.
+ */
 void gigaset_stop(struct cardstate *cs)
 {
        mutex_lock(&cs->mutex);
@@ -1020,6 +1091,14 @@ struct cardstate *gigaset_get_cs_by_tty(struct tty_struct *tty)
        return gigaset_get_cs_by_minor(tty->index + tty->driver->minor_start);
 }
 
+/**
+ * gigaset_freedriver() - free all associated ressources of a driver
+ * @drv:       driver descriptor structure.
+ *
+ * Unregisters the driver from the system and deallocates the driver
+ * structure @drv and all structures referenced from it.
+ * All devices should be shut down before calling this.
+ */
 void gigaset_freedriver(struct gigaset_driver *drv)
 {
        unsigned long flags;
@@ -1035,14 +1114,16 @@ void gigaset_freedriver(struct gigaset_driver *drv)
 }
 EXPORT_SYMBOL_GPL(gigaset_freedriver);
 
-/* gigaset_initdriver
+/**
+ * gigaset_initdriver() - initialize driver structure
+ * @minor:     First minor number
+ * @minors:    Number of minors this driver can handle
+ * @procname:  Name of the driver
+ * @devname:   Name of the device files (prefix without minor number)
+ *
  * Allocate and initialize gigaset_driver structure. Initialize interface.
- * parameters:
- *     minor           First minor number
- *     minors          Number of minors this driver can handle
- *     procname        Name of the driver
- *     devname         Name of the device files (prefix without minor number)
- * return value:
+ *
+ * Return value:
  *     Pointer to the gigaset_driver structure on success, NULL on failure.
  */
 struct gigaset_driver *gigaset_initdriver(unsigned minor, unsigned minors,
@@ -1095,6 +1176,13 @@ error:
 }
 EXPORT_SYMBOL_GPL(gigaset_initdriver);
 
+/**
+ * gigaset_blockdriver() - block driver
+ * @drv:       driver descriptor structure.
+ *
+ * Prevents the driver from attaching new devices, in preparation for
+ * deregistration.
+ */
 void gigaset_blockdriver(struct gigaset_driver *drv)
 {
        drv->blocked = 1;
@@ -1110,7 +1198,7 @@ static int __init gigaset_init_module(void)
        if (gigaset_debuglevel == 1)
                gigaset_debuglevel = DEBUG_DEFAULT;
 
-       pr_info(DRIVER_DESC "\n");
+       pr_info(DRIVER_DESC DRIVER_DESC_DEBUG "\n");
        return 0;
 }
 
index 2d91049..cc768ca 100644 (file)
@@ -207,7 +207,6 @@ struct reply_t gigaset_tab_nocid[] =
        /* leave dle mode */
        {RSP_INIT,      0,  0,SEQ_DLE0,           201, 5, {0},             "^SDLE=0\r"},
        {RSP_OK,      201,201, -1,                202,-1},
-       //{RSP_ZDLE,    202,202,  0,                202, 0, {ACT_ERROR}},//DELETE
        {RSP_ZDLE,    202,202,  0,                  0, 0, {ACT_DLE0}},
        {RSP_NODEV,   200,249, -1,                  0, 0, {ACT_FAKEDLE0}},
        {RSP_ERROR,   200,249, -1,                  0, 0, {ACT_FAILDLE0}},
@@ -265,6 +264,7 @@ struct reply_t gigaset_tab_nocid[] =
        {EV_SHUTDOWN,  -1, -1, -1,                 -1,-1, {ACT_SHUTDOWN}}, //FIXME
 
        /* misc. */
+       {RSP_ERROR,    -1, -1, -1,                 -1, -1, {ACT_ERROR} },
        {RSP_EMPTY,    -1, -1, -1,                 -1,-1, {ACT_DEBUG}}, //FIXME
        {RSP_ZCFGT,    -1, -1, -1,                 -1,-1, {ACT_DEBUG}}, //FIXME
        {RSP_ZCFG,     -1, -1, -1,                 -1,-1, {ACT_DEBUG}}, //FIXME
@@ -328,10 +328,9 @@ struct reply_t gigaset_tab_cid[] =
        {RSP_INIT,     -1, -1,SEQ_HUP,            401, 5, {0},             "+VLS=0\r"}, /* hang up */ //-1,-1?
        {RSP_OK,      401,401, -1,                402, 5},
        {RSP_ZVLS,    402,402,  0,                403, 5},
-       {RSP_ZSAU,    403,403,ZSAU_DISCONNECT_REQ, -1,-1, {ACT_DEBUG}}, /* if not remote hup */
-       //{RSP_ZSAU,    403,403,ZSAU_NULL,          401, 0, {ACT_ERROR}}, //DELETE//FIXME -> DLE0 // should we do this _before_ hanging up for base driver?
-       {RSP_ZSAU,    403,403,ZSAU_NULL,            0, 0, {ACT_DISCONNECT}}, //FIXME -> DLE0 // should we do this _before_ hanging up for base driver?
-       {RSP_NODEV,   401,403, -1,                  0, 0, {ACT_FAKEHUP}}, //FIXME -> DLE0 // should we do this _before_ hanging up for base driver?
+       {RSP_ZSAU,    403, 403, ZSAU_DISCONNECT_REQ, -1, -1, {ACT_DEBUG} },
+       {RSP_ZSAU,    403, 403, ZSAU_NULL,            0,  0, {ACT_DISCONNECT} },
+       {RSP_NODEV,   401, 403, -1,                   0,  0, {ACT_FAKEHUP} },
        {RSP_ERROR,   401,401, -1,                  0, 0, {ACT_ABORTHUP}},
        {EV_TIMEOUT,  401,403, -1,                  0, 0, {ACT_ABORTHUP}},
 
@@ -474,8 +473,13 @@ static int cid_of_response(char *s)
        //FIXME is ;<digit>+ at end of non-CID response really impossible?
 }
 
-/* This function will be called via task queue from the callback handler.
- * We received a modem response and have to handle it..
+/**
+ * gigaset_handle_modem_response() - process received modem response
+ * @cs:                device descriptor structure.
+ *
+ * Called by asyncdata/isocdata if a block of data received from the
+ * device must be processed as a modem command response. The data is
+ * already in the cs structure.
  */
 void gigaset_handle_modem_response(struct cardstate *cs)
 {
@@ -707,6 +711,11 @@ static void disconnect(struct at_state_t **at_state_p)
        if (bcs) {
                /* B channel assigned: invoke hardware specific handler */
                cs->ops->close_bchannel(bcs);
+               /* notify LL */
+               if (bcs->chstate & (CHS_D_UP | CHS_NOTIFY_LL)) {
+                       bcs->chstate &= ~(CHS_D_UP | CHS_NOTIFY_LL);
+                       gigaset_i4l_channel_cmd(bcs, ISDN_STAT_DHUP);
+               }
        } else {
                /* no B channel assigned: just deallocate */
                spin_lock_irqsave(&cs->lock, flags);
@@ -1429,11 +1438,12 @@ static void do_action(int action, struct cardstate *cs,
                cs->gotfwver = -1;
                dev_err(cs->dev, "could not read firmware version.\n");
                break;
-#ifdef CONFIG_GIGASET_DEBUG
        case ACT_ERROR:
-               *p_genresp = 1;
-               *p_resp_code = RSP_ERROR;
+               gig_dbg(DEBUG_ANY, "%s: ERROR response in ConState %d",
+                       __func__, at_state->ConState);
+               cs->cur_at_seq = SEQ_NONE;
                break;
+#ifdef CONFIG_GIGASET_DEBUG
        case ACT_TEST:
                {
                        static int count = 3; //2; //1;
index 9b22f9c..654489d 100644 (file)
@@ -51,6 +51,12 @@ static int writebuf_from_LL(int driverID, int channel, int ack,
                return -ENODEV;
        }
        bcs = &cs->bcs[channel];
+
+       /* can only handle linear sk_buffs */
+       if (skb_linearize(skb) < 0) {
+               dev_err(cs->dev, "%s: skb_linearize failed\n", __func__);
+               return -ENOMEM;
+       }
        len = skb->len;
 
        gig_dbg(DEBUG_LLDATA,
@@ -79,6 +85,14 @@ static int writebuf_from_LL(int driverID, int channel, int ack,
        return cs->ops->send_skb(bcs, skb);
 }
 
+/**
+ * gigaset_skb_sent() - acknowledge sending an skb
+ * @bcs:       B channel descriptor structure.
+ * @skb:       sent data.
+ *
+ * Called by hardware module {bas,ser,usb}_gigaset when the data in a
+ * skb has been successfully sent, for signalling completion to the LL.
+ */
 void gigaset_skb_sent(struct bc_state *bcs, struct sk_buff *skb)
 {
        unsigned len;
@@ -455,6 +469,15 @@ int gigaset_isdn_setup_accept(struct at_state_t *at_state)
        return 0;
 }
 
+/**
+ * gigaset_isdn_icall() - signal incoming call
+ * @at_state:  connection state structure.
+ *
+ * Called by main module to notify the LL that an incoming call has been
+ * received. @at_state contains the parameters of the call.
+ *
+ * Return value: call disposition (ICALL_*)
+ */
 int gigaset_isdn_icall(struct at_state_t *at_state)
 {
        struct cardstate *cs = at_state->cs;
index f33ac27..6a8e138 100644 (file)
@@ -616,6 +616,15 @@ void gigaset_if_free(struct cardstate *cs)
        tty_unregister_device(drv->tty, cs->minor_index);
 }
 
+/**
+ * gigaset_if_receive() - pass a received block of data to the tty device
+ * @cs:                device descriptor structure.
+ * @buffer:    received data.
+ * @len:       number of bytes received.
+ *
+ * Called by asyncdata/isocdata if a block of data received from the
+ * device must be sent to userspace through the ttyG* device.
+ */
 void gigaset_if_receive(struct cardstate *cs,
                        unsigned char *buffer, size_t len)
 {
index bed38fc..9f3ef7b 100644 (file)
@@ -429,7 +429,7 @@ static inline int hdlc_buildframe(struct isowbuf_t *iwb,
                return -EAGAIN;
        }
 
-       dump_bytes(DEBUG_STREAM, "snd data", in, count);
+       dump_bytes(DEBUG_STREAM_DUMP, "snd data", in, count);
 
        /* bitstuff and checksum input data */
        fcs = PPP_INITFCS;
@@ -448,7 +448,6 @@ static inline int hdlc_buildframe(struct isowbuf_t *iwb,
        /* put closing flag and repeat byte for flag idle */
        isowbuf_putflag(iwb);
        end = isowbuf_donewrite(iwb);
-       dump_bytes(DEBUG_STREAM_DUMP, "isowbuf", iwb->data, end + 1);
        return end;
 }
 
@@ -482,6 +481,8 @@ static inline int trans_buildframe(struct isowbuf_t *iwb,
        }
 
        gig_dbg(DEBUG_STREAM, "put %d bytes", count);
+       dump_bytes(DEBUG_STREAM_DUMP, "snd data", in, count);
+
        write = iwb->write;
        do {
                c = bitrev8(*in++);
@@ -583,7 +584,7 @@ static inline void hdlc_done(struct bc_state *bcs)
                procskb->tail -= 2;
                gig_dbg(DEBUG_ISO, "%s: good frame (%d octets)",
                        __func__, procskb->len);
-               dump_bytes(DEBUG_STREAM,
+               dump_bytes(DEBUG_STREAM_DUMP,
                           "rcv data", procskb->data, procskb->len);
                bcs->hw.bas->goodbytes += procskb->len;
                gigaset_rcv_skb(procskb, bcs->cs, bcs);
@@ -878,6 +879,8 @@ static inline void trans_receive(unsigned char *src, unsigned count,
                        dobytes--;
                }
                if (dobytes == 0) {
+                       dump_bytes(DEBUG_STREAM_DUMP,
+                                  "rcv data", skb->data, skb->len);
                        gigaset_rcv_skb(skb, bcs->cs, bcs);
                        bcs->skb = skb = dev_alloc_skb(SBUFSIZE + HW_HDR_LEN);
                        if (!skb) {
@@ -973,16 +976,17 @@ void gigaset_isoc_input(struct inbuf_t *inbuf)
 
 /* == data output ========================================================== */
 
-/* gigaset_send_skb
- * called by common.c to queue an skb for sending
- * and start transmission if necessary
- * parameters:
- *     B Channel control structure
- *     skb
- * return value:
- *     number of bytes accepted for sending
- *     (skb->len if ok, 0 if out of buffer space)
- *     or error code (< 0, eg. -EINVAL)
+/**
+ * gigaset_isoc_send_skb() - queue an skb for sending
+ * @bcs:       B channel descriptor structure.
+ * @skb:       data to send.
+ *
+ * Called by i4l.c to queue an skb for sending, and start transmission if
+ * necessary.
+ *
+ * Return value:
+ *     number of bytes accepted for sending (skb->len) if ok,
+ *     error code < 0 (eg. -ENODEV) on error
  */
 int gigaset_isoc_send_skb(struct bc_state *bcs, struct sk_buff *skb)
 {
index d30ce5b..85a8fd8 100644 (file)
@@ -10,6 +10,7 @@
  *
  */
  
+#include <linux/sched.h>
 #include "hisax.h"
 #include "isdnl1.h"
 #include "isac.h"
index 5c46a71..8d22f50 100644 (file)
@@ -11,6 +11,7 @@
  */
 
 #include <linux/init.h>
+#include <linux/sched.h>
 #include "hisax.h"
 #include "hfc_2bds0.h"
 #include "isdnl1.h"
index d110a77..1091473 100644 (file)
@@ -20,6 +20,7 @@
 #include "hfc_pci.h"
 #include "isdnl1.h"
 #include <linux/pci.h>
+#include <linux/sched.h>
 #include <linux/interrupt.h>
 
 static const char *hfcpci_revision = "$Revision: 1.48.2.4 $";
index 8f9f491..90b35e1 100644 (file)
@@ -11,6 +11,7 @@
  *
  */
 
+#include <linux/cred.h>
 #include <linux/module.h>
 #include <linux/poll.h>
 #include <linux/proc_fs.h>
index 8991d2c..8bcae28 100644 (file)
@@ -13,6 +13,7 @@
 #include <linux/module.h>
 #include <linux/poll.h>
 #include <linux/proc_fs.h>
+#include <linux/sched.h>
 #include <linux/smp_lock.h>
 
 #include "hysdn_defs.h"
index 74032d0..7511f08 100644 (file)
@@ -83,19 +83,19 @@ static __inline__ isdn_net_local * isdn_net_get_locked_lp(isdn_net_dev *nd)
 
        spin_lock_irqsave(&nd->queue_lock, flags);
        lp = nd->queue;         /* get lp on top of queue */
-       spin_lock(&nd->queue->xmit_lock);
        while (isdn_net_lp_busy(nd->queue)) {
-               spin_unlock(&nd->queue->xmit_lock);
                nd->queue = nd->queue->next;
                if (nd->queue == lp) { /* not found -- should never happen */
                        lp = NULL;
                        goto errout;
                }
-               spin_lock(&nd->queue->xmit_lock);
        }
        lp = nd->queue;
        nd->queue = nd->queue->next;
+       spin_unlock_irqrestore(&nd->queue_lock, flags);
+       spin_lock(&lp->xmit_lock);
        local_bh_disable();
+       return lp;
 errout:
        spin_unlock_irqrestore(&nd->queue_lock, flags);
        return lp;
index 8c66bcb..123c1d6 100644 (file)
@@ -23,6 +23,7 @@
 #include <linux/kernel.h>
 
 #include <linux/types.h>
+#include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/mm.h>
 #include <linux/interrupt.h>
index e075e8d..30f0f45 100644 (file)
@@ -27,6 +27,7 @@
 #include <linux/string.h>
 #include <linux/kernel.h>
 #include <linux/types.h>
+#include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/interrupt.h>
 #include <linux/workqueue.h>
index dd0acd0..5a07748 100644 (file)
@@ -8,6 +8,7 @@
 #include <linux/init.h>
 #include <linux/interrupt.h>
 #include <linux/delay.h>
+#include <linux/sched.h>
 #include "includes.h"
 #include "hardware.h"
 #include "card.h"
index 1864818..daaf866 100644 (file)
@@ -16,6 +16,7 @@
 #include <linux/uaccess.h>
 #include <linux/interrupt.h>
 #include <linux/module.h>
+#include <linux/sched.h>
 #include "lg.h"
 
 /* Allow Guests to use a non-128 (ie. non-Linux) syscall trap. */
index b40fb9b..6f308a4 100644 (file)
@@ -405,7 +405,11 @@ static int __init via_pmu_start(void)
                printk(KERN_ERR "via-pmu: can't map interrupt\n");
                return -ENODEV;
        }
-       if (request_irq(irq, via_pmu_interrupt, 0, "VIA-PMU", (void *)0)) {
+       /* We set IRQF_TIMER because we don't want the interrupt to be disabled
+        * between the 2 passes of driver suspend, we control our own disabling
+        * for that one
+        */
+       if (request_irq(irq, via_pmu_interrupt, IRQF_TIMER, "VIA-PMU", (void *)0)) {
                printk(KERN_ERR "via-pmu: can't request irq %d\n", irq);
                return -ENODEV;
        }
@@ -419,7 +423,7 @@ static int __init via_pmu_start(void)
                        gpio_irq = irq_of_parse_and_map(gpio_node, 0);
 
                if (gpio_irq != NO_IRQ) {
-                       if (request_irq(gpio_irq, gpio1_interrupt, 0,
+                       if (request_irq(gpio_irq, gpio1_interrupt, IRQF_TIMER,
                                        "GPIO1 ADB", (void *)0))
                                printk(KERN_ERR "pmu: can't get irq %d"
                                       " (GPIO1)\n", gpio_irq);
@@ -925,8 +929,7 @@ proc_write_options(struct file *file, const char __user *buffer,
 
 #ifdef CONFIG_ADB
 /* Send an ADB command */
-static int
-pmu_send_request(struct adb_request *req, int sync)
+static int pmu_send_request(struct adb_request *req, int sync)
 {
        int i, ret;
 
@@ -1005,16 +1008,11 @@ pmu_send_request(struct adb_request *req, int sync)
 }
 
 /* Enable/disable autopolling */
-static int
-pmu_adb_autopoll(int devs)
+static int __pmu_adb_autopoll(int devs)
 {
        struct adb_request req;
 
-       if ((vias == NULL) || (!pmu_fully_inited) || !pmu_has_adb)
-               return -ENXIO;
-
        if (devs) {
-               adb_dev_map = devs;
                pmu_request(&req, NULL, 5, PMU_ADB_CMD, 0, 0x86,
                            adb_dev_map >> 8, adb_dev_map);
                pmu_adb_flags = 2;
@@ -1027,9 +1025,17 @@ pmu_adb_autopoll(int devs)
        return 0;
 }
 
+static int pmu_adb_autopoll(int devs)
+{
+       if ((vias == NULL) || (!pmu_fully_inited) || !pmu_has_adb)
+               return -ENXIO;
+
+       adb_dev_map = devs;
+       return __pmu_adb_autopoll(devs);
+}
+
 /* Reset the ADB bus */
-static int
-pmu_adb_reset_bus(void)
+static int pmu_adb_reset_bus(void)
 {
        struct adb_request req;
        int save_autopoll = adb_dev_map;
@@ -1038,13 +1044,13 @@ pmu_adb_reset_bus(void)
                return -ENXIO;
 
        /* anyone got a better idea?? */
-       pmu_adb_autopoll(0);
+       __pmu_adb_autopoll(0);
 
-       req.nbytes = 5;
+       req.nbytes = 4;
        req.done = NULL;
        req.data[0] = PMU_ADB_CMD;
-       req.data[1] = 0;
-       req.data[2] = ADB_BUSRESET;
+       req.data[1] = ADB_BUSRESET;
+       req.data[2] = 0;
        req.data[3] = 0;
        req.data[4] = 0;
        req.reply_len = 0;
@@ -1056,7 +1062,7 @@ pmu_adb_reset_bus(void)
        pmu_wait_complete(&req);
 
        if (save_autopoll != 0)
-               pmu_adb_autopoll(save_autopoll);
+               __pmu_adb_autopoll(save_autopoll);
 
        return 0;
 }
index 1dc4185..e355e7f 100644 (file)
@@ -46,7 +46,7 @@ obj-$(CONFIG_DM_LOG_USERSPACE)        += dm-log-userspace.o
 obj-$(CONFIG_DM_ZERO)          += dm-zero.o
 
 quiet_cmd_unroll = UNROLL  $@
-      cmd_unroll = $(PERL) $(srctree)/$(src)/unroll.pl $(UNROLL) \
+      cmd_unroll = $(AWK) -f$(srctree)/$(src)/unroll.awk -vN=$(UNROLL) \
                    < $< > $@ || ( rm -f $@ && exit 1 )
 
 ifeq ($(CONFIG_ALTIVEC),y)
@@ -59,56 +59,56 @@ endif
 
 targets += raid6int1.c
 $(obj)/raid6int1.c:   UNROLL := 1
-$(obj)/raid6int1.c:   $(src)/raid6int.uc $(src)/unroll.pl FORCE
+$(obj)/raid6int1.c:   $(src)/raid6int.uc $(src)/unroll.awk FORCE
        $(call if_changed,unroll)
 
 targets += raid6int2.c
 $(obj)/raid6int2.c:   UNROLL := 2
-$(obj)/raid6int2.c:   $(src)/raid6int.uc $(src)/unroll.pl FORCE
+$(obj)/raid6int2.c:   $(src)/raid6int.uc $(src)/unroll.awk FORCE
        $(call if_changed,unroll)
 
 targets += raid6int4.c
 $(obj)/raid6int4.c:   UNROLL := 4
-$(obj)/raid6int4.c:   $(src)/raid6int.uc $(src)/unroll.pl FORCE
+$(obj)/raid6int4.c:   $(src)/raid6int.uc $(src)/unroll.awk FORCE
        $(call if_changed,unroll)
 
 targets += raid6int8.c
 $(obj)/raid6int8.c:   UNROLL := 8
-$(obj)/raid6int8.c:   $(src)/raid6int.uc $(src)/unroll.pl FORCE
+$(obj)/raid6int8.c:   $(src)/raid6int.uc $(src)/unroll.awk FORCE
        $(call if_changed,unroll)
 
 targets += raid6int16.c
 $(obj)/raid6int16.c:  UNROLL := 16
-$(obj)/raid6int16.c:  $(src)/raid6int.uc $(src)/unroll.pl FORCE
+$(obj)/raid6int16.c:  $(src)/raid6int.uc $(src)/unroll.awk FORCE
        $(call if_changed,unroll)
 
 targets += raid6int32.c
 $(obj)/raid6int32.c:  UNROLL := 32
-$(obj)/raid6int32.c:  $(src)/raid6int.uc $(src)/unroll.pl FORCE
+$(obj)/raid6int32.c:  $(src)/raid6int.uc $(src)/unroll.awk FORCE
        $(call if_changed,unroll)
 
 CFLAGS_raid6altivec1.o += $(altivec_flags)
 targets += raid6altivec1.c
 $(obj)/raid6altivec1.c:   UNROLL := 1
-$(obj)/raid6altivec1.c:   $(src)/raid6altivec.uc $(src)/unroll.pl FORCE
+$(obj)/raid6altivec1.c:   $(src)/raid6altivec.uc $(src)/unroll.awk FORCE
        $(call if_changed,unroll)
 
 CFLAGS_raid6altivec2.o += $(altivec_flags)
 targets += raid6altivec2.c
 $(obj)/raid6altivec2.c:   UNROLL := 2
-$(obj)/raid6altivec2.c:   $(src)/raid6altivec.uc $(src)/unroll.pl FORCE
+$(obj)/raid6altivec2.c:   $(src)/raid6altivec.uc $(src)/unroll.awk FORCE
        $(call if_changed,unroll)
 
 CFLAGS_raid6altivec4.o += $(altivec_flags)
 targets += raid6altivec4.c
 $(obj)/raid6altivec4.c:   UNROLL := 4
-$(obj)/raid6altivec4.c:   $(src)/raid6altivec.uc $(src)/unroll.pl FORCE
+$(obj)/raid6altivec4.c:   $(src)/raid6altivec.uc $(src)/unroll.awk FORCE
        $(call if_changed,unroll)
 
 CFLAGS_raid6altivec8.o += $(altivec_flags)
 targets += raid6altivec8.c
 $(obj)/raid6altivec8.c:   UNROLL := 8
-$(obj)/raid6altivec8.c:   $(src)/raid6altivec.uc $(src)/unroll.pl FORCE
+$(obj)/raid6altivec8.c:   $(src)/raid6altivec.uc $(src)/unroll.awk FORCE
        $(call if_changed,unroll)
 
 quiet_cmd_mktable = TABLE   $@
index 6986b00..60e2b32 100644 (file)
@@ -1624,10 +1624,11 @@ int bitmap_create(mddev_t *mddev)
        bitmap->offset = mddev->bitmap_offset;
        if (file) {
                get_file(file);
-               do_sync_mapping_range(file->f_mapping, 0, LLONG_MAX,
-                                     SYNC_FILE_RANGE_WAIT_BEFORE |
-                                     SYNC_FILE_RANGE_WRITE |
-                                     SYNC_FILE_RANGE_WAIT_AFTER);
+               /* As future accesses to this file will use bmap,
+                * and bypass the page cache, we must sync the file
+                * first.
+                */
+               vfs_fsync(file, file->f_dentry, 1);
        }
        /* read superblock from bitmap file (this sets bitmap->chunksize) */
        err = bitmap_read_sb(bitmap);
index 556acff..7dbe652 100644 (file)
@@ -138,16 +138,6 @@ int dm_exception_store_type_unregister(struct dm_exception_store_type *type)
 }
 EXPORT_SYMBOL(dm_exception_store_type_unregister);
 
-/*
- * Round a number up to the nearest 'size' boundary.  size must
- * be a power of 2.
- */
-static ulong round_up(ulong n, ulong size)
-{
-       size--;
-       return (n + size) & ~size;
-}
-
 static int set_chunk_size(struct dm_exception_store *store,
                          const char *chunk_size_arg, char **error)
 {
@@ -155,7 +145,8 @@ static int set_chunk_size(struct dm_exception_store *store,
        char *value;
 
        chunk_size_ulong = simple_strtoul(chunk_size_arg, &value, 10);
-       if (*chunk_size_arg == '\0' || *value != '\0') {
+       if (*chunk_size_arg == '\0' || *value != '\0' ||
+           chunk_size_ulong > UINT_MAX) {
                *error = "Invalid chunk size";
                return -EINVAL;
        }
@@ -165,40 +156,35 @@ static int set_chunk_size(struct dm_exception_store *store,
                return 0;
        }
 
-       /*
-        * Chunk size must be multiple of page size.  Silently
-        * round up if it's not.
-        */
-       chunk_size_ulong = round_up(chunk_size_ulong, PAGE_SIZE >> 9);
-
-       return dm_exception_store_set_chunk_size(store, chunk_size_ulong,
+       return dm_exception_store_set_chunk_size(store,
+                                                (unsigned) chunk_size_ulong,
                                                 error);
 }
 
 int dm_exception_store_set_chunk_size(struct dm_exception_store *store,
-                                     unsigned long chunk_size_ulong,
+                                     unsigned chunk_size,
                                      char **error)
 {
        /* Check chunk_size is a power of 2 */
-       if (!is_power_of_2(chunk_size_ulong)) {
+       if (!is_power_of_2(chunk_size)) {
                *error = "Chunk size is not a power of 2";
                return -EINVAL;
        }
 
        /* Validate the chunk size against the device block size */
-       if (chunk_size_ulong % (bdev_logical_block_size(store->cow->bdev) >> 9)) {
+       if (chunk_size % (bdev_logical_block_size(store->cow->bdev) >> 9)) {
                *error = "Chunk size is not a multiple of device blocksize";
                return -EINVAL;
        }
 
-       if (chunk_size_ulong > INT_MAX >> SECTOR_SHIFT) {
+       if (chunk_size > INT_MAX >> SECTOR_SHIFT) {
                *error = "Chunk size is too high";
                return -EINVAL;
        }
 
-       store->chunk_size = chunk_size_ulong;
-       store->chunk_mask = chunk_size_ulong - 1;
-       store->chunk_shift = ffs(chunk_size_ulong) - 1;
+       store->chunk_size = chunk_size;
+       store->chunk_mask = chunk_size - 1;
+       store->chunk_shift = ffs(chunk_size) - 1;
 
        return 0;
 }
@@ -251,7 +237,7 @@ int dm_exception_store_create(struct dm_target *ti, int argc, char **argv,
 
        r = set_chunk_size(tmp_store, argv[2], &ti->error);
        if (r)
-               goto bad_cow;
+               goto bad_ctr;
 
        r = type->ctr(tmp_store, 0, NULL);
        if (r) {
index 812c718..8a223a4 100644 (file)
@@ -101,9 +101,9 @@ struct dm_exception_store {
        struct dm_dev *cow;
 
        /* Size of data blocks saved - must be a power of 2 */
-       chunk_t chunk_size;
-       chunk_t chunk_mask;
-       chunk_t chunk_shift;
+       unsigned chunk_size;
+       unsigned chunk_mask;
+       unsigned chunk_shift;
 
        void *context;
 };
@@ -169,7 +169,7 @@ int dm_exception_store_type_register(struct dm_exception_store_type *type);
 int dm_exception_store_type_unregister(struct dm_exception_store_type *type);
 
 int dm_exception_store_set_chunk_size(struct dm_exception_store *store,
-                                     unsigned long chunk_size_ulong,
+                                     unsigned chunk_size,
                                      char **error);
 
 int dm_exception_store_create(struct dm_target *ti, int argc, char **argv,
index 652bd33..7ac2c14 100644 (file)
@@ -156,7 +156,7 @@ static int userspace_ctr(struct dm_dirty_log *log, struct dm_target *ti,
        }
 
        /* The ptr value is sufficient for local unique id */
-       lc->luid = (uint64_t)lc;
+       lc->luid = (unsigned long)lc;
 
        lc->ti = ti;
 
index d5b2e08..0c74642 100644 (file)
@@ -284,12 +284,13 @@ static int read_header(struct pstore *ps, int *new_snapshot)
 {
        int r;
        struct disk_header *dh;
-       chunk_t chunk_size;
+       unsigned chunk_size;
        int chunk_size_supplied = 1;
        char *chunk_err;
 
        /*
-        * Use default chunk size (or hardsect_size, if larger) if none supplied
+        * Use default chunk size (or logical_block_size, if larger)
+        * if none supplied
         */
        if (!ps->store->chunk_size) {
                ps->store->chunk_size = max(DM_CHUNK_SIZE_DEFAULT_SECTORS,
@@ -334,10 +335,9 @@ static int read_header(struct pstore *ps, int *new_snapshot)
                return 0;
 
        if (chunk_size_supplied)
-               DMWARN("chunk size %llu in device metadata overrides "
-                      "table chunk size of %llu.",
-                      (unsigned long long)chunk_size,
-                      (unsigned long long)ps->store->chunk_size);
+               DMWARN("chunk size %u in device metadata overrides "
+                      "table chunk size of %u.",
+                      chunk_size, ps->store->chunk_size);
 
        /* We had a bogus chunk_size. Fix stuff up. */
        free_area(ps);
@@ -345,8 +345,8 @@ static int read_header(struct pstore *ps, int *new_snapshot)
        r = dm_exception_store_set_chunk_size(ps->store, chunk_size,
                                              &chunk_err);
        if (r) {
-               DMERR("invalid on-disk chunk size %llu: %s.",
-                     (unsigned long long)chunk_size, chunk_err);
+               DMERR("invalid on-disk chunk size %u: %s.",
+                     chunk_size, chunk_err);
                return r;
        }
 
index 57f1bf7..3a3ba46 100644 (file)
@@ -296,6 +296,7 @@ static void __insert_origin(struct origin *o)
  */
 static int register_snapshot(struct dm_snapshot *snap)
 {
+       struct dm_snapshot *l;
        struct origin *o, *new_o;
        struct block_device *bdev = snap->origin->bdev;
 
@@ -319,7 +320,11 @@ static int register_snapshot(struct dm_snapshot *snap)
                __insert_origin(o);
        }
 
-       list_add_tail(&snap->list, &o->snapshots);
+       /* Sort the list according to chunk size, largest-first smallest-last */
+       list_for_each_entry(l, &o->snapshots, list)
+               if (l->store->chunk_size < snap->store->chunk_size)
+                       break;
+       list_add_tail(&snap->list, &l->list);
 
        up_write(&_origins_lock);
        return 0;
@@ -668,6 +673,11 @@ static int snapshot_ctr(struct dm_target *ti, unsigned int argc, char **argv)
        bio_list_init(&s->queued_bios);
        INIT_WORK(&s->queued_bios_work, flush_queued_bios);
 
+       if (!s->store->chunk_size) {
+               ti->error = "Chunk size not set";
+               goto bad_load_and_register;
+       }
+
        /* Add snapshot to the list of snapshots for this origin */
        /* Exceptions aren't triggered till snapshot_resume() is called */
        if (register_snapshot(s)) {
@@ -951,7 +961,7 @@ static void start_copy(struct dm_snap_pending_exception *pe)
 
        src.bdev = bdev;
        src.sector = chunk_to_sector(s->store, pe->e.old_chunk);
-       src.count = min(s->store->chunk_size, dev_size - src.sector);
+       src.count = min((sector_t)s->store->chunk_size, dev_size - src.sector);
 
        dest.bdev = s->store->cow->bdev;
        dest.sector = chunk_to_sector(s->store, pe->e.new_chunk);
@@ -1142,6 +1152,8 @@ static int snapshot_status(struct dm_target *ti, status_type_t type,
        unsigned sz = 0;
        struct dm_snapshot *snap = ti->private;
 
+       down_write(&snap->lock);
+
        switch (type) {
        case STATUSTYPE_INFO:
                if (!snap->valid)
@@ -1173,6 +1185,8 @@ static int snapshot_status(struct dm_target *ti, status_type_t type,
                break;
        }
 
+       up_write(&snap->lock);
+
        return 0;
 }
 
@@ -1388,7 +1402,7 @@ static void origin_resume(struct dm_target *ti)
        struct dm_dev *dev = ti->private;
        struct dm_snapshot *snap;
        struct origin *o;
-       chunk_t chunk_size = 0;
+       unsigned chunk_size = 0;
 
        down_read(&_origins_lock);
        o = __lookup_origin(dev->bdev);
@@ -1465,7 +1479,7 @@ static int __init dm_snapshot_init(void)
        r = dm_register_target(&snapshot_target);
        if (r) {
                DMERR("snapshot target register failed %d", r);
-               return r;
+               goto bad_register_snapshot_target;
        }
 
        r = dm_register_target(&origin_target);
@@ -1522,6 +1536,9 @@ bad2:
        dm_unregister_target(&origin_target);
 bad1:
        dm_unregister_target(&snapshot_target);
+
+bad_register_snapshot_target:
+       dm_exception_store_exit();
        return r;
 }
 
index 23e76fe..724efc6 100644 (file)
@@ -47,6 +47,7 @@ struct dm_io {
        atomic_t io_count;
        struct bio *bio;
        unsigned long start_time;
+       spinlock_t endio_lock;
 };
 
 /*
@@ -130,7 +131,7 @@ struct mapped_device {
        /*
         * A list of ios that arrived while we were suspended.
         */
-       atomic_t pending;
+       atomic_t pending[2];
        wait_queue_head_t wait;
        struct work_struct work;
        struct bio_list deferred;
@@ -453,13 +454,14 @@ static void start_io_acct(struct dm_io *io)
 {
        struct mapped_device *md = io->md;
        int cpu;
+       int rw = bio_data_dir(io->bio);
 
        io->start_time = jiffies;
 
        cpu = part_stat_lock();
        part_round_stats(cpu, &dm_disk(md)->part0);
        part_stat_unlock();
-       dm_disk(md)->part0.in_flight = atomic_inc_return(&md->pending);
+       dm_disk(md)->part0.in_flight[rw] = atomic_inc_return(&md->pending[rw]);
 }
 
 static void end_io_acct(struct dm_io *io)
@@ -479,8 +481,9 @@ static void end_io_acct(struct dm_io *io)
         * After this is decremented the bio must not be touched if it is
         * a barrier.
         */
-       dm_disk(md)->part0.in_flight = pending =
-               atomic_dec_return(&md->pending);
+       dm_disk(md)->part0.in_flight[rw] = pending =
+               atomic_dec_return(&md->pending[rw]);
+       pending += atomic_read(&md->pending[rw^0x1]);
 
        /* nudge anyone waiting on suspend queue */
        if (!pending)
@@ -576,8 +579,12 @@ static void dec_pending(struct dm_io *io, int error)
        struct mapped_device *md = io->md;
 
        /* Push-back supersedes any I/O errors */
-       if (error && !(io->error > 0 && __noflush_suspending(md)))
-               io->error = error;
+       if (unlikely(error)) {
+               spin_lock_irqsave(&io->endio_lock, flags);
+               if (!(io->error > 0 && __noflush_suspending(md)))
+                       io->error = error;
+               spin_unlock_irqrestore(&io->endio_lock, flags);
+       }
 
        if (atomic_dec_and_test(&io->io_count)) {
                if (io->error == DM_ENDIO_REQUEUE) {
@@ -1224,6 +1231,7 @@ static void __split_and_process_bio(struct mapped_device *md, struct bio *bio)
        atomic_set(&ci.io->io_count, 1);
        ci.io->bio = bio;
        ci.io->md = md;
+       spin_lock_init(&ci.io->endio_lock);
        ci.sector = bio->bi_sector;
        ci.sector_count = bio_sectors(bio);
        if (unlikely(bio_empty_barrier(bio)))
@@ -1785,7 +1793,8 @@ static struct mapped_device *alloc_dev(int minor)
        if (!md->disk)
                goto bad_disk;
 
-       atomic_set(&md->pending, 0);
+       atomic_set(&md->pending[0], 0);
+       atomic_set(&md->pending[1], 0);
        init_waitqueue_head(&md->wait);
        INIT_WORK(&md->work, dm_wq_work);
        init_waitqueue_head(&md->eventq);
@@ -1819,6 +1828,7 @@ static struct mapped_device *alloc_dev(int minor)
 bad_bdev:
        destroy_workqueue(md->wq);
 bad_thread:
+       del_gendisk(md->disk);
        put_disk(md->disk);
 bad_disk:
        blk_cleanup_queue(md->queue);
@@ -2088,7 +2098,8 @@ static int dm_wait_for_completion(struct mapped_device *md, int interruptible)
                                break;
                        }
                        spin_unlock_irqrestore(q->queue_lock, flags);
-               } else if (!atomic_read(&md->pending))
+               } else if (!atomic_read(&md->pending[0]) &&
+                                       !atomic_read(&md->pending[1]))
                        break;
 
                if (interruptible == TASK_INTERRUPTIBLE &&
index 26ba42a..10eb1fc 100644 (file)
@@ -2631,7 +2631,7 @@ static void analyze_sbs(mddev_t * mddev)
                        rdev->desc_nr = i++;
                        rdev->raid_disk = rdev->desc_nr;
                        set_bit(In_sync, &rdev->flags);
-               } else if (rdev->raid_disk >= mddev->raid_disks) {
+               } else if (rdev->raid_disk >= (mddev->raid_disks - min(0, mddev->delta_disks))) {
                        rdev->raid_disk = -1;
                        clear_bit(In_sync, &rdev->flags);
                }
index d1b9bd5..a053423 100644 (file)
@@ -64,7 +64,7 @@ static void * r1bio_pool_alloc(gfp_t gfp_flags, void *data)
 
        /* allocate a r1bio with room for raid_disks entries in the bios array */
        r1_bio = kzalloc(size, gfp_flags);
-       if (!r1_bio)
+       if (!r1_bio && pi->mddev)
                unplug_slaves(pi->mddev);
 
        return r1_bio;
@@ -1683,6 +1683,7 @@ static void raid1d(mddev_t *mddev)
                                generic_make_request(bio);
                        }
                }
+               cond_resched();
        }
        if (unplug)
                unplug_slaves(mddev);
@@ -1978,13 +1979,14 @@ static int run(mddev_t *mddev)
        conf->poolinfo = kmalloc(sizeof(*conf->poolinfo), GFP_KERNEL);
        if (!conf->poolinfo)
                goto out_no_mem;
-       conf->poolinfo->mddev = mddev;
+       conf->poolinfo->mddev = NULL;
        conf->poolinfo->raid_disks = mddev->raid_disks;
        conf->r1bio_pool = mempool_create(NR_RAID1_BIOS, r1bio_pool_alloc,
                                          r1bio_pool_free,
                                          conf->poolinfo);
        if (!conf->r1bio_pool)
                goto out_no_mem;
+       conf->poolinfo->mddev = mddev;
 
        spin_lock_init(&conf->device_lock);
        mddev->queue->queue_lock = &conf->device_lock;
index 51c4c5c..c2cb7b8 100644 (file)
@@ -68,7 +68,7 @@ static void * r10bio_pool_alloc(gfp_t gfp_flags, void *data)
 
        /* allocate a r10bio with room for raid_disks entries in the bios array */
        r10_bio = kzalloc(size, gfp_flags);
-       if (!r10_bio)
+       if (!r10_bio && conf->mddev)
                unplug_slaves(conf->mddev);
 
        return r10_bio;
@@ -1632,6 +1632,7 @@ static void raid10d(mddev_t *mddev)
                                generic_make_request(bio);
                        }
                }
+               cond_resched();
        }
        if (unplug)
                unplug_slaves(mddev);
@@ -2095,7 +2096,6 @@ static int run(mddev_t *mddev)
        if (!conf->tmppage)
                goto out_free_conf;
 
-       conf->mddev = mddev;
        conf->raid_disks = mddev->raid_disks;
        conf->near_copies = nc;
        conf->far_copies = fc;
@@ -2132,6 +2132,7 @@ static int run(mddev_t *mddev)
                goto out_free_conf;
        }
 
+       conf->mddev = mddev;
        spin_lock_init(&conf->device_lock);
        mddev->queue->queue_lock = &conf->device_lock;
 
index 9482980..81abefc 100644 (file)
@@ -156,13 +156,16 @@ static inline int raid6_next_disk(int disk, int raid_disks)
 static int raid6_idx_to_slot(int idx, struct stripe_head *sh,
                             int *count, int syndrome_disks)
 {
-       int slot;
+       int slot = *count;
 
+       if (sh->ddf_layout)
+               (*count)++;
        if (idx == sh->pd_idx)
                return syndrome_disks;
        if (idx == sh->qd_idx)
                return syndrome_disks + 1;
-       slot = (*count)++;
+       if (!sh->ddf_layout)
+               (*count)++;
        return slot;
 }
 
@@ -717,7 +720,7 @@ static int set_syndrome_sources(struct page **srcs, struct stripe_head *sh)
        int i;
 
        for (i = 0; i < disks; i++)
-               srcs[i] = (void *)raid6_empty_zero_page;
+               srcs[i] = NULL;
 
        count = 0;
        i = d0_idx;
@@ -727,9 +730,8 @@ static int set_syndrome_sources(struct page **srcs, struct stripe_head *sh)
                srcs[slot] = sh->dev[i].page;
                i = raid6_next_disk(i, disks);
        } while (i != d0_idx);
-       BUG_ON(count != syndrome_disks);
 
-       return count;
+       return syndrome_disks;
 }
 
 static struct dma_async_tx_descriptor *
@@ -814,7 +816,7 @@ ops_run_compute6_2(struct stripe_head *sh, struct raid5_percpu *percpu)
         * slot number conversion for 'faila' and 'failb'
         */
        for (i = 0; i < disks ; i++)
-               blocks[i] = (void *)raid6_empty_zero_page;
+               blocks[i] = NULL;
        count = 0;
        i = d0_idx;
        do {
@@ -828,7 +830,6 @@ ops_run_compute6_2(struct stripe_head *sh, struct raid5_percpu *percpu)
                        failb = slot;
                i = raid6_next_disk(i, disks);
        } while (i != d0_idx);
-       BUG_ON(count != syndrome_disks);
 
        BUG_ON(faila == failb);
        if (failb < faila)
@@ -845,7 +846,7 @@ ops_run_compute6_2(struct stripe_head *sh, struct raid5_percpu *percpu)
                        init_async_submit(&submit, ASYNC_TX_FENCE, NULL,
                                          ops_complete_compute, sh,
                                          to_addr_conv(sh, percpu));
-                       return async_gen_syndrome(blocks, 0, count+2,
+                       return async_gen_syndrome(blocks, 0, syndrome_disks+2,
                                                  STRIPE_SIZE, &submit);
                } else {
                        struct page *dest;
@@ -1139,7 +1140,7 @@ static void ops_run_check_pq(struct stripe_head *sh, struct raid5_percpu *percpu
                           &sh->ops.zero_sum_result, percpu->spare_page, &submit);
 }
 
-static void raid_run_ops(struct stripe_head *sh, unsigned long ops_request)
+static void __raid_run_ops(struct stripe_head *sh, unsigned long ops_request)
 {
        int overlap_clear = 0, i, disks = sh->disks;
        struct dma_async_tx_descriptor *tx = NULL;
@@ -1204,22 +1205,55 @@ static void raid_run_ops(struct stripe_head *sh, unsigned long ops_request)
        put_cpu();
 }
 
+#ifdef CONFIG_MULTICORE_RAID456
+static void async_run_ops(void *param, async_cookie_t cookie)
+{
+       struct stripe_head *sh = param;
+       unsigned long ops_request = sh->ops.request;
+
+       clear_bit_unlock(STRIPE_OPS_REQ_PENDING, &sh->state);
+       wake_up(&sh->ops.wait_for_ops);
+
+       __raid_run_ops(sh, ops_request);
+       release_stripe(sh);
+}
+
+static void raid_run_ops(struct stripe_head *sh, unsigned long ops_request)
+{
+       /* since handle_stripe can be called outside of raid5d context
+        * we need to ensure sh->ops.request is de-staged before another
+        * request arrives
+        */
+       wait_event(sh->ops.wait_for_ops,
+                  !test_and_set_bit_lock(STRIPE_OPS_REQ_PENDING, &sh->state));
+       sh->ops.request = ops_request;
+
+       atomic_inc(&sh->count);
+       async_schedule(async_run_ops, sh);
+}
+#else
+#define raid_run_ops __raid_run_ops
+#endif
+
 static int grow_one_stripe(raid5_conf_t *conf)
 {
        struct stripe_head *sh;
+       int disks = max(conf->raid_disks, conf->previous_raid_disks);
        sh = kmem_cache_alloc(conf->slab_cache, GFP_KERNEL);
        if (!sh)
                return 0;
-       memset(sh, 0, sizeof(*sh) + (conf->raid_disks-1)*sizeof(struct r5dev));
+       memset(sh, 0, sizeof(*sh) + (disks-1)*sizeof(struct r5dev));
        sh->raid_conf = conf;
        spin_lock_init(&sh->lock);
+       #ifdef CONFIG_MULTICORE_RAID456
+       init_waitqueue_head(&sh->ops.wait_for_ops);
+       #endif
 
-       if (grow_buffers(sh, conf->raid_disks)) {
-               shrink_buffers(sh, conf->raid_disks);
+       if (grow_buffers(sh, disks)) {
+               shrink_buffers(sh, disks);
                kmem_cache_free(conf->slab_cache, sh);
                return 0;
        }
-       sh->disks = conf->raid_disks;
        /* we just created an active stripe so... */
        atomic_set(&sh->count, 1);
        atomic_inc(&conf->active_stripes);
@@ -1231,7 +1265,7 @@ static int grow_one_stripe(raid5_conf_t *conf)
 static int grow_stripes(raid5_conf_t *conf, int num)
 {
        struct kmem_cache *sc;
-       int devs = conf->raid_disks;
+       int devs = max(conf->raid_disks, conf->previous_raid_disks);
 
        sprintf(conf->cache_name[0],
                "raid%d-%s", conf->level, mdname(conf->mddev));
@@ -1329,6 +1363,9 @@ static int resize_stripes(raid5_conf_t *conf, int newsize)
 
                nsh->raid_conf = conf;
                spin_lock_init(&nsh->lock);
+               #ifdef CONFIG_MULTICORE_RAID456
+               init_waitqueue_head(&nsh->ops.wait_for_ops);
+               #endif
 
                list_add(&nsh->lru, &newstripes);
        }
@@ -1899,10 +1936,15 @@ static sector_t compute_blocknr(struct stripe_head *sh, int i, int previous)
                case ALGORITHM_PARITY_N:
                        break;
                case ALGORITHM_ROTATING_N_CONTINUE:
+                       /* Like left_symmetric, but P is before Q */
                        if (sh->pd_idx == 0)
                                i--;    /* P D D D Q */
-                       else if (i > sh->pd_idx)
-                               i -= 2; /* D D Q P D */
+                       else {
+                               /* D D Q P D */
+                               if (i < sh->pd_idx)
+                                       i += raid_disks;
+                               i -= (sh->pd_idx + 1);
+                       }
                        break;
                case ALGORITHM_LEFT_ASYMMETRIC_6:
                case ALGORITHM_RIGHT_ASYMMETRIC_6:
@@ -2896,7 +2938,7 @@ static void handle_stripe_expansion(raid5_conf_t *conf, struct stripe_head *sh,
  *
  */
 
-static bool handle_stripe5(struct stripe_head *sh)
+static void handle_stripe5(struct stripe_head *sh)
 {
        raid5_conf_t *conf = sh->raid_conf;
        int disks = sh->disks, i;
@@ -3167,11 +3209,9 @@ static bool handle_stripe5(struct stripe_head *sh)
        ops_run_io(sh, &s);
 
        return_io(return_bi);
-
-       return blocked_rdev == NULL;
 }
 
-static bool handle_stripe6(struct stripe_head *sh)
+static void handle_stripe6(struct stripe_head *sh)
 {
        raid5_conf_t *conf = sh->raid_conf;
        int disks = sh->disks;
@@ -3455,17 +3495,14 @@ static bool handle_stripe6(struct stripe_head *sh)
        ops_run_io(sh, &s);
 
        return_io(return_bi);
-
-       return blocked_rdev == NULL;
 }
 
-/* returns true if the stripe was handled */
-static bool handle_stripe(struct stripe_head *sh)
+static void handle_stripe(struct stripe_head *sh)
 {
        if (sh->raid_conf->level == 6)
-               return handle_stripe6(sh);
+               handle_stripe6(sh);
        else
-               return handle_stripe5(sh);
+               handle_stripe5(sh);
 }
 
 static void raid5_activate_delayed(raid5_conf_t *conf)
@@ -3503,9 +3540,10 @@ static void unplug_slaves(mddev_t *mddev)
 {
        raid5_conf_t *conf = mddev->private;
        int i;
+       int devs = max(conf->raid_disks, conf->previous_raid_disks);
 
        rcu_read_lock();
-       for (i = 0; i < conf->raid_disks; i++) {
+       for (i = 0; i < devs; i++) {
                mdk_rdev_t *rdev = rcu_dereference(conf->disks[i].rdev);
                if (rdev && !test_bit(Faulty, &rdev->flags) && atomic_read(&rdev->nr_pending)) {
                        struct request_queue *r_queue = bdev_get_queue(rdev->bdev);
@@ -4277,9 +4315,7 @@ static inline sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *ski
        clear_bit(STRIPE_INSYNC, &sh->state);
        spin_unlock(&sh->lock);
 
-       /* wait for any blocked device to be handled */
-       while (unlikely(!handle_stripe(sh)))
-               ;
+       handle_stripe(sh);
        release_stripe(sh);
 
        return STRIPE_SECTORS;
@@ -4349,37 +4385,6 @@ static int  retry_aligned_read(raid5_conf_t *conf, struct bio *raid_bio)
        return handled;
 }
 
-#ifdef CONFIG_MULTICORE_RAID456
-static void __process_stripe(void *param, async_cookie_t cookie)
-{
-       struct stripe_head *sh = param;
-
-       handle_stripe(sh);
-       release_stripe(sh);
-}
-
-static void process_stripe(struct stripe_head *sh, struct list_head *domain)
-{
-       async_schedule_domain(__process_stripe, sh, domain);
-}
-
-static void synchronize_stripe_processing(struct list_head *domain)
-{
-       async_synchronize_full_domain(domain);
-}
-#else
-static void process_stripe(struct stripe_head *sh, struct list_head *domain)
-{
-       handle_stripe(sh);
-       release_stripe(sh);
-       cond_resched();
-}
-
-static void synchronize_stripe_processing(struct list_head *domain)
-{
-}
-#endif
-
 
 /*
  * This is our raid5 kernel thread.
@@ -4393,7 +4398,6 @@ static void raid5d(mddev_t *mddev)
        struct stripe_head *sh;
        raid5_conf_t *conf = mddev->private;
        int handled;
-       LIST_HEAD(raid_domain);
 
        pr_debug("+++ raid5d active\n");
 
@@ -4430,7 +4434,9 @@ static void raid5d(mddev_t *mddev)
                spin_unlock_irq(&conf->device_lock);
                
                handled++;
-               process_stripe(sh, &raid_domain);
+               handle_stripe(sh);
+               release_stripe(sh);
+               cond_resched();
 
                spin_lock_irq(&conf->device_lock);
        }
@@ -4438,7 +4444,6 @@ static void raid5d(mddev_t *mddev)
 
        spin_unlock_irq(&conf->device_lock);
 
-       synchronize_stripe_processing(&raid_domain);
        async_tx_issue_pending_all();
        unplug_slaves(mddev);
 
@@ -4558,13 +4563,9 @@ raid5_size(mddev_t *mddev, sector_t sectors, int raid_disks)
 
        if (!sectors)
                sectors = mddev->dev_sectors;
-       if (!raid_disks) {
+       if (!raid_disks)
                /* size is defined by the smallest of previous and new size */
-               if (conf->raid_disks < conf->previous_raid_disks)
-                       raid_disks = conf->raid_disks;
-               else
-                       raid_disks = conf->previous_raid_disks;
-       }
+               raid_disks = min(conf->raid_disks, conf->previous_raid_disks);
 
        sectors &= ~((sector_t)mddev->chunk_sectors - 1);
        sectors &= ~((sector_t)mddev->new_chunk_sectors - 1);
@@ -4665,7 +4666,7 @@ static int raid5_alloc_percpu(raid5_conf_t *conf)
                        }
                        per_cpu_ptr(conf->percpu, cpu)->spare_page = spare_page;
                }
-               scribble = kmalloc(scribble_len(conf->raid_disks), GFP_KERNEL);
+               scribble = kmalloc(conf->scribble_len, GFP_KERNEL);
                if (!scribble) {
                        err = -ENOMEM;
                        break;
@@ -4686,7 +4687,7 @@ static int raid5_alloc_percpu(raid5_conf_t *conf)
 static raid5_conf_t *setup_conf(mddev_t *mddev)
 {
        raid5_conf_t *conf;
-       int raid_disk, memory;
+       int raid_disk, memory, max_disks;
        mdk_rdev_t *rdev;
        struct disk_info *disk;
 
@@ -4722,15 +4723,28 @@ static raid5_conf_t *setup_conf(mddev_t *mddev)
        conf = kzalloc(sizeof(raid5_conf_t), GFP_KERNEL);
        if (conf == NULL)
                goto abort;
+       spin_lock_init(&conf->device_lock);
+       init_waitqueue_head(&conf->wait_for_stripe);
+       init_waitqueue_head(&conf->wait_for_overlap);
+       INIT_LIST_HEAD(&conf->handle_list);
+       INIT_LIST_HEAD(&conf->hold_list);
+       INIT_LIST_HEAD(&conf->delayed_list);
+       INIT_LIST_HEAD(&conf->bitmap_list);
+       INIT_LIST_HEAD(&conf->inactive_list);
+       atomic_set(&conf->active_stripes, 0);
+       atomic_set(&conf->preread_active_stripes, 0);
+       atomic_set(&conf->active_aligned_reads, 0);
+       conf->bypass_threshold = BYPASS_THRESHOLD;
 
        conf->raid_disks = mddev->raid_disks;
-       conf->scribble_len = scribble_len(conf->raid_disks);
        if (mddev->reshape_position == MaxSector)
                conf->previous_raid_disks = mddev->raid_disks;
        else
                conf->previous_raid_disks = mddev->raid_disks - mddev->delta_disks;
+       max_disks = max(conf->raid_disks, conf->previous_raid_disks);
+       conf->scribble_len = scribble_len(max_disks);
 
-       conf->disks = kzalloc(conf->raid_disks * sizeof(struct disk_info),
+       conf->disks = kzalloc(max_disks * sizeof(struct disk_info),
                              GFP_KERNEL);
        if (!conf->disks)
                goto abort;
@@ -4744,24 +4758,11 @@ static raid5_conf_t *setup_conf(mddev_t *mddev)
        if (raid5_alloc_percpu(conf) != 0)
                goto abort;
 
-       spin_lock_init(&conf->device_lock);
-       init_waitqueue_head(&conf->wait_for_stripe);
-       init_waitqueue_head(&conf->wait_for_overlap);
-       INIT_LIST_HEAD(&conf->handle_list);
-       INIT_LIST_HEAD(&conf->hold_list);
-       INIT_LIST_HEAD(&conf->delayed_list);
-       INIT_LIST_HEAD(&conf->bitmap_list);
-       INIT_LIST_HEAD(&conf->inactive_list);
-       atomic_set(&conf->active_stripes, 0);
-       atomic_set(&conf->preread_active_stripes, 0);
-       atomic_set(&conf->active_aligned_reads, 0);
-       conf->bypass_threshold = BYPASS_THRESHOLD;
-
        pr_debug("raid5: run(%s) called.\n", mdname(mddev));
 
        list_for_each_entry(rdev, &mddev->disks, same_set) {
                raid_disk = rdev->raid_disk;
-               if (raid_disk >= conf->raid_disks
+               if (raid_disk >= max_disks
                    || raid_disk < 0)
                        continue;
                disk = conf->disks + raid_disk;
@@ -4793,7 +4794,7 @@ static raid5_conf_t *setup_conf(mddev_t *mddev)
        }
 
        memory = conf->max_nr_stripes * (sizeof(struct stripe_head) +
-                conf->raid_disks * ((sizeof(struct bio) + PAGE_SIZE))) / 1024;
+                max_disks * ((sizeof(struct bio) + PAGE_SIZE))) / 1024;
        if (grow_stripes(conf, conf->max_nr_stripes)) {
                printk(KERN_ERR
                        "raid5: couldn't allocate %dkB for buffers\n", memory);
@@ -4918,7 +4919,8 @@ static int run(mddev_t *mddev)
                    test_bit(In_sync, &rdev->flags))
                        working_disks++;
 
-       mddev->degraded = conf->raid_disks - working_disks;
+       mddev->degraded = (max(conf->raid_disks, conf->previous_raid_disks)
+                          - working_disks);
 
        if (mddev->degraded > conf->max_degraded) {
                printk(KERN_ERR "raid5: not enough operational devices for %s"
index 2390e0e..dd70835 100644 (file)
@@ -214,12 +214,20 @@ struct stripe_head {
        int                     disks;          /* disks in stripe */
        enum check_states       check_state;
        enum reconstruct_states reconstruct_state;
-       /* stripe_operations
+       /**
+        * struct stripe_operations
         * @target - STRIPE_OP_COMPUTE_BLK target
+        * @target2 - 2nd compute target in the raid6 case
+        * @zero_sum_result - P and Q verification flags
+        * @request - async service request flags for raid_run_ops
         */
        struct stripe_operations {
                int                  target, target2;
                enum sum_check_flags zero_sum_result;
+               #ifdef CONFIG_MULTICORE_RAID456
+               unsigned long        request;
+               wait_queue_head_t    wait_for_ops;
+               #endif
        } ops;
        struct r5dev {
                struct bio      req;
@@ -294,6 +302,8 @@ struct r6_state {
 #define        STRIPE_FULL_WRITE       13 /* all blocks are set to be overwritten */
 #define        STRIPE_BIOFILL_RUN      14
 #define        STRIPE_COMPUTE_RUN      15
+#define        STRIPE_OPS_REQ_PENDING  16
+
 /*
  * Operation request flags
  */
@@ -478,7 +488,7 @@ static inline int algorithm_valid_raid6(int layout)
 {
        return (layout >= 0 && layout <= 5)
                ||
-               (layout == 8 || layout == 10)
+               (layout >= 8 && layout <= 10)
                ||
                (layout >= 16 && layout <= 20);
 }
index 699dfee..2654d5c 100644 (file)
@@ -15,7 +15,7 @@
  *
  * $#-way unrolled portable integer math RAID-6 instruction set
  *
- * This file is postprocessed using unroll.pl
+ * This file is postprocessed using unroll.awk
  *
  * <benh> hpa: in process,
  * you can just "steal" the vec unit with enable_kernel_altivec() (but
index f9bf9cb..d1e276a 100644 (file)
@@ -15,7 +15,7 @@
  *
  * $#-way unrolled portable integer math RAID-6 instruction set
  *
- * This file is postprocessed using unroll.pl
+ * This file is postprocessed using unroll.awk
  */
 
 #include <linux/raid/pq.h>
index 58ffdf4..2874cbe 100644 (file)
@@ -7,7 +7,7 @@ CC       = gcc
 OPTFLAGS = -O2                 # Adjust as desired
 CFLAGS  = -I.. -I ../../../include -g $(OPTFLAGS)
 LD      = ld
-PERL    = perl
+AWK     = awk
 AR      = ar
 RANLIB  = ranlib
 
@@ -35,35 +35,35 @@ raid6.a: raid6int1.o raid6int2.o raid6int4.o raid6int8.o raid6int16.o \
 raid6test: test.c raid6.a
        $(CC) $(CFLAGS) -o raid6test $^
 
-raid6altivec1.c: raid6altivec.uc ../unroll.pl
-       $(PERL) ../unroll.pl 1 < raid6altivec.uc > $@
+raid6altivec1.c: raid6altivec.uc ../unroll.awk
+       $(AWK) ../unroll.awk -vN=1 < raid6altivec.uc > $@
 
-raid6altivec2.c: raid6altivec.uc ../unroll.pl
-       $(PERL) ../unroll.pl 2 < raid6altivec.uc > $@
+raid6altivec2.c: raid6altivec.uc ../unroll.awk
+       $(AWK) ../unroll.awk -vN=2 < raid6altivec.uc > $@
 
-raid6altivec4.c: raid6altivec.uc ../unroll.pl
-       $(PERL) ../unroll.pl 4 < raid6altivec.uc > $@
+raid6altivec4.c: raid6altivec.uc ../unroll.awk
+       $(AWK) ../unroll.awk -vN=4 < raid6altivec.uc > $@
 
-raid6altivec8.c: raid6altivec.uc ../unroll.pl
-       $(PERL) ../unroll.pl 8 < raid6altivec.uc > $@
+raid6altivec8.c: raid6altivec.uc ../unroll.awk
+       $(AWK) ../unroll.awk -vN=8 < raid6altivec.uc > $@
 
-raid6int1.c: raid6int.uc ../unroll.pl
-       $(PERL) ../unroll.pl 1 < raid6int.uc > $@
+raid6int1.c: raid6int.uc ../unroll.awk
+       $(AWK) ../unroll.awk -vN=1 < raid6int.uc > $@
 
-raid6int2.c: raid6int.uc ../unroll.pl
-       $(PERL) ../unroll.pl 2 < raid6int.uc > $@
+raid6int2.c: raid6int.uc ../unroll.awk
+       $(AWK) ../unroll.awk -vN=2 < raid6int.uc > $@
 
-raid6int4.c: raid6int.uc ../unroll.pl
-       $(PERL) ../unroll.pl 4 < raid6int.uc > $@
+raid6int4.c: raid6int.uc ../unroll.awk
+       $(AWK) ../unroll.awk -vN=4 < raid6int.uc > $@
 
-raid6int8.c: raid6int.uc ../unroll.pl
-       $(PERL) ../unroll.pl 8 < raid6int.uc > $@
+raid6int8.c: raid6int.uc ../unroll.awk
+       $(AWK) ../unroll.awk -vN=8 < raid6int.uc > $@
 
-raid6int16.c: raid6int.uc ../unroll.pl
-       $(PERL) ../unroll.pl 16 < raid6int.uc > $@
+raid6int16.c: raid6int.uc ../unroll.awk
+       $(AWK) ../unroll.awk -vN=16 < raid6int.uc > $@
 
-raid6int32.c: raid6int.uc ../unroll.pl
-       $(PERL) ../unroll.pl 32 < raid6int.uc > $@
+raid6int32.c: raid6int.uc ../unroll.awk
+       $(AWK) ../unroll.awk -vN=32 < raid6int.uc > $@
 
 raid6tables.c: mktables
        ./mktables > raid6tables.c
diff --git a/drivers/md/unroll.awk b/drivers/md/unroll.awk
new file mode 100644 (file)
index 0000000..c6aa036
--- /dev/null
@@ -0,0 +1,20 @@
+
+# This filter requires one command line option of form -vN=n
+# where n must be a decimal number.
+#
+# Repeat each input line containing $$ n times, replacing $$ with 0...n-1.
+# Replace each $# with n, and each $* with a single $.
+
+BEGIN {
+       n = N + 0
+}
+{
+       if (/\$\$/) { rep = n } else { rep = 1 }
+       for (i = 0; i < rep; ++i) {
+               tmp = $0
+               gsub(/\$\$/, i, tmp)
+               gsub(/\$\#/, n, tmp)
+               gsub(/\$\*/, "$", tmp)
+               print tmp
+       }
+}
diff --git a/drivers/md/unroll.pl b/drivers/md/unroll.pl
deleted file mode 100644 (file)
index 3acc710..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-#!/usr/bin/perl
-#
-# Take a piece of C code and for each line which contains the sequence $$
-# repeat n times with $ replaced by 0...n-1; the sequence $# is replaced
-# by the unrolling factor, and $* with a single $
-#
-
-($n) = @ARGV;
-$n += 0;
-
-while ( defined($line = <STDIN>) ) {
-    if ( $line =~ /\$\$/ ) {
-       $rep = $n;
-    } else {
-       $rep = 1;
-    }
-    for ( $i = 0 ; $i < $rep ; $i++ ) {
-       $tmp = $line;
-       $tmp =~ s/\$\$/$i/g;
-       $tmp =~ s/\$\#/$n/g;
-       $tmp =~ s/\$\*/\$/g;
-       print $tmp;
-    }
-}
index 8c9ae0a..0241a7c 100644 (file)
@@ -63,6 +63,7 @@
 #include <asm/uaccess.h>
 #include <linux/crc32.h>
 #include <linux/mutex.h>
+#include <linux/sched.h>
 
 #include "dvb_demux.h"
 #include "dvb_net.h"
index 4b1bc05..01e1eef 100644 (file)
@@ -28,6 +28,7 @@
  */
 #include <linux/module.h>
 #include <linux/pci.h>
+#include <linux/sched.h>
 #include <linux/init.h>
 #include <linux/videodev.h>
 #include <media/v4l2-common.h>
index f1ccf98..8e93c6f 100644 (file)
@@ -17,6 +17,7 @@
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/mm.h>
+#include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/interrupt.h>
 
index 53cdd67..032ebae 100644 (file)
@@ -21,6 +21,7 @@
 #include <linux/init.h>
 #include <linux/module.h>
 #include <linux/moduleparam.h>
+#include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/interrupt.h>
 
index bc2ec21..34f3f36 100644 (file)
@@ -56,6 +56,7 @@
 #include <linux/init.h>
 #include <linux/module.h>
 #include <linux/fs.h>
+#include <linux/sched.h>
 
 #define my_VERSION     MPT_LINUX_VERSION_COMMON
 #define MYNAM          "mptlan"
index e424cf6..a1c47ee 100644 (file)
@@ -480,7 +480,6 @@ static int
 add_children(struct twl4030_platform_data *pdata, unsigned long features)
 {
        struct device   *child;
-       struct device   *usb_transceiver = NULL;
 
        if (twl_has_bci() && pdata->bci && !(features & TPS_SUBSET)) {
                child = add_child(3, "twl4030_bci",
@@ -532,16 +531,61 @@ add_children(struct twl4030_platform_data *pdata, unsigned long features)
        }
 
        if (twl_has_usb() && pdata->usb) {
+
+               static struct regulator_consumer_supply usb1v5 = {
+                       .supply =       "usb1v5",
+               };
+               static struct regulator_consumer_supply usb1v8 = {
+                       .supply =       "usb1v8",
+               };
+               static struct regulator_consumer_supply usb3v1 = {
+                       .supply =       "usb3v1",
+               };
+
+       /* First add the regulators so that they can be used by transceiver */
+               if (twl_has_regulator()) {
+                       /* this is a template that gets copied */
+                       struct regulator_init_data usb_fixed = {
+                               .constraints.valid_modes_mask =
+                                       REGULATOR_MODE_NORMAL
+                                       | REGULATOR_MODE_STANDBY,
+                               .constraints.valid_ops_mask =
+                                       REGULATOR_CHANGE_MODE
+                                       | REGULATOR_CHANGE_STATUS,
+                       };
+
+                       child = add_regulator_linked(TWL4030_REG_VUSB1V5,
+                                                     &usb_fixed, &usb1v5, 1);
+                       if (IS_ERR(child))
+                               return PTR_ERR(child);
+
+                       child = add_regulator_linked(TWL4030_REG_VUSB1V8,
+                                                     &usb_fixed, &usb1v8, 1);
+                       if (IS_ERR(child))
+                               return PTR_ERR(child);
+
+                       child = add_regulator_linked(TWL4030_REG_VUSB3V1,
+                                                     &usb_fixed, &usb3v1, 1);
+                       if (IS_ERR(child))
+                               return PTR_ERR(child);
+
+               }
+
                child = add_child(0, "twl4030_usb",
                                pdata->usb, sizeof(*pdata->usb),
                                true,
                                /* irq0 = USB_PRES, irq1 = USB */
                                pdata->irq_base + 8 + 2, pdata->irq_base + 4);
+
                if (IS_ERR(child))
                        return PTR_ERR(child);
 
                /* we need to connect regulators to this transceiver */
-               usb_transceiver = child;
+               if (twl_has_regulator() && child) {
+                       usb1v5.dev = child;
+                       usb1v8.dev = child;
+                       usb3v1.dev = child;
+               }
        }
 
        if (twl_has_watchdog()) {
@@ -580,47 +624,6 @@ add_children(struct twl4030_platform_data *pdata, unsigned long features)
                        return PTR_ERR(child);
        }
 
-       if (twl_has_regulator() && usb_transceiver) {
-               static struct regulator_consumer_supply usb1v5 = {
-                       .supply =       "usb1v5",
-               };
-               static struct regulator_consumer_supply usb1v8 = {
-                       .supply =       "usb1v8",
-               };
-               static struct regulator_consumer_supply usb3v1 = {
-                       .supply =       "usb3v1",
-               };
-
-               /* this is a template that gets copied */
-               struct regulator_init_data usb_fixed = {
-                       .constraints.valid_modes_mask =
-                                 REGULATOR_MODE_NORMAL
-                               | REGULATOR_MODE_STANDBY,
-                       .constraints.valid_ops_mask =
-                                 REGULATOR_CHANGE_MODE
-                               | REGULATOR_CHANGE_STATUS,
-               };
-
-               usb1v5.dev = usb_transceiver;
-               usb1v8.dev = usb_transceiver;
-               usb3v1.dev = usb_transceiver;
-
-               child = add_regulator_linked(TWL4030_REG_VUSB1V5, &usb_fixed,
-                               &usb1v5, 1);
-               if (IS_ERR(child))
-                       return PTR_ERR(child);
-
-               child = add_regulator_linked(TWL4030_REG_VUSB1V8, &usb_fixed,
-                               &usb1v8, 1);
-               if (IS_ERR(child))
-                       return PTR_ERR(child);
-
-               child = add_regulator_linked(TWL4030_REG_VUSB3V1, &usb_fixed,
-                               &usb3v1, 1);
-               if (IS_ERR(child))
-                       return PTR_ERR(child);
-       }
-
        /* maybe add LDOs that are omitted on cost-reduced parts */
        if (twl_has_regulator() && !(features & TPS_SUBSET)) {
                child = add_regulator(TWL4030_REG_VPLL2, pdata->vpll2);
@@ -792,7 +795,7 @@ twl4030_probe(struct i2c_client *client, const struct i2c_device_id *id)
                        twl->client = i2c_new_dummy(client->adapter,
                                        twl->address);
                        if (!twl->client) {
-                               dev_err(&twl->client->dev,
+                               dev_err(&client->dev,
                                        "can't attach client %d\n", i);
                                status = -ENOMEM;
                                goto fail;
index fea9085..60c3988 100644 (file)
@@ -18,6 +18,7 @@
  */
 #include <linux/module.h>
 #include <linux/kernel.h>
+#include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/init.h>
 #include <linux/errno.h>
index d3015df..ac056ea 100644 (file)
@@ -507,6 +507,8 @@ int wm831x_irq_init(struct wm831x *wm831x, int irq)
 {
        int i, ret;
 
+       mutex_init(&wm831x->irq_lock);
+
        if (!irq) {
                dev_warn(wm831x->dev,
                         "No interrupt specified - functionality limited\n");
@@ -521,7 +523,6 @@ int wm831x_irq_init(struct wm831x *wm831x, int irq)
        }
 
        wm831x->irq = irq;
-       mutex_init(&wm831x->irq_lock);
        INIT_WORK(&wm831x->irq_work, wm831x_irq_worker);
 
        /* Mask the individual interrupt sources */
index 1ad27c6..a92a3a7 100644 (file)
@@ -18,6 +18,7 @@
 #include <linux/device.h>
 #include <linux/file.h>
 #include <linux/cdev.h>
+#include <linux/sched.h>
 #include <linux/spinlock.h>
 #include <linux/delay.h>
 #include <linux/uaccess.h>
index 276d3fb..e203173 100644 (file)
@@ -22,6 +22,7 @@
  *
  */
 
+#include <linux/sched.h>
 #include "ibmasm.h"
 #include "lowlevel.h"
 
index 68a0a5b..572d41f 100644 (file)
@@ -22,6 +22,7 @@
  *
  */
 
+#include <linux/sched.h>
 #include "ibmasm.h"
 #include "lowlevel.h"
 
index bec9e2c..2de487a 100644 (file)
@@ -20,6 +20,7 @@
  *
  */
 
+#include <linux/sched.h>
 #include "ibmasm.h"
 #include "dot_command.h"
 
index 90a95ce..04c2726 100644 (file)
@@ -22,6 +22,7 @@
 #include <linux/interrupt.h>
 #include <linux/cdev.h>
 #include <linux/phantom.h>
+#include <linux/sched.h>
 #include <linux/smp_lock.h>
 
 #include <asm/atomic.h>
index e1035c8..f85dcd5 100644 (file)
@@ -29,6 +29,8 @@ static int cistpl_vers_1(struct mmc_card *card, struct sdio_func *func,
        unsigned i, nr_strings;
        char **buffer, *string;
 
+       /* Find all null-terminated (including zero length) strings in
+          the TPLLV1_INFO field. Trailing garbage is ignored. */
        buf += 2;
        size -= 2;
 
@@ -39,11 +41,8 @@ static int cistpl_vers_1(struct mmc_card *card, struct sdio_func *func,
                if (buf[i] == 0)
                        nr_strings++;
        }
-
-       if (nr_strings < 4) {
-               printk(KERN_WARNING "SDIO: ignoring broken CISTPL_VERS_1\n");
+       if (nr_strings == 0)
                return 0;
-       }
 
        size = i;
 
index e556d42..63924e0 100644 (file)
@@ -72,7 +72,6 @@
 #include <asm/irq.h>
 #include <asm/gpio.h>
 
-#include <asm/mach/mmc.h>
 #include <mach/board.h>
 #include <mach/cpu.h>
 #include <mach/at91_mci.h>
index 4487cc0..0aecaae 100644 (file)
@@ -2013,7 +2013,7 @@ static struct platform_driver omap_hsmmc_driver = {
 static int __init omap_hsmmc_init(void)
 {
        /* Register the MMC driver */
-       return platform_driver_register(&omap_hsmmc_driver);
+       return platform_driver_probe(&omap_hsmmc_driver, omap_hsmmc_probe);
 }
 
 static void __exit omap_hsmmc_cleanup(void)
index 5e0b152..b00d673 100644 (file)
@@ -693,7 +693,7 @@ static int pxamci_probe(struct platform_device *pdev)
        if (gpio_is_valid(gpio_ro)) {
                ret = gpio_request(gpio_ro, "mmc card read only");
                if (ret) {
-                       dev_err(&pdev->dev, "Failed requesting gpio_ro %d\n", gpio_power);
+                       dev_err(&pdev->dev, "Failed requesting gpio_ro %d\n", gpio_ro);
                        goto err_gpio_ro;
                }
                gpio_direction_input(gpio_ro);
@@ -701,7 +701,7 @@ static int pxamci_probe(struct platform_device *pdev)
        if (gpio_is_valid(gpio_cd)) {
                ret = gpio_request(gpio_cd, "mmc card detect");
                if (ret) {
-                       dev_err(&pdev->dev, "Failed requesting gpio_cd %d\n", gpio_power);
+                       dev_err(&pdev->dev, "Failed requesting gpio_cd %d\n", gpio_cd);
                        goto err_gpio_cd;
                }
                gpio_direction_input(gpio_cd);
index 379c316..4c19269 100644 (file)
@@ -21,6 +21,7 @@
 #include <linux/interrupt.h>
 #include <linux/mutex.h>
 #include <linux/math64.h>
+#include <linux/sched.h>
 
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/partitions.h>
index c2baf33..0a11721 100644 (file)
@@ -20,6 +20,7 @@
 #include <linux/device.h>
 #include <linux/mutex.h>
 #include <linux/interrupt.h>
+#include <linux/sched.h>
 
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/partitions.h>
index e1f7d0a..14cec04 100644 (file)
@@ -42,6 +42,7 @@
 #include <linux/log2.h>
 #include <linux/kthread.h>
 #include <linux/reboot.h>
+#include <linux/kernel.h>
 #include "ubi.h"
 
 /* Maximum length of the 'mtd=' parameter */
@@ -1257,7 +1258,7 @@ static int __init bytes_str_to_int(const char *str)
        unsigned long result;
 
        result = simple_strtoul(str, &endp, 0);
-       if (str == endp || result < 0) {
+       if (str == endp || result >= INT_MAX) {
                printk(KERN_ERR "UBI error: incorrect bytes count: \"%s\"\n",
                       str);
                return -EINVAL;
index e7161ad..90af61a 100644 (file)
@@ -794,16 +794,15 @@ static int process_eb(struct ubi_device *ubi, struct ubi_scan_info *si,
                 * number.
                 */
                image_seq = be32_to_cpu(ech->image_seq);
-               if (!si->image_seq_set) {
+               if (!ubi->image_seq && image_seq)
                        ubi->image_seq = image_seq;
-                       si->image_seq_set = 1;
-               } else if (ubi->image_seq && ubi->image_seq != image_seq) {
+               if (ubi->image_seq && image_seq &&
+                   ubi->image_seq != image_seq) {
                        ubi_err("bad image sequence number %d in PEB %d, "
                                "expected %d", image_seq, pnum, ubi->image_seq);
                        ubi_dbg_dump_ec_hdr(ech);
                        return -EINVAL;
                }
-
        }
 
        /* OK, we've done with the EC header, let's look at the VID header */
index bab3169..ff179ad 100644 (file)
@@ -103,7 +103,6 @@ struct ubi_scan_volume {
  * @ec_sum: a temporary variable used when calculating @mean_ec
  * @ec_count: a temporary variable used when calculating @mean_ec
  * @corr_count: count of corrupted PEBs
- * @image_seq_set: indicates @ubi->image_seq is known
  *
  * This data structure contains the result of scanning and may be used by other
  * UBI sub-systems to build final UBI data structures, further error-recovery
@@ -127,7 +126,6 @@ struct ubi_scan_info {
        uint64_t ec_sum;
        int ec_count;
        int corr_count;
-       int image_seq_set;
 };
 
 struct ubi_device;
index 7127760..e19ca4b 100644 (file)
@@ -1741,6 +1741,7 @@ config KS8851
 config KS8851_MLL
        tristate "Micrel KS8851 MLL"
        depends on HAS_IOMEM
+       select MII
        help
          This platform driver is for Micrel KS8851 Address/data bus
          multiplexed network chip.
@@ -2482,6 +2483,8 @@ config S6GMAC
          To compile this driver as a module, choose M here. The module
          will be called s6gmac.
 
+source "drivers/net/stmmac/Kconfig"
+
 endif # NETDEV_1000
 
 #
@@ -3230,4 +3233,12 @@ config VIRTIO_NET
          This is the virtual network driver for virtio.  It can be used with
           lguest or QEMU based VMMs (like KVM or Xen).  Say Y or M.
 
+config VMXNET3
+       tristate "VMware VMXNET3 ethernet driver"
+       depends on PCI && X86 && INET
+       help
+         This driver supports VMware's vmxnet3 virtual ethernet NIC.
+         To compile this driver as a module, choose M here: the
+         module will be called vmxnet3.
+
 endif # NETDEVICES
index d866b8c..246323d 100644 (file)
@@ -2,6 +2,10 @@
 # Makefile for the Linux network (ethercard) device drivers.
 #
 
+obj-$(CONFIG_MII) += mii.o
+obj-$(CONFIG_MDIO) += mdio.o
+obj-$(CONFIG_PHYLIB) += phy/
+
 obj-$(CONFIG_TI_DAVINCI_EMAC) += davinci_emac.o
 
 obj-$(CONFIG_E1000) += e1000/
@@ -26,6 +30,7 @@ obj-$(CONFIG_TEHUTI) += tehuti.o
 obj-$(CONFIG_ENIC) += enic/
 obj-$(CONFIG_JME) += jme.o
 obj-$(CONFIG_BE2NET) += benet/
+obj-$(CONFIG_VMXNET3) += vmxnet3/
 
 gianfar_driver-objs := gianfar.o \
                gianfar_ethtool.o \
@@ -95,15 +100,12 @@ obj-$(CONFIG_VIA_VELOCITY) += via-velocity.o
 obj-$(CONFIG_ADAPTEC_STARFIRE) += starfire.o
 obj-$(CONFIG_RIONET) += rionet.o
 obj-$(CONFIG_SH_ETH) += sh_eth.o
+obj-$(CONFIG_STMMAC_ETH) += stmmac/
 
 #
 # end link order section
 #
 
-obj-$(CONFIG_MII) += mii.o
-obj-$(CONFIG_MDIO) += mdio.o
-obj-$(CONFIG_PHYLIB) += phy/
-
 obj-$(CONFIG_SUNDANCE) += sundance.o
 obj-$(CONFIG_HAMACHI) += hamachi.o
 obj-$(CONFIG_NET) += Space.o loopback.o
index 5f0b05c..d82a9a9 100644 (file)
@@ -1209,7 +1209,8 @@ static int __devinit ace_init(struct net_device *dev)
        memset(ap->info, 0, sizeof(struct ace_info));
        memset(ap->skb, 0, sizeof(struct ace_skb));
 
-       if (ace_load_firmware(dev))
+       ecode = ace_load_firmware(dev);
+       if (ecode)
                goto init_error;
 
        ap->fw_running = 0;
index fdf5937..ce6f1ac 100644 (file)
@@ -34,6 +34,7 @@
  *
  *
  */
+#include <linux/capability.h>
 #include <linux/dma-mapping.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
@@ -721,7 +722,7 @@ static inline void update_rx_stats(struct net_device *dev, u32 status)
                ps->rx_errors++;
                if (status & RX_MISSED_FRAME)
                        ps->rx_missed_errors++;
-               if (status & (RX_OVERLEN | RX_OVERLEN | RX_LEN_ERROR))
+               if (status & (RX_OVERLEN | RX_RUNT | RX_LEN_ERROR))
                        ps->rx_length_errors++;
                if (status & RX_CRC_ERROR)
                        ps->rx_crc_errors++;
@@ -794,8 +795,6 @@ static int au1000_rx(struct net_device *dev)
                                        printk("rx len error\n");
                                if (status & RX_U_CNTRL_FRAME)
                                        printk("rx u control frame\n");
-                               if (status & RX_MISSED_FRAME)
-                                       printk("rx miss\n");
                        }
                }
                prxd->buff_stat = (u32)(pDB->dma_addr | RX_DMA_ENABLE);
index 79d35d1..28a0eda 100644 (file)
@@ -243,15 +243,26 @@ static int be_POST_stage_get(struct be_adapter *adapter, u16 *stage)
 
 int be_cmd_POST(struct be_adapter *adapter)
 {
-       u16 stage, error;
+       u16 stage;
+       int status, timeout = 0;
 
-       error = be_POST_stage_get(adapter, &stage);
-       if (error || stage != POST_STAGE_ARMFW_RDY) {
-               dev_err(&adapter->pdev->dev, "POST failed.\n");
-               return -1;
-       }
+       do {
+               status = be_POST_stage_get(adapter, &stage);
+               if (status) {
+                       dev_err(&adapter->pdev->dev, "POST error; stage=0x%x\n",
+                               stage);
+                       return -1;
+               } else if (stage != POST_STAGE_ARMFW_RDY) {
+                       set_current_state(TASK_INTERRUPTIBLE);
+                       schedule_timeout(2 * HZ);
+                       timeout += 2;
+               } else {
+                       return 0;
+               }
+       } while (timeout < 20);
 
-       return 0;
+       dev_err(&adapter->pdev->dev, "POST timeout; stage=0x%x\n", stage);
+       return -1;
 }
 
 static inline void *embedded_payload(struct be_mcc_wrb *wrb)
@@ -729,8 +740,8 @@ int be_cmd_q_destroy(struct be_adapter *adapter, struct be_queue_info *q,
 /* Create an rx filtering policy configuration on an i/f
  * Uses mbox
  */
-int be_cmd_if_create(struct be_adapter *adapter, u32 flags, u8 *mac,
-               bool pmac_invalid, u32 *if_handle, u32 *pmac_id)
+int be_cmd_if_create(struct be_adapter *adapter, u32 cap_flags, u32 en_flags,
+               u8 *mac, bool pmac_invalid, u32 *if_handle, u32 *pmac_id)
 {
        struct be_mcc_wrb *wrb;
        struct be_cmd_req_if_create *req;
@@ -746,8 +757,8 @@ int be_cmd_if_create(struct be_adapter *adapter, u32 flags, u8 *mac,
        be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
                OPCODE_COMMON_NTWK_INTERFACE_CREATE, sizeof(*req));
 
-       req->capability_flags = cpu_to_le32(flags);
-       req->enable_flags = cpu_to_le32(flags);
+       req->capability_flags = cpu_to_le32(cap_flags);
+       req->enable_flags = cpu_to_le32(en_flags);
        req->pmac_invalid = pmac_invalid;
        if (!pmac_invalid)
                memcpy(req->mac_addr, mac, ETH_ALEN);
@@ -1129,7 +1140,6 @@ int be_cmd_write_flashrom(struct be_adapter *adapter, struct be_dma_mem *cmd,
        spin_lock_bh(&adapter->mcc_lock);
 
        wrb = wrb_from_mccq(adapter);
-       req = embedded_payload(wrb);
        sge = nonembedded_sgl(wrb);
 
        be_wrb_hdr_prepare(wrb, cmd->size, false, 1);
index 8b4c2cb..4995378 100644 (file)
@@ -62,7 +62,7 @@ enum {
        MCC_STATUS_QUEUE_FLUSHING = 0x4,
 /* The command is completing with a DMA error */
        MCC_STATUS_DMA_FAILED = 0x5,
-       MCC_STATUS_NOT_SUPPORTED = 0x66
+       MCC_STATUS_NOT_SUPPORTED = 66
 };
 
 #define CQE_STATUS_COMPL_MASK          0xFFFF
@@ -720,8 +720,9 @@ extern int be_cmd_mac_addr_query(struct be_adapter *adapter, u8 *mac_addr,
 extern int be_cmd_pmac_add(struct be_adapter *adapter, u8 *mac_addr,
                        u32 if_id, u32 *pmac_id);
 extern int be_cmd_pmac_del(struct be_adapter *adapter, u32 if_id, u32 pmac_id);
-extern int be_cmd_if_create(struct be_adapter *adapter, u32 if_flags, u8 *mac,
-                       bool pmac_invalid, u32 *if_handle, u32 *pmac_id);
+extern int be_cmd_if_create(struct be_adapter *adapter, u32 cap_flags,
+                       u32 en_flags, u8 *mac, bool pmac_invalid,
+                       u32 *if_handle, u32 *pmac_id);
 extern int be_cmd_if_destroy(struct be_adapter *adapter, u32 if_handle);
 extern int be_cmd_eq_create(struct be_adapter *adapter,
                        struct be_queue_info *eq, int eq_delay);
index 11445df..cda5bf2 100644 (file)
@@ -358,7 +358,7 @@ const struct ethtool_ops be_ethtool_ops = {
        .get_rx_csum = be_get_rx_csum,
        .set_rx_csum = be_set_rx_csum,
        .get_tx_csum = ethtool_op_get_tx_csum,
-       .set_tx_csum = ethtool_op_set_tx_csum,
+       .set_tx_csum = ethtool_op_set_tx_hw_csum,
        .get_sg = ethtool_op_get_sg,
        .set_sg = ethtool_op_set_sg,
        .get_tso = ethtool_op_get_tso,
index 2f9b501..1f941f0 100644 (file)
@@ -197,7 +197,7 @@ void netdev_stats_update(struct be_adapter *adapter)
        /* no space available in linux */
        dev_stats->tx_dropped = 0;
 
-       dev_stats->multicast = port_stats->tx_multicastframes;
+       dev_stats->multicast = port_stats->rx_multicast_frames;
        dev_stats->collisions = 0;
 
        /* detailed tx_errors */
@@ -1620,19 +1620,22 @@ static int be_open(struct net_device *netdev)
 static int be_setup(struct be_adapter *adapter)
 {
        struct net_device *netdev = adapter->netdev;
-       u32 if_flags;
+       u32 cap_flags, en_flags;
        int status;
 
-       if_flags = BE_IF_FLAGS_BROADCAST | BE_IF_FLAGS_PROMISCUOUS |
-               BE_IF_FLAGS_MCAST_PROMISCUOUS | BE_IF_FLAGS_UNTAGGED |
-               BE_IF_FLAGS_PASS_L3L4_ERRORS;
-       status = be_cmd_if_create(adapter, if_flags, netdev->dev_addr,
-                       false/* pmac_invalid */, &adapter->if_handle,
-                       &adapter->pmac_id);
+       cap_flags = BE_IF_FLAGS_UNTAGGED | BE_IF_FLAGS_BROADCAST |
+                       BE_IF_FLAGS_MCAST_PROMISCUOUS |
+                       BE_IF_FLAGS_PROMISCUOUS |
+                       BE_IF_FLAGS_PASS_L3L4_ERRORS;
+       en_flags = BE_IF_FLAGS_UNTAGGED | BE_IF_FLAGS_BROADCAST |
+                       BE_IF_FLAGS_PASS_L3L4_ERRORS;
+
+       status = be_cmd_if_create(adapter, cap_flags, en_flags,
+                       netdev->dev_addr, false/* pmac_invalid */,
+                       &adapter->if_handle, &adapter->pmac_id);
        if (status != 0)
                goto do_none;
 
-
        status = be_tx_queues_create(adapter);
        if (status != 0)
                goto if_destroy;
@@ -1899,8 +1902,8 @@ static void be_netdev_init(struct net_device *netdev)
        struct be_adapter *adapter = netdev_priv(netdev);
 
        netdev->features |= NETIF_F_SG | NETIF_F_HW_VLAN_RX | NETIF_F_TSO |
-               NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_FILTER | NETIF_F_IP_CSUM |
-               NETIF_F_IPV6_CSUM | NETIF_F_GRO;
+               NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_FILTER | NETIF_F_HW_CSUM |
+               NETIF_F_GRO;
 
        netdev->flags |= IFF_MULTICAST;
 
@@ -2055,6 +2058,10 @@ static int be_hw_up(struct be_adapter *adapter)
        if (status)
                return status;
 
+       status = be_cmd_reset_function(adapter);
+       if (status)
+               return status;
+
        status = be_cmd_get_fw_ver(adapter, adapter->fw_ver);
        if (status)
                return status;
@@ -2108,10 +2115,6 @@ static int __devinit be_probe(struct pci_dev *pdev,
        if (status)
                goto free_netdev;
 
-       status = be_cmd_reset_function(adapter);
-       if (status)
-               goto ctrl_clean;
-
        status = be_stats_init(adapter);
        if (status)
                goto ctrl_clean;
index 6c7f795..a4d8340 100644 (file)
@@ -361,9 +361,12 @@ struct l2_fhdr {
 #define BNX2_L2CTX_CTX_TYPE_CTX_BD_CHN_TYPE_VALUE       (1<<28)
 
 #define BNX2_L2CTX_HOST_BDIDX                          0x00000004
-#define BNX2_L2CTX_STATUSB_NUM_SHIFT                    16
-#define BNX2_L2CTX_STATUSB_NUM(sb_id)                   \
-       (((sb_id) > 0) ? (((sb_id) + 7) << BNX2_L2CTX_STATUSB_NUM_SHIFT) : 0)
+#define BNX2_L2CTX_L5_STATUSB_NUM_SHIFT                         16
+#define BNX2_L2CTX_L2_STATUSB_NUM_SHIFT                         24
+#define BNX2_L2CTX_L5_STATUSB_NUM(sb_id)               \
+       (((sb_id) > 0) ? (((sb_id) + 7) << BNX2_L2CTX_L5_STATUSB_NUM_SHIFT) : 0)
+#define BNX2_L2CTX_L2_STATUSB_NUM(sb_id)               \
+       (((sb_id) > 0) ? (((sb_id) + 7) << BNX2_L2CTX_L2_STATUSB_NUM_SHIFT) : 0)
 #define BNX2_L2CTX_HOST_BSEQ                           0x00000008
 #define BNX2_L2CTX_NX_BSEQ                             0x0000000c
 #define BNX2_L2CTX_NX_BDHADDR_HI                       0x00000010
index 69c5b15..40fb5ee 100644 (file)
@@ -691,7 +691,7 @@ static int bond_check_dev_link(struct bonding *bond,
                               struct net_device *slave_dev, int reporting)
 {
        const struct net_device_ops *slave_ops = slave_dev->netdev_ops;
-       static int (*ioctl)(struct net_device *, struct ifreq *, int);
+       int (*ioctl)(struct net_device *, struct ifreq *, int);
        struct ifreq ifr;
        struct mii_ioctl_data *mii;
 
@@ -3665,10 +3665,10 @@ static int bond_xmit_hash_policy_l23(struct sk_buff *skb,
 
        if (skb->protocol == htons(ETH_P_IP)) {
                return ((ntohl(iph->saddr ^ iph->daddr) & 0xffff) ^
-                       (data->h_dest[5] ^ bond_dev->dev_addr[5])) % count;
+                       (data->h_dest[5] ^ data->h_source[5])) % count;
        }
 
-       return (data->h_dest[5] ^ bond_dev->dev_addr[5]) % count;
+       return (data->h_dest[5] ^ data->h_source[5]) % count;
 }
 
 /*
@@ -3695,7 +3695,7 @@ static int bond_xmit_hash_policy_l34(struct sk_buff *skb,
 
        }
 
-       return (data->h_dest[5] ^ bond_dev->dev_addr[5]) % count;
+       return (data->h_dest[5] ^ data->h_source[5]) % count;
 }
 
 /*
@@ -3706,7 +3706,7 @@ static int bond_xmit_hash_policy_l2(struct sk_buff *skb,
 {
        struct ethhdr *data = (struct ethhdr *)skb->data;
 
-       return (data->h_dest[5] ^ bond_dev->dev_addr[5]) % count;
+       return (data->h_dest[5] ^ data->h_source[5]) % count;
 }
 
 /*-------------------------- Device entry points ----------------------------*/
index ff449de..8762a27 100644 (file)
@@ -22,6 +22,7 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/device.h>
+#include <linux/sched.h>
 #include <linux/sysdev.h>
 #include <linux/fs.h>
 #include <linux/types.h>
index 3373560..9dd076a 100644 (file)
@@ -213,6 +213,7 @@ static struct of_device_id __devinitdata sja1000_ofp_table[] = {
        {.compatible = "nxp,sja1000"},
        {},
 };
+MODULE_DEVICE_TABLE(of, sja1000_ofp_table);
 
 static struct of_platform_driver sja1000_ofp_driver = {
        .owner = THIS_MODULE,
index 46c87ec..3bf1b04 100644 (file)
@@ -2264,9 +2264,9 @@ static void cnic_init_bnx2_rx_ring(struct cnic_dev *dev)
        cnic_ctx_wr(dev, cid_addr, BNX2_L2CTX_CTX_TYPE, val);
 
        if (sb_id == 0)
-               val = 2 << BNX2_L2CTX_STATUSB_NUM_SHIFT;
+               val = 2 << BNX2_L2CTX_L2_STATUSB_NUM_SHIFT;
        else
-               val = BNX2_L2CTX_STATUSB_NUM(sb_id);
+               val = BNX2_L2CTX_L2_STATUSB_NUM(sb_id);
        cnic_ctx_wr(dev, cid_addr, BNX2_L2CTX_HOST_BDIDX, val);
 
        rxbd = (struct rx_bd *) (cp->l2_ring + BCM_PAGE_SIZE);
@@ -2423,7 +2423,7 @@ static int cnic_start_bnx2_hw(struct cnic_dev *dev)
        cp->int_num = 0;
        if (ethdev->drv_state & CNIC_DRV_STATE_USING_MSIX) {
                u32 sb_id = cp->status_blk_num;
-               u32 sb = BNX2_L2CTX_STATUSB_NUM(sb_id);
+               u32 sb = BNX2_L2CTX_L5_STATUSB_NUM(sb_id);
 
                cp->int_num = sb_id << BNX2_PCICFG_INT_ACK_CMD_INT_NUM_SHIFT;
                cnic_ctx_wr(dev, cp->kwq_cid_addr, L5_KRNLQ_HOST_QIDX, sb);
index 65a2d0b..f72c56d 100644 (file)
@@ -333,6 +333,9 @@ static const char emac_version_string[] = "TI DaVinci EMAC Linux v6.1";
 #define EMAC_DM646X_MAC_EOI_C0_RXEN    (0x01)
 #define EMAC_DM646X_MAC_EOI_C0_TXEN    (0x02)
 
+/* EMAC Stats Clear Mask */
+#define EMAC_STATS_CLR_MASK    (0xFFFFFFFF)
+
 /** net_buf_obj: EMAC network bufferdata structure
  *
  * EMAC network buffer data structure
@@ -2548,40 +2551,49 @@ static int emac_dev_stop(struct net_device *ndev)
 static struct net_device_stats *emac_dev_getnetstats(struct net_device *ndev)
 {
        struct emac_priv *priv = netdev_priv(ndev);
+       u32 mac_control;
+       u32 stats_clear_mask;
 
        /* update emac hardware stats and reset the registers*/
 
+       mac_control = emac_read(EMAC_MACCONTROL);
+
+       if (mac_control & EMAC_MACCONTROL_GMIIEN)
+               stats_clear_mask = EMAC_STATS_CLR_MASK;
+       else
+               stats_clear_mask = 0;
+
        priv->net_dev_stats.multicast += emac_read(EMAC_RXMCASTFRAMES);
-       emac_write(EMAC_RXMCASTFRAMES, EMAC_ALL_MULTI_REG_VALUE);
+       emac_write(EMAC_RXMCASTFRAMES, stats_clear_mask);
 
        priv->net_dev_stats.collisions += (emac_read(EMAC_TXCOLLISION) +
                                           emac_read(EMAC_TXSINGLECOLL) +
                                           emac_read(EMAC_TXMULTICOLL));
-       emac_write(EMAC_TXCOLLISION, EMAC_ALL_MULTI_REG_VALUE);
-       emac_write(EMAC_TXSINGLECOLL, EMAC_ALL_MULTI_REG_VALUE);
-       emac_write(EMAC_TXMULTICOLL, EMAC_ALL_MULTI_REG_VALUE);
+       emac_write(EMAC_TXCOLLISION, stats_clear_mask);
+       emac_write(EMAC_TXSINGLECOLL, stats_clear_mask);
+       emac_write(EMAC_TXMULTICOLL, stats_clear_mask);
 
        priv->net_dev_stats.rx_length_errors += (emac_read(EMAC_RXOVERSIZED) +
                                                emac_read(EMAC_RXJABBER) +
                                                emac_read(EMAC_RXUNDERSIZED));
-       emac_write(EMAC_RXOVERSIZED, EMAC_ALL_MULTI_REG_VALUE);
-       emac_write(EMAC_RXJABBER, EMAC_ALL_MULTI_REG_VALUE);
-       emac_write(EMAC_RXUNDERSIZED, EMAC_ALL_MULTI_REG_VALUE);
+       emac_write(EMAC_RXOVERSIZED, stats_clear_mask);
+       emac_write(EMAC_RXJABBER, stats_clear_mask);
+       emac_write(EMAC_RXUNDERSIZED, stats_clear_mask);
 
        priv->net_dev_stats.rx_over_errors += (emac_read(EMAC_RXSOFOVERRUNS) +
                                               emac_read(EMAC_RXMOFOVERRUNS));
-       emac_write(EMAC_RXSOFOVERRUNS, EMAC_ALL_MULTI_REG_VALUE);
-       emac_write(EMAC_RXMOFOVERRUNS, EMAC_ALL_MULTI_REG_VALUE);
+       emac_write(EMAC_RXSOFOVERRUNS, stats_clear_mask);
+       emac_write(EMAC_RXMOFOVERRUNS, stats_clear_mask);
 
        priv->net_dev_stats.rx_fifo_errors += emac_read(EMAC_RXDMAOVERRUNS);
-       emac_write(EMAC_RXDMAOVERRUNS, EMAC_ALL_MULTI_REG_VALUE);
+       emac_write(EMAC_RXDMAOVERRUNS, stats_clear_mask);
 
        priv->net_dev_stats.tx_carrier_errors +=
                emac_read(EMAC_TXCARRIERSENSE);
-       emac_write(EMAC_TXCARRIERSENSE, EMAC_ALL_MULTI_REG_VALUE);
+       emac_write(EMAC_TXCARRIERSENSE, stats_clear_mask);
 
        priv->net_dev_stats.tx_fifo_errors = emac_read(EMAC_TXUNDERRUN);
-       emac_write(EMAC_TXUNDERRUN, EMAC_ALL_MULTI_REG_VALUE);
+       emac_write(EMAC_TXUNDERRUN, stats_clear_mask);
 
        return &priv->net_dev_stats;
 }
index 9686c1f..7a3bdac 100644 (file)
 
 #include <linux/module.h>
 #include <linux/kernel.h>
+#include <linux/sched.h>
 #include <linux/string.h>
 #include <linux/errno.h>
 #include <linux/ioport.h>
index 80817c2..fb1c924 100644 (file)
@@ -50,7 +50,7 @@
 #define DM9000_RCSR           0x32
 
 #define CHIPR_DM9000A         0x19
-#define CHIPR_DM9000B         0x1B
+#define CHIPR_DM9000B         0x1A
 
 #define DM9000_MRCMDX          0xF0
 #define DM9000_MRCMD           0xF2
index 679965c..3c29a20 100644 (file)
 #include <linux/moduleparam.h>
 #include <linux/kernel.h>
 #include <linux/types.h>
+#include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/delay.h>
 #include <linux/init.h>
@@ -1426,19 +1427,31 @@ static int e100_phy_init(struct nic *nic)
        } else
                DPRINTK(HW, DEBUG, "phy_addr = %d\n", nic->mii.phy_id);
 
-       /* Isolate all the PHY ids */
-       for (addr = 0; addr < 32; addr++)
-               mdio_write(netdev, addr, MII_BMCR, BMCR_ISOLATE);
-       /* Select the discovered PHY */
-       bmcr &= ~BMCR_ISOLATE;
-       mdio_write(netdev, nic->mii.phy_id, MII_BMCR, bmcr);
-
        /* Get phy ID */
        id_lo = mdio_read(netdev, nic->mii.phy_id, MII_PHYSID1);
        id_hi = mdio_read(netdev, nic->mii.phy_id, MII_PHYSID2);
        nic->phy = (u32)id_hi << 16 | (u32)id_lo;
        DPRINTK(HW, DEBUG, "phy ID = 0x%08X\n", nic->phy);
 
+       /* Select the phy and isolate the rest */
+       for (addr = 0; addr < 32; addr++) {
+               if (addr != nic->mii.phy_id) {
+                       mdio_write(netdev, addr, MII_BMCR, BMCR_ISOLATE);
+               } else if (nic->phy != phy_82552_v) {
+                       bmcr = mdio_read(netdev, addr, MII_BMCR);
+                       mdio_write(netdev, addr, MII_BMCR,
+                               bmcr & ~BMCR_ISOLATE);
+               }
+       }
+       /*
+        * Workaround for 82552:
+        * Clear the ISOLATE bit on selected phy_id last (mirrored on all
+        * other phy_id's) using bmcr value from addr discovery loop above.
+        */
+       if (nic->phy == phy_82552_v)
+               mdio_write(netdev, nic->mii.phy_id, MII_BMCR,
+                       bmcr & ~BMCR_ISOLATE);
+
        /* Handle National tx phys */
 #define NCS_PHY_MODEL_MASK     0xFFF0FFFF
        if ((nic->phy & NCS_PHY_MODEL_MASK) == phy_nsc_tx) {
index b53b40b..d1e0563 100644 (file)
@@ -1803,7 +1803,7 @@ struct e1000_info e1000_82574_info = {
                                  | FLAG_HAS_AMT
                                  | FLAG_HAS_CTRLEXT_ON_LOAD,
        .pba                    = 20,
-       .max_hw_frame_size      = ETH_FRAME_LEN + ETH_FCS_LEN,
+       .max_hw_frame_size      = DEFAULT_JUMBO,
        .get_variants           = e1000_get_variants_82571,
        .mac_ops                = &e82571_mac_ops,
        .phy_ops                = &e82_phy_ops_bm,
@@ -1820,7 +1820,7 @@ struct e1000_info e1000_82583_info = {
                                  | FLAG_HAS_AMT
                                  | FLAG_HAS_CTRLEXT_ON_LOAD,
        .pba                    = 20,
-       .max_hw_frame_size      = DEFAULT_JUMBO,
+       .max_hw_frame_size      = ETH_FRAME_LEN + ETH_FCS_LEN,
        .get_variants           = e1000_get_variants_82571,
        .mac_ops                = &e82571_mac_ops,
        .phy_ops                = &e82_phy_ops_bm,
index c0f185b..1190167 100644 (file)
@@ -76,6 +76,7 @@
 /* Extended Device Control */
 #define E1000_CTRL_EXT_SDP7_DATA 0x00000080 /* Value of SW Definable Pin 7 */
 #define E1000_CTRL_EXT_EE_RST    0x00002000 /* Reinitialize from EEPROM */
+#define E1000_CTRL_EXT_SPD_BYPS  0x00008000 /* Speed Select Bypass */
 #define E1000_CTRL_EXT_RO_DIS    0x00020000 /* Relaxed Ordering disable */
 #define E1000_CTRL_EXT_DMA_DYN_CLK_EN 0x00080000 /* DMA Dynamic Clock Gating */
 #define E1000_CTRL_EXT_LINK_MODE_MASK 0x00C00000
 /* Extended Configuration Control and Size */
 #define E1000_EXTCNF_CTRL_MDIO_SW_OWNERSHIP      0x00000020
 #define E1000_EXTCNF_CTRL_LCD_WRITE_ENABLE       0x00000001
+#define E1000_EXTCNF_CTRL_OEM_WRITE_ENABLE       0x00000008
 #define E1000_EXTCNF_CTRL_SWFLAG                 0x00000020
 #define E1000_EXTCNF_SIZE_EXT_PCIE_LENGTH_MASK   0x00FF0000
 #define E1000_EXTCNF_SIZE_EXT_PCIE_LENGTH_SHIFT          16
index 981936c..189dfa2 100644 (file)
@@ -141,6 +141,20 @@ struct e1000_info;
 #define HV_TNCRS_UPPER         PHY_REG(778, 29) /* Transmit with no CRS */
 #define HV_TNCRS_LOWER         PHY_REG(778, 30)
 
+/* BM PHY Copper Specific Status */
+#define BM_CS_STATUS                      17
+#define BM_CS_STATUS_LINK_UP              0x0400
+#define BM_CS_STATUS_RESOLVED             0x0800
+#define BM_CS_STATUS_SPEED_MASK           0xC000
+#define BM_CS_STATUS_SPEED_1000           0x8000
+
+/* 82577 Mobile Phy Status Register */
+#define HV_M_STATUS                       26
+#define HV_M_STATUS_AUTONEG_COMPLETE      0x1000
+#define HV_M_STATUS_SPEED_MASK            0x0300
+#define HV_M_STATUS_SPEED_1000            0x0200
+#define HV_M_STATUS_LINK_UP               0x0040
+
 enum e1000_boards {
        board_82571,
        board_82572,
@@ -519,9 +533,13 @@ extern s32 e1000e_phy_force_speed_duplex_igp(struct e1000_hw *hw);
 extern s32 e1000e_get_cable_length_igp_2(struct e1000_hw *hw);
 extern s32 e1000e_get_phy_info_igp(struct e1000_hw *hw);
 extern s32 e1000e_read_phy_reg_igp(struct e1000_hw *hw, u32 offset, u16 *data);
+extern s32 e1000e_read_phy_reg_igp_locked(struct e1000_hw *hw, u32 offset,
+                                          u16 *data);
 extern s32 e1000e_phy_hw_reset_generic(struct e1000_hw *hw);
 extern s32 e1000e_set_d3_lplu_state(struct e1000_hw *hw, bool active);
 extern s32 e1000e_write_phy_reg_igp(struct e1000_hw *hw, u32 offset, u16 data);
+extern s32 e1000e_write_phy_reg_igp_locked(struct e1000_hw *hw, u32 offset,
+                                           u16 data);
 extern s32 e1000e_phy_sw_reset(struct e1000_hw *hw);
 extern s32 e1000e_phy_force_speed_duplex_m88(struct e1000_hw *hw);
 extern s32 e1000e_get_cfg_done(struct e1000_hw *hw);
@@ -538,7 +556,11 @@ extern s32 e1000e_read_phy_reg_bm2(struct e1000_hw *hw, u32 offset, u16 *data);
 extern s32 e1000e_write_phy_reg_bm2(struct e1000_hw *hw, u32 offset, u16 data);
 extern void e1000e_phy_force_speed_duplex_setup(struct e1000_hw *hw, u16 *phy_ctrl);
 extern s32 e1000e_write_kmrn_reg(struct e1000_hw *hw, u32 offset, u16 data);
+extern s32 e1000e_write_kmrn_reg_locked(struct e1000_hw *hw, u32 offset,
+                                        u16 data);
 extern s32 e1000e_read_kmrn_reg(struct e1000_hw *hw, u32 offset, u16 *data);
+extern s32 e1000e_read_kmrn_reg_locked(struct e1000_hw *hw, u32 offset,
+                                       u16 *data);
 extern s32 e1000e_phy_has_link_generic(struct e1000_hw *hw, u32 iterations,
                               u32 usec_interval, bool *success);
 extern s32 e1000e_phy_reset_dsp(struct e1000_hw *hw);
@@ -546,7 +568,11 @@ extern s32 e1000e_read_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 *data);
 extern s32 e1000e_write_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 data);
 extern s32 e1000e_check_downshift(struct e1000_hw *hw);
 extern s32 e1000_read_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 *data);
+extern s32 e1000_read_phy_reg_hv_locked(struct e1000_hw *hw, u32 offset,
+                                        u16 *data);
 extern s32 e1000_write_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 data);
+extern s32 e1000_write_phy_reg_hv_locked(struct e1000_hw *hw, u32 offset,
+                                         u16 data);
 extern s32 e1000_set_mdio_slow_mode_hv(struct e1000_hw *hw, bool slow);
 extern s32 e1000_link_stall_workaround_hv(struct e1000_hw *hw);
 extern s32 e1000_copper_link_setup_82577(struct e1000_hw *hw);
index fd44d9f..aaea41e 100644 (file)
@@ -764,11 +764,13 @@ struct e1000_phy_operations {
        s32  (*get_cable_length)(struct e1000_hw *);
        s32  (*get_phy_info)(struct e1000_hw *);
        s32  (*read_phy_reg)(struct e1000_hw *, u32, u16 *);
+       s32  (*read_phy_reg_locked)(struct e1000_hw *, u32, u16 *);
        void (*release_phy)(struct e1000_hw *);
        s32  (*reset_phy)(struct e1000_hw *);
        s32  (*set_d0_lplu_state)(struct e1000_hw *, bool);
        s32  (*set_d3_lplu_state)(struct e1000_hw *, bool);
        s32  (*write_phy_reg)(struct e1000_hw *, u32, u16);
+       s32  (*write_phy_reg_locked)(struct e1000_hw *, u32, u16);
        s32  (*cfg_on_link_up)(struct e1000_hw *);
 };
 
@@ -901,6 +903,7 @@ struct e1000_shadow_ram {
 struct e1000_dev_spec_ich8lan {
        bool kmrn_lock_loss_workaround_enabled;
        struct e1000_shadow_ram shadow_ram[E1000_ICH8_SHADOW_RAM_WORDS];
+       bool nvm_k1_enabled;
 };
 
 struct e1000_hw {
index 99df2ab..51ddb04 100644 (file)
 
 #define HV_LED_CONFIG          PHY_REG(768, 30) /* LED Configuration */
 
+#define SW_FLAG_TIMEOUT    1000 /* SW Semaphore flag timeout in milliseconds */
+
+/* SMBus Address Phy Register */
+#define HV_SMB_ADDR            PHY_REG(768, 26)
+#define HV_SMB_ADDR_PEC_EN     0x0200
+#define HV_SMB_ADDR_VALID      0x0080
+
+/* Strapping Option Register - RO */
+#define E1000_STRAP                     0x0000C
+#define E1000_STRAP_SMBUS_ADDRESS_MASK  0x00FE0000
+#define E1000_STRAP_SMBUS_ADDRESS_SHIFT 17
+
+/* OEM Bits Phy Register */
+#define HV_OEM_BITS            PHY_REG(768, 25)
+#define HV_OEM_BITS_LPLU       0x0004 /* Low Power Link Up */
+#define HV_OEM_BITS_GBE_DIS    0x0040 /* Gigabit Disable */
+#define HV_OEM_BITS_RESTART_AN 0x0400 /* Restart Auto-negotiation */
+
+#define E1000_NVM_K1_CONFIG 0x1B /* NVM K1 Config Word */
+#define E1000_NVM_K1_ENABLE 0x1  /* NVM Enable K1 bit */
+
 /* ICH GbE Flash Hardware Sequencing Flash Status Register bit breakdown */
 /* Offset 04h HSFSTS */
 union ich8_hws_flash_status {
@@ -200,6 +221,10 @@ static s32 e1000_setup_led_pchlan(struct e1000_hw *hw);
 static s32 e1000_cleanup_led_pchlan(struct e1000_hw *hw);
 static s32 e1000_led_on_pchlan(struct e1000_hw *hw);
 static s32 e1000_led_off_pchlan(struct e1000_hw *hw);
+static s32 e1000_set_lplu_state_pchlan(struct e1000_hw *hw, bool active);
+static void e1000_lan_init_done_ich8lan(struct e1000_hw *hw);
+static s32  e1000_k1_gig_workaround_hv(struct e1000_hw *hw, bool link);
+static s32 e1000_configure_k1_ich8lan(struct e1000_hw *hw, bool k1_enable);
 
 static inline u16 __er16flash(struct e1000_hw *hw, unsigned long reg)
 {
@@ -242,7 +267,11 @@ static s32 e1000_init_phy_params_pchlan(struct e1000_hw *hw)
 
        phy->ops.check_polarity       = e1000_check_polarity_ife_ich8lan;
        phy->ops.read_phy_reg         = e1000_read_phy_reg_hv;
+       phy->ops.read_phy_reg_locked  = e1000_read_phy_reg_hv_locked;
+       phy->ops.set_d0_lplu_state    = e1000_set_lplu_state_pchlan;
+       phy->ops.set_d3_lplu_state    = e1000_set_lplu_state_pchlan;
        phy->ops.write_phy_reg        = e1000_write_phy_reg_hv;
+       phy->ops.write_phy_reg_locked = e1000_write_phy_reg_hv_locked;
        phy->autoneg_mask             = AUTONEG_ADVERTISE_SPEED_DEFAULT;
 
        phy->id = e1000_phy_unknown;
@@ -303,6 +332,8 @@ static s32 e1000_init_phy_params_ich8lan(struct e1000_hw *hw)
        case IGP03E1000_E_PHY_ID:
                phy->type = e1000_phy_igp_3;
                phy->autoneg_mask = AUTONEG_ADVERTISE_SPEED_DEFAULT;
+               phy->ops.read_phy_reg_locked = e1000e_read_phy_reg_igp_locked;
+               phy->ops.write_phy_reg_locked = e1000e_write_phy_reg_igp_locked;
                break;
        case IFE_E_PHY_ID:
        case IFE_PLUS_E_PHY_ID:
@@ -469,14 +500,6 @@ static s32 e1000_check_for_copper_link_ich8lan(struct e1000_hw *hw)
                goto out;
        }
 
-       if (hw->mac.type == e1000_pchlan) {
-               ret_val = e1000e_write_kmrn_reg(hw,
-                                                  E1000_KMRNCTRLSTA_K1_CONFIG,
-                                                  E1000_KMRNCTRLSTA_K1_ENABLE);
-               if (ret_val)
-                       goto out;
-       }
-
        /*
         * First we want to see if the MII Status Register reports
         * link.  If so, then we want to get the current speed/duplex
@@ -486,6 +509,12 @@ static s32 e1000_check_for_copper_link_ich8lan(struct e1000_hw *hw)
        if (ret_val)
                goto out;
 
+       if (hw->mac.type == e1000_pchlan) {
+               ret_val = e1000_k1_gig_workaround_hv(hw, link);
+               if (ret_val)
+                       goto out;
+       }
+
        if (!link)
                goto out; /* No link detected */
 
@@ -568,12 +597,39 @@ static s32 e1000_get_variants_ich8lan(struct e1000_adapter *adapter)
 static DEFINE_MUTEX(nvm_mutex);
 
 /**
+ *  e1000_acquire_nvm_ich8lan - Acquire NVM mutex
+ *  @hw: pointer to the HW structure
+ *
+ *  Acquires the mutex for performing NVM operations.
+ **/
+static s32 e1000_acquire_nvm_ich8lan(struct e1000_hw *hw)
+{
+       mutex_lock(&nvm_mutex);
+
+       return 0;
+}
+
+/**
+ *  e1000_release_nvm_ich8lan - Release NVM mutex
+ *  @hw: pointer to the HW structure
+ *
+ *  Releases the mutex used while performing NVM operations.
+ **/
+static void e1000_release_nvm_ich8lan(struct e1000_hw *hw)
+{
+       mutex_unlock(&nvm_mutex);
+
+       return;
+}
+
+static DEFINE_MUTEX(swflag_mutex);
+
+/**
  *  e1000_acquire_swflag_ich8lan - Acquire software control flag
  *  @hw: pointer to the HW structure
  *
- *  Acquires the software control flag for performing NVM and PHY
- *  operations.  This is a function pointer entry point only called by
- *  read/write routines for the PHY and NVM parts.
+ *  Acquires the software control flag for performing PHY and select
+ *  MAC CSR accesses.
  **/
 static s32 e1000_acquire_swflag_ich8lan(struct e1000_hw *hw)
 {
@@ -582,7 +638,7 @@ static s32 e1000_acquire_swflag_ich8lan(struct e1000_hw *hw)
 
        might_sleep();
 
-       mutex_lock(&nvm_mutex);
+       mutex_lock(&swflag_mutex);
 
        while (timeout) {
                extcnf_ctrl = er32(EXTCNF_CTRL);
@@ -599,7 +655,7 @@ static s32 e1000_acquire_swflag_ich8lan(struct e1000_hw *hw)
                goto out;
        }
 
-       timeout = PHY_CFG_TIMEOUT * 2;
+       timeout = SW_FLAG_TIMEOUT;
 
        extcnf_ctrl |= E1000_EXTCNF_CTRL_SWFLAG;
        ew32(EXTCNF_CTRL, extcnf_ctrl);
@@ -623,7 +679,7 @@ static s32 e1000_acquire_swflag_ich8lan(struct e1000_hw *hw)
 
 out:
        if (ret_val)
-               mutex_unlock(&nvm_mutex);
+               mutex_unlock(&swflag_mutex);
 
        return ret_val;
 }
@@ -632,9 +688,8 @@ out:
  *  e1000_release_swflag_ich8lan - Release software control flag
  *  @hw: pointer to the HW structure
  *
- *  Releases the software control flag for performing NVM and PHY operations.
- *  This is a function pointer entry point only called by read/write
- *  routines for the PHY and NVM parts.
+ *  Releases the software control flag for performing PHY and select
+ *  MAC CSR accesses.
  **/
 static void e1000_release_swflag_ich8lan(struct e1000_hw *hw)
 {
@@ -644,7 +699,9 @@ static void e1000_release_swflag_ich8lan(struct e1000_hw *hw)
        extcnf_ctrl &= ~E1000_EXTCNF_CTRL_SWFLAG;
        ew32(EXTCNF_CTRL, extcnf_ctrl);
 
-       mutex_unlock(&nvm_mutex);
+       mutex_unlock(&swflag_mutex);
+
+       return;
 }
 
 /**
@@ -752,6 +809,326 @@ static s32 e1000_phy_force_speed_duplex_ich8lan(struct e1000_hw *hw)
 }
 
 /**
+ *  e1000_sw_lcd_config_ich8lan - SW-based LCD Configuration
+ *  @hw:   pointer to the HW structure
+ *
+ *  SW should configure the LCD from the NVM extended configuration region
+ *  as a workaround for certain parts.
+ **/
+static s32 e1000_sw_lcd_config_ich8lan(struct e1000_hw *hw)
+{
+       struct e1000_phy_info *phy = &hw->phy;
+       u32 i, data, cnf_size, cnf_base_addr, sw_cfg_mask;
+       s32 ret_val;
+       u16 word_addr, reg_data, reg_addr, phy_page = 0;
+
+       ret_val = hw->phy.ops.acquire_phy(hw);
+       if (ret_val)
+               return ret_val;
+
+       /*
+        * Initialize the PHY from the NVM on ICH platforms.  This
+        * is needed due to an issue where the NVM configuration is
+        * not properly autoloaded after power transitions.
+        * Therefore, after each PHY reset, we will load the
+        * configuration data out of the NVM manually.
+        */
+       if ((hw->mac.type == e1000_ich8lan && phy->type == e1000_phy_igp_3) ||
+               (hw->mac.type == e1000_pchlan)) {
+               struct e1000_adapter *adapter = hw->adapter;
+
+               /* Check if SW needs to configure the PHY */
+               if ((adapter->pdev->device == E1000_DEV_ID_ICH8_IGP_M_AMT) ||
+                   (adapter->pdev->device == E1000_DEV_ID_ICH8_IGP_M) ||
+                   (hw->mac.type == e1000_pchlan))
+                       sw_cfg_mask = E1000_FEXTNVM_SW_CONFIG_ICH8M;
+               else
+                       sw_cfg_mask = E1000_FEXTNVM_SW_CONFIG;
+
+               data = er32(FEXTNVM);
+               if (!(data & sw_cfg_mask))
+                       goto out;
+
+               /* Wait for basic configuration completes before proceeding */
+               e1000_lan_init_done_ich8lan(hw);
+
+               /*
+                * Make sure HW does not configure LCD from PHY
+                * extended configuration before SW configuration
+                */
+               data = er32(EXTCNF_CTRL);
+               if (data & E1000_EXTCNF_CTRL_LCD_WRITE_ENABLE)
+                       goto out;
+
+               cnf_size = er32(EXTCNF_SIZE);
+               cnf_size &= E1000_EXTCNF_SIZE_EXT_PCIE_LENGTH_MASK;
+               cnf_size >>= E1000_EXTCNF_SIZE_EXT_PCIE_LENGTH_SHIFT;
+               if (!cnf_size)
+                       goto out;
+
+               cnf_base_addr = data & E1000_EXTCNF_CTRL_EXT_CNF_POINTER_MASK;
+               cnf_base_addr >>= E1000_EXTCNF_CTRL_EXT_CNF_POINTER_SHIFT;
+
+               if (!(data & E1000_EXTCNF_CTRL_OEM_WRITE_ENABLE) &&
+                   (hw->mac.type == e1000_pchlan)) {
+                       /*
+                        * HW configures the SMBus address and LEDs when the
+                        * OEM and LCD Write Enable bits are set in the NVM.
+                        * When both NVM bits are cleared, SW will configure
+                        * them instead.
+                        */
+                       data = er32(STRAP);
+                       data &= E1000_STRAP_SMBUS_ADDRESS_MASK;
+                       reg_data = data >> E1000_STRAP_SMBUS_ADDRESS_SHIFT;
+                       reg_data |= HV_SMB_ADDR_PEC_EN | HV_SMB_ADDR_VALID;
+                       ret_val = e1000_write_phy_reg_hv_locked(hw, HV_SMB_ADDR,
+                                                               reg_data);
+                       if (ret_val)
+                               goto out;
+
+                       data = er32(LEDCTL);
+                       ret_val = e1000_write_phy_reg_hv_locked(hw,
+                                                               HV_LED_CONFIG,
+                                                               (u16)data);
+                       if (ret_val)
+                               goto out;
+               }
+               /* Configure LCD from extended configuration region. */
+
+               /* cnf_base_addr is in DWORD */
+               word_addr = (u16)(cnf_base_addr << 1);
+
+               for (i = 0; i < cnf_size; i++) {
+                       ret_val = e1000_read_nvm(hw, (word_addr + i * 2), 1,
+                                                  &reg_data);
+                       if (ret_val)
+                               goto out;
+
+                       ret_val = e1000_read_nvm(hw, (word_addr + i * 2 + 1),
+                                                  1, &reg_addr);
+                       if (ret_val)
+                               goto out;
+
+                       /* Save off the PHY page for future writes. */
+                       if (reg_addr == IGP01E1000_PHY_PAGE_SELECT) {
+                               phy_page = reg_data;
+                               continue;
+                       }
+
+                       reg_addr &= PHY_REG_MASK;
+                       reg_addr |= phy_page;
+
+                       ret_val = phy->ops.write_phy_reg_locked(hw,
+                                                           (u32)reg_addr,
+                                                           reg_data);
+                       if (ret_val)
+                               goto out;
+               }
+       }
+
+out:
+       hw->phy.ops.release_phy(hw);
+       return ret_val;
+}
+
+/**
+ *  e1000_k1_gig_workaround_hv - K1 Si workaround
+ *  @hw:   pointer to the HW structure
+ *  @link: link up bool flag
+ *
+ *  If K1 is enabled for 1Gbps, the MAC might stall when transitioning
+ *  from a lower speed.  This workaround disables K1 whenever link is at 1Gig
+ *  If link is down, the function will restore the default K1 setting located
+ *  in the NVM.
+ **/
+static s32 e1000_k1_gig_workaround_hv(struct e1000_hw *hw, bool link)
+{
+       s32 ret_val = 0;
+       u16 status_reg = 0;
+       bool k1_enable = hw->dev_spec.ich8lan.nvm_k1_enabled;
+
+       if (hw->mac.type != e1000_pchlan)
+               goto out;
+
+       /* Wrap the whole flow with the sw flag */
+       ret_val = hw->phy.ops.acquire_phy(hw);
+       if (ret_val)
+               goto out;
+
+       /* Disable K1 when link is 1Gbps, otherwise use the NVM setting */
+       if (link) {
+               if (hw->phy.type == e1000_phy_82578) {
+                       ret_val = hw->phy.ops.read_phy_reg_locked(hw,
+                                                                 BM_CS_STATUS,
+                                                                 &status_reg);
+                       if (ret_val)
+                               goto release;
+
+                       status_reg &= BM_CS_STATUS_LINK_UP |
+                                     BM_CS_STATUS_RESOLVED |
+                                     BM_CS_STATUS_SPEED_MASK;
+
+                       if (status_reg == (BM_CS_STATUS_LINK_UP |
+                                          BM_CS_STATUS_RESOLVED |
+                                          BM_CS_STATUS_SPEED_1000))
+                               k1_enable = false;
+               }
+
+               if (hw->phy.type == e1000_phy_82577) {
+                       ret_val = hw->phy.ops.read_phy_reg_locked(hw,
+                                                                 HV_M_STATUS,
+                                                                 &status_reg);
+                       if (ret_val)
+                               goto release;
+
+                       status_reg &= HV_M_STATUS_LINK_UP |
+                                     HV_M_STATUS_AUTONEG_COMPLETE |
+                                     HV_M_STATUS_SPEED_MASK;
+
+                       if (status_reg == (HV_M_STATUS_LINK_UP |
+                                          HV_M_STATUS_AUTONEG_COMPLETE |
+                                          HV_M_STATUS_SPEED_1000))
+                               k1_enable = false;
+               }
+
+               /* Link stall fix for link up */
+               ret_val = hw->phy.ops.write_phy_reg_locked(hw, PHY_REG(770, 19),
+                                                          0x0100);
+               if (ret_val)
+                       goto release;
+
+       } else {
+               /* Link stall fix for link down */
+               ret_val = hw->phy.ops.write_phy_reg_locked(hw, PHY_REG(770, 19),
+                                                          0x4100);
+               if (ret_val)
+                       goto release;
+       }
+
+       ret_val = e1000_configure_k1_ich8lan(hw, k1_enable);
+
+release:
+       hw->phy.ops.release_phy(hw);
+out:
+       return ret_val;
+}
+
+/**
+ *  e1000_configure_k1_ich8lan - Configure K1 power state
+ *  @hw: pointer to the HW structure
+ *  @enable: K1 state to configure
+ *
+ *  Configure the K1 power state based on the provided parameter.
+ *  Assumes semaphore already acquired.
+ *
+ *  Success returns 0, Failure returns -E1000_ERR_PHY (-2)
+ **/
+static s32 e1000_configure_k1_ich8lan(struct e1000_hw *hw, bool k1_enable)
+{
+       s32 ret_val = 0;
+       u32 ctrl_reg = 0;
+       u32 ctrl_ext = 0;
+       u32 reg = 0;
+       u16 kmrn_reg = 0;
+
+       ret_val = e1000e_read_kmrn_reg_locked(hw,
+                                            E1000_KMRNCTRLSTA_K1_CONFIG,
+                                            &kmrn_reg);
+       if (ret_val)
+               goto out;
+
+       if (k1_enable)
+               kmrn_reg |= E1000_KMRNCTRLSTA_K1_ENABLE;
+       else
+               kmrn_reg &= ~E1000_KMRNCTRLSTA_K1_ENABLE;
+
+       ret_val = e1000e_write_kmrn_reg_locked(hw,
+                                             E1000_KMRNCTRLSTA_K1_CONFIG,
+                                             kmrn_reg);
+       if (ret_val)
+               goto out;
+
+       udelay(20);
+       ctrl_ext = er32(CTRL_EXT);
+       ctrl_reg = er32(CTRL);
+
+       reg = ctrl_reg & ~(E1000_CTRL_SPD_1000 | E1000_CTRL_SPD_100);
+       reg |= E1000_CTRL_FRCSPD;
+       ew32(CTRL, reg);
+
+       ew32(CTRL_EXT, ctrl_ext | E1000_CTRL_EXT_SPD_BYPS);
+       udelay(20);
+       ew32(CTRL, ctrl_reg);
+       ew32(CTRL_EXT, ctrl_ext);
+       udelay(20);
+
+out:
+       return ret_val;
+}
+
+/**
+ *  e1000_oem_bits_config_ich8lan - SW-based LCD Configuration
+ *  @hw:       pointer to the HW structure
+ *  @d0_state: boolean if entering d0 or d3 device state
+ *
+ *  SW will configure Gbe Disable and LPLU based on the NVM. The four bits are
+ *  collectively called OEM bits.  The OEM Write Enable bit and SW Config bit
+ *  in NVM determines whether HW should configure LPLU and Gbe Disable.
+ **/
+static s32 e1000_oem_bits_config_ich8lan(struct e1000_hw *hw, bool d0_state)
+{
+       s32 ret_val = 0;
+       u32 mac_reg;
+       u16 oem_reg;
+
+       if (hw->mac.type != e1000_pchlan)
+               return ret_val;
+
+       ret_val = hw->phy.ops.acquire_phy(hw);
+       if (ret_val)
+               return ret_val;
+
+       mac_reg = er32(EXTCNF_CTRL);
+       if (mac_reg & E1000_EXTCNF_CTRL_OEM_WRITE_ENABLE)
+               goto out;
+
+       mac_reg = er32(FEXTNVM);
+       if (!(mac_reg & E1000_FEXTNVM_SW_CONFIG_ICH8M))
+               goto out;
+
+       mac_reg = er32(PHY_CTRL);
+
+       ret_val = hw->phy.ops.read_phy_reg_locked(hw, HV_OEM_BITS, &oem_reg);
+       if (ret_val)
+               goto out;
+
+       oem_reg &= ~(HV_OEM_BITS_GBE_DIS | HV_OEM_BITS_LPLU);
+
+       if (d0_state) {
+               if (mac_reg & E1000_PHY_CTRL_GBE_DISABLE)
+                       oem_reg |= HV_OEM_BITS_GBE_DIS;
+
+               if (mac_reg & E1000_PHY_CTRL_D0A_LPLU)
+                       oem_reg |= HV_OEM_BITS_LPLU;
+       } else {
+               if (mac_reg & E1000_PHY_CTRL_NOND0A_GBE_DISABLE)
+                       oem_reg |= HV_OEM_BITS_GBE_DIS;
+
+               if (mac_reg & E1000_PHY_CTRL_NOND0A_LPLU)
+                       oem_reg |= HV_OEM_BITS_LPLU;
+       }
+       /* Restart auto-neg to activate the bits */
+       oem_reg |= HV_OEM_BITS_RESTART_AN;
+       ret_val = hw->phy.ops.write_phy_reg_locked(hw, HV_OEM_BITS, oem_reg);
+
+out:
+       hw->phy.ops.release_phy(hw);
+
+       return ret_val;
+}
+
+
+/**
  *  e1000_hv_phy_workarounds_ich8lan - A series of Phy workarounds to be
  *  done after every PHY reset.
  **/
@@ -791,10 +1168,20 @@ static s32 e1000_hv_phy_workarounds_ich8lan(struct e1000_hw *hw)
        ret_val = hw->phy.ops.acquire_phy(hw);
        if (ret_val)
                return ret_val;
+
        hw->phy.addr = 1;
-       e1000e_write_phy_reg_mdic(hw, IGP01E1000_PHY_PAGE_SELECT, 0);
+       ret_val = e1000e_write_phy_reg_mdic(hw, IGP01E1000_PHY_PAGE_SELECT, 0);
+       if (ret_val)
+               goto out;
        hw->phy.ops.release_phy(hw);
 
+       /*
+        * Configure the K1 Si workaround during phy reset assuming there is
+        * link so that it disables K1 if link is in 1Gbps.
+        */
+       ret_val = e1000_k1_gig_workaround_hv(hw, true);
+
+out:
        return ret_val;
 }
 
@@ -840,11 +1227,8 @@ static void e1000_lan_init_done_ich8lan(struct e1000_hw *hw)
  **/
 static s32 e1000_phy_hw_reset_ich8lan(struct e1000_hw *hw)
 {
-       struct e1000_phy_info *phy = &hw->phy;
-       u32 i;
-       u32 data, cnf_size, cnf_base_addr, sw_cfg_mask;
-       s32 ret_val;
-       u16 word_addr, reg_data, reg_addr, phy_page = 0;
+       s32 ret_val = 0;
+       u16 reg;
 
        ret_val = e1000e_phy_hw_reset_generic(hw);
        if (ret_val)
@@ -859,81 +1243,20 @@ static s32 e1000_phy_hw_reset_ich8lan(struct e1000_hw *hw)
                        return ret_val;
        }
 
-       /*
-        * Initialize the PHY from the NVM on ICH platforms.  This
-        * is needed due to an issue where the NVM configuration is
-        * not properly autoloaded after power transitions.
-        * Therefore, after each PHY reset, we will load the
-        * configuration data out of the NVM manually.
-        */
-       if (hw->mac.type == e1000_ich8lan && phy->type == e1000_phy_igp_3) {
-               struct e1000_adapter *adapter = hw->adapter;
-
-               /* Check if SW needs configure the PHY */
-               if ((adapter->pdev->device == E1000_DEV_ID_ICH8_IGP_M_AMT) ||
-                   (adapter->pdev->device == E1000_DEV_ID_ICH8_IGP_M))
-                       sw_cfg_mask = E1000_FEXTNVM_SW_CONFIG_ICH8M;
-               else
-                       sw_cfg_mask = E1000_FEXTNVM_SW_CONFIG;
-
-               data = er32(FEXTNVM);
-               if (!(data & sw_cfg_mask))
-                       return 0;
-
-               /* Wait for basic configuration completes before proceeding */
-               e1000_lan_init_done_ich8lan(hw);
-
-               /*
-                * Make sure HW does not configure LCD from PHY
-                * extended configuration before SW configuration
-                */
-               data = er32(EXTCNF_CTRL);
-               if (data & E1000_EXTCNF_CTRL_LCD_WRITE_ENABLE)
-                       return 0;
-
-               cnf_size = er32(EXTCNF_SIZE);
-               cnf_size &= E1000_EXTCNF_SIZE_EXT_PCIE_LENGTH_MASK;
-               cnf_size >>= E1000_EXTCNF_SIZE_EXT_PCIE_LENGTH_SHIFT;
-               if (!cnf_size)
-                       return 0;
-
-               cnf_base_addr = data & E1000_EXTCNF_CTRL_EXT_CNF_POINTER_MASK;
-               cnf_base_addr >>= E1000_EXTCNF_CTRL_EXT_CNF_POINTER_SHIFT;
-
-               /* Configure LCD from extended configuration region. */
-
-               /* cnf_base_addr is in DWORD */
-               word_addr = (u16)(cnf_base_addr << 1);
-
-               for (i = 0; i < cnf_size; i++) {
-                       ret_val = e1000_read_nvm(hw,
-                                               (word_addr + i * 2),
-                                               1,
-                                               &reg_data);
-                       if (ret_val)
-                               return ret_val;
-
-                       ret_val = e1000_read_nvm(hw,
-                                               (word_addr + i * 2 + 1),
-                                               1,
-                                               &reg_addr);
-                       if (ret_val)
-                               return ret_val;
-
-                       /* Save off the PHY page for future writes. */
-                       if (reg_addr == IGP01E1000_PHY_PAGE_SELECT) {
-                               phy_page = reg_data;
-                               continue;
-                       }
+       /* Dummy read to clear the phy wakeup bit after lcd reset */
+       if (hw->mac.type == e1000_pchlan)
+               e1e_rphy(hw, BM_WUC, &reg);
 
-                       reg_addr |= phy_page;
+       /* Configure the LCD with the extended configuration region in NVM */
+       ret_val = e1000_sw_lcd_config_ich8lan(hw);
+       if (ret_val)
+               goto out;
 
-                       ret_val = e1e_wphy(hw, (u32)reg_addr, reg_data);
-                       if (ret_val)
-                               return ret_val;
-               }
-       }
+       /* Configure the LCD with the OEM bits in NVM */
+       if (hw->mac.type == e1000_pchlan)
+               ret_val = e1000_oem_bits_config_ich8lan(hw, true);
 
+out:
        return 0;
 }
 
@@ -1054,6 +1377,38 @@ static s32 e1000_check_polarity_ife_ich8lan(struct e1000_hw *hw)
 }
 
 /**
+ *  e1000_set_lplu_state_pchlan - Set Low Power Link Up state
+ *  @hw: pointer to the HW structure
+ *  @active: true to enable LPLU, false to disable
+ *
+ *  Sets the LPLU state according to the active flag.  For PCH, if OEM write
+ *  bit are disabled in the NVM, writing the LPLU bits in the MAC will not set
+ *  the phy speed. This function will manually set the LPLU bit and restart
+ *  auto-neg as hw would do. D3 and D0 LPLU will call the same function
+ *  since it configures the same bit.
+ **/
+static s32 e1000_set_lplu_state_pchlan(struct e1000_hw *hw, bool active)
+{
+       s32 ret_val = 0;
+       u16 oem_reg;
+
+       ret_val = e1e_rphy(hw, HV_OEM_BITS, &oem_reg);
+       if (ret_val)
+               goto out;
+
+       if (active)
+               oem_reg |= HV_OEM_BITS_LPLU;
+       else
+               oem_reg &= ~HV_OEM_BITS_LPLU;
+
+       oem_reg |= HV_OEM_BITS_RESTART_AN;
+       ret_val = e1e_wphy(hw, HV_OEM_BITS, oem_reg);
+
+out:
+       return ret_val;
+}
+
+/**
  *  e1000_set_d0_lplu_state_ich8lan - Set Low Power Linkup D0 state
  *  @hw: pointer to the HW structure
  *  @active: TRUE to enable LPLU, FALSE to disable
@@ -1314,12 +1669,11 @@ static s32 e1000_read_nvm_ich8lan(struct e1000_hw *hw, u16 offset, u16 words,
        if ((offset >= nvm->word_size) || (words > nvm->word_size - offset) ||
            (words == 0)) {
                hw_dbg(hw, "nvm parameter(s) out of bounds\n");
-               return -E1000_ERR_NVM;
+               ret_val = -E1000_ERR_NVM;
+               goto out;
        }
 
-       ret_val = e1000_acquire_swflag_ich8lan(hw);
-       if (ret_val)
-               goto out;
+       nvm->ops.acquire_nvm(hw);
 
        ret_val = e1000_valid_nvm_bank_detect_ich8lan(hw, &bank);
        if (ret_val) {
@@ -1345,7 +1699,7 @@ static s32 e1000_read_nvm_ich8lan(struct e1000_hw *hw, u16 offset, u16 words,
                }
        }
 
-       e1000_release_swflag_ich8lan(hw);
+       nvm->ops.release_nvm(hw);
 
 out:
        if (ret_val)
@@ -1603,11 +1957,15 @@ static s32 e1000_write_nvm_ich8lan(struct e1000_hw *hw, u16 offset, u16 words,
                return -E1000_ERR_NVM;
        }
 
+       nvm->ops.acquire_nvm(hw);
+
        for (i = 0; i < words; i++) {
                dev_spec->shadow_ram[offset+i].modified = 1;
                dev_spec->shadow_ram[offset+i].value = data[i];
        }
 
+       nvm->ops.release_nvm(hw);
+
        return 0;
 }
 
@@ -1637,9 +1995,7 @@ static s32 e1000_update_nvm_checksum_ich8lan(struct e1000_hw *hw)
        if (nvm->type != e1000_nvm_flash_sw)
                goto out;
 
-       ret_val = e1000_acquire_swflag_ich8lan(hw);
-       if (ret_val)
-               goto out;
+       nvm->ops.acquire_nvm(hw);
 
        /*
         * We're writing to the opposite bank so if we're on bank 1,
@@ -1657,7 +2013,7 @@ static s32 e1000_update_nvm_checksum_ich8lan(struct e1000_hw *hw)
                old_bank_offset = 0;
                ret_val = e1000_erase_flash_bank_ich8lan(hw, 1);
                if (ret_val) {
-                       e1000_release_swflag_ich8lan(hw);
+                       nvm->ops.release_nvm(hw);
                        goto out;
                }
        } else {
@@ -1665,7 +2021,7 @@ static s32 e1000_update_nvm_checksum_ich8lan(struct e1000_hw *hw)
                new_bank_offset = 0;
                ret_val = e1000_erase_flash_bank_ich8lan(hw, 0);
                if (ret_val) {
-                       e1000_release_swflag_ich8lan(hw);
+                       nvm->ops.release_nvm(hw);
                        goto out;
                }
        }
@@ -1723,7 +2079,7 @@ static s32 e1000_update_nvm_checksum_ich8lan(struct e1000_hw *hw)
        if (ret_val) {
                /* Possibly read-only, see e1000e_write_protect_nvm_ich8lan() */
                hw_dbg(hw, "Flash commit failed.\n");
-               e1000_release_swflag_ich8lan(hw);
+               nvm->ops.release_nvm(hw);
                goto out;
        }
 
@@ -1736,7 +2092,7 @@ static s32 e1000_update_nvm_checksum_ich8lan(struct e1000_hw *hw)
        act_offset = new_bank_offset + E1000_ICH_NVM_SIG_WORD;
        ret_val = e1000_read_flash_word_ich8lan(hw, act_offset, &data);
        if (ret_val) {
-               e1000_release_swflag_ich8lan(hw);
+               nvm->ops.release_nvm(hw);
                goto out;
        }
        data &= 0xBFFF;
@@ -1744,7 +2100,7 @@ static s32 e1000_update_nvm_checksum_ich8lan(struct e1000_hw *hw)
                                                       act_offset * 2 + 1,
                                                       (u8)(data >> 8));
        if (ret_val) {
-               e1000_release_swflag_ich8lan(hw);
+               nvm->ops.release_nvm(hw);
                goto out;
        }
 
@@ -1757,7 +2113,7 @@ static s32 e1000_update_nvm_checksum_ich8lan(struct e1000_hw *hw)
        act_offset = (old_bank_offset + E1000_ICH_NVM_SIG_WORD) * 2 + 1;
        ret_val = e1000_retry_write_flash_byte_ich8lan(hw, act_offset, 0);
        if (ret_val) {
-               e1000_release_swflag_ich8lan(hw);
+               nvm->ops.release_nvm(hw);
                goto out;
        }
 
@@ -1767,7 +2123,7 @@ static s32 e1000_update_nvm_checksum_ich8lan(struct e1000_hw *hw)
                dev_spec->shadow_ram[i].value = 0xFFFF;
        }
 
-       e1000_release_swflag_ich8lan(hw);
+       nvm->ops.release_nvm(hw);
 
        /*
         * Reload the EEPROM, or else modifications will not appear
@@ -1831,14 +2187,12 @@ static s32 e1000_validate_nvm_checksum_ich8lan(struct e1000_hw *hw)
  **/
 void e1000e_write_protect_nvm_ich8lan(struct e1000_hw *hw)
 {
+       struct e1000_nvm_info *nvm = &hw->nvm;
        union ich8_flash_protected_range pr0;
        union ich8_hws_flash_status hsfsts;
        u32 gfpreg;
-       s32 ret_val;
 
-       ret_val = e1000_acquire_swflag_ich8lan(hw);
-       if (ret_val)
-               return;
+       nvm->ops.acquire_nvm(hw);
 
        gfpreg = er32flash(ICH_FLASH_GFPREG);
 
@@ -1859,7 +2213,7 @@ void e1000e_write_protect_nvm_ich8lan(struct e1000_hw *hw)
        hsfsts.hsf_status.flockdn = true;
        ew32flash(ICH_FLASH_HSFSTS, hsfsts.regval);
 
-       e1000_release_swflag_ich8lan(hw);
+       nvm->ops.release_nvm(hw);
 }
 
 /**
@@ -2229,6 +2583,8 @@ static s32 e1000_get_bus_info_ich8lan(struct e1000_hw *hw)
  **/
 static s32 e1000_reset_hw_ich8lan(struct e1000_hw *hw)
 {
+       struct e1000_dev_spec_ich8lan *dev_spec = &hw->dev_spec.ich8lan;
+       u16 reg;
        u32 ctrl, icr, kab;
        s32 ret_val;
 
@@ -2263,6 +2619,18 @@ static s32 e1000_reset_hw_ich8lan(struct e1000_hw *hw)
                ew32(PBS, E1000_PBS_16K);
        }
 
+       if (hw->mac.type == e1000_pchlan) {
+               /* Save the NVM K1 bit setting*/
+               ret_val = e1000_read_nvm(hw, E1000_NVM_K1_CONFIG, 1, &reg);
+               if (ret_val)
+                       return ret_val;
+
+               if (reg & E1000_NVM_K1_ENABLE)
+                       dev_spec->nvm_k1_enabled = true;
+               else
+                       dev_spec->nvm_k1_enabled = false;
+       }
+
        ctrl = er32(CTRL);
 
        if (!e1000_check_reset_block(hw)) {
@@ -2304,7 +2672,19 @@ static s32 e1000_reset_hw_ich8lan(struct e1000_hw *hw)
                        hw_dbg(hw, "Auto Read Done did not complete\n");
                }
        }
+       /* Dummy read to clear the phy wakeup bit after lcd reset */
+       if (hw->mac.type == e1000_pchlan)
+               e1e_rphy(hw, BM_WUC, &reg);
 
+       ret_val = e1000_sw_lcd_config_ich8lan(hw);
+       if (ret_val)
+               goto out;
+
+       if (hw->mac.type == e1000_pchlan) {
+               ret_val = e1000_oem_bits_config_ich8lan(hw, true);
+               if (ret_val)
+                       goto out;
+       }
        /*
         * For PCH, this write will make sure that any noise
         * will be detected as a CRC error and be dropped rather than show up
@@ -2323,6 +2703,7 @@ static s32 e1000_reset_hw_ich8lan(struct e1000_hw *hw)
        if (hw->mac.type == e1000_pchlan)
                ret_val = e1000_hv_phy_workarounds_ich8lan(hw);
 
+out:
        return ret_val;
 }
 
@@ -2627,14 +3008,6 @@ static s32 e1000_get_link_up_info_ich8lan(struct e1000_hw *hw, u16 *speed,
        if (ret_val)
                return ret_val;
 
-       if ((hw->mac.type == e1000_pchlan) && (*speed == SPEED_1000)) {
-               ret_val = e1000e_write_kmrn_reg(hw,
-                                                 E1000_KMRNCTRLSTA_K1_CONFIG,
-                                                 E1000_KMRNCTRLSTA_K1_DISABLE);
-               if (ret_val)
-                       return ret_val;
-       }
-
        if ((hw->mac.type == e1000_ich8lan) &&
            (hw->phy.type == e1000_phy_igp_3) &&
            (*speed == SPEED_1000)) {
@@ -2843,9 +3216,8 @@ void e1000e_disable_gig_wol_ich8lan(struct e1000_hw *hw)
                            E1000_PHY_CTRL_GBE_DISABLE;
                ew32(PHY_CTRL, phy_ctrl);
 
-               /* Workaround SWFLAG unexpectedly set during S0->Sx */
                if (hw->mac.type == e1000_pchlan)
-                       udelay(500);
+                       e1000_phy_hw_reset_ich8lan(hw);
        default:
                break;
        }
@@ -3113,9 +3485,9 @@ static struct e1000_phy_operations ich8_phy_ops = {
 };
 
 static struct e1000_nvm_operations ich8_nvm_ops = {
-       .acquire_nvm            = e1000_acquire_swflag_ich8lan,
+       .acquire_nvm            = e1000_acquire_nvm_ich8lan,
        .read_nvm               = e1000_read_nvm_ich8lan,
-       .release_nvm            = e1000_release_swflag_ich8lan,
+       .release_nvm            = e1000_release_nvm_ich8lan,
        .update_nvm             = e1000_update_nvm_checksum_ich8lan,
        .valid_led_default      = e1000_valid_led_default_ich8lan,
        .validate_nvm           = e1000_validate_nvm_checksum_ich8lan,
index 994401f..03175b3 100644 (file)
@@ -95,13 +95,6 @@ static const u16 e1000_igp_2_cable_length_table[] =
 /* BM PHY Copper Specific Control 1 */
 #define BM_CS_CTRL1                       16
 
-/* BM PHY Copper Specific Status */
-#define BM_CS_STATUS                      17
-#define BM_CS_STATUS_LINK_UP              0x0400
-#define BM_CS_STATUS_RESOLVED             0x0800
-#define BM_CS_STATUS_SPEED_MASK           0xC000
-#define BM_CS_STATUS_SPEED_1000           0x8000
-
 #define HV_MUX_DATA_CTRL               PHY_REG(776, 16)
 #define HV_MUX_DATA_CTRL_GEN_TO_MAC    0x0400
 #define HV_MUX_DATA_CTRL_FORCE_SPEED   0x0004
@@ -164,16 +157,25 @@ s32 e1000e_get_phy_id(struct e1000_hw *hw)
                 * MDIC mode. No harm in trying again in this case since
                 * the PHY ID is unknown at this point anyway
                 */
+               ret_val = phy->ops.acquire_phy(hw);
+               if (ret_val)
+                       goto out;
                ret_val = e1000_set_mdio_slow_mode_hv(hw, true);
                if (ret_val)
                        goto out;
+               phy->ops.release_phy(hw);
 
                retry_count++;
        }
 out:
        /* Revert to MDIO fast mode, if applicable */
-       if (retry_count)
+       if (retry_count) {
+               ret_val = phy->ops.acquire_phy(hw);
+               if (ret_val)
+                       return ret_val;
                ret_val = e1000_set_mdio_slow_mode_hv(hw, false);
+               phy->ops.release_phy(hw);
+       }
 
        return ret_val;
 }
@@ -354,94 +356,173 @@ s32 e1000e_write_phy_reg_m88(struct e1000_hw *hw, u32 offset, u16 data)
 }
 
 /**
- *  e1000e_read_phy_reg_igp - Read igp PHY register
+ *  __e1000e_read_phy_reg_igp - Read igp PHY register
  *  @hw: pointer to the HW structure
  *  @offset: register offset to be read
  *  @data: pointer to the read data
+ *  @locked: semaphore has already been acquired or not
  *
  *  Acquires semaphore, if necessary, then reads the PHY register at offset
- *  and storing the retrieved information in data.  Release any acquired
+ *  and stores the retrieved information in data.  Release any acquired
  *  semaphores before exiting.
  **/
-s32 e1000e_read_phy_reg_igp(struct e1000_hw *hw, u32 offset, u16 *data)
+static s32 __e1000e_read_phy_reg_igp(struct e1000_hw *hw, u32 offset, u16 *data,
+                                    bool locked)
 {
-       s32 ret_val;
+       s32 ret_val = 0;
 
-       ret_val = hw->phy.ops.acquire_phy(hw);
-       if (ret_val)
-               return ret_val;
+       if (!locked) {
+               if (!(hw->phy.ops.acquire_phy))
+                       goto out;
+
+               ret_val = hw->phy.ops.acquire_phy(hw);
+               if (ret_val)
+                       goto out;
+       }
 
        if (offset > MAX_PHY_MULTI_PAGE_REG) {
                ret_val = e1000e_write_phy_reg_mdic(hw,
                                                    IGP01E1000_PHY_PAGE_SELECT,
                                                    (u16)offset);
-               if (ret_val) {
-                       hw->phy.ops.release_phy(hw);
-                       return ret_val;
-               }
+               if (ret_val)
+                       goto release;
        }
 
        ret_val = e1000e_read_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset,
-                                          data);
-
-       hw->phy.ops.release_phy(hw);
+                                         data);
 
+release:
+       if (!locked)
+               hw->phy.ops.release_phy(hw);
+out:
        return ret_val;
 }
 
 /**
+ *  e1000e_read_phy_reg_igp - Read igp PHY register
+ *  @hw: pointer to the HW structure
+ *  @offset: register offset to be read
+ *  @data: pointer to the read data
+ *
+ *  Acquires semaphore then reads the PHY register at offset and stores the
+ *  retrieved information in data.
+ *  Release the acquired semaphore before exiting.
+ **/
+s32 e1000e_read_phy_reg_igp(struct e1000_hw *hw, u32 offset, u16 *data)
+{
+       return __e1000e_read_phy_reg_igp(hw, offset, data, false);
+}
+
+/**
+ *  e1000e_read_phy_reg_igp_locked - Read igp PHY register
+ *  @hw: pointer to the HW structure
+ *  @offset: register offset to be read
+ *  @data: pointer to the read data
+ *
+ *  Reads the PHY register at offset and stores the retrieved information
+ *  in data.  Assumes semaphore already acquired.
+ **/
+s32 e1000e_read_phy_reg_igp_locked(struct e1000_hw *hw, u32 offset, u16 *data)
+{
+       return __e1000e_read_phy_reg_igp(hw, offset, data, true);
+}
+
+/**
  *  e1000e_write_phy_reg_igp - Write igp PHY register
  *  @hw: pointer to the HW structure
  *  @offset: register offset to write to
  *  @data: data to write at register offset
+ *  @locked: semaphore has already been acquired or not
  *
  *  Acquires semaphore, if necessary, then writes the data to PHY register
  *  at the offset.  Release any acquired semaphores before exiting.
  **/
-s32 e1000e_write_phy_reg_igp(struct e1000_hw *hw, u32 offset, u16 data)
+static s32 __e1000e_write_phy_reg_igp(struct e1000_hw *hw, u32 offset, u16 data,
+                                     bool locked)
 {
-       s32 ret_val;
+       s32 ret_val = 0;
 
-       ret_val = hw->phy.ops.acquire_phy(hw);
-       if (ret_val)
-               return ret_val;
+       if (!locked) {
+               if (!(hw->phy.ops.acquire_phy))
+                       goto out;
+
+               ret_val = hw->phy.ops.acquire_phy(hw);
+               if (ret_val)
+                       goto out;
+       }
 
        if (offset > MAX_PHY_MULTI_PAGE_REG) {
                ret_val = e1000e_write_phy_reg_mdic(hw,
                                                    IGP01E1000_PHY_PAGE_SELECT,
                                                    (u16)offset);
-               if (ret_val) {
-                       hw->phy.ops.release_phy(hw);
-                       return ret_val;
-               }
+               if (ret_val)
+                       goto release;
        }
 
        ret_val = e1000e_write_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset,
                                            data);
 
-       hw->phy.ops.release_phy(hw);
+release:
+       if (!locked)
+               hw->phy.ops.release_phy(hw);
 
+out:
        return ret_val;
 }
 
 /**
- *  e1000e_read_kmrn_reg - Read kumeran register
+ *  e1000e_write_phy_reg_igp - Write igp PHY register
+ *  @hw: pointer to the HW structure
+ *  @offset: register offset to write to
+ *  @data: data to write at register offset
+ *
+ *  Acquires semaphore then writes the data to PHY register
+ *  at the offset.  Release any acquired semaphores before exiting.
+ **/
+s32 e1000e_write_phy_reg_igp(struct e1000_hw *hw, u32 offset, u16 data)
+{
+       return __e1000e_write_phy_reg_igp(hw, offset, data, false);
+}
+
+/**
+ *  e1000e_write_phy_reg_igp_locked - Write igp PHY register
+ *  @hw: pointer to the HW structure
+ *  @offset: register offset to write to
+ *  @data: data to write at register offset
+ *
+ *  Writes the data to PHY register at the offset.
+ *  Assumes semaphore already acquired.
+ **/
+s32 e1000e_write_phy_reg_igp_locked(struct e1000_hw *hw, u32 offset, u16 data)
+{
+       return __e1000e_write_phy_reg_igp(hw, offset, data, true);
+}
+
+/**
+ *  __e1000_read_kmrn_reg - Read kumeran register
  *  @hw: pointer to the HW structure
  *  @offset: register offset to be read
  *  @data: pointer to the read data
+ *  @locked: semaphore has already been acquired or not
  *
  *  Acquires semaphore, if necessary.  Then reads the PHY register at offset
  *  using the kumeran interface.  The information retrieved is stored in data.
  *  Release any acquired semaphores before exiting.
  **/
-s32 e1000e_read_kmrn_reg(struct e1000_hw *hw, u32 offset, u16 *data)
+static s32 __e1000_read_kmrn_reg(struct e1000_hw *hw, u32 offset, u16 *data,
+                                 bool locked)
 {
        u32 kmrnctrlsta;
-       s32 ret_val;
+       s32 ret_val = 0;
 
-       ret_val = hw->phy.ops.acquire_phy(hw);
-       if (ret_val)
-               return ret_val;
+       if (!locked) {
+               if (!(hw->phy.ops.acquire_phy))
+                       goto out;
+
+               ret_val = hw->phy.ops.acquire_phy(hw);
+               if (ret_val)
+                       goto out;
+       }
 
        kmrnctrlsta = ((offset << E1000_KMRNCTRLSTA_OFFSET_SHIFT) &
                       E1000_KMRNCTRLSTA_OFFSET) | E1000_KMRNCTRLSTA_REN;
@@ -452,41 +533,111 @@ s32 e1000e_read_kmrn_reg(struct e1000_hw *hw, u32 offset, u16 *data)
        kmrnctrlsta = er32(KMRNCTRLSTA);
        *data = (u16)kmrnctrlsta;
 
-       hw->phy.ops.release_phy(hw);
+       if (!locked)
+               hw->phy.ops.release_phy(hw);
 
+out:
        return ret_val;
 }
 
 /**
- *  e1000e_write_kmrn_reg - Write kumeran register
+ *  e1000e_read_kmrn_reg -  Read kumeran register
+ *  @hw: pointer to the HW structure
+ *  @offset: register offset to be read
+ *  @data: pointer to the read data
+ *
+ *  Acquires semaphore then reads the PHY register at offset using the
+ *  kumeran interface.  The information retrieved is stored in data.
+ *  Release the acquired semaphore before exiting.
+ **/
+s32 e1000e_read_kmrn_reg(struct e1000_hw *hw, u32 offset, u16 *data)
+{
+       return __e1000_read_kmrn_reg(hw, offset, data, false);
+}
+
+/**
+ *  e1000e_read_kmrn_reg_locked -  Read kumeran register
+ *  @hw: pointer to the HW structure
+ *  @offset: register offset to be read
+ *  @data: pointer to the read data
+ *
+ *  Reads the PHY register at offset using the kumeran interface.  The
+ *  information retrieved is stored in data.
+ *  Assumes semaphore already acquired.
+ **/
+s32 e1000e_read_kmrn_reg_locked(struct e1000_hw *hw, u32 offset, u16 *data)
+{
+       return __e1000_read_kmrn_reg(hw, offset, data, true);
+}
+
+/**
+ *  __e1000_write_kmrn_reg - Write kumeran register
  *  @hw: pointer to the HW structure
  *  @offset: register offset to write to
  *  @data: data to write at register offset
+ *  @locked: semaphore has already been acquired or not
  *
  *  Acquires semaphore, if necessary.  Then write the data to PHY register
  *  at the offset using the kumeran interface.  Release any acquired semaphores
  *  before exiting.
  **/
-s32 e1000e_write_kmrn_reg(struct e1000_hw *hw, u32 offset, u16 data)
+static s32 __e1000_write_kmrn_reg(struct e1000_hw *hw, u32 offset, u16 data,
+                                  bool locked)
 {
        u32 kmrnctrlsta;
-       s32 ret_val;
+       s32 ret_val = 0;
 
-       ret_val = hw->phy.ops.acquire_phy(hw);
-       if (ret_val)
-               return ret_val;
+       if (!locked) {
+               if (!(hw->phy.ops.acquire_phy))
+                       goto out;
+
+               ret_val = hw->phy.ops.acquire_phy(hw);
+               if (ret_val)
+                       goto out;
+       }
 
        kmrnctrlsta = ((offset << E1000_KMRNCTRLSTA_OFFSET_SHIFT) &
                       E1000_KMRNCTRLSTA_OFFSET) | data;
        ew32(KMRNCTRLSTA, kmrnctrlsta);
 
        udelay(2);
-       hw->phy.ops.release_phy(hw);
 
+       if (!locked)
+               hw->phy.ops.release_phy(hw);
+
+out:
        return ret_val;
 }
 
 /**
+ *  e1000e_write_kmrn_reg -  Write kumeran register
+ *  @hw: pointer to the HW structure
+ *  @offset: register offset to write to
+ *  @data: data to write at register offset
+ *
+ *  Acquires semaphore then writes the data to the PHY register at the offset
+ *  using the kumeran interface.  Release the acquired semaphore before exiting.
+ **/
+s32 e1000e_write_kmrn_reg(struct e1000_hw *hw, u32 offset, u16 data)
+{
+       return __e1000_write_kmrn_reg(hw, offset, data, false);
+}
+
+/**
+ *  e1000e_write_kmrn_reg_locked -  Write kumeran register
+ *  @hw: pointer to the HW structure
+ *  @offset: register offset to write to
+ *  @data: data to write at register offset
+ *
+ *  Write the data to PHY register at the offset using the kumeran interface.
+ *  Assumes semaphore already acquired.
+ **/
+s32 e1000e_write_kmrn_reg_locked(struct e1000_hw *hw, u32 offset, u16 data)
+{
+       return __e1000_write_kmrn_reg(hw, offset, data, true);
+}
+
+/**
  *  e1000_copper_link_setup_82577 - Setup 82577 PHY for copper link
  *  @hw: pointer to the HW structure
  *
@@ -2105,6 +2256,10 @@ s32 e1000e_write_phy_reg_bm(struct e1000_hw *hw, u32 offset, u16 data)
        u32 page = offset >> IGP_PAGE_SHIFT;
        u32 page_shift = 0;
 
+       ret_val = hw->phy.ops.acquire_phy(hw);
+       if (ret_val)
+               return ret_val;
+
        /* Page 800 works differently than the rest so it has its own func */
        if (page == BM_WUC_PAGE) {
                ret_val = e1000_access_phy_wakeup_reg_bm(hw, offset, &data,
@@ -2112,10 +2267,6 @@ s32 e1000e_write_phy_reg_bm(struct e1000_hw *hw, u32 offset, u16 data)
                goto out;
        }
 
-       ret_val = hw->phy.ops.acquire_phy(hw);
-       if (ret_val)
-               goto out;
-
        hw->phy.addr = e1000_get_phy_addr_for_bm_page(page, offset);
 
        if (offset > MAX_PHY_MULTI_PAGE_REG) {
@@ -2135,18 +2286,15 @@ s32 e1000e_write_phy_reg_bm(struct e1000_hw *hw, u32 offset, u16 data)
                /* Page is shifted left, PHY expects (page x 32) */
                ret_val = e1000e_write_phy_reg_mdic(hw, page_select,
                                                    (page << page_shift));
-               if (ret_val) {
-                       hw->phy.ops.release_phy(hw);
+               if (ret_val)
                        goto out;
-               }
        }
 
        ret_val = e1000e_write_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset,
                                            data);
 
-       hw->phy.ops.release_phy(hw);
-
 out:
+       hw->phy.ops.release_phy(hw);
        return ret_val;
 }
 
@@ -2167,6 +2315,10 @@ s32 e1000e_read_phy_reg_bm(struct e1000_hw *hw, u32 offset, u16 *data)
        u32 page = offset >> IGP_PAGE_SHIFT;
        u32 page_shift = 0;
 
+       ret_val = hw->phy.ops.acquire_phy(hw);
+       if (ret_val)
+               return ret_val;
+
        /* Page 800 works differently than the rest so it has its own func */
        if (page == BM_WUC_PAGE) {
                ret_val = e1000_access_phy_wakeup_reg_bm(hw, offset, data,
@@ -2174,10 +2326,6 @@ s32 e1000e_read_phy_reg_bm(struct e1000_hw *hw, u32 offset, u16 *data)
                goto out;
        }
 
-       ret_val = hw->phy.ops.acquire_phy(hw);
-       if (ret_val)
-               goto out;
-
        hw->phy.addr = e1000_get_phy_addr_for_bm_page(page, offset);
 
        if (offset > MAX_PHY_MULTI_PAGE_REG) {
@@ -2197,17 +2345,14 @@ s32 e1000e_read_phy_reg_bm(struct e1000_hw *hw, u32 offset, u16 *data)
                /* Page is shifted left, PHY expects (page x 32) */
                ret_val = e1000e_write_phy_reg_mdic(hw, page_select,
                                                    (page << page_shift));
-               if (ret_val) {
-                       hw->phy.ops.release_phy(hw);
+               if (ret_val)
                        goto out;
-               }
        }
 
        ret_val = e1000e_read_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset,
                                           data);
-       hw->phy.ops.release_phy(hw);
-
 out:
+       hw->phy.ops.release_phy(hw);
        return ret_val;
 }
 
@@ -2226,17 +2371,17 @@ s32 e1000e_read_phy_reg_bm2(struct e1000_hw *hw, u32 offset, u16 *data)
        s32 ret_val;
        u16 page = (u16)(offset >> IGP_PAGE_SHIFT);
 
+       ret_val = hw->phy.ops.acquire_phy(hw);
+       if (ret_val)
+               return ret_val;
+
        /* Page 800 works differently than the rest so it has its own func */
        if (page == BM_WUC_PAGE) {
                ret_val = e1000_access_phy_wakeup_reg_bm(hw, offset, data,
                                                         true);
-               return ret_val;
+               goto out;
        }
 
-       ret_val = hw->phy.ops.acquire_phy(hw);
-       if (ret_val)
-               return ret_val;
-
        hw->phy.addr = 1;
 
        if (offset > MAX_PHY_MULTI_PAGE_REG) {
@@ -2245,16 +2390,14 @@ s32 e1000e_read_phy_reg_bm2(struct e1000_hw *hw, u32 offset, u16 *data)
                ret_val = e1000e_write_phy_reg_mdic(hw, BM_PHY_PAGE_SELECT,
                                                    page);
 
-               if (ret_val) {
-                       hw->phy.ops.release_phy(hw);
-                       return ret_val;
-               }
+               if (ret_val)
+                       goto out;
        }
 
        ret_val = e1000e_read_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset,
                                           data);
+out:
        hw->phy.ops.release_phy(hw);
-
        return ret_val;
 }
 
@@ -2272,17 +2415,17 @@ s32 e1000e_write_phy_reg_bm2(struct e1000_hw *hw, u32 offset, u16 data)
        s32 ret_val;
        u16 page = (u16)(offset >> IGP_PAGE_SHIFT);
 
+       ret_val = hw->phy.ops.acquire_phy(hw);
+       if (ret_val)
+               return ret_val;
+
        /* Page 800 works differently than the rest so it has its own func */
        if (page == BM_WUC_PAGE) {
                ret_val = e1000_access_phy_wakeup_reg_bm(hw, offset, &data,
                                                         false);
-               return ret_val;
+               goto out;
        }
 
-       ret_val = hw->phy.ops.acquire_phy(hw);
-       if (ret_val)
-               return ret_val;
-
        hw->phy.addr = 1;
 
        if (offset > MAX_PHY_MULTI_PAGE_REG) {
@@ -2290,17 +2433,15 @@ s32 e1000e_write_phy_reg_bm2(struct e1000_hw *hw, u32 offset, u16 data)
                ret_val = e1000e_write_phy_reg_mdic(hw, BM_PHY_PAGE_SELECT,
                                                    page);
 
-               if (ret_val) {
-                       hw->phy.ops.release_phy(hw);
-                       return ret_val;
-               }
+               if (ret_val)
+                       goto out;
        }
 
        ret_val = e1000e_write_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset,
                                            data);
 
+out:
        hw->phy.ops.release_phy(hw);
-
        return ret_val;
 }
 
@@ -2320,6 +2461,8 @@ s32 e1000e_write_phy_reg_bm2(struct e1000_hw *hw, u32 offset, u16 data)
  *  3) Write the address using the address opcode (0x11)
  *  4) Read or write the data using the data opcode (0x12)
  *  5) Restore 769_17.2 to its original value
+ *
+ *  Assumes semaphore already acquired.
  **/
 static s32 e1000_access_phy_wakeup_reg_bm(struct e1000_hw *hw, u32 offset,
                                          u16 *data, bool read)
@@ -2327,20 +2470,12 @@ static s32 e1000_access_phy_wakeup_reg_bm(struct e1000_hw *hw, u32 offset,
        s32 ret_val;
        u16 reg = BM_PHY_REG_NUM(offset);
        u16 phy_reg = 0;
-       u8  phy_acquired = 1;
-
 
        /* Gig must be disabled for MDIO accesses to page 800 */
        if ((hw->mac.type == e1000_pchlan) &&
           (!(er32(PHY_CTRL) & E1000_PHY_CTRL_GBE_DISABLE)))
                hw_dbg(hw, "Attempting to access page 800 while gig enabled\n");
 
-       ret_val = hw->phy.ops.acquire_phy(hw);
-       if (ret_val) {
-               phy_acquired = 0;
-               goto out;
-       }
-
        /* All operations in this function are phy address 1 */
        hw->phy.addr = 1;
 
@@ -2397,8 +2532,6 @@ static s32 e1000_access_phy_wakeup_reg_bm(struct e1000_hw *hw, u32 offset,
        ret_val = e1000e_write_phy_reg_mdic(hw, BM_WUC_ENABLE_REG, phy_reg);
 
 out:
-       if (phy_acquired == 1)
-               hw->phy.ops.release_phy(hw);
        return ret_val;
 }
 
@@ -2439,52 +2572,63 @@ static s32 e1000_set_d0_lplu_state(struct e1000_hw *hw, bool active)
        return 0;
 }
 
+/**
+ *  e1000_set_mdio_slow_mode_hv - Set slow MDIO access mode
+ *  @hw:   pointer to the HW structure
+ *  @slow: true for slow mode, false for normal mode
+ *
+ *  Assumes semaphore already acquired.
+ **/
 s32 e1000_set_mdio_slow_mode_hv(struct e1000_hw *hw, bool slow)
 {
        s32 ret_val = 0;
        u16 data = 0;
 
-       ret_val = hw->phy.ops.acquire_phy(hw);
-       if (ret_val)
-               return ret_val;
-
        /* Set MDIO mode - page 769, register 16: 0x2580==slow, 0x2180==fast */
        hw->phy.addr = 1;
        ret_val = e1000e_write_phy_reg_mdic(hw, IGP01E1000_PHY_PAGE_SELECT,
                                         (BM_PORT_CTRL_PAGE << IGP_PAGE_SHIFT));
-       if (ret_val) {
-               hw->phy.ops.release_phy(hw);
-               return ret_val;
-       }
+       if (ret_val)
+               goto out;
+
        ret_val = e1000e_write_phy_reg_mdic(hw, BM_CS_CTRL1,
                                           (0x2180 | (slow << 10)));
+       if (ret_val)
+               goto out;
 
        /* dummy read when reverting to fast mode - throw away result */
        if (!slow)
-               e1000e_read_phy_reg_mdic(hw, BM_CS_CTRL1, &data);
-
-       hw->phy.ops.release_phy(hw);
+               ret_val = e1000e_read_phy_reg_mdic(hw, BM_CS_CTRL1, &data);
 
+out:
        return ret_val;
 }
 
 /**
- *  e1000_read_phy_reg_hv -  Read HV PHY register
+ *  __e1000_read_phy_reg_hv -  Read HV PHY register
  *  @hw: pointer to the HW structure
  *  @offset: register offset to be read
  *  @data: pointer to the read data
+ *  @locked: semaphore has already been acquired or not
  *
  *  Acquires semaphore, if necessary, then reads the PHY register at offset
- *  and storing the retrieved information in data.  Release any acquired
+ *  and stores the retrieved information in data.  Release any acquired
  *  semaphore before exiting.
  **/
-s32 e1000_read_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 *data)
+static s32 __e1000_read_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 *data,
+                                   bool locked)
 {
        s32 ret_val;
        u16 page = BM_PHY_REG_PAGE(offset);
        u16 reg = BM_PHY_REG_NUM(offset);
        bool in_slow_mode = false;
 
+       if (!locked) {
+               ret_val = hw->phy.ops.acquire_phy(hw);
+               if (ret_val)
+                       return ret_val;
+       }
+
        /* Workaround failure in MDIO access while cable is disconnected */
        if ((hw->phy.type == e1000_phy_82577) &&
            !(er32(STATUS) & E1000_STATUS_LU)) {
@@ -2508,10 +2652,6 @@ s32 e1000_read_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 *data)
                goto out;
        }
 
-       ret_val = hw->phy.ops.acquire_phy(hw);
-       if (ret_val)
-               goto out;
-
        hw->phy.addr = e1000_get_phy_addr_for_hv_page(page);
 
        if (page == HV_INTC_FC_PAGE_START)
@@ -2529,42 +2669,76 @@ s32 e1000_read_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 *data)
                        ret_val = e1000e_write_phy_reg_mdic(hw,
                                                     IGP01E1000_PHY_PAGE_SELECT,
                                                     (page << IGP_PAGE_SHIFT));
-                       if (ret_val) {
-                               hw->phy.ops.release_phy(hw);
-                               goto out;
-                       }
                        hw->phy.addr = phy_addr;
                }
        }
 
        ret_val = e1000e_read_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & reg,
                                          data);
-       hw->phy.ops.release_phy(hw);
-
 out:
        /* Revert to MDIO fast mode, if applicable */
        if ((hw->phy.type == e1000_phy_82577) && in_slow_mode)
                ret_val = e1000_set_mdio_slow_mode_hv(hw, false);
 
+       if (!locked)
+               hw->phy.ops.release_phy(hw);
+
        return ret_val;
 }
 
 /**
- *  e1000_write_phy_reg_hv - Write HV PHY register
+ *  e1000_read_phy_reg_hv -  Read HV PHY register
+ *  @hw: pointer to the HW structure
+ *  @offset: register offset to be read
+ *  @data: pointer to the read data
+ *
+ *  Acquires semaphore then reads the PHY register at offset and stores
+ *  the retrieved information in data.  Release the acquired semaphore
+ *  before exiting.
+ **/
+s32 e1000_read_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 *data)
+{
+       return __e1000_read_phy_reg_hv(hw, offset, data, false);
+}
+
+/**
+ *  e1000_read_phy_reg_hv_locked -  Read HV PHY register
+ *  @hw: pointer to the HW structure
+ *  @offset: register offset to be read
+ *  @data: pointer to the read data
+ *
+ *  Reads the PHY register at offset and stores the retrieved information
+ *  in data.  Assumes semaphore already acquired.
+ **/
+s32 e1000_read_phy_reg_hv_locked(struct e1000_hw *hw, u32 offset, u16 *data)
+{
+       return __e1000_read_phy_reg_hv(hw, offset, data, true);
+}
+
+/**
+ *  __e1000_write_phy_reg_hv - Write HV PHY register
  *  @hw: pointer to the HW structure
  *  @offset: register offset to write to
  *  @data: data to write at register offset
+ *  @locked: semaphore has already been acquired or not
  *
  *  Acquires semaphore, if necessary, then writes the data to PHY register
  *  at the offset.  Release any acquired semaphores before exiting.
  **/
-s32 e1000_write_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 data)
+static s32 __e1000_write_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 data,
+                                    bool locked)
 {
        s32 ret_val;
        u16 page = BM_PHY_REG_PAGE(offset);
        u16 reg = BM_PHY_REG_NUM(offset);
        bool in_slow_mode = false;
 
+       if (!locked) {
+               ret_val = hw->phy.ops.acquire_phy(hw);
+               if (ret_val)
+                       return ret_val;
+       }
+
        /* Workaround failure in MDIO access while cable is disconnected */
        if ((hw->phy.type == e1000_phy_82577) &&
            !(er32(STATUS) & E1000_STATUS_LU)) {
@@ -2588,10 +2762,6 @@ s32 e1000_write_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 data)
                goto out;
        }
 
-       ret_val = hw->phy.ops.acquire_phy(hw);
-       if (ret_val)
-               goto out;
-
        hw->phy.addr = e1000_get_phy_addr_for_hv_page(page);
 
        if (page == HV_INTC_FC_PAGE_START)
@@ -2607,15 +2777,10 @@ s32 e1000_write_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 data)
            ((MAX_PHY_REG_ADDRESS & reg) == 0) &&
            (data & (1 << 11))) {
                u16 data2 = 0x7EFF;
-               hw->phy.ops.release_phy(hw);
                ret_val = e1000_access_phy_debug_regs_hv(hw, (1 << 6) | 0x3,
                                                         &data2, false);
                if (ret_val)
                        goto out;
-
-               ret_val = hw->phy.ops.acquire_phy(hw);
-               if (ret_val)
-                       goto out;
        }
 
        if (reg > MAX_PHY_MULTI_PAGE_REG) {
@@ -2630,27 +2795,53 @@ s32 e1000_write_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 data)
                        ret_val = e1000e_write_phy_reg_mdic(hw,
                                                     IGP01E1000_PHY_PAGE_SELECT,
                                                     (page << IGP_PAGE_SHIFT));
-                       if (ret_val) {
-                               hw->phy.ops.release_phy(hw);
-                               goto out;
-                       }
                        hw->phy.addr = phy_addr;
                }
        }
 
        ret_val = e1000e_write_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & reg,
                                          data);
-       hw->phy.ops.release_phy(hw);
 
 out:
        /* Revert to MDIO fast mode, if applicable */
        if ((hw->phy.type == e1000_phy_82577) && in_slow_mode)
                ret_val = e1000_set_mdio_slow_mode_hv(hw, false);
 
+       if (!locked)
+               hw->phy.ops.release_phy(hw);
+
        return ret_val;
 }
 
 /**
+ *  e1000_write_phy_reg_hv - Write HV PHY register
+ *  @hw: pointer to the HW structure
+ *  @offset: register offset to write to
+ *  @data: data to write at register offset
+ *
+ *  Acquires semaphore then writes the data to PHY register at the offset.
+ *  Release the acquired semaphores before exiting.
+ **/
+s32 e1000_write_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 data)
+{
+       return __e1000_write_phy_reg_hv(hw, offset, data, false);
+}
+
+/**
+ *  e1000_write_phy_reg_hv_locked - Write HV PHY register
+ *  @hw: pointer to the HW structure
+ *  @offset: register offset to write to
+ *  @data: data to write at register offset
+ *
+ *  Writes the data to PHY register at the offset.  Assumes semaphore
+ *  already acquired.
+ **/
+s32 e1000_write_phy_reg_hv_locked(struct e1000_hw *hw, u32 offset, u16 data)
+{
+       return __e1000_write_phy_reg_hv(hw, offset, data, true);
+}
+
+/**
  *  e1000_get_phy_addr_for_hv_page - Get PHY adrress based on page
  *  @page: page to be accessed
  **/
@@ -2671,10 +2862,9 @@ static u32 e1000_get_phy_addr_for_hv_page(u32 page)
  *  @data: pointer to the data to be read or written
  *  @read: determines if operation is read or written
  *
- *  Acquires semaphore, if necessary, then reads the PHY register at offset
- *  and storing the retreived information in data.  Release any acquired
- *  semaphores before exiting.  Note that the procedure to read these regs
- *  uses the address port and data port to read/write.
+ *  Reads the PHY register at offset and stores the retreived information
+ *  in data.  Assumes semaphore already acquired.  Note that the procedure
+ *  to read these regs uses the address port and data port to read/write.
  **/
 static s32 e1000_access_phy_debug_regs_hv(struct e1000_hw *hw, u32 offset,
                                           u16 *data, bool read)
@@ -2682,20 +2872,12 @@ static s32 e1000_access_phy_debug_regs_hv(struct e1000_hw *hw, u32 offset,
        s32 ret_val;
        u32 addr_reg = 0;
        u32 data_reg = 0;
-       u8  phy_acquired = 1;
 
        /* This takes care of the difference with desktop vs mobile phy */
        addr_reg = (hw->phy.type == e1000_phy_82578) ?
                   I82578_ADDR_REG : I82577_ADDR_REG;
        data_reg = addr_reg + 1;
 
-       ret_val = hw->phy.ops.acquire_phy(hw);
-       if (ret_val) {
-               hw_dbg(hw, "Could not acquire PHY\n");
-               phy_acquired = 0;
-               goto out;
-       }
-
        /* All operations in this function are phy address 2 */
        hw->phy.addr = 2;
 
@@ -2718,8 +2900,6 @@ static s32 e1000_access_phy_debug_regs_hv(struct e1000_hw *hw, u32 offset,
        }
 
 out:
-       if (phy_acquired == 1)
-               hw->phy.ops.release_phy(hw);
        return ret_val;
 }
 
index d4d9a3e..f5b96ca 100644 (file)
  * Sorry, I had to rewrite most of this for 2.5.x -DaveM
  */
 
+#include <linux/capability.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
index b7311bc..f7d9ac8 100644 (file)
 #include <linux/mii.h>
 #include <linux/phy.h>
 #include <linux/platform_device.h>
+#include <linux/sched.h>
 #include <net/ethoc.h>
 
+static int buffer_size = 0x8000; /* 32 KBytes */
+module_param(buffer_size, int, 0);
+MODULE_PARM_DESC(buffer_size, "DMA buffer allocation size");
+
 /* register offsets */
 #define        MODER           0x00
 #define        INT_SOURCE      0x04
  * struct ethoc - driver-private device structure
  * @iobase:    pointer to I/O memory region
  * @membase:   pointer to buffer memory region
+ * @dma_alloc: dma allocated buffer size
  * @num_tx:    number of send buffers
  * @cur_tx:    last send buffer written
  * @dty_tx:    last buffer actually sent
 struct ethoc {
        void __iomem *iobase;
        void __iomem *membase;
+       int dma_alloc;
 
        unsigned int num_tx;
        unsigned int cur_tx;
@@ -216,24 +223,25 @@ struct ethoc_bd {
        u32 addr;
 };
 
-static u32 ethoc_read(struct ethoc *dev, loff_t offset)
+static inline u32 ethoc_read(struct ethoc *dev, loff_t offset)
 {
        return ioread32(dev->iobase + offset);
 }
 
-static void ethoc_write(struct ethoc *dev, loff_t offset, u32 data)
+static inline void ethoc_write(struct ethoc *dev, loff_t offset, u32 data)
 {
        iowrite32(data, dev->iobase + offset);
 }
 
-static void ethoc_read_bd(struct ethoc *dev, int index, struct ethoc_bd *bd)
+static inline void ethoc_read_bd(struct ethoc *dev, int index,
+               struct ethoc_bd *bd)
 {
        loff_t offset = ETHOC_BD_BASE + (index * sizeof(struct ethoc_bd));
        bd->stat = ethoc_read(dev, offset + 0);
        bd->addr = ethoc_read(dev, offset + 4);
 }
 
-static void ethoc_write_bd(struct ethoc *dev, int index,
+static inline void ethoc_write_bd(struct ethoc *dev, int index,
                const struct ethoc_bd *bd)
 {
        loff_t offset = ETHOC_BD_BASE + (index * sizeof(struct ethoc_bd));
@@ -241,33 +249,33 @@ static void ethoc_write_bd(struct ethoc *dev, int index,
        ethoc_write(dev, offset + 4, bd->addr);
 }
 
-static void ethoc_enable_irq(struct ethoc *dev, u32 mask)
+static inline void ethoc_enable_irq(struct ethoc *dev, u32 mask)
 {
        u32 imask = ethoc_read(dev, INT_MASK);
        imask |= mask;
        ethoc_write(dev, INT_MASK, imask);
 }
 
-static void ethoc_disable_irq(struct ethoc *dev, u32 mask)
+static inline void ethoc_disable_irq(struct ethoc *dev, u32 mask)
 {
        u32 imask = ethoc_read(dev, INT_MASK);
        imask &= ~mask;
        ethoc_write(dev, INT_MASK, imask);
 }
 
-static void ethoc_ack_irq(struct ethoc *dev, u32 mask)
+static inline void ethoc_ack_irq(struct ethoc *dev, u32 mask)
 {
        ethoc_write(dev, INT_SOURCE, mask);
 }
 
-static void ethoc_enable_rx_and_tx(struct ethoc *dev)
+static inline void ethoc_enable_rx_and_tx(struct ethoc *dev)
 {
        u32 mode = ethoc_read(dev, MODER);
        mode |= MODER_RXEN | MODER_TXEN;
        ethoc_write(dev, MODER, mode);
 }
 
-static void ethoc_disable_rx_and_tx(struct ethoc *dev)
+static inline void ethoc_disable_rx_and_tx(struct ethoc *dev)
 {
        u32 mode = ethoc_read(dev, MODER);
        mode &= ~(MODER_RXEN | MODER_TXEN);
@@ -284,7 +292,7 @@ static int ethoc_init_ring(struct ethoc *dev)
        dev->cur_rx = 0;
 
        /* setup transmission buffers */
-       bd.addr = 0;
+       bd.addr = virt_to_phys(dev->membase);
        bd.stat = TX_BD_IRQ | TX_BD_CRC;
 
        for (i = 0; i < dev->num_tx; i++) {
@@ -295,7 +303,6 @@ static int ethoc_init_ring(struct ethoc *dev)
                bd.addr += ETHOC_BUFSIZ;
        }
 
-       bd.addr = dev->num_tx * ETHOC_BUFSIZ;
        bd.stat = RX_BD_EMPTY | RX_BD_IRQ;
 
        for (i = 0; i < dev->num_rx; i++) {
@@ -400,8 +407,12 @@ static int ethoc_rx(struct net_device *dev, int limit)
                if (ethoc_update_rx_stats(priv, &bd) == 0) {
                        int size = bd.stat >> 16;
                        struct sk_buff *skb = netdev_alloc_skb(dev, size);
+
+                       size -= 4; /* strip the CRC */
+                       skb_reserve(skb, 2); /* align TCP/IP header */
+
                        if (likely(skb)) {
-                               void *src = priv->membase + bd.addr;
+                               void *src = phys_to_virt(bd.addr);
                                memcpy_fromio(skb_put(skb, size), src, size);
                                skb->protocol = eth_type_trans(skb, dev);
                                priv->stats.rx_packets++;
@@ -498,7 +509,7 @@ static irqreturn_t ethoc_interrupt(int irq, void *dev_id)
                return IRQ_NONE;
        }
 
-       ethoc_ack_irq(priv, INT_MASK_ALL);
+       ethoc_ack_irq(priv, pending);
 
        if (pending & INT_MASK_BUSY) {
                dev_err(&dev->dev, "packet dropped\n");
@@ -653,9 +664,10 @@ static int ethoc_open(struct net_device *dev)
        if (ret)
                return ret;
 
-       /* calculate the number of TX/RX buffers */
-       num_bd = (dev->mem_end - dev->mem_start + 1) / ETHOC_BUFSIZ;
-       priv->num_tx = min(min_tx, num_bd / 4);
+       /* calculate the number of TX/RX buffers, maximum 128 supported */
+       num_bd = min_t(unsigned int,
+               128, (dev->mem_end - dev->mem_start + 1) / ETHOC_BUFSIZ);
+       priv->num_tx = max(min_tx, num_bd / 4);
        priv->num_rx = num_bd - priv->num_tx;
        ethoc_write(priv, TX_BD_NUM, priv->num_tx);
 
@@ -823,7 +835,7 @@ static netdev_tx_t ethoc_start_xmit(struct sk_buff *skb, struct net_device *dev)
        else
                bd.stat &= ~TX_BD_PAD;
 
-       dest = priv->membase + bd.addr;
+       dest = phys_to_virt(bd.addr);
        memcpy_toio(dest, skb->data, skb->len);
 
        bd.stat &= ~(TX_BD_STATS | TX_BD_LEN_MASK);
@@ -903,22 +915,19 @@ static int ethoc_probe(struct platform_device *pdev)
 
        /* obtain buffer memory space */
        res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
-       if (!res) {
-               dev_err(&pdev->dev, "cannot obtain memory space\n");
-               ret = -ENXIO;
-               goto free;
-       }
-
-       mem = devm_request_mem_region(&pdev->dev, res->start,
+       if (res) {
+               mem = devm_request_mem_region(&pdev->dev, res->start,
                        res->end - res->start + 1, res->name);
-       if (!mem) {
-               dev_err(&pdev->dev, "cannot request memory space\n");
-               ret = -ENXIO;
-               goto free;
+               if (!mem) {
+                       dev_err(&pdev->dev, "cannot request memory space\n");
+                       ret = -ENXIO;
+                       goto free;
+               }
+
+               netdev->mem_start = mem->start;
+               netdev->mem_end   = mem->end;
        }
 
-       netdev->mem_start = mem->start;
-       netdev->mem_end   = mem->end;
 
        /* obtain device IRQ number */
        res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
@@ -933,6 +942,7 @@ static int ethoc_probe(struct platform_device *pdev)
        /* setup driver-private data */
        priv = netdev_priv(netdev);
        priv->netdev = netdev;
+       priv->dma_alloc = 0;
 
        priv->iobase = devm_ioremap_nocache(&pdev->dev, netdev->base_addr,
                        mmio->end - mmio->start + 1);
@@ -942,12 +952,27 @@ static int ethoc_probe(struct platform_device *pdev)
                goto error;
        }
 
-       priv->membase = devm_ioremap_nocache(&pdev->dev, netdev->mem_start,
-                       mem->end - mem->start + 1);
-       if (!priv->membase) {
-               dev_err(&pdev->dev, "cannot remap memory space\n");
-               ret = -ENXIO;
-               goto error;
+       if (netdev->mem_end) {
+               priv->membase = devm_ioremap_nocache(&pdev->dev,
+                       netdev->mem_start, mem->end - mem->start + 1);
+               if (!priv->membase) {
+                       dev_err(&pdev->dev, "cannot remap memory space\n");
+                       ret = -ENXIO;
+                       goto error;
+               }
+       } else {
+               /* Allocate buffer memory */
+               priv->membase = dma_alloc_coherent(NULL,
+                       buffer_size, (void *)&netdev->mem_start,
+                       GFP_KERNEL);
+               if (!priv->membase) {
+                       dev_err(&pdev->dev, "cannot allocate %dB buffer\n",
+                               buffer_size);
+                       ret = -ENOMEM;
+                       goto error;
+               }
+               netdev->mem_end = netdev->mem_start + buffer_size;
+               priv->dma_alloc = buffer_size;
        }
 
        /* Allow the platform setup code to pass in a MAC address. */
@@ -1034,6 +1059,9 @@ free_mdio:
        kfree(priv->mdio->irq);
        mdiobus_free(priv->mdio);
 free:
+       if (priv->dma_alloc)
+               dma_free_coherent(NULL, priv->dma_alloc, priv->membase,
+                       netdev->mem_start);
        free_netdev(netdev);
 out:
        return ret;
@@ -1059,7 +1087,9 @@ static int ethoc_remove(struct platform_device *pdev)
                        kfree(priv->mdio->irq);
                        mdiobus_free(priv->mdio);
                }
-
+               if (priv->dma_alloc)
+                       dma_free_coherent(NULL, priv->dma_alloc, priv->membase,
+                               netdev->mem_start);
                unregister_netdev(netdev);
                free_netdev(netdev);
        }
index b2a5ec8..dd4ba01 100644 (file)
 
 #include <linux/module.h>
 #include <linux/kernel.h>
+#include <linux/sched.h>
 #include <linux/string.h>
 #include <linux/errno.h>
 #include <linux/ioport.h>
index 2923438..16a1d58 100644 (file)
@@ -1654,7 +1654,7 @@ static const struct net_device_ops fec_netdev_ops = {
   *
   * index is only used in legacy code
   */
-int __init fec_enet_init(struct net_device *dev, int index)
+static int fec_enet_init(struct net_device *dev, int index)
 {
        struct fec_enet_private *fep = netdev_priv(dev);
        struct bufdesc *cbd_base;
index c40113f..66dace6 100644 (file)
@@ -759,12 +759,6 @@ static void mpc52xx_fec_reset(struct net_device *dev)
 
        mpc52xx_fec_hw_init(dev);
 
-       if (priv->phydev) {
-               phy_stop(priv->phydev);
-               phy_write(priv->phydev, MII_BMCR, BMCR_RESET);
-               phy_start(priv->phydev);
-       }
-
        bcom_fec_rx_reset(priv->rx_dmatsk);
        bcom_fec_tx_reset(priv->tx_dmatsk);
 
index 31e6d62..ee0f3c6 100644 (file)
@@ -155,6 +155,7 @@ static struct of_device_id mpc52xx_fec_mdio_match[] = {
        { .compatible = "mpc5200b-fec-phy", },
        {}
 };
+MODULE_DEVICE_TABLE(of, mpc52xx_fec_mdio_match);
 
 struct of_platform_driver mpc52xx_fec_mdio_driver = {
        .name = "mpc5200b-fec-phy",
index 0a1c2bb..e1da466 100644 (file)
@@ -49,6 +49,7 @@
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
 #include <linux/delay.h>
+#include <linux/sched.h>
 #include <linux/spinlock.h>
 #include <linux/ethtool.h>
 #include <linux/timer.h>
index 2bc2d2b..ec2f503 100644 (file)
@@ -1110,6 +1110,7 @@ static struct of_device_id fs_enet_match[] = {
 #endif
        {}
 };
+MODULE_DEVICE_TABLE(of, fs_enet_match);
 
 static struct of_platform_driver fs_enet_driver = {
        .name   = "fs_enet",
index 93b481b..24ff9f4 100644 (file)
@@ -221,6 +221,7 @@ static struct of_device_id fs_enet_mdio_bb_match[] = {
        },
        {},
 };
+MODULE_DEVICE_TABLE(of, fs_enet_mdio_bb_match);
 
 static struct of_platform_driver fs_enet_bb_mdio_driver = {
        .name = "fsl-bb-mdio",
index a2d69c1..96eba42 100644 (file)
@@ -219,6 +219,7 @@ static struct of_device_id fs_enet_mdio_fec_match[] = {
 #endif
        {},
 };
+MODULE_DEVICE_TABLE(of, fs_enet_mdio_fec_match);
 
 static struct of_platform_driver fs_enet_fec_mdio_driver = {
        .name = "fsl-fec-mdio",
index d167090..6ac4648 100644 (file)
@@ -407,6 +407,7 @@ static struct of_device_id fsl_pq_mdio_match[] = {
        },
        {},
 };
+MODULE_DEVICE_TABLE(of, fsl_pq_mdio_match);
 
 static struct of_platform_driver fsl_pq_mdio_driver = {
        .name = "fsl-pq_mdio",
index 1e5289f..5bf31f1 100644 (file)
@@ -2325,9 +2325,6 @@ static irqreturn_t gfar_error(int irq, void *dev_id)
        return IRQ_HANDLED;
 }
 
-/* work with hotplug and coldplug */
-MODULE_ALIAS("platform:fsl-gianfar");
-
 static struct of_device_id gfar_match[] =
 {
        {
@@ -2336,6 +2333,7 @@ static struct of_device_id gfar_match[] =
        },
        {},
 };
+MODULE_DEVICE_TABLE(of, gfar_match);
 
 /* Structure for a device driver */
 static struct of_platform_driver gfar_driver = {
index 1d5064a..f7519a5 100644 (file)
@@ -145,6 +145,7 @@ static int tx_params[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1};
 /* Time in jiffies before concluding the transmitter is hung. */
 #define TX_TIMEOUT  (5*HZ)
 
+#include <linux/capability.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/string.h>
index 7bcaf7c..e344c84 100644 (file)
@@ -44,6 +44,7 @@
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
+#include <linux/sched.h>
 #include <linux/string.h>
 #include <linux/workqueue.h>
 #include <linux/fs.h>
index aa4488e..ed60fd6 100644 (file)
@@ -71,6 +71,7 @@
 
 /*****************************************************************************/
 
+#include <linux/capability.h>
 #include <linux/module.h>
 #include <linux/ioport.h>
 #include <linux/string.h>
index 88c5935..1686f6d 100644 (file)
@@ -61,6 +61,7 @@
 
 /*****************************************************************************/
 
+#include <linux/capability.h>
 #include <linux/module.h>
 #include <linux/ioport.h>
 #include <linux/string.h>
index 0013c40..91c5790 100644 (file)
@@ -42,6 +42,7 @@
 
 /*****************************************************************************/
 
+#include <linux/capability.h>
 #include <linux/module.h>
 #include <linux/types.h>
 #include <linux/net.h>
index a9a1a99..dd86651 100644 (file)
@@ -98,6 +98,7 @@
 
 #include <linux/module.h>
 #include <linux/kernel.h>
+#include <linux/sched.h>
 #include <linux/string.h>
 #include <linux/errno.h>
 #include <linux/ioport.h>
index 89c82c5..3fae875 100644 (file)
@@ -24,6 +24,7 @@
  *
  */
 
+#include <linux/module.h>
 #include <linux/sched.h>
 #include <linux/string.h>
 #include <linux/errno.h>
@@ -443,7 +444,7 @@ static u32 __emac_calc_base_mr1(struct emac_instance *dev, int tx_size, int rx_s
                ret |= EMAC_MR1_TFS_2K;
                break;
        default:
-               printk(KERN_WARNING "%s: Unknown Rx FIFO size %d\n",
+               printk(KERN_WARNING "%s: Unknown Tx FIFO size %d\n",
                       dev->ndev->name, tx_size);
        }
 
@@ -470,6 +471,9 @@ static u32 __emac4_calc_base_mr1(struct emac_instance *dev, int tx_size, int rx_
        DBG2(dev, "__emac4_calc_base_mr1" NL);
 
        switch(tx_size) {
+       case 16384:
+               ret |= EMAC4_MR1_TFS_16K;
+               break;
        case 4096:
                ret |= EMAC4_MR1_TFS_4K;
                break;
@@ -477,7 +481,7 @@ static u32 __emac4_calc_base_mr1(struct emac_instance *dev, int tx_size, int rx_
                ret |= EMAC4_MR1_TFS_2K;
                break;
        default:
-               printk(KERN_WARNING "%s: Unknown Rx FIFO size %d\n",
+               printk(KERN_WARNING "%s: Unknown Tx FIFO size %d\n",
                       dev->ndev->name, tx_size);
        }
 
@@ -2985,6 +2989,7 @@ static struct of_device_id emac_match[] =
        },
        {},
 };
+MODULE_DEVICE_TABLE(of, emac_match);
 
 static struct of_platform_driver emac_driver = {
        .name = "emac",
index 0afc2cf..d34adf9 100644 (file)
@@ -153,6 +153,7 @@ struct emac_regs {
 #define EMAC4_MR1_RFS_16K              0x00280000
 #define EMAC4_MR1_TFS_2K                       0x00020000
 #define EMAC4_MR1_TFS_4K               0x00030000
+#define EMAC4_MR1_TFS_16K              0x00050000
 #define EMAC4_MR1_TR                   0x00008000
 #define EMAC4_MR1_MWSW_001             0x00001000
 #define EMAC4_MR1_JPSM                 0x00000800
index 801f088..030913f 100644 (file)
@@ -98,12 +98,13 @@ static void ri_tasklet(unsigned long dev)
                stats->tx_packets++;
                stats->tx_bytes +=skb->len;
 
-               skb->dev = __dev_get_by_index(&init_net, skb->iif);
+               skb->dev = dev_get_by_index(&init_net, skb->iif);
                if (!skb->dev) {
                        dev_kfree_skb(skb);
                        stats->tx_dropped++;
                        break;
                }
+               dev_put(skb->dev);
                skb->iif = _dev->ifindex;
 
                if (from & AT_EGRESS) {
index d004c35..b243ed3 100644 (file)
@@ -34,6 +34,7 @@
 #include <linux/interrupt.h>
 #include <linux/if_ether.h>
 #include <linux/ethtool.h>
+#include <linux/sched.h>
 
 #include "igb.h"
 
@@ -731,7 +732,7 @@ static int igb_set_ringparam(struct net_device *netdev,
 {
        struct igb_adapter *adapter = netdev_priv(netdev);
        struct igb_ring *temp_ring;
-       int i, err;
+       int i, err = 0;
        u32 new_rx_count, new_tx_count;
 
        if ((ring->rx_mini_pending) || (ring->rx_jumbo_pending))
@@ -751,18 +752,30 @@ static int igb_set_ringparam(struct net_device *netdev,
                return 0;
        }
 
+       while (test_and_set_bit(__IGB_RESETTING, &adapter->state))
+               msleep(1);
+
+       if (!netif_running(adapter->netdev)) {
+               for (i = 0; i < adapter->num_tx_queues; i++)
+                       adapter->tx_ring[i].count = new_tx_count;
+               for (i = 0; i < adapter->num_rx_queues; i++)
+                       adapter->rx_ring[i].count = new_rx_count;
+               adapter->tx_ring_count = new_tx_count;
+               adapter->rx_ring_count = new_rx_count;
+               goto clear_reset;
+       }
+
        if (adapter->num_tx_queues > adapter->num_rx_queues)
                temp_ring = vmalloc(adapter->num_tx_queues * sizeof(struct igb_ring));
        else
                temp_ring = vmalloc(adapter->num_rx_queues * sizeof(struct igb_ring));
-       if (!temp_ring)
-               return -ENOMEM;
 
-       while (test_and_set_bit(__IGB_RESETTING, &adapter->state))
-               msleep(1);
+       if (!temp_ring) {
+               err = -ENOMEM;
+               goto clear_reset;
+       }
 
-       if (netif_running(adapter->netdev))
-               igb_down(adapter);
+       igb_down(adapter);
 
        /*
         * We can't just free everything and then setup again,
@@ -819,14 +832,11 @@ static int igb_set_ringparam(struct net_device *netdev,
 
                adapter->rx_ring_count = new_rx_count;
        }
-
-       err = 0;
 err_setup:
-       if (netif_running(adapter->netdev))
-               igb_up(adapter);
-
-       clear_bit(__IGB_RESETTING, &adapter->state);
+       igb_up(adapter);
        vfree(temp_ring);
+clear_reset:
+       clear_bit(__IGB_RESETTING, &adapter->state);
        return err;
 }
 
index ee17a09..c68265b 100644 (file)
@@ -279,7 +279,7 @@ static int igbvf_set_ringparam(struct net_device *netdev,
 {
        struct igbvf_adapter *adapter = netdev_priv(netdev);
        struct igbvf_ring *temp_ring;
-       int err;
+       int err = 0;
        u32 new_rx_count, new_tx_count;
 
        if ((ring->rx_mini_pending) || (ring->rx_jumbo_pending))
@@ -299,15 +299,22 @@ static int igbvf_set_ringparam(struct net_device *netdev,
                return 0;
        }
 
-       temp_ring = vmalloc(sizeof(struct igbvf_ring));
-       if (!temp_ring)
-               return -ENOMEM;
-
        while (test_and_set_bit(__IGBVF_RESETTING, &adapter->state))
                msleep(1);
 
-       if (netif_running(adapter->netdev))
-               igbvf_down(adapter);
+       if (!netif_running(adapter->netdev)) {
+               adapter->tx_ring->count = new_tx_count;
+               adapter->rx_ring->count = new_rx_count;
+               goto clear_reset;
+       }
+
+       temp_ring = vmalloc(sizeof(struct igbvf_ring));
+       if (!temp_ring) {
+               err = -ENOMEM;
+               goto clear_reset;
+       }
+
+       igbvf_down(adapter);
 
        /*
         * We can't just free everything and then setup again,
@@ -339,14 +346,11 @@ static int igbvf_set_ringparam(struct net_device *netdev,
 
                memcpy(adapter->rx_ring, temp_ring,sizeof(struct igbvf_ring));
        }
-
-       err = 0;
 err_setup:
-       if (netif_running(adapter->netdev))
-               igbvf_up(adapter);
-
-       clear_bit(__IGBVF_RESETTING, &adapter->state);
+       igbvf_up(adapter);
        vfree(temp_ring);
+clear_reset:
+       clear_bit(__IGBVF_RESETTING, &adapter->state);
        return err;
 }
 
index 38bf7cf..c412e80 100644 (file)
@@ -232,8 +232,11 @@ static int sa1100_irda_startup(struct sa1100_irda *si)
        /*
         * Ensure that the ports for this device are setup correctly.
         */
-       if (si->pdata->startup)
-               si->pdata->startup(si->dev);
+       if (si->pdata->startup) {
+               ret = si->pdata->startup(si->dev);
+               if (ret)
+                       return ret;
+       }
 
        /*
         * Configure PPC for IRDA - we want to drive TXD2 low.
index fcf287b..99e1ec0 100644 (file)
 #include <linux/module.h>
 #include <linux/delay.h>
 #include <linux/init.h>
+#include <linux/sched.h>
 
 #include <net/irda/irda.h>
 
index 2ec58dc..34b0492 100644 (file)
@@ -330,6 +330,8 @@ static enum ixgbe_media_type ixgbe_get_media_type_82599(struct ixgbe_hw *hw)
 
        switch (hw->device_id) {
        case IXGBE_DEV_ID_82599_KX4:
+       case IXGBE_DEV_ID_82599_KX4_MEZZ:
+       case IXGBE_DEV_ID_82599_COMBO_BACKPLANE:
        case IXGBE_DEV_ID_82599_XAUI_LOM:
                /* Default device ID is mezzanine card KX/KX4 */
                media_type = ixgbe_media_type_backplane;
index fa314cb..856c18c 100644 (file)
@@ -798,7 +798,7 @@ static int ixgbe_set_ringparam(struct net_device *netdev,
 {
        struct ixgbe_adapter *adapter = netdev_priv(netdev);
        struct ixgbe_ring *temp_tx_ring, *temp_rx_ring;
-       int i, err;
+       int i, err = 0;
        u32 new_rx_count, new_tx_count;
        bool need_update = false;
 
@@ -822,6 +822,16 @@ static int ixgbe_set_ringparam(struct net_device *netdev,
        while (test_and_set_bit(__IXGBE_RESETTING, &adapter->state))
                msleep(1);
 
+       if (!netif_running(adapter->netdev)) {
+               for (i = 0; i < adapter->num_tx_queues; i++)
+                       adapter->tx_ring[i].count = new_tx_count;
+               for (i = 0; i < adapter->num_rx_queues; i++)
+                       adapter->rx_ring[i].count = new_rx_count;
+               adapter->tx_ring_count = new_tx_count;
+               adapter->rx_ring_count = new_rx_count;
+               goto err_setup;
+       }
+
        temp_tx_ring = kcalloc(adapter->num_tx_queues,
                               sizeof(struct ixgbe_ring), GFP_KERNEL);
        if (!temp_tx_ring) {
@@ -879,8 +889,7 @@ static int ixgbe_set_ringparam(struct net_device *netdev,
 
        /* if rings need to be updated, here's the place to do it in one shot */
        if (need_update) {
-               if (netif_running(netdev))
-                       ixgbe_down(adapter);
+               ixgbe_down(adapter);
 
                /* tx */
                if (new_tx_count != adapter->tx_ring_count) {
@@ -897,13 +906,8 @@ static int ixgbe_set_ringparam(struct net_device *netdev,
                        temp_rx_ring = NULL;
                        adapter->rx_ring_count = new_rx_count;
                }
-       }
-
-       /* success! */
-       err = 0;
-       if (netif_running(netdev))
                ixgbe_up(adapter);
-
+       }
 err_setup:
        clear_bit(__IXGBE_RESETTING, &adapter->state);
        return err;
index 28fbb9d..cbb143c 100644 (file)
@@ -97,8 +97,12 @@ static struct pci_device_id ixgbe_pci_tbl[] = {
         board_82599 },
        {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82599_SFP),
         board_82599 },
+       {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82599_KX4_MEZZ),
+        board_82599 },
        {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82599_CX4),
         board_82599 },
+       {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82599_COMBO_BACKPLANE),
+        board_82599 },
 
        /* required last entry */
        {0, }
index 7c93e92..ef4bdd5 100644 (file)
 #define IXGBE_DEV_ID_82598_SR_DUAL_PORT_EM      0x10E1
 #define IXGBE_DEV_ID_82598EB_XF_LR       0x10F4
 #define IXGBE_DEV_ID_82599_KX4           0x10F7
+#define IXGBE_DEV_ID_82599_KX4_MEZZ      0x1514
 #define IXGBE_DEV_ID_82599_CX4           0x10F9
 #define IXGBE_DEV_ID_82599_SFP           0x10FB
 #define IXGBE_DEV_ID_82599_XAUI_LOM      0x10FC
+#define IXGBE_DEV_ID_82599_COMBO_BACKPLANE 0x10F8
 
 /* General Registers */
 #define IXGBE_CTRL      0x00000
index b02a981..34a6cfd 100644 (file)
@@ -119,24 +119,9 @@ static struct ixp2400_msf_parameters enp2611_msf_parameters =
        }
 };
 
-struct enp2611_ixpdev_priv
-{
-       struct ixpdev_priv              ixpdev_priv;
-       struct net_device_stats         stats;
-};
-
 static struct net_device *nds[3];
 static struct timer_list link_check_timer;
 
-static struct net_device_stats *enp2611_get_stats(struct net_device *dev)
-{
-       struct enp2611_ixpdev_priv *ip = netdev_priv(dev);
-
-       pm3386_get_stats(ip->ixpdev_priv.channel, &(ip->stats));
-
-       return &(ip->stats);
-}
-
 /* @@@ Poll the SFP moddef0 line too.  */
 /* @@@ Try to use the pm3386 DOOL interrupt as well.  */
 static void enp2611_check_link_status(unsigned long __dummy)
@@ -203,14 +188,13 @@ static int __init enp2611_init_module(void)
 
        ports = pm3386_port_count();
        for (i = 0; i < ports; i++) {
-               nds[i] = ixpdev_alloc(i, sizeof(struct enp2611_ixpdev_priv));
+               nds[i] = ixpdev_alloc(i, sizeof(struct ixpdev_priv));
                if (nds[i] == NULL) {
                        while (--i >= 0)
                                free_netdev(nds[i]);
                        return -ENOMEM;
                }
 
-               nds[i]->get_stats = enp2611_get_stats;
                pm3386_init_port(i);
                pm3386_get_mac(i, nds[i]->dev_addr);
        }
index 1272434..9aee0cc 100644 (file)
@@ -21,6 +21,7 @@
 #include "ixp2400_tx.ucode"
 #include "ixpdev_priv.h"
 #include "ixpdev.h"
+#include "pm3386.h"
 
 #define DRV_MODULE_VERSION     "0.2"
 
@@ -271,6 +272,15 @@ static int ixpdev_close(struct net_device *dev)
        return 0;
 }
 
+static struct net_device_stats *ixpdev_get_stats(struct net_device *dev)
+{
+       struct ixpdev_priv *ip = netdev_priv(dev);
+
+       pm3386_get_stats(ip->channel, &(dev->stats));
+
+       return &(dev->stats);
+}
+
 static const struct net_device_ops ixpdev_netdev_ops = {
        .ndo_open               = ixpdev_open,
        .ndo_stop               = ixpdev_close,
@@ -278,6 +288,7 @@ static const struct net_device_ops ixpdev_netdev_ops = {
        .ndo_change_mtu         = eth_change_mtu,
        .ndo_validate_addr      = eth_validate_addr,
        .ndo_set_mac_address    = eth_mac_addr,
+       .ndo_get_stats          = ixpdev_get_stats,
 #ifdef CONFIG_NET_POLL_CONTROLLER
        .ndo_poll_controller    = ixpdev_poll_controller,
 #endif
index 2378358..a23f739 100644 (file)
@@ -171,6 +171,36 @@ static void ks8851_wrreg16(struct ks8851_net *ks, unsigned reg, unsigned val)
 }
 
 /**
+ * ks8851_wrreg8 - write 8bit register value to chip
+ * @ks: The chip state
+ * @reg: The register address
+ * @val: The value to write
+ *
+ * Issue a write to put the value @val into the register specified in @reg.
+ */
+static void ks8851_wrreg8(struct ks8851_net *ks, unsigned reg, unsigned val)
+{
+       struct spi_transfer *xfer = &ks->spi_xfer1;
+       struct spi_message *msg = &ks->spi_msg1;
+       __le16 txb[2];
+       int ret;
+       int bit;
+
+       bit = 1 << (reg & 3);
+
+       txb[0] = cpu_to_le16(MK_OP(bit, reg) | KS_SPIOP_WR);
+       txb[1] = val;
+
+       xfer->tx_buf = txb;
+       xfer->rx_buf = NULL;
+       xfer->len = 3;
+
+       ret = spi_sync(ks->spidev, msg);
+       if (ret < 0)
+               ks_err(ks, "spi_sync() failed\n");
+}
+
+/**
  * ks8851_rx_1msg - select whether to use one or two messages for spi read
  * @ks: The device structure
  *
@@ -322,13 +352,12 @@ static void ks8851_soft_reset(struct ks8851_net *ks, unsigned op)
 static int ks8851_write_mac_addr(struct net_device *dev)
 {
        struct ks8851_net *ks = netdev_priv(dev);
-       u16 *mcp = (u16 *)dev->dev_addr;
+       int i;
 
        mutex_lock(&ks->lock);
 
-       ks8851_wrreg16(ks, KS_MARL, mcp[0]);
-       ks8851_wrreg16(ks, KS_MARM, mcp[1]);
-       ks8851_wrreg16(ks, KS_MARH, mcp[2]);
+       for (i = 0; i < ETH_ALEN; i++)
+               ks8851_wrreg8(ks, KS_MAR(i), dev->dev_addr[i]);
 
        mutex_unlock(&ks->lock);
 
@@ -951,7 +980,7 @@ static void ks8851_set_rx_mode(struct net_device *dev)
                        mcptr = mcptr->next;
                }
 
-               rxctrl.rxcr1 = RXCR1_RXME | RXCR1_RXAE | RXCR1_RXPAFMA;
+               rxctrl.rxcr1 = RXCR1_RXME | RXCR1_RXPAFMA;
        } else {
                /* just accept broadcast / unicast */
                rxctrl.rxcr1 = RXCR1_RXPAFMA;
@@ -1239,6 +1268,9 @@ static int __devinit ks8851_probe(struct spi_device *spi)
        ndev->netdev_ops = &ks8851_netdev_ops;
        ndev->irq = spi->irq;
 
+       /* issue a global soft reset to reset the device. */
+       ks8851_soft_reset(ks, GRR_GSR);
+
        /* simple check for a valid chip being connected to the bus */
 
        if ((ks8851_rdreg16(ks, KS_CIDER) & ~CIDER_REV_MASK) != CIDER_ID) {
index 85abe14..f52c312 100644 (file)
@@ -16,6 +16,7 @@
 #define CCR_32PIN                              (1 << 0)
 
 /* MAC address registers */
+#define KS_MAR(_m)                             0x15 - (_m)
 #define KS_MARL                                        0x10
 #define KS_MARM                                        0x12
 #define KS_MARH                                        0x14
index 3dd481e..291a505 100644 (file)
@@ -1282,6 +1282,8 @@ static struct pci_device_id mlx4_pci_table[] = {
        { PCI_VDEVICE(MELLANOX, 0x6372) }, /* MT25458 ConnectX EN 10GBASE-T 10GigE */
        { PCI_VDEVICE(MELLANOX, 0x675a) }, /* MT25458 ConnectX EN 10GBASE-T+Gen2 10GigE */
        { PCI_VDEVICE(MELLANOX, 0x6764) }, /* MT26468 ConnectX EN 10GigE PCIe gen2*/
+       { PCI_VDEVICE(MELLANOX, 0x6746) }, /* MT26438 ConnectX EN 40GigE PCIe gen2 5GT/s */
+       { PCI_VDEVICE(MELLANOX, 0x676e) }, /* MT26478 ConnectX2 40GigE PCIe gen2 */
        { 0, }
 };
 
index 6930c87..f362451 100644 (file)
@@ -75,7 +75,7 @@
 #include "myri10ge_mcp.h"
 #include "myri10ge_mcp_gen_header.h"
 
-#define MYRI10GE_VERSION_STR "1.5.0-1.432"
+#define MYRI10GE_VERSION_STR "1.5.1-1.451"
 
 MODULE_DESCRIPTION("Myricom 10G driver (10GbE)");
 MODULE_AUTHOR("Maintainer: help@myri.com");
@@ -1624,10 +1624,21 @@ myri10ge_get_settings(struct net_device *netdev, struct ethtool_cmd *cmd)
                        return 0;
                }
        }
-       if (*ptr == 'R' || *ptr == 'Q') {
-               /* We've found either an XFP or quad ribbon fiber */
+       if (*ptr == '2')
+               ptr++;
+       if (*ptr == 'R' || *ptr == 'Q' || *ptr == 'S') {
+               /* We've found either an XFP, quad ribbon fiber, or SFP+ */
                cmd->port = PORT_FIBRE;
+               cmd->supported |= SUPPORTED_FIBRE;
+               cmd->advertising |= ADVERTISED_FIBRE;
+       } else {
+               cmd->port = PORT_OTHER;
        }
+       if (*ptr == 'R' || *ptr == 'S')
+               cmd->transceiver = XCVR_EXTERNAL;
+       else
+               cmd->transceiver = XCVR_INTERNAL;
+
        return 0;
 }
 
index 7a71774..1c46da6 100644 (file)
@@ -419,6 +419,7 @@ enum {
 #define NETXEN_CRB_ROMUSB      \
        NETXEN_PCI_CRB_WINDOW(NETXEN_HW_PX_MAP_CRB_ROMUSB)
 #define NETXEN_CRB_I2Q         NETXEN_PCI_CRB_WINDOW(NETXEN_HW_PX_MAP_CRB_I2Q)
+#define NETXEN_CRB_I2C0                NETXEN_PCI_CRB_WINDOW(NETXEN_HW_PX_MAP_CRB_I2C0)
 #define NETXEN_CRB_SMB         NETXEN_PCI_CRB_WINDOW(NETXEN_HW_PX_MAP_CRB_SMB)
 #define NETXEN_CRB_MAX         NETXEN_PCI_CRB_WINDOW(64)
 
index 3231400..3185a98 100644 (file)
@@ -1901,22 +1901,16 @@ netxen_setup_hwops(struct netxen_adapter *adapter)
 
 int netxen_nic_get_board_info(struct netxen_adapter *adapter)
 {
-       int offset, board_type, magic, header_version;
+       int offset, board_type, magic;
        struct pci_dev *pdev = adapter->pdev;
 
        offset = NX_FW_MAGIC_OFFSET;
        if (netxen_rom_fast_read(adapter, offset, &magic))
                return -EIO;
 
-       offset = NX_HDR_VERSION_OFFSET;
-       if (netxen_rom_fast_read(adapter, offset, &header_version))
-               return -EIO;
-
-       if (magic != NETXEN_BDINFO_MAGIC ||
-                       header_version != NETXEN_BDINFO_VERSION) {
-               dev_err(&pdev->dev,
-                       "invalid board config, magic=%08x, version=%08x\n",
-                       magic, header_version);
+       if (magic != NETXEN_BDINFO_MAGIC) {
+               dev_err(&pdev->dev, "invalid board config, magic=%08x\n",
+                       magic);
                return -EIO;
        }
 
index 91c2bc6..e40b914 100644 (file)
@@ -531,6 +531,8 @@ int netxen_pinit_from_rom(struct netxen_adapter *adapter, int verbose)
                        continue;
 
                if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) {
+                       if (off == (NETXEN_CRB_I2C0 + 0x1c))
+                               continue;
                        /* do not reset PCI */
                        if (off == (ROMUSB_GLB + 0xbc))
                                continue;
@@ -553,12 +555,6 @@ int netxen_pinit_from_rom(struct netxen_adapter *adapter, int verbose)
                                continue;
                }
 
-               if (off == NETXEN_ADDR_ERROR) {
-                       printk(KERN_ERR "%s: Err: Unknown addr: 0x%08x\n",
-                                       netxen_nic_driver_name, buf[i].addr);
-                       continue;
-               }
-
                init_delay = 1;
                /* After writing this register, HW needs time for CRB */
                /* to quiet down (else crb_window returns 0xffffffff) */
index b5aa974..0b4a56a 100644 (file)
@@ -595,7 +595,8 @@ netxen_setup_pci_map(struct netxen_adapter *adapter)
        void __iomem *mem_ptr2 = NULL;
        void __iomem *db_ptr = NULL;
 
-       unsigned long mem_base, mem_len, db_base, db_len = 0, pci_len0 = 0;
+       resource_size_t mem_base, db_base;
+       unsigned long mem_len, db_len = 0, pci_len0 = 0;
 
        struct pci_dev *pdev = adapter->pdev;
        int pci_func = adapter->ahw.pci_func;
@@ -1714,7 +1715,7 @@ netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
        /* 4 fragments per cmd des */
        no_of_desc = (frag_count + 3) >> 2;
 
-       if (unlikely(no_of_desc + 2) > netxen_tx_avail(tx_ring)) {
+       if (unlikely(no_of_desc + 2 > netxen_tx_avail(tx_ring))) {
                netif_stop_queue(netdev);
                return NETDEV_TX_BUSY;
        }
@@ -1918,6 +1919,7 @@ static void netxen_tx_timeout_task(struct work_struct *work)
 
 request_reset:
        adapter->need_fw_reset = 1;
+       clear_bit(__NX_RESETTING, &adapter->state);
 }
 
 struct net_device_stats *netxen_nic_get_stats(struct net_device *netdev)
index f9364d0..d6c7ac6 100644 (file)
@@ -3545,7 +3545,7 @@ static int niu_process_rx_pkt(struct napi_struct *napi, struct niu *np,
        rp->rcr_index = index;
 
        skb_reserve(skb, NET_IP_ALIGN);
-       __pskb_pull_tail(skb, min(len, NIU_RXPULL_MAX));
+       __pskb_pull_tail(skb, min(len, VLAN_ETH_HLEN));
 
        rp->rx_packets++;
        rp->rx_bytes += skb->len;
index c594e19..57fd483 100644 (file)
 #include <linux/compiler.h>
 #include <linux/prefetch.h>
 #include <linux/ethtool.h>
+#include <linux/sched.h>
 #include <linux/timer.h>
 #include <linux/if_vlan.h>
 #include <linux/rtnetlink.h>
index 064a4fe..28a8622 100644 (file)
@@ -71,6 +71,9 @@ pasemi_mac_ethtool_get_settings(struct net_device *netdev,
        struct pasemi_mac *mac = netdev_priv(netdev);
        struct phy_device *phydev = mac->phydev;
 
+       if (!phydev)
+               return -EOPNOTSUPP;
+
        return phy_ethtool_gset(phydev, cmd);
 }
 
index ee8ad3e..b58965a 100644 (file)
@@ -251,6 +251,7 @@ static void el3_tx_timeout(struct net_device *dev);
 static int el3_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
 static const struct ethtool_ops netdev_ethtool_ops;
 static void set_rx_mode(struct net_device *dev);
+static void set_multicast_list(struct net_device *dev);
 
 static void tc574_detach(struct pcmcia_device *p_dev);
 
@@ -266,7 +267,7 @@ static const struct net_device_ops el3_netdev_ops = {
        .ndo_tx_timeout         = el3_tx_timeout,
        .ndo_get_stats          = el3_get_stats,
        .ndo_do_ioctl           = el3_ioctl,
-       .ndo_set_multicast_list = set_rx_mode,
+       .ndo_set_multicast_list = set_multicast_list,
        .ndo_change_mtu         = eth_change_mtu,
        .ndo_set_mac_address    = eth_mac_addr,
        .ndo_validate_addr      = eth_validate_addr,
@@ -1161,6 +1162,16 @@ static void set_rx_mode(struct net_device *dev)
                outw(SetRxFilter | RxStation | RxBroadcast, ioaddr + EL3_CMD);
 }
 
+static void set_multicast_list(struct net_device *dev)
+{
+       struct el3_private *lp = netdev_priv(dev);
+       unsigned long flags;
+
+       spin_lock_irqsave(&lp->window_lock, flags);
+       set_rx_mode(dev);
+       spin_unlock_irqrestore(&lp->window_lock, flags);
+}
+
 static int el3_close(struct net_device *dev)
 {
        unsigned int ioaddr = dev->base_addr;
index 474876c..94c9ad2 100644 (file)
@@ -1754,14 +1754,14 @@ static struct pcmcia_device_id pcnet_ids[] = {
        PCMCIA_PFC_DEVICE_CIS_PROD_ID12(0, "Psion Dacom", "Gold Card V34 Ethernet", 0xf5f025c2, 0x338e8155, "cis/PCMLM28.cis"),
        PCMCIA_PFC_DEVICE_CIS_PROD_ID12(0, "Psion Dacom", "Gold Card V34 Ethernet GSM", 0xf5f025c2, 0x4ae85d35, "cis/PCMLM28.cis"),
        PCMCIA_PFC_DEVICE_CIS_PROD_ID12(0, "LINKSYS", "PCMLM28", 0xf7cb0b07, 0x66881874, "cis/PCMLM28.cis"),
-       PCMCIA_MFC_DEVICE_CIS_PROD_ID12(0, "DAYNA COMMUNICATIONS", "LAN AND MODEM MULTIFUNCTION", 0x8fdf8f89, 0xdd5ed9e8, "DP83903.cis"),
-       PCMCIA_MFC_DEVICE_CIS_PROD_ID4(0, "NSC MF LAN/Modem", 0x58fc6056, "DP83903.cis"),
-       PCMCIA_MFC_DEVICE_CIS_MANF_CARD(0, 0x0175, 0x0000, "DP83903.cis"),
+       PCMCIA_MFC_DEVICE_CIS_PROD_ID12(0, "DAYNA COMMUNICATIONS", "LAN AND MODEM MULTIFUNCTION", 0x8fdf8f89, 0xdd5ed9e8, "cis/DP83903.cis"),
+       PCMCIA_MFC_DEVICE_CIS_PROD_ID4(0, "NSC MF LAN/Modem", 0x58fc6056, "cis/DP83903.cis"),
+       PCMCIA_MFC_DEVICE_CIS_MANF_CARD(0, 0x0175, 0x0000, "cis/DP83903.cis"),
        PCMCIA_DEVICE_CIS_MANF_CARD(0xc00f, 0x0002, "cis/LA-PCM.cis"),
        PCMCIA_DEVICE_CIS_PROD_ID12("KTI", "PE520 PLUS", 0xad180345, 0x9d58d392, "PE520.cis"),
-       PCMCIA_DEVICE_CIS_PROD_ID12("NDC", "Ethernet", 0x01c43ae1, 0x00b2e941, "NE2K.cis"),
-       PCMCIA_DEVICE_CIS_PROD_ID12("PMX   ", "PE-200", 0x34f3f1c8, 0x10b59f8c, "PE-200.cis"),
-       PCMCIA_DEVICE_CIS_PROD_ID12("TAMARACK", "Ethernet", 0xcf434fba, 0x00b2e941, "tamarack.cis"),
+       PCMCIA_DEVICE_CIS_PROD_ID12("NDC", "Ethernet", 0x01c43ae1, 0x00b2e941, "cis/NE2K.cis"),
+       PCMCIA_DEVICE_CIS_PROD_ID12("PMX   ", "PE-200", 0x34f3f1c8, 0x10b59f8c, "cis/PE-200.cis"),
+       PCMCIA_DEVICE_CIS_PROD_ID12("TAMARACK", "Ethernet", 0xcf434fba, 0x00b2e941, "cis/tamarack.cis"),
        PCMCIA_DEVICE_PROD_ID12("Ethernet", "CF Size PC Card", 0x00b2e941, 0x43ac239b),
        PCMCIA_DEVICE_PROD_ID123("Fast Ethernet", "CF Size PC Card", "1.0",
                0xb4be14e3, 0x43ac239b, 0x0877b627),
index 6d28b18..c1b3f09 100644 (file)
@@ -31,6 +31,7 @@ static const char *const version =
 
 #include <linux/module.h>
 #include <linux/kernel.h>
+#include <linux/sched.h>
 #include <linux/string.h>
 #include <linux/errno.h>
 #include <linux/ioport.h>
index 250e10f..8659d34 100644 (file)
@@ -238,6 +238,7 @@ static struct of_device_id mdio_ofgpio_match[] = {
        },
        {},
 };
+MODULE_DEVICE_TABLE(of, mdio_ofgpio_match);
 
 static struct of_platform_driver mdio_ofgpio_driver = {
        .name = "mdio-gpio",
index 7cbf6f9..2559991 100644 (file)
@@ -111,9 +111,6 @@ struct pppoe_net {
        rwlock_t hash_lock;
 };
 
-/* to eliminate a race btw pppoe_flush_dev and pppoe_release */
-static DEFINE_SPINLOCK(flush_lock);
-
 /*
  * PPPoE could be in the following stages:
  * 1) Discovery stage (to obtain remote MAC and Session ID)
@@ -303,45 +300,48 @@ static void pppoe_flush_dev(struct net_device *dev)
        write_lock_bh(&pn->hash_lock);
        for (i = 0; i < PPPOE_HASH_SIZE; i++) {
                struct pppox_sock *po = pn->hash_table[i];
+               struct sock *sk;
 
-               while (po != NULL) {
-                       struct sock *sk;
-                       if (po->pppoe_dev != dev) {
+               while (po) {
+                       while (po && po->pppoe_dev != dev) {
                                po = po->next;
-                               continue;
                        }
+
+                       if (!po)
+                               break;
+
                        sk = sk_pppox(po);
-                       spin_lock(&flush_lock);
-                       po->pppoe_dev = NULL;
-                       spin_unlock(&flush_lock);
-                       dev_put(dev);
 
                        /* We always grab the socket lock, followed by the
-                        * hash_lock, in that order.  Since we should
-                        * hold the sock lock while doing any unbinding,
-                        * we need to release the lock we're holding.
-                        * Hold a reference to the sock so it doesn't disappear
-                        * as we're jumping between locks.
+                        * hash_lock, in that order.  Since we should hold the
+                        * sock lock while doing any unbinding, we need to
+                        * release the lock we're holding.  Hold a reference to
+                        * the sock so it doesn't disappear as we're jumping
+                        * between locks.
                         */
 
                        sock_hold(sk);
-
                        write_unlock_bh(&pn->hash_lock);
                        lock_sock(sk);
 
-                       if (sk->sk_state & (PPPOX_CONNECTED | PPPOX_BOUND)) {
+                       if (po->pppoe_dev == dev
+                           && sk->sk_state & (PPPOX_CONNECTED | PPPOX_BOUND)) {
                                pppox_unbind_sock(sk);
                                sk->sk_state = PPPOX_ZOMBIE;
                                sk->sk_state_change(sk);
+                               po->pppoe_dev = NULL;
+                               dev_put(dev);
                        }
 
                        release_sock(sk);
                        sock_put(sk);
 
-                       /* Restart scan at the beginning of this hash chain.
-                        * While the lock was dropped the chain contents may
-                        * have changed.
+                       /* Restart the process from the start of the current
+                        * hash chain. We dropped locks so the world may have
+                        * change from underneath us.
                         */
+
+                       BUG_ON(pppoe_pernet(dev_net(dev)) == NULL);
                        write_lock_bh(&pn->hash_lock);
                        po = pn->hash_table[i];
                }
@@ -388,11 +388,16 @@ static int pppoe_rcv_core(struct sock *sk, struct sk_buff *skb)
        struct pppox_sock *po = pppox_sk(sk);
        struct pppox_sock *relay_po;
 
+       /* Backlog receive. Semantics of backlog rcv preclude any code from
+        * executing in lock_sock()/release_sock() bounds; meaning sk->sk_state
+        * can't change.
+        */
+
        if (sk->sk_state & PPPOX_BOUND) {
                ppp_input(&po->chan, skb);
        } else if (sk->sk_state & PPPOX_RELAY) {
-               relay_po = get_item_by_addr(dev_net(po->pppoe_dev),
-                                               &po->pppoe_relay);
+               relay_po = get_item_by_addr(sock_net(sk),
+                                           &po->pppoe_relay);
                if (relay_po == NULL)
                        goto abort_kfree;
 
@@ -447,6 +452,10 @@ static int pppoe_rcv(struct sk_buff *skb, struct net_device *dev,
                goto drop;
 
        pn = pppoe_pernet(dev_net(dev));
+
+       /* Note that get_item does a sock_hold(), so sk_pppox(po)
+        * is known to be safe.
+        */
        po = get_item(pn, ph->sid, eth_hdr(skb)->h_source, dev->ifindex);
        if (!po)
                goto drop;
@@ -561,6 +570,7 @@ static int pppoe_release(struct socket *sock)
        struct sock *sk = sock->sk;
        struct pppox_sock *po;
        struct pppoe_net *pn;
+       struct net *net = NULL;
 
        if (!sk)
                return 0;
@@ -571,44 +581,28 @@ static int pppoe_release(struct socket *sock)
                return -EBADF;
        }
 
+       po = pppox_sk(sk);
+
+       if (sk->sk_state & (PPPOX_CONNECTED | PPPOX_BOUND)) {
+               dev_put(po->pppoe_dev);
+               po->pppoe_dev = NULL;
+       }
+
        pppox_unbind_sock(sk);
 
        /* Signal the death of the socket. */
        sk->sk_state = PPPOX_DEAD;
 
-       /*
-        * pppoe_flush_dev could lead to a race with
-        * this routine so we use flush_lock to eliminate
-        * such a case (we only need per-net specific data)
-        */
-       spin_lock(&flush_lock);
-       po = pppox_sk(sk);
-       if (!po->pppoe_dev) {
-               spin_unlock(&flush_lock);
-               goto out;
-       }
-       pn = pppoe_pernet(dev_net(po->pppoe_dev));
-       spin_unlock(&flush_lock);
+       net = sock_net(sk);
+       pn = pppoe_pernet(net);
 
        /*
         * protect "po" from concurrent updates
         * on pppoe_flush_dev
         */
-       write_lock_bh(&pn->hash_lock);
+       delete_item(pn, po->pppoe_pa.sid, po->pppoe_pa.remote,
+                   po->pppoe_ifindex);
 
-       po = pppox_sk(sk);
-       if (stage_session(po->pppoe_pa.sid))
-               __delete_item(pn, po->pppoe_pa.sid, po->pppoe_pa.remote,
-                               po->pppoe_ifindex);
-
-       if (po->pppoe_dev) {
-               dev_put(po->pppoe_dev);
-               po->pppoe_dev = NULL;
-       }
-
-       write_unlock_bh(&pn->hash_lock);
-
-out:
        sock_orphan(sk);
        sock->sk = NULL;
 
@@ -625,8 +619,9 @@ static int pppoe_connect(struct socket *sock, struct sockaddr *uservaddr,
        struct sock *sk = sock->sk;
        struct sockaddr_pppox *sp = (struct sockaddr_pppox *)uservaddr;
        struct pppox_sock *po = pppox_sk(sk);
-       struct net_device *dev;
+       struct net_device *dev = NULL;
        struct pppoe_net *pn;
+       struct net *net = NULL;
        int error;
 
        lock_sock(sk);
@@ -652,12 +647,14 @@ static int pppoe_connect(struct socket *sock, struct sockaddr *uservaddr,
        /* Delete the old binding */
        if (stage_session(po->pppoe_pa.sid)) {
                pppox_unbind_sock(sk);
+               pn = pppoe_pernet(sock_net(sk));
+               delete_item(pn, po->pppoe_pa.sid,
+                           po->pppoe_pa.remote, po->pppoe_ifindex);
                if (po->pppoe_dev) {
-                       pn = pppoe_pernet(dev_net(po->pppoe_dev));
-                       delete_item(pn, po->pppoe_pa.sid,
-                               po->pppoe_pa.remote, po->pppoe_ifindex);
                        dev_put(po->pppoe_dev);
+                       po->pppoe_dev = NULL;
                }
+
                memset(sk_pppox(po) + 1, 0,
                       sizeof(struct pppox_sock) - sizeof(struct sock));
                sk->sk_state = PPPOX_NONE;
@@ -666,16 +663,15 @@ static int pppoe_connect(struct socket *sock, struct sockaddr *uservaddr,
        /* Re-bind in session stage only */
        if (stage_session(sp->sa_addr.pppoe.sid)) {
                error = -ENODEV;
-               dev = dev_get_by_name(sock_net(sk), sp->sa_addr.pppoe.dev);
+               net = sock_net(sk);
+               dev = dev_get_by_name(net, sp->sa_addr.pppoe.dev);
                if (!dev)
-                       goto end;
+                       goto err_put;
 
                po->pppoe_dev = dev;
                po->pppoe_ifindex = dev->ifindex;
-               pn = pppoe_pernet(dev_net(dev));
-               write_lock_bh(&pn->hash_lock);
+               pn = pppoe_pernet(net);
                if (!(dev->flags & IFF_UP)) {
-                       write_unlock_bh(&pn->hash_lock);
                        goto err_put;
                }
 
@@ -683,6 +679,7 @@ static int pppoe_connect(struct socket *sock, struct sockaddr *uservaddr,
                       &sp->sa_addr.pppoe,
                       sizeof(struct pppoe_addr));
 
+               write_lock_bh(&pn->hash_lock);
                error = __set_item(pn, po);
                write_unlock_bh(&pn->hash_lock);
                if (error < 0)
@@ -696,8 +693,11 @@ static int pppoe_connect(struct socket *sock, struct sockaddr *uservaddr,
                po->chan.ops = &pppoe_chan_ops;
 
                error = ppp_register_net_channel(dev_net(dev), &po->chan);
-               if (error)
+               if (error) {
+                       delete_item(pn, po->pppoe_pa.sid,
+                                   po->pppoe_pa.remote, po->pppoe_ifindex);
                        goto err_put;
+               }
 
                sk->sk_state = PPPOX_CONNECTED;
        }
@@ -915,6 +915,14 @@ static int __pppoe_xmit(struct sock *sk, struct sk_buff *skb)
        struct pppoe_hdr *ph;
        int data_len = skb->len;
 
+       /* The higher-level PPP code (ppp_unregister_channel()) ensures the PPP
+        * xmit operations conclude prior to an unregistration call.  Thus
+        * sk->sk_state cannot change, so we don't need to do lock_sock().
+        * But, we also can't do a lock_sock since that introduces a potential
+        * deadlock as we'd reverse the lock ordering used when calling
+        * ppp_unregister_channel().
+        */
+
        if (sock_flag(sk, SOCK_DEAD) || !(sk->sk_state & PPPOX_CONNECTED))
                goto abort;
 
@@ -944,7 +952,6 @@ static int __pppoe_xmit(struct sock *sk, struct sk_buff *skb)
                        po->pppoe_pa.remote, NULL, data_len);
 
        dev_queue_xmit(skb);
-
        return 1;
 
 abort:
index 30d5585..c2383ad 100644 (file)
@@ -9,6 +9,7 @@
 
 #include <linux/pci.h>
 #include <linux/netdevice.h>
+#include <linux/rtnetlink.h>
 
 /*
  * General definitions...
@@ -94,6 +95,7 @@ enum {
 
        /* Misc. stuff */
        MAILBOX_COUNT = 16,
+       MAILBOX_TIMEOUT = 5,
 
        PROC_ADDR_RDY = (1 << 31),
        PROC_ADDR_R = (1 << 30),
@@ -135,9 +137,9 @@ enum {
        RST_FO_TFO = (1 << 0),
        RST_FO_RR_MASK = 0x00060000,
        RST_FO_RR_CQ_CAM = 0x00000000,
-       RST_FO_RR_DROP = 0x00000001,
-       RST_FO_RR_DQ = 0x00000002,
-       RST_FO_RR_RCV_FUNC_CQ = 0x00000003,
+       RST_FO_RR_DROP = 0x00000002,
+       RST_FO_RR_DQ = 0x00000004,
+       RST_FO_RR_RCV_FUNC_CQ = 0x00000006,
        RST_FO_FRB = (1 << 12),
        RST_FO_MOP = (1 << 13),
        RST_FO_REG = (1 << 14),
@@ -802,6 +804,12 @@ enum {
        MB_CMD_SET_PORT_CFG = 0x00000122,
        MB_CMD_GET_PORT_CFG = 0x00000123,
        MB_CMD_GET_LINK_STS = 0x00000124,
+       MB_CMD_SET_MGMNT_TFK_CTL = 0x00000160, /* Set Mgmnt Traffic Control */
+       MB_SET_MPI_TFK_STOP = (1 << 0),
+       MB_SET_MPI_TFK_RESUME = (1 << 1),
+       MB_CMD_GET_MGMNT_TFK_CTL = 0x00000161, /* Get Mgmnt Traffic Control */
+       MB_GET_MPI_TFK_STOPPED = (1 << 0),
+       MB_GET_MPI_TFK_FIFO_EMPTY = (1 << 1),
 
        /* Mailbox Command Status. */
        MB_CMD_STS_GOOD = 0x00004000,   /* Success. */
@@ -1167,7 +1175,7 @@ struct ricb {
 #define RSS_RI6 0x40
 #define RSS_RT6 0x80
        __le16 mask;
-       __le32 hash_cq_id[256];
+       u8 hash_cq_id[1024];
        __le32 ipv6_hash_key[10];
        __le32 ipv4_hash_key[4];
 } __attribute((packed));
@@ -1477,7 +1485,6 @@ struct ql_adapter {
        u32 mailbox_in;
        u32 mailbox_out;
        struct mbox_params idc_mbc;
-       struct mutex    mpi_mutex;
 
        int tx_ring_size;
        int rx_ring_size;
@@ -1606,6 +1613,8 @@ int ql_read_mpi_reg(struct ql_adapter *qdev, u32 reg, u32 *data);
 int ql_mb_about_fw(struct ql_adapter *qdev);
 void ql_link_on(struct ql_adapter *qdev);
 void ql_link_off(struct ql_adapter *qdev);
+int ql_mb_set_mgmnt_traffic_ctl(struct ql_adapter *qdev, u32 control);
+int ql_wait_fifo_empty(struct ql_adapter *qdev);
 
 #if 1
 #define QL_ALL_DUMP
index 68f9bd2..5207394 100644 (file)
@@ -45,7 +45,6 @@ static int ql_update_ring_coalescing(struct ql_adapter *qdev)
        if (!netif_running(qdev->ndev))
                return status;
 
-       spin_lock(&qdev->hw_lock);
        /* Skip the default queue, and update the outbound handler
         * queues if they changed.
         */
@@ -92,7 +91,6 @@ static int ql_update_ring_coalescing(struct ql_adapter *qdev)
                }
        }
 exit:
-       spin_unlock(&qdev->hw_lock);
        return status;
 }
 
index 3d0efea..cea7531 100644 (file)
@@ -34,7 +34,6 @@
 #include <linux/etherdevice.h>
 #include <linux/ethtool.h>
 #include <linux/skbuff.h>
-#include <linux/rtnetlink.h>
 #include <linux/if_vlan.h>
 #include <linux/delay.h>
 #include <linux/mm.h>
@@ -321,6 +320,37 @@ static int ql_set_mac_addr_reg(struct ql_adapter *qdev, u8 *addr, u32 type,
 
        switch (type) {
        case MAC_ADDR_TYPE_MULTI_MAC:
+               {
+                       u32 upper = (addr[0] << 8) | addr[1];
+                       u32 lower = (addr[2] << 24) | (addr[3] << 16) |
+                                       (addr[4] << 8) | (addr[5]);
+
+                       status =
+                               ql_wait_reg_rdy(qdev,
+                               MAC_ADDR_IDX, MAC_ADDR_MW, 0);
+                       if (status)
+                               goto exit;
+                       ql_write32(qdev, MAC_ADDR_IDX, (offset++) |
+                               (index << MAC_ADDR_IDX_SHIFT) |
+                               type | MAC_ADDR_E);
+                       ql_write32(qdev, MAC_ADDR_DATA, lower);
+                       status =
+                               ql_wait_reg_rdy(qdev,
+                               MAC_ADDR_IDX, MAC_ADDR_MW, 0);
+                       if (status)
+                               goto exit;
+                       ql_write32(qdev, MAC_ADDR_IDX, (offset++) |
+                               (index << MAC_ADDR_IDX_SHIFT) |
+                               type | MAC_ADDR_E);
+
+                       ql_write32(qdev, MAC_ADDR_DATA, upper);
+                       status =
+                               ql_wait_reg_rdy(qdev,
+                               MAC_ADDR_IDX, MAC_ADDR_MW, 0);
+                       if (status)
+                               goto exit;
+                       break;
+               }
        case MAC_ADDR_TYPE_CAM_MAC:
                {
                        u32 cam_output;
@@ -366,16 +396,14 @@ static int ql_set_mac_addr_reg(struct ql_adapter *qdev, u8 *addr, u32 type,
                           and possibly the function id.  Right now we hardcode
                           the route field to NIC core.
                         */
-                       if (type == MAC_ADDR_TYPE_CAM_MAC) {
-                               cam_output = (CAM_OUT_ROUTE_NIC |
-                                             (qdev->
-                                              func << CAM_OUT_FUNC_SHIFT) |
-                                               (0 << CAM_OUT_CQ_ID_SHIFT));
-                               if (qdev->vlgrp)
-                                       cam_output |= CAM_OUT_RV;
-                               /* route to NIC core */
-                               ql_write32(qdev, MAC_ADDR_DATA, cam_output);
-                       }
+                       cam_output = (CAM_OUT_ROUTE_NIC |
+                                     (qdev->
+                                      func << CAM_OUT_FUNC_SHIFT) |
+                                       (0 << CAM_OUT_CQ_ID_SHIFT));
+                       if (qdev->vlgrp)
+                               cam_output |= CAM_OUT_RV;
+                       /* route to NIC core */
+                       ql_write32(qdev, MAC_ADDR_DATA, cam_output);
                        break;
                }
        case MAC_ADDR_TYPE_VLAN:
@@ -547,14 +575,14 @@ static int ql_set_routing_reg(struct ql_adapter *qdev, u32 index, u32 mask,
                }
        case RT_IDX_MCAST:      /* Pass up All Multicast frames. */
                {
-                       value = RT_IDX_DST_CAM_Q |      /* dest */
+                       value = RT_IDX_DST_DFLT_Q |     /* dest */
                            RT_IDX_TYPE_NICQ |  /* type */
                            (RT_IDX_ALLMULTI_SLOT << RT_IDX_IDX_SHIFT);/* index */
                        break;
                }
        case RT_IDX_MCAST_MATCH:        /* Pass up matched Multicast frames. */
                {
-                       value = RT_IDX_DST_CAM_Q |      /* dest */
+                       value = RT_IDX_DST_DFLT_Q |     /* dest */
                            RT_IDX_TYPE_NICQ |  /* type */
                            (RT_IDX_MCAST_MATCH_SLOT << RT_IDX_IDX_SHIFT);/* index */
                        break;
@@ -1926,12 +1954,10 @@ static void ql_vlan_rx_add_vid(struct net_device *ndev, u16 vid)
        status = ql_sem_spinlock(qdev, SEM_MAC_ADDR_MASK);
        if (status)
                return;
-       spin_lock(&qdev->hw_lock);
        if (ql_set_mac_addr_reg
            (qdev, (u8 *) &enable_bit, MAC_ADDR_TYPE_VLAN, vid)) {
                QPRINTK(qdev, IFUP, ERR, "Failed to init vlan address.\n");
        }
-       spin_unlock(&qdev->hw_lock);
        ql_sem_unlock(qdev, SEM_MAC_ADDR_MASK);
 }
 
@@ -1945,12 +1971,10 @@ static void ql_vlan_rx_kill_vid(struct net_device *ndev, u16 vid)
        if (status)
                return;
 
-       spin_lock(&qdev->hw_lock);
        if (ql_set_mac_addr_reg
            (qdev, (u8 *) &enable_bit, MAC_ADDR_TYPE_VLAN, vid)) {
                QPRINTK(qdev, IFUP, ERR, "Failed to clear vlan address.\n");
        }
-       spin_unlock(&qdev->hw_lock);
        ql_sem_unlock(qdev, SEM_MAC_ADDR_MASK);
 
 }
@@ -2001,15 +2025,17 @@ static irqreturn_t qlge_isr(int irq, void *dev_id)
        /*
         * Check MPI processor activity.
         */
-       if (var & STS_PI) {
+       if ((var & STS_PI) &&
+               (ql_read32(qdev, INTR_MASK) & INTR_MASK_PI)) {
                /*
                 * We've got an async event or mailbox completion.
                 * Handle it and clear the source of the interrupt.
                 */
                QPRINTK(qdev, INTR, ERR, "Got MPI processor interrupt.\n");
                ql_disable_completion_interrupt(qdev, intr_context->intr);
-               queue_delayed_work_on(smp_processor_id(), qdev->workqueue,
-                                     &qdev->mpi_work, 0);
+               ql_write32(qdev, INTR_MASK, (INTR_MASK_PI << 16));
+               queue_delayed_work_on(smp_processor_id(),
+                               qdev->workqueue, &qdev->mpi_work, 0);
                work_done++;
        }
 
@@ -3080,6 +3106,12 @@ err_irq:
 
 static int ql_start_rss(struct ql_adapter *qdev)
 {
+       u8 init_hash_seed[] = {0x6d, 0x5a, 0x56, 0xda, 0x25, 0x5b, 0x0e, 0xc2,
+                               0x41, 0x67, 0x25, 0x3d, 0x43, 0xa3, 0x8f,
+                               0xb0, 0xd0, 0xca, 0x2b, 0xcb, 0xae, 0x7b,
+                               0x30, 0xb4, 0x77, 0xcb, 0x2d, 0xa3, 0x80,
+                               0x30, 0xf2, 0x0c, 0x6a, 0x42, 0xb7, 0x3b,
+                               0xbe, 0xac, 0x01, 0xfa};
        struct ricb *ricb = &qdev->ricb;
        int status = 0;
        int i;
@@ -3089,21 +3121,17 @@ static int ql_start_rss(struct ql_adapter *qdev)
 
        ricb->base_cq = RSS_L4K;
        ricb->flags =
-           (RSS_L6K | RSS_LI | RSS_LB | RSS_LM | RSS_RI4 | RSS_RI6 | RSS_RT4 |
-            RSS_RT6);
-       ricb->mask = cpu_to_le16(qdev->rss_ring_count - 1);
+               (RSS_L6K | RSS_LI | RSS_LB | RSS_LM | RSS_RT4 | RSS_RT6);
+       ricb->mask = cpu_to_le16((u16)(0x3ff));
 
        /*
         * Fill out the Indirection Table.
         */
-       for (i = 0; i < 256; i++)
-               hash_id[i] = i & (qdev->rss_ring_count - 1);
+       for (i = 0; i < 1024; i++)
+               hash_id[i] = (i & (qdev->rss_ring_count - 1));
 
-       /*
-        * Random values for the IPv6 and IPv4 Hash Keys.
-        */
-       get_random_bytes((void *)&ricb->ipv6_hash_key[0], 40);
-       get_random_bytes((void *)&ricb->ipv4_hash_key[0], 16);
+       memcpy((void *)&ricb->ipv6_hash_key[0], init_hash_seed, 40);
+       memcpy((void *)&ricb->ipv4_hash_key[0], init_hash_seed, 16);
 
        QPRINTK(qdev, IFUP, DEBUG, "Initializing RSS.\n");
 
@@ -3242,6 +3270,13 @@ static int ql_adapter_initialize(struct ql_adapter *qdev)
        ql_write32(qdev, SPLT_HDR, SPLT_HDR_EP |
                min(SMALL_BUFFER_SIZE, MAX_SPLIT_SIZE));
 
+       /* Set RX packet routing to use port/pci function on which the
+        * packet arrived on in addition to usual frame routing.
+        * This is helpful on bonding where both interfaces can have
+        * the same MAC address.
+        */
+       ql_write32(qdev, RST_FO, RST_FO_RR_MASK | RST_FO_RR_RCV_FUNC_CQ);
+
        /* Start up the rx queues. */
        for (i = 0; i < qdev->rx_ring_count; i++) {
                status = ql_start_rx_ring(qdev, &qdev->rx_ring[i]);
@@ -3314,6 +3349,13 @@ static int ql_adapter_reset(struct ql_adapter *qdev)
 
        end_jiffies = jiffies +
                max((unsigned long)1, usecs_to_jiffies(30));
+
+       /* Stop management traffic. */
+       ql_mb_set_mgmnt_traffic_ctl(qdev, MB_SET_MPI_TFK_STOP);
+
+       /* Wait for the NIC and MGMNT FIFOs to empty. */
+       ql_wait_fifo_empty(qdev);
+
        ql_write32(qdev, RST_FO, (RST_FO_FR << 16) | RST_FO_FR);
 
        do {
@@ -3329,6 +3371,8 @@ static int ql_adapter_reset(struct ql_adapter *qdev)
                status = -ETIMEDOUT;
        }
 
+       /* Resume management traffic. */
+       ql_mb_set_mgmnt_traffic_ctl(qdev, MB_SET_MPI_TFK_RESUME);
        return status;
 }
 
@@ -3585,7 +3629,6 @@ static void qlge_set_multicast_list(struct net_device *ndev)
        status = ql_sem_spinlock(qdev, SEM_RT_IDX_MASK);
        if (status)
                return;
-       spin_lock(&qdev->hw_lock);
        /*
         * Set or clear promiscuous mode if a
         * transition is taking place.
@@ -3662,7 +3705,6 @@ static void qlge_set_multicast_list(struct net_device *ndev)
                }
        }
 exit:
-       spin_unlock(&qdev->hw_lock);
        ql_sem_unlock(qdev, SEM_RT_IDX_MASK);
 }
 
@@ -3682,10 +3724,8 @@ static int qlge_set_mac_address(struct net_device *ndev, void *p)
        status = ql_sem_spinlock(qdev, SEM_MAC_ADDR_MASK);
        if (status)
                return status;
-       spin_lock(&qdev->hw_lock);
        status = ql_set_mac_addr_reg(qdev, (u8 *) ndev->dev_addr,
                        MAC_ADDR_TYPE_CAM_MAC, qdev->func * MAX_CQ);
-       spin_unlock(&qdev->hw_lock);
        if (status)
                QPRINTK(qdev, HW, ERR, "Failed to load MAC address.\n");
        ql_sem_unlock(qdev, SEM_MAC_ADDR_MASK);
@@ -3711,6 +3751,12 @@ static void ql_asic_reset_work(struct work_struct *work)
        status = ql_adapter_up(qdev);
        if (status)
                goto error;
+
+       /* Restore rx mode. */
+       clear_bit(QL_ALLMULTI, &qdev->flags);
+       clear_bit(QL_PROMISCUOUS, &qdev->flags);
+       qlge_set_multicast_list(qdev->ndev);
+
        rtnl_unlock();
        return;
 error:
@@ -3870,6 +3916,7 @@ static int __devinit ql_init_device(struct pci_dev *pdev,
                goto err_out;
        }
 
+       pci_save_state(pdev);
        qdev->reg_base =
            ioremap_nocache(pci_resource_start(pdev, 1),
                            pci_resource_len(pdev, 1));
@@ -3928,7 +3975,6 @@ static int __devinit ql_init_device(struct pci_dev *pdev,
        INIT_DELAYED_WORK(&qdev->mpi_work, ql_mpi_work);
        INIT_DELAYED_WORK(&qdev->mpi_port_cfg_work, ql_mpi_port_cfg_work);
        INIT_DELAYED_WORK(&qdev->mpi_idc_work, ql_mpi_idc_work);
-       mutex_init(&qdev->mpi_mutex);
        init_completion(&qdev->ide_completion);
 
        if (!cards_found) {
@@ -4025,6 +4071,33 @@ static void __devexit qlge_remove(struct pci_dev *pdev)
        free_netdev(ndev);
 }
 
+/* Clean up resources without touching hardware. */
+static void ql_eeh_close(struct net_device *ndev)
+{
+       int i;
+       struct ql_adapter *qdev = netdev_priv(ndev);
+
+       if (netif_carrier_ok(ndev)) {
+               netif_carrier_off(ndev);
+               netif_stop_queue(ndev);
+       }
+
+       if (test_bit(QL_ADAPTER_UP, &qdev->flags))
+               cancel_delayed_work_sync(&qdev->asic_reset_work);
+       cancel_delayed_work_sync(&qdev->mpi_reset_work);
+       cancel_delayed_work_sync(&qdev->mpi_work);
+       cancel_delayed_work_sync(&qdev->mpi_idc_work);
+       cancel_delayed_work_sync(&qdev->mpi_port_cfg_work);
+
+       for (i = 0; i < qdev->rss_ring_count; i++)
+               netif_napi_del(&qdev->rx_ring[i].napi);
+
+       clear_bit(QL_ADAPTER_UP, &qdev->flags);
+       ql_tx_ring_clean(qdev);
+       ql_free_rx_buffers(qdev);
+       ql_release_adapter_resources(qdev);
+}
+
 /*
  * This callback is called by the PCI subsystem whenever
  * a PCI bus error is detected.
@@ -4033,17 +4106,21 @@ static pci_ers_result_t qlge_io_error_detected(struct pci_dev *pdev,
                                               enum pci_channel_state state)
 {
        struct net_device *ndev = pci_get_drvdata(pdev);
-       struct ql_adapter *qdev = netdev_priv(ndev);
 
-       netif_device_detach(ndev);
-
-       if (state == pci_channel_io_perm_failure)
+       switch (state) {
+       case pci_channel_io_normal:
+               return PCI_ERS_RESULT_CAN_RECOVER;
+       case pci_channel_io_frozen:
+               netif_device_detach(ndev);
+               if (netif_running(ndev))
+                       ql_eeh_close(ndev);
+               pci_disable_device(pdev);
+               return PCI_ERS_RESULT_NEED_RESET;
+       case pci_channel_io_perm_failure:
+               dev_err(&pdev->dev,
+                       "%s: pci_channel_io_perm_failure.\n", __func__);
                return PCI_ERS_RESULT_DISCONNECT;
-
-       if (netif_running(ndev))
-               ql_adapter_down(qdev);
-
-       pci_disable_device(pdev);
+       }
 
        /* Request a slot reset. */
        return PCI_ERS_RESULT_NEED_RESET;
@@ -4060,25 +4137,15 @@ static pci_ers_result_t qlge_io_slot_reset(struct pci_dev *pdev)
        struct net_device *ndev = pci_get_drvdata(pdev);
        struct ql_adapter *qdev = netdev_priv(ndev);
 
+       pdev->error_state = pci_channel_io_normal;
+
+       pci_restore_state(pdev);
        if (pci_enable_device(pdev)) {
                QPRINTK(qdev, IFUP, ERR,
                        "Cannot re-enable PCI device after reset.\n");
                return PCI_ERS_RESULT_DISCONNECT;
        }
-
        pci_set_master(pdev);
-
-       netif_carrier_off(ndev);
-       ql_adapter_reset(qdev);
-
-       /* Make sure the EEPROM is good */
-       memcpy(ndev->perm_addr, ndev->dev_addr, ndev->addr_len);
-
-       if (!is_valid_ether_addr(ndev->perm_addr)) {
-               QPRINTK(qdev, IFUP, ERR, "After reset, invalid MAC address.\n");
-               return PCI_ERS_RESULT_DISCONNECT;
-       }
-
        return PCI_ERS_RESULT_RECOVERED;
 }
 
@@ -4086,17 +4153,21 @@ static void qlge_io_resume(struct pci_dev *pdev)
 {
        struct net_device *ndev = pci_get_drvdata(pdev);
        struct ql_adapter *qdev = netdev_priv(ndev);
+       int err = 0;
 
-       pci_set_master(pdev);
-
+       if (ql_adapter_reset(qdev))
+               QPRINTK(qdev, DRV, ERR, "reset FAILED!\n");
        if (netif_running(ndev)) {
-               if (ql_adapter_up(qdev)) {
+               err = qlge_open(ndev);
+               if (err) {
                        QPRINTK(qdev, IFUP, ERR,
                                "Device initialization failed after reset.\n");
                        return;
                }
+       } else {
+               QPRINTK(qdev, IFUP, ERR,
+                       "Device was not running prior to EEH.\n");
        }
-
        netif_device_attach(ndev);
 }
 
index 6685bd9..bcf13c9 100644 (file)
@@ -470,9 +470,9 @@ end:
  */
 static int ql_mailbox_command(struct ql_adapter *qdev, struct mbox_params *mbcp)
 {
-       int status, count;
+       int status;
+       unsigned long count;
 
-       mutex_lock(&qdev->mpi_mutex);
 
        /* Begin polled mode for MPI */
        ql_write32(qdev, INTR_MASK, (INTR_MASK_PI << 16));
@@ -492,9 +492,9 @@ static int ql_mailbox_command(struct ql_adapter *qdev, struct mbox_params *mbcp)
        /* Wait for the command to complete. We loop
         * here because some AEN might arrive while
         * we're waiting for the mailbox command to
-        * complete. If more than 5 arrive then we can
+        * complete. If more than 5 seconds expire we can
         * assume something is wrong. */
-       count = 5;
+       count = jiffies + HZ * MAILBOX_TIMEOUT;
        do {
                /* Wait for the interrupt to come in. */
                status = ql_wait_mbx_cmd_cmplt(qdev);
@@ -518,15 +518,15 @@ static int ql_mailbox_command(struct ql_adapter *qdev, struct mbox_params *mbcp)
                                        MB_CMD_STS_GOOD) ||
                        ((mbcp->mbox_out[0] & 0x0000f000) ==
                                        MB_CMD_STS_INTRMDT))
-                       break;
-       } while (--count);
+                       goto done;
+       } while (time_before(jiffies, count));
 
-       if (!count) {
-               QPRINTK(qdev, DRV, ERR,
-                       "Timed out waiting for mailbox complete.\n");
-               status = -ETIMEDOUT;
-               goto end;
-       }
+       QPRINTK(qdev, DRV, ERR,
+               "Timed out waiting for mailbox complete.\n");
+       status = -ETIMEDOUT;
+       goto end;
+
+done:
 
        /* Now we can clear the interrupt condition
         * and look at our status.
@@ -541,7 +541,6 @@ static int ql_mailbox_command(struct ql_adapter *qdev, struct mbox_params *mbcp)
                status = -EIO;
        }
 end:
-       mutex_unlock(&qdev->mpi_mutex);
        /* End polled mode for MPI */
        ql_write32(qdev, INTR_MASK, (INTR_MASK_PI << 16) | INTR_MASK_PI);
        return status;
@@ -770,13 +769,104 @@ static int ql_idc_wait(struct ql_adapter *qdev)
        return status;
 }
 
+int ql_mb_set_mgmnt_traffic_ctl(struct ql_adapter *qdev, u32 control)
+{
+       struct mbox_params mbc;
+       struct mbox_params *mbcp = &mbc;
+       int status;
+
+       memset(mbcp, 0, sizeof(struct mbox_params));
+
+       mbcp->in_count = 1;
+       mbcp->out_count = 2;
+
+       mbcp->mbox_in[0] = MB_CMD_SET_MGMNT_TFK_CTL;
+       mbcp->mbox_in[1] = control;
+
+       status = ql_mailbox_command(qdev, mbcp);
+       if (status)
+               return status;
+
+       if (mbcp->mbox_out[0] == MB_CMD_STS_GOOD)
+               return status;
+
+       if (mbcp->mbox_out[0] == MB_CMD_STS_INVLD_CMD) {
+               QPRINTK(qdev, DRV, ERR,
+                       "Command not supported by firmware.\n");
+               status = -EINVAL;
+       } else if (mbcp->mbox_out[0] == MB_CMD_STS_ERR) {
+               /* This indicates that the firmware is
+                * already in the state we are trying to
+                * change it to.
+                */
+               QPRINTK(qdev, DRV, ERR,
+                       "Command parameters make no change.\n");
+       }
+       return status;
+}
+
+/* Returns a negative error code or the mailbox command status. */
+static int ql_mb_get_mgmnt_traffic_ctl(struct ql_adapter *qdev, u32 *control)
+{
+       struct mbox_params mbc;
+       struct mbox_params *mbcp = &mbc;
+       int status;
+
+       memset(mbcp, 0, sizeof(struct mbox_params));
+       *control = 0;
+
+       mbcp->in_count = 1;
+       mbcp->out_count = 1;
+
+       mbcp->mbox_in[0] = MB_CMD_GET_MGMNT_TFK_CTL;
+
+       status = ql_mailbox_command(qdev, mbcp);
+       if (status)
+               return status;
+
+       if (mbcp->mbox_out[0] == MB_CMD_STS_GOOD) {
+               *control = mbcp->mbox_in[1];
+               return status;
+       }
+
+       if (mbcp->mbox_out[0] == MB_CMD_STS_INVLD_CMD) {
+               QPRINTK(qdev, DRV, ERR,
+                       "Command not supported by firmware.\n");
+               status = -EINVAL;
+       } else if (mbcp->mbox_out[0] == MB_CMD_STS_ERR) {
+               QPRINTK(qdev, DRV, ERR,
+                       "Failed to get MPI traffic control.\n");
+               status = -EIO;
+       }
+       return status;
+}
+
+int ql_wait_fifo_empty(struct ql_adapter *qdev)
+{
+       int count = 5;
+       u32 mgmnt_fifo_empty;
+       u32 nic_fifo_empty;
+
+       do {
+               nic_fifo_empty = ql_read32(qdev, STS) & STS_NFE;
+               ql_mb_get_mgmnt_traffic_ctl(qdev, &mgmnt_fifo_empty);
+               mgmnt_fifo_empty &= MB_GET_MPI_TFK_FIFO_EMPTY;
+               if (nic_fifo_empty && mgmnt_fifo_empty)
+                       return 0;
+               msleep(100);
+       } while (count-- > 0);
+       return -ETIMEDOUT;
+}
+
 /* API called in work thread context to set new TX/RX
  * maximum frame size values to match MTU.
  */
 static int ql_set_port_cfg(struct ql_adapter *qdev)
 {
        int status;
+       rtnl_lock();
        status = ql_mb_set_port_cfg(qdev);
+       rtnl_unlock();
        if (status)
                return status;
        status = ql_idc_wait(qdev);
@@ -797,7 +887,9 @@ void ql_mpi_port_cfg_work(struct work_struct *work)
            container_of(work, struct ql_adapter, mpi_port_cfg_work.work);
        int status;
 
+       rtnl_lock();
        status = ql_mb_get_port_cfg(qdev);
+       rtnl_unlock();
        if (status) {
                QPRINTK(qdev, DRV, ERR,
                        "Bug: Failed to get port config data.\n");
@@ -855,7 +947,9 @@ void ql_mpi_idc_work(struct work_struct *work)
                 * needs to be set.
                 * */
                set_bit(QL_CAM_RT_SET, &qdev->flags);
+               rtnl_lock();
                status = ql_mb_idc_ack(qdev);
+               rtnl_unlock();
                if (status) {
                        QPRINTK(qdev, DRV, ERR,
                        "Bug: No pending IDC!\n");
@@ -871,7 +965,9 @@ void ql_mpi_work(struct work_struct *work)
        struct mbox_params *mbcp = &mbc;
        int err = 0;
 
-       mutex_lock(&qdev->mpi_mutex);
+       rtnl_lock();
+       /* Begin polled mode for MPI */
+       ql_write32(qdev, INTR_MASK, (INTR_MASK_PI << 16));
 
        while (ql_read32(qdev, STS) & STS_PI) {
                memset(mbcp, 0, sizeof(struct mbox_params));
@@ -884,7 +980,9 @@ void ql_mpi_work(struct work_struct *work)
                        break;
        }
 
-       mutex_unlock(&qdev->mpi_mutex);
+       /* End polled mode for MPI */
+       ql_write32(qdev, INTR_MASK, (INTR_MASK_PI << 16) | INTR_MASK_PI);
+       rtnl_unlock();
        ql_enable_completion_interrupt(qdev, 0);
 }
 
index 50c6a3c..fa49356 100644 (file)
@@ -115,7 +115,9 @@ enum mac_version {
        RTL_GIGA_MAC_VER_22 = 0x16, // 8168C
        RTL_GIGA_MAC_VER_23 = 0x17, // 8168CP
        RTL_GIGA_MAC_VER_24 = 0x18, // 8168CP
-       RTL_GIGA_MAC_VER_25 = 0x19  // 8168D
+       RTL_GIGA_MAC_VER_25 = 0x19, // 8168D
+       RTL_GIGA_MAC_VER_26 = 0x1a, // 8168D
+       RTL_GIGA_MAC_VER_27 = 0x1b  // 8168DP
 };
 
 #define _R(NAME,MAC,MASK) \
@@ -150,7 +152,9 @@ static const struct {
        _R("RTL8168c/8111c",    RTL_GIGA_MAC_VER_22, 0xff7e1880), // PCI-E
        _R("RTL8168cp/8111cp",  RTL_GIGA_MAC_VER_23, 0xff7e1880), // PCI-E
        _R("RTL8168cp/8111cp",  RTL_GIGA_MAC_VER_24, 0xff7e1880), // PCI-E
-       _R("RTL8168d/8111d",    RTL_GIGA_MAC_VER_25, 0xff7e1880)  // PCI-E
+       _R("RTL8168d/8111d",    RTL_GIGA_MAC_VER_25, 0xff7e1880), // PCI-E
+       _R("RTL8168d/8111d",    RTL_GIGA_MAC_VER_26, 0xff7e1880), // PCI-E
+       _R("RTL8168dp/8111dp",  RTL_GIGA_MAC_VER_27, 0xff7e1880)  // PCI-E
 };
 #undef _R
 
@@ -253,6 +257,13 @@ enum rtl8168_8101_registers {
        DBG_REG                 = 0xd1,
 #define        FIX_NAK_1                       (1 << 4)
 #define        FIX_NAK_2                       (1 << 3)
+       EFUSEAR                 = 0xdc,
+#define        EFUSEAR_FLAG                    0x80000000
+#define        EFUSEAR_WRITE_CMD               0x80000000
+#define        EFUSEAR_READ_CMD                0x00000000
+#define        EFUSEAR_REG_MASK                0x03ff
+#define        EFUSEAR_REG_SHIFT               8
+#define        EFUSEAR_DATA_MASK               0xff
 };
 
 enum rtl_register_content {
@@ -568,6 +579,14 @@ static void mdio_patch(void __iomem *ioaddr, int reg_addr, int value)
        mdio_write(ioaddr, reg_addr, mdio_read(ioaddr, reg_addr) | value);
 }
 
+static void mdio_plus_minus(void __iomem *ioaddr, int reg_addr, int p, int m)
+{
+       int val;
+
+       val = mdio_read(ioaddr, reg_addr);
+       mdio_write(ioaddr, reg_addr, (val | p) & ~m);
+}
+
 static void rtl_mdio_write(struct net_device *dev, int phy_id, int location,
                           int val)
 {
@@ -651,6 +670,24 @@ static u32 rtl_csi_read(void __iomem *ioaddr, int addr)
        return value;
 }
 
+static u8 rtl8168d_efuse_read(void __iomem *ioaddr, int reg_addr)
+{
+       u8 value = 0xff;
+       unsigned int i;
+
+       RTL_W32(EFUSEAR, (reg_addr & EFUSEAR_REG_MASK) << EFUSEAR_REG_SHIFT);
+
+       for (i = 0; i < 300; i++) {
+               if (RTL_R32(EFUSEAR) & EFUSEAR_FLAG) {
+                       value = RTL_R32(EFUSEAR) & EFUSEAR_DATA_MASK;
+                       break;
+               }
+               udelay(100);
+       }
+
+       return value;
+}
+
 static void rtl8169_irq_mask_and_ack(void __iomem *ioaddr)
 {
        RTL_W16(IntrMask, 0x0000);
@@ -992,7 +1029,10 @@ static void rtl8169_vlan_rx_register(struct net_device *dev,
 
        spin_lock_irqsave(&tp->lock, flags);
        tp->vlgrp = grp;
-       if (tp->vlgrp)
+       /*
+        * Do not disable RxVlan on 8110SCd.
+        */
+       if (tp->vlgrp || (tp->mac_version == RTL_GIGA_MAC_VER_05))
                tp->cp_cmd |= RxVlan;
        else
                tp->cp_cmd &= ~RxVlan;
@@ -1243,7 +1283,10 @@ static void rtl8169_get_mac_version(struct rtl8169_private *tp,
                int mac_version;
        } mac_info[] = {
                /* 8168D family. */
-               { 0x7c800000, 0x28000000,       RTL_GIGA_MAC_VER_25 },
+               { 0x7cf00000, 0x28300000,       RTL_GIGA_MAC_VER_26 },
+               { 0x7cf00000, 0x28100000,       RTL_GIGA_MAC_VER_25 },
+               { 0x7c800000, 0x28800000,       RTL_GIGA_MAC_VER_27 },
+               { 0x7c800000, 0x28000000,       RTL_GIGA_MAC_VER_26 },
 
                /* 8168C family. */
                { 0x7cf00000, 0x3ca00000,       RTL_GIGA_MAC_VER_24 },
@@ -1648,74 +1691,903 @@ static void rtl8168c_4_hw_phy_config(void __iomem *ioaddr)
        rtl8168c_3_hw_phy_config(ioaddr);
 }
 
-static void rtl8168d_hw_phy_config(void __iomem *ioaddr)
+static void rtl8168d_1_hw_phy_config(void __iomem *ioaddr)
 {
-       struct phy_reg phy_reg_init_0[] = {
+       static struct phy_reg phy_reg_init_0[] = {
                { 0x1f, 0x0001 },
-               { 0x09, 0x2770 },
-               { 0x08, 0x04d0 },
-               { 0x0b, 0xad15 },
-               { 0x0c, 0x5bf0 },
-               { 0x1c, 0xf101 },
+               { 0x06, 0x4064 },
+               { 0x07, 0x2863 },
+               { 0x08, 0x059c },
+               { 0x09, 0x26b4 },
+               { 0x0a, 0x6a19 },
+               { 0x0b, 0xdcc8 },
+               { 0x10, 0xf06d },
+               { 0x14, 0x7f68 },
+               { 0x18, 0x7fd9 },
+               { 0x1c, 0xf0ff },
+               { 0x1d, 0x3d9c },
                { 0x1f, 0x0003 },
-               { 0x14, 0x94d7 },
-               { 0x12, 0xf4d6 },
-               { 0x09, 0xca0f },
-               { 0x1f, 0x0002 },
-               { 0x0b, 0x0b10 },
-               { 0x0c, 0xd1f7 },
-               { 0x1f, 0x0002 },
-               { 0x06, 0x5461 },
+               { 0x12, 0xf49f },
+               { 0x13, 0x070b },
+               { 0x1a, 0x05ad },
+               { 0x14, 0x94c0 }
+       };
+       static struct phy_reg phy_reg_init_1[] = {
                { 0x1f, 0x0002 },
-               { 0x05, 0x6662 },
+               { 0x06, 0x5561 },
+               { 0x1f, 0x0005 },
+               { 0x05, 0x8332 },
+               { 0x06, 0x5561 }
+       };
+       static struct phy_reg phy_reg_init_2[] = {
+               { 0x1f, 0x0005 },
+               { 0x05, 0xffc2 },
+               { 0x1f, 0x0005 },
+               { 0x05, 0x8000 },
+               { 0x06, 0xf8f9 },
+               { 0x06, 0xfaef },
+               { 0x06, 0x59ee },
+               { 0x06, 0xf8ea },
+               { 0x06, 0x00ee },
+               { 0x06, 0xf8eb },
+               { 0x06, 0x00e0 },
+               { 0x06, 0xf87c },
+               { 0x06, 0xe1f8 },
+               { 0x06, 0x7d59 },
+               { 0x06, 0x0fef },
+               { 0x06, 0x0139 },
+               { 0x06, 0x029e },
+               { 0x06, 0x06ef },
+               { 0x06, 0x1039 },
+               { 0x06, 0x089f },
+               { 0x06, 0x2aee },
+               { 0x06, 0xf8ea },
+               { 0x06, 0x00ee },
+               { 0x06, 0xf8eb },
+               { 0x06, 0x01e0 },
+               { 0x06, 0xf87c },
+               { 0x06, 0xe1f8 },
+               { 0x06, 0x7d58 },
+               { 0x06, 0x409e },
+               { 0x06, 0x0f39 },
+               { 0x06, 0x46aa },
+               { 0x06, 0x0bbf },
+               { 0x06, 0x8290 },
+               { 0x06, 0xd682 },
+               { 0x06, 0x9802 },
+               { 0x06, 0x014f },
+               { 0x06, 0xae09 },
+               { 0x06, 0xbf82 },
+               { 0x06, 0x98d6 },
+               { 0x06, 0x82a0 },
+               { 0x06, 0x0201 },
+               { 0x06, 0x4fef },
+               { 0x06, 0x95fe },
+               { 0x06, 0xfdfc },
+               { 0x06, 0x05f8 },
+               { 0x06, 0xf9fa },
+               { 0x06, 0xeef8 },
+               { 0x06, 0xea00 },
+               { 0x06, 0xeef8 },
+               { 0x06, 0xeb00 },
+               { 0x06, 0xe2f8 },
+               { 0x06, 0x7ce3 },
+               { 0x06, 0xf87d },
+               { 0x06, 0xa511 },
+               { 0x06, 0x1112 },
+               { 0x06, 0xd240 },
+               { 0x06, 0xd644 },
+               { 0x06, 0x4402 },
+               { 0x06, 0x8217 },
+               { 0x06, 0xd2a0 },
+               { 0x06, 0xd6aa },
+               { 0x06, 0xaa02 },
+               { 0x06, 0x8217 },
+               { 0x06, 0xae0f },
+               { 0x06, 0xa544 },
+               { 0x06, 0x4402 },
+               { 0x06, 0xae4d },
+               { 0x06, 0xa5aa },
+               { 0x06, 0xaa02 },
+               { 0x06, 0xae47 },
+               { 0x06, 0xaf82 },
+               { 0x06, 0x13ee },
+               { 0x06, 0x834e },
+               { 0x06, 0x00ee },
+               { 0x06, 0x834d },
+               { 0x06, 0x0fee },
+               { 0x06, 0x834c },
+               { 0x06, 0x0fee },
+               { 0x06, 0x834f },
+               { 0x06, 0x00ee },
+               { 0x06, 0x8351 },
+               { 0x06, 0x00ee },
+               { 0x06, 0x834a },
+               { 0x06, 0xffee },
+               { 0x06, 0x834b },
+               { 0x06, 0xffe0 },
+               { 0x06, 0x8330 },
+               { 0x06, 0xe183 },
+               { 0x06, 0x3158 },
+               { 0x06, 0xfee4 },
+               { 0x06, 0xf88a },
+               { 0x06, 0xe5f8 },
+               { 0x06, 0x8be0 },
+               { 0x06, 0x8332 },
+               { 0x06, 0xe183 },
+               { 0x06, 0x3359 },
+               { 0x06, 0x0fe2 },
+               { 0x06, 0x834d },
+               { 0x06, 0x0c24 },
+               { 0x06, 0x5af0 },
+               { 0x06, 0x1e12 },
+               { 0x06, 0xe4f8 },
+               { 0x06, 0x8ce5 },
+               { 0x06, 0xf88d },
+               { 0x06, 0xaf82 },
+               { 0x06, 0x13e0 },
+               { 0x06, 0x834f },
+               { 0x06, 0x10e4 },
+               { 0x06, 0x834f },
+               { 0x06, 0xe083 },
+               { 0x06, 0x4e78 },
+               { 0x06, 0x009f },
+               { 0x06, 0x0ae0 },
+               { 0x06, 0x834f },
+               { 0x06, 0xa010 },
+               { 0x06, 0xa5ee },
+               { 0x06, 0x834e },
+               { 0x06, 0x01e0 },
+               { 0x06, 0x834e },
+               { 0x06, 0x7805 },
+               { 0x06, 0x9e9a },
+               { 0x06, 0xe083 },
+               { 0x06, 0x4e78 },
+               { 0x06, 0x049e },
+               { 0x06, 0x10e0 },
+               { 0x06, 0x834e },
+               { 0x06, 0x7803 },
+               { 0x06, 0x9e0f },
+               { 0x06, 0xe083 },
+               { 0x06, 0x4e78 },
+               { 0x06, 0x019e },
+               { 0x06, 0x05ae },
+               { 0x06, 0x0caf },
+               { 0x06, 0x81f8 },
+               { 0x06, 0xaf81 },
+               { 0x06, 0xa3af },
+               { 0x06, 0x81dc },
+               { 0x06, 0xaf82 },
+               { 0x06, 0x13ee },
+               { 0x06, 0x8348 },
+               { 0x06, 0x00ee },
+               { 0x06, 0x8349 },
+               { 0x06, 0x00e0 },
+               { 0x06, 0x8351 },
+               { 0x06, 0x10e4 },
+               { 0x06, 0x8351 },
+               { 0x06, 0x5801 },
+               { 0x06, 0x9fea },
+               { 0x06, 0xd000 },
+               { 0x06, 0xd180 },
+               { 0x06, 0x1f66 },
+               { 0x06, 0xe2f8 },
+               { 0x06, 0xeae3 },
+               { 0x06, 0xf8eb },
+               { 0x06, 0x5af8 },
+               { 0x06, 0x1e20 },
+               { 0x06, 0xe6f8 },
+               { 0x06, 0xeae5 },
+               { 0x06, 0xf8eb },
+               { 0x06, 0xd302 },
+               { 0x06, 0xb3fe },
+               { 0x06, 0xe2f8 },
+               { 0x06, 0x7cef },
+               { 0x06, 0x325b },
+               { 0x06, 0x80e3 },
+               { 0x06, 0xf87d },
+               { 0x06, 0x9e03 },
+               { 0x06, 0x7dff },
+               { 0x06, 0xff0d },
+               { 0x06, 0x581c },
+               { 0x06, 0x551a },
+               { 0x06, 0x6511 },
+               { 0x06, 0xa190 },
+               { 0x06, 0xd3e2 },
+               { 0x06, 0x8348 },
+               { 0x06, 0xe383 },
+               { 0x06, 0x491b },
+               { 0x06, 0x56ab },
+               { 0x06, 0x08ef },
+               { 0x06, 0x56e6 },
+               { 0x06, 0x8348 },
+               { 0x06, 0xe783 },
+               { 0x06, 0x4910 },
+               { 0x06, 0xd180 },
+               { 0x06, 0x1f66 },
+               { 0x06, 0xa004 },
+               { 0x06, 0xb9e2 },
+               { 0x06, 0x8348 },
+               { 0x06, 0xe383 },
+               { 0x06, 0x49ef },
+               { 0x06, 0x65e2 },
+               { 0x06, 0x834a },
+               { 0x06, 0xe383 },
+               { 0x06, 0x4b1b },
+               { 0x06, 0x56aa },
+               { 0x06, 0x0eef },
+               { 0x06, 0x56e6 },
+               { 0x06, 0x834a },
+               { 0x06, 0xe783 },
+               { 0x06, 0x4be2 },
+               { 0x06, 0x834d },
+               { 0x06, 0xe683 },
+               { 0x06, 0x4ce0 },
+               { 0x06, 0x834d },
+               { 0x06, 0xa000 },
+               { 0x06, 0x0caf },
+               { 0x06, 0x81dc },
+               { 0x06, 0xe083 },
+               { 0x06, 0x4d10 },
+               { 0x06, 0xe483 },
+               { 0x06, 0x4dae },
+               { 0x06, 0x0480 },
+               { 0x06, 0xe483 },
+               { 0x06, 0x4de0 },
+               { 0x06, 0x834e },
+               { 0x06, 0x7803 },
+               { 0x06, 0x9e0b },
+               { 0x06, 0xe083 },
+               { 0x06, 0x4e78 },
+               { 0x06, 0x049e },
+               { 0x06, 0x04ee },
+               { 0x06, 0x834e },
+               { 0x06, 0x02e0 },
+               { 0x06, 0x8332 },
+               { 0x06, 0xe183 },
+               { 0x06, 0x3359 },
+               { 0x06, 0x0fe2 },
+               { 0x06, 0x834d },
+               { 0x06, 0x0c24 },
+               { 0x06, 0x5af0 },
+               { 0x06, 0x1e12 },
+               { 0x06, 0xe4f8 },
+               { 0x06, 0x8ce5 },
+               { 0x06, 0xf88d },
+               { 0x06, 0xe083 },
+               { 0x06, 0x30e1 },
+               { 0x06, 0x8331 },
+               { 0x06, 0x6801 },
+               { 0x06, 0xe4f8 },
+               { 0x06, 0x8ae5 },
+               { 0x06, 0xf88b },
+               { 0x06, 0xae37 },
+               { 0x06, 0xee83 },
+               { 0x06, 0x4e03 },
+               { 0x06, 0xe083 },
+               { 0x06, 0x4ce1 },
+               { 0x06, 0x834d },
+               { 0x06, 0x1b01 },
+               { 0x06, 0x9e04 },
+               { 0x06, 0xaaa1 },
+               { 0x06, 0xaea8 },
+               { 0x06, 0xee83 },
+               { 0x06, 0x4e04 },
+               { 0x06, 0xee83 },
+               { 0x06, 0x4f00 },
+               { 0x06, 0xaeab },
+               { 0x06, 0xe083 },
+               { 0x06, 0x4f78 },
+               { 0x06, 0x039f },
+               { 0x06, 0x14ee },
+               { 0x06, 0x834e },
+               { 0x06, 0x05d2 },
+               { 0x06, 0x40d6 },
+               { 0x06, 0x5554 },
+               { 0x06, 0x0282 },
+               { 0x06, 0x17d2 },
+               { 0x06, 0xa0d6 },
+               { 0x06, 0xba00 },
+               { 0x06, 0x0282 },
+               { 0x06, 0x17fe },
+               { 0x06, 0xfdfc },
+               { 0x06, 0x05f8 },
+               { 0x06, 0xe0f8 },
+               { 0x06, 0x60e1 },
+               { 0x06, 0xf861 },
+               { 0x06, 0x6802 },
+               { 0x06, 0xe4f8 },
+               { 0x06, 0x60e5 },
+               { 0x06, 0xf861 },
+               { 0x06, 0xe0f8 },
+               { 0x06, 0x48e1 },
+               { 0x06, 0xf849 },
+               { 0x06, 0x580f },
+               { 0x06, 0x1e02 },
+               { 0x06, 0xe4f8 },
+               { 0x06, 0x48e5 },
+               { 0x06, 0xf849 },
+               { 0x06, 0xd000 },
+               { 0x06, 0x0282 },
+               { 0x06, 0x5bbf },
+               { 0x06, 0x8350 },
+               { 0x06, 0xef46 },
+               { 0x06, 0xdc19 },
+               { 0x06, 0xddd0 },
+               { 0x06, 0x0102 },
+               { 0x06, 0x825b },
+               { 0x06, 0x0282 },
+               { 0x06, 0x77e0 },
+               { 0x06, 0xf860 },
+               { 0x06, 0xe1f8 },
+               { 0x06, 0x6158 },
+               { 0x06, 0xfde4 },
+               { 0x06, 0xf860 },
+               { 0x06, 0xe5f8 },
+               { 0x06, 0x61fc },
+               { 0x06, 0x04f9 },
+               { 0x06, 0xfafb },
+               { 0x06, 0xc6bf },
+               { 0x06, 0xf840 },
+               { 0x06, 0xbe83 },
+               { 0x06, 0x50a0 },
+               { 0x06, 0x0101 },
+               { 0x06, 0x071b },
+               { 0x06, 0x89cf },
+               { 0x06, 0xd208 },
+               { 0x06, 0xebdb },
+               { 0x06, 0x19b2 },
+               { 0x06, 0xfbff },
+               { 0x06, 0xfefd },
+               { 0x06, 0x04f8 },
+               { 0x06, 0xe0f8 },
+               { 0x06, 0x48e1 },
+               { 0x06, 0xf849 },
+               { 0x06, 0x6808 },
+               { 0x06, 0xe4f8 },
+               { 0x06, 0x48e5 },
+               { 0x06, 0xf849 },
+               { 0x06, 0x58f7 },
+               { 0x06, 0xe4f8 },
+               { 0x06, 0x48e5 },
+               { 0x06, 0xf849 },
+               { 0x06, 0xfc04 },
+               { 0x06, 0x4d20 },
+               { 0x06, 0x0002 },
+               { 0x06, 0x4e22 },
+               { 0x06, 0x0002 },
+               { 0x06, 0x4ddf },
+               { 0x06, 0xff01 },
+               { 0x06, 0x4edd },
+               { 0x06, 0xff01 },
+               { 0x05, 0x83d4 },
+               { 0x06, 0x8000 },
+               { 0x05, 0x83d8 },
+               { 0x06, 0x8051 },
+               { 0x02, 0x6010 },
+               { 0x03, 0xdc00 },
+               { 0x05, 0xfff6 },
+               { 0x06, 0x00fc },
                { 0x1f, 0x0000 },
-               { 0x14, 0x0060 },
+
                { 0x1f, 0x0000 },
-               { 0x0d, 0xf8a0 },
+               { 0x0d, 0xf880 },
+               { 0x1f, 0x0000 }
+       };
+
+       rtl_phy_write(ioaddr, phy_reg_init_0, ARRAY_SIZE(phy_reg_init_0));
+
+       mdio_write(ioaddr, 0x1f, 0x0002);
+       mdio_plus_minus(ioaddr, 0x0b, 0x0010, 0x00ef);
+       mdio_plus_minus(ioaddr, 0x0c, 0xa200, 0x5d00);
+
+       rtl_phy_write(ioaddr, phy_reg_init_1, ARRAY_SIZE(phy_reg_init_1));
+
+       if (rtl8168d_efuse_read(ioaddr, 0x01) == 0xb1) {
+               struct phy_reg phy_reg_init[] = {
+                       { 0x1f, 0x0002 },
+                       { 0x05, 0x669a },
+                       { 0x1f, 0x0005 },
+                       { 0x05, 0x8330 },
+                       { 0x06, 0x669a },
+                       { 0x1f, 0x0002 }
+               };
+               int val;
+
+               rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init));
+
+               val = mdio_read(ioaddr, 0x0d);
+
+               if ((val & 0x00ff) != 0x006c) {
+                       u32 set[] = {
+                               0x0065, 0x0066, 0x0067, 0x0068,
+                               0x0069, 0x006a, 0x006b, 0x006c
+                       };
+                       int i;
+
+                       mdio_write(ioaddr, 0x1f, 0x0002);
+
+                       val &= 0xff00;
+                       for (i = 0; i < ARRAY_SIZE(set); i++)
+                               mdio_write(ioaddr, 0x0d, val | set[i]);
+               }
+       } else {
+               struct phy_reg phy_reg_init[] = {
+                       { 0x1f, 0x0002 },
+                       { 0x05, 0x6662 },
+                       { 0x1f, 0x0005 },
+                       { 0x05, 0x8330 },
+                       { 0x06, 0x6662 }
+               };
+
+               rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init));
+       }
+
+       mdio_write(ioaddr, 0x1f, 0x0002);
+       mdio_patch(ioaddr, 0x0d, 0x0300);
+       mdio_patch(ioaddr, 0x0f, 0x0010);
+
+       mdio_write(ioaddr, 0x1f, 0x0002);
+       mdio_plus_minus(ioaddr, 0x02, 0x0100, 0x0600);
+       mdio_plus_minus(ioaddr, 0x03, 0x0000, 0xe000);
+
+       rtl_phy_write(ioaddr, phy_reg_init_2, ARRAY_SIZE(phy_reg_init_2));
+}
+
+static void rtl8168d_2_hw_phy_config(void __iomem *ioaddr)
+{
+       static struct phy_reg phy_reg_init_0[] = {
+               { 0x1f, 0x0001 },
+               { 0x06, 0x4064 },
+               { 0x07, 0x2863 },
+               { 0x08, 0x059c },
+               { 0x09, 0x26b4 },
+               { 0x0a, 0x6a19 },
+               { 0x0b, 0xdcc8 },
+               { 0x10, 0xf06d },
+               { 0x14, 0x7f68 },
+               { 0x18, 0x7fd9 },
+               { 0x1c, 0xf0ff },
+               { 0x1d, 0x3d9c },
+               { 0x1f, 0x0003 },
+               { 0x12, 0xf49f },
+               { 0x13, 0x070b },
+               { 0x1a, 0x05ad },
+               { 0x14, 0x94c0 },
+
+               { 0x1f, 0x0002 },
+               { 0x06, 0x5561 },
                { 0x1f, 0x0005 },
-               { 0x05, 0xffc2 }
+               { 0x05, 0x8332 },
+               { 0x06, 0x5561 }
+       };
+       static struct phy_reg phy_reg_init_1[] = {
+               { 0x1f, 0x0005 },
+               { 0x05, 0xffc2 },
+               { 0x1f, 0x0005 },
+               { 0x05, 0x8000 },
+               { 0x06, 0xf8f9 },
+               { 0x06, 0xfaee },
+               { 0x06, 0xf8ea },
+               { 0x06, 0x00ee },
+               { 0x06, 0xf8eb },
+               { 0x06, 0x00e2 },
+               { 0x06, 0xf87c },
+               { 0x06, 0xe3f8 },
+               { 0x06, 0x7da5 },
+               { 0x06, 0x1111 },
+               { 0x06, 0x12d2 },
+               { 0x06, 0x40d6 },
+               { 0x06, 0x4444 },
+               { 0x06, 0x0281 },
+               { 0x06, 0xc6d2 },
+               { 0x06, 0xa0d6 },
+               { 0x06, 0xaaaa },
+               { 0x06, 0x0281 },
+               { 0x06, 0xc6ae },
+               { 0x06, 0x0fa5 },
+               { 0x06, 0x4444 },
+               { 0x06, 0x02ae },
+               { 0x06, 0x4da5 },
+               { 0x06, 0xaaaa },
+               { 0x06, 0x02ae },
+               { 0x06, 0x47af },
+               { 0x06, 0x81c2 },
+               { 0x06, 0xee83 },
+               { 0x06, 0x4e00 },
+               { 0x06, 0xee83 },
+               { 0x06, 0x4d0f },
+               { 0x06, 0xee83 },
+               { 0x06, 0x4c0f },
+               { 0x06, 0xee83 },
+               { 0x06, 0x4f00 },
+               { 0x06, 0xee83 },
+               { 0x06, 0x5100 },
+               { 0x06, 0xee83 },
+               { 0x06, 0x4aff },
+               { 0x06, 0xee83 },
+               { 0x06, 0x4bff },
+               { 0x06, 0xe083 },
+               { 0x06, 0x30e1 },
+               { 0x06, 0x8331 },
+               { 0x06, 0x58fe },
+               { 0x06, 0xe4f8 },
+               { 0x06, 0x8ae5 },
+               { 0x06, 0xf88b },
+               { 0x06, 0xe083 },
+               { 0x06, 0x32e1 },
+               { 0x06, 0x8333 },
+               { 0x06, 0x590f },
+               { 0x06, 0xe283 },
+               { 0x06, 0x4d0c },
+               { 0x06, 0x245a },
+               { 0x06, 0xf01e },
+               { 0x06, 0x12e4 },
+               { 0x06, 0xf88c },
+               { 0x06, 0xe5f8 },
+               { 0x06, 0x8daf },
+               { 0x06, 0x81c2 },
+               { 0x06, 0xe083 },
+               { 0x06, 0x4f10 },
+               { 0x06, 0xe483 },
+               { 0x06, 0x4fe0 },
+               { 0x06, 0x834e },
+               { 0x06, 0x7800 },
+               { 0x06, 0x9f0a },
+               { 0x06, 0xe083 },
+               { 0x06, 0x4fa0 },
+               { 0x06, 0x10a5 },
+               { 0x06, 0xee83 },
+               { 0x06, 0x4e01 },
+               { 0x06, 0xe083 },
+               { 0x06, 0x4e78 },
+               { 0x06, 0x059e },
+               { 0x06, 0x9ae0 },
+               { 0x06, 0x834e },
+               { 0x06, 0x7804 },
+               { 0x06, 0x9e10 },
+               { 0x06, 0xe083 },
+               { 0x06, 0x4e78 },
+               { 0x06, 0x039e },
+               { 0x06, 0x0fe0 },
+               { 0x06, 0x834e },
+               { 0x06, 0x7801 },
+               { 0x06, 0x9e05 },
+               { 0x06, 0xae0c },
+               { 0x06, 0xaf81 },
+               { 0x06, 0xa7af },
+               { 0x06, 0x8152 },
+               { 0x06, 0xaf81 },
+               { 0x06, 0x8baf },
+               { 0x06, 0x81c2 },
+               { 0x06, 0xee83 },
+               { 0x06, 0x4800 },
+               { 0x06, 0xee83 },
+               { 0x06, 0x4900 },
+               { 0x06, 0xe083 },
+               { 0x06, 0x5110 },
+               { 0x06, 0xe483 },
+               { 0x06, 0x5158 },
+               { 0x06, 0x019f },
+               { 0x06, 0xead0 },
+               { 0x06, 0x00d1 },
+               { 0x06, 0x801f },
+               { 0x06, 0x66e2 },
+               { 0x06, 0xf8ea },
+               { 0x06, 0xe3f8 },
+               { 0x06, 0xeb5a },
+               { 0x06, 0xf81e },
+               { 0x06, 0x20e6 },
+               { 0x06, 0xf8ea },
+               { 0x06, 0xe5f8 },
+               { 0x06, 0xebd3 },
+               { 0x06, 0x02b3 },
+               { 0x06, 0xfee2 },
+               { 0x06, 0xf87c },
+               { 0x06, 0xef32 },
+               { 0x06, 0x5b80 },
+               { 0x06, 0xe3f8 },
+               { 0x06, 0x7d9e },
+               { 0x06, 0x037d },
+               { 0x06, 0xffff },
+               { 0x06, 0x0d58 },
+               { 0x06, 0x1c55 },
+               { 0x06, 0x1a65 },
+               { 0x06, 0x11a1 },
+               { 0x06, 0x90d3 },
+               { 0x06, 0xe283 },
+               { 0x06, 0x48e3 },
+               { 0x06, 0x8349 },
+               { 0x06, 0x1b56 },
+               { 0x06, 0xab08 },
+               { 0x06, 0xef56 },
+               { 0x06, 0xe683 },
+               { 0x06, 0x48e7 },
+               { 0x06, 0x8349 },
+               { 0x06, 0x10d1 },
+               { 0x06, 0x801f },
+               { 0x06, 0x66a0 },
+               { 0x06, 0x04b9 },
+               { 0x06, 0xe283 },
+               { 0x06, 0x48e3 },
+               { 0x06, 0x8349 },
+               { 0x06, 0xef65 },
+               { 0x06, 0xe283 },
+               { 0x06, 0x4ae3 },
+               { 0x06, 0x834b },
+               { 0x06, 0x1b56 },
+               { 0x06, 0xaa0e },
+               { 0x06, 0xef56 },
+               { 0x06, 0xe683 },
+               { 0x06, 0x4ae7 },
+               { 0x06, 0x834b },
+               { 0x06, 0xe283 },
+               { 0x06, 0x4de6 },
+               { 0x06, 0x834c },
+               { 0x06, 0xe083 },
+               { 0x06, 0x4da0 },
+               { 0x06, 0x000c },
+               { 0x06, 0xaf81 },
+               { 0x06, 0x8be0 },
+               { 0x06, 0x834d },
+               { 0x06, 0x10e4 },
+               { 0x06, 0x834d },
+               { 0x06, 0xae04 },
+               { 0x06, 0x80e4 },
+               { 0x06, 0x834d },
+               { 0x06, 0xe083 },
+               { 0x06, 0x4e78 },
+               { 0x06, 0x039e },
+               { 0x06, 0x0be0 },
+               { 0x06, 0x834e },
+               { 0x06, 0x7804 },
+               { 0x06, 0x9e04 },
+               { 0x06, 0xee83 },
+               { 0x06, 0x4e02 },
+               { 0x06, 0xe083 },
+               { 0x06, 0x32e1 },
+               { 0x06, 0x8333 },
+               { 0x06, 0x590f },
+               { 0x06, 0xe283 },
+               { 0x06, 0x4d0c },
+               { 0x06, 0x245a },
+               { 0x06, 0xf01e },
+               { 0x06, 0x12e4 },
+               { 0x06, 0xf88c },
+               { 0x06, 0xe5f8 },
+               { 0x06, 0x8de0 },
+               { 0x06, 0x8330 },
+               { 0x06, 0xe183 },
+               { 0x06, 0x3168 },
+               { 0x06, 0x01e4 },
+               { 0x06, 0xf88a },
+               { 0x06, 0xe5f8 },
+               { 0x06, 0x8bae },
+               { 0x06, 0x37ee },
+               { 0x06, 0x834e },
+               { 0x06, 0x03e0 },
+               { 0x06, 0x834c },
+               { 0x06, 0xe183 },
+               { 0x06, 0x4d1b },
+               { 0x06, 0x019e },
+               { 0x06, 0x04aa },
+               { 0x06, 0xa1ae },
+               { 0x06, 0xa8ee },
+               { 0x06, 0x834e },
+               { 0x06, 0x04ee },
+               { 0x06, 0x834f },
+               { 0x06, 0x00ae },
+               { 0x06, 0xabe0 },
+               { 0x06, 0x834f },
+               { 0x06, 0x7803 },
+               { 0x06, 0x9f14 },
+               { 0x06, 0xee83 },
+               { 0x06, 0x4e05 },
+               { 0x06, 0xd240 },
+               { 0x06, 0xd655 },
+               { 0x06, 0x5402 },
+               { 0x06, 0x81c6 },
+               { 0x06, 0xd2a0 },
+               { 0x06, 0xd6ba },
+               { 0x06, 0x0002 },
+               { 0x06, 0x81c6 },
+               { 0x06, 0xfefd },
+               { 0x06, 0xfc05 },
+               { 0x06, 0xf8e0 },
+               { 0x06, 0xf860 },
+               { 0x06, 0xe1f8 },
+               { 0x06, 0x6168 },
+               { 0x06, 0x02e4 },
+               { 0x06, 0xf860 },
+               { 0x06, 0xe5f8 },
+               { 0x06, 0x61e0 },
+               { 0x06, 0xf848 },
+               { 0x06, 0xe1f8 },
+               { 0x06, 0x4958 },
+               { 0x06, 0x0f1e },
+               { 0x06, 0x02e4 },
+               { 0x06, 0xf848 },
+               { 0x06, 0xe5f8 },
+               { 0x06, 0x49d0 },
+               { 0x06, 0x0002 },
+               { 0x06, 0x820a },
+               { 0x06, 0xbf83 },
+               { 0x06, 0x50ef },
+               { 0x06, 0x46dc },
+               { 0x06, 0x19dd },
+               { 0x06, 0xd001 },
+               { 0x06, 0x0282 },
+               { 0x06, 0x0a02 },
+               { 0x06, 0x8226 },
+               { 0x06, 0xe0f8 },
+               { 0x06, 0x60e1 },
+               { 0x06, 0xf861 },
+               { 0x06, 0x58fd },
+               { 0x06, 0xe4f8 },
+               { 0x06, 0x60e5 },
+               { 0x06, 0xf861 },
+               { 0x06, 0xfc04 },
+               { 0x06, 0xf9fa },
+               { 0x06, 0xfbc6 },
+               { 0x06, 0xbff8 },
+               { 0x06, 0x40be },
+               { 0x06, 0x8350 },
+               { 0x06, 0xa001 },
+               { 0x06, 0x0107 },
+               { 0x06, 0x1b89 },
+               { 0x06, 0xcfd2 },
+               { 0x06, 0x08eb },
+               { 0x06, 0xdb19 },
+               { 0x06, 0xb2fb },
+               { 0x06, 0xfffe },
+               { 0x06, 0xfd04 },
+               { 0x06, 0xf8e0 },
+               { 0x06, 0xf848 },
+               { 0x06, 0xe1f8 },
+               { 0x06, 0x4968 },
+               { 0x06, 0x08e4 },
+               { 0x06, 0xf848 },
+               { 0x06, 0xe5f8 },
+               { 0x06, 0x4958 },
+               { 0x06, 0xf7e4 },
+               { 0x06, 0xf848 },
+               { 0x06, 0xe5f8 },
+               { 0x06, 0x49fc },
+               { 0x06, 0x044d },
+               { 0x06, 0x2000 },
+               { 0x06, 0x024e },
+               { 0x06, 0x2200 },
+               { 0x06, 0x024d },
+               { 0x06, 0xdfff },
+               { 0x06, 0x014e },
+               { 0x06, 0xddff },
+               { 0x06, 0x0100 },
+               { 0x05, 0x83d8 },
+               { 0x06, 0x8000 },
+               { 0x03, 0xdc00 },
+               { 0x05, 0xfff6 },
+               { 0x06, 0x00fc },
+               { 0x1f, 0x0000 },
+
+               { 0x1f, 0x0000 },
+               { 0x0d, 0xf880 },
+               { 0x1f, 0x0000 }
        };
 
        rtl_phy_write(ioaddr, phy_reg_init_0, ARRAY_SIZE(phy_reg_init_0));
 
-       if (mdio_read(ioaddr, 0x06) == 0xc400) {
-               struct phy_reg phy_reg_init_1[] = {
+       if (rtl8168d_efuse_read(ioaddr, 0x01) == 0xb1) {
+               struct phy_reg phy_reg_init[] = {
+                       { 0x1f, 0x0002 },
+                       { 0x05, 0x669a },
                        { 0x1f, 0x0005 },
-                       { 0x01, 0x0300 },
-                       { 0x1f, 0x0000 },
-                       { 0x11, 0x401c },
-                       { 0x16, 0x4100 },
+                       { 0x05, 0x8330 },
+                       { 0x06, 0x669a },
+
+                       { 0x1f, 0x0002 }
+               };
+               int val;
+
+               rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init));
+
+               val = mdio_read(ioaddr, 0x0d);
+               if ((val & 0x00ff) != 0x006c) {
+                       u32 set[] = {
+                               0x0065, 0x0066, 0x0067, 0x0068,
+                               0x0069, 0x006a, 0x006b, 0x006c
+                       };
+                       int i;
+
+                       mdio_write(ioaddr, 0x1f, 0x0002);
+
+                       val &= 0xff00;
+                       for (i = 0; i < ARRAY_SIZE(set); i++)
+                               mdio_write(ioaddr, 0x0d, val | set[i]);
+               }
+       } else {
+               struct phy_reg phy_reg_init[] = {
+                       { 0x1f, 0x0002 },
+                       { 0x05, 0x2642 },
                        { 0x1f, 0x0005 },
-                       { 0x07, 0x0010 },
-                       { 0x05, 0x83dc },
-                       { 0x06, 0x087d },
-                       { 0x05, 0x8300 },
-                       { 0x06, 0x0101 },
-                       { 0x06, 0x05f8 },
-                       { 0x06, 0xf9fa },
-                       { 0x06, 0xfbef },
-                       { 0x06, 0x79e2 },
-                       { 0x06, 0x835f },
-                       { 0x06, 0xe0f8 },
-                       { 0x06, 0x9ae1 },
-                       { 0x06, 0xf89b },
-                       { 0x06, 0xef31 },
-                       { 0x06, 0x3b65 },
-                       { 0x06, 0xaa07 },
-                       { 0x06, 0x81e4 },
-                       { 0x06, 0xf89a },
-                       { 0x06, 0xe5f8 },
-                       { 0x06, 0x9baf },
-                       { 0x06, 0x06ae },
-                       { 0x05, 0x83dc },
-                       { 0x06, 0x8300 },
+                       { 0x05, 0x8330 },
+                       { 0x06, 0x2642 }
                };
 
-               rtl_phy_write(ioaddr, phy_reg_init_1,
-                             ARRAY_SIZE(phy_reg_init_1));
+               rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init));
        }
 
-       mdio_write(ioaddr, 0x1f, 0x0000);
+       mdio_write(ioaddr, 0x1f, 0x0002);
+       mdio_plus_minus(ioaddr, 0x02, 0x0100, 0x0600);
+       mdio_plus_minus(ioaddr, 0x03, 0x0000, 0xe000);
+
+       mdio_write(ioaddr, 0x1f, 0x0001);
+       mdio_write(ioaddr, 0x17, 0x0cc0);
+
+       mdio_write(ioaddr, 0x1f, 0x0002);
+       mdio_patch(ioaddr, 0x0f, 0x0017);
+
+       rtl_phy_write(ioaddr, phy_reg_init_1, ARRAY_SIZE(phy_reg_init_1));
+}
+
+static void rtl8168d_3_hw_phy_config(void __iomem *ioaddr)
+{
+       struct phy_reg phy_reg_init[] = {
+               { 0x1f, 0x0002 },
+               { 0x10, 0x0008 },
+               { 0x0d, 0x006c },
+
+               { 0x1f, 0x0000 },
+               { 0x0d, 0xf880 },
+
+               { 0x1f, 0x0001 },
+               { 0x17, 0x0cc0 },
+
+               { 0x1f, 0x0001 },
+               { 0x0b, 0xa4d8 },
+               { 0x09, 0x281c },
+               { 0x07, 0x2883 },
+               { 0x0a, 0x6b35 },
+               { 0x1d, 0x3da4 },
+               { 0x1c, 0xeffd },
+               { 0x14, 0x7f52 },
+               { 0x18, 0x7fc6 },
+               { 0x08, 0x0601 },
+               { 0x06, 0x4063 },
+               { 0x10, 0xf074 },
+               { 0x1f, 0x0003 },
+               { 0x13, 0x0789 },
+               { 0x12, 0xf4bd },
+               { 0x1a, 0x04fd },
+               { 0x14, 0x84b0 },
+               { 0x1f, 0x0000 },
+               { 0x00, 0x9200 },
+
+               { 0x1f, 0x0005 },
+               { 0x01, 0x0340 },
+               { 0x1f, 0x0001 },
+               { 0x04, 0x4000 },
+               { 0x03, 0x1d21 },
+               { 0x02, 0x0c32 },
+               { 0x01, 0x0200 },
+               { 0x00, 0x5554 },
+               { 0x04, 0x4800 },
+               { 0x04, 0x4000 },
+               { 0x04, 0xf000 },
+               { 0x03, 0xdf01 },
+               { 0x02, 0xdf20 },
+               { 0x01, 0x101a },
+               { 0x00, 0xa0ff },
+               { 0x04, 0xf800 },
+               { 0x04, 0xf000 },
+               { 0x1f, 0x0000 },
+
+               { 0x1f, 0x0007 },
+               { 0x1e, 0x0023 },
+               { 0x16, 0x0000 },
+               { 0x1f, 0x0000 }
+       };
+
+       rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init));
 }
 
 static void rtl8102e_hw_phy_config(void __iomem *ioaddr)
@@ -1792,7 +2664,13 @@ static void rtl_hw_phy_config(struct net_device *dev)
                rtl8168cp_2_hw_phy_config(ioaddr);
                break;
        case RTL_GIGA_MAC_VER_25:
-               rtl8168d_hw_phy_config(ioaddr);
+               rtl8168d_1_hw_phy_config(ioaddr);
+               break;
+       case RTL_GIGA_MAC_VER_26:
+               rtl8168d_2_hw_phy_config(ioaddr);
+               break;
+       case RTL_GIGA_MAC_VER_27:
+               rtl8168d_3_hw_phy_config(ioaddr);
                break;
 
        default:
@@ -2322,6 +3200,14 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
        }
 
        rtl8169_init_phy(dev, tp);
+
+       /*
+        * Pretend we are using VLANs; This bypasses a nasty bug where
+        * Interrupts stop flowing on high load on 8110SCd controllers.
+        */
+       if (tp->mac_version == RTL_GIGA_MAC_VER_05)
+               RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) | RxVlan);
+
        device_set_wakeup_enable(&pdev->dev, tp->features & RTL_FEATURE_WOL);
 
 out:
@@ -2493,7 +3379,7 @@ static u16 rtl_rw_cpluscmd(void __iomem *ioaddr)
 static void rtl_set_rx_max_size(void __iomem *ioaddr, unsigned int rx_buf_sz)
 {
        /* Low hurts. Let's disable the filtering. */
-       RTL_W16(RxMaxSize, rx_buf_sz);
+       RTL_W16(RxMaxSize, rx_buf_sz + 1);
 }
 
 static void rtl8169_set_magic_reg(void __iomem *ioaddr, unsigned mac_version)
@@ -2863,6 +3749,8 @@ static void rtl_hw_start_8168(struct net_device *dev)
        break;
 
        case RTL_GIGA_MAC_VER_25:
+       case RTL_GIGA_MAC_VER_26:
+       case RTL_GIGA_MAC_VER_27:
                rtl_hw_start_8168d(ioaddr, pdev);
        break;
 
index ee366c5..c9c70ab 100644 (file)
@@ -36,6 +36,7 @@ static char version[] = "sb1000.c:v1.1.2 6/01/98 (fventuri@mediaone.net)\n";
 
 #include <linux/module.h>
 #include <linux/kernel.h>
+#include <linux/sched.h>
 #include <linux/string.h>
 #include <linux/interrupt.h>
 #include <linux/errno.h>
index 01f9432..98bff5a 100644 (file)
@@ -444,7 +444,8 @@ static void efx_rx_packet__check_len(struct efx_rx_queue *rx_queue,
  * the appropriate LRO method
  */
 static void efx_rx_packet_lro(struct efx_channel *channel,
-                             struct efx_rx_buffer *rx_buf)
+                             struct efx_rx_buffer *rx_buf,
+                             bool checksummed)
 {
        struct napi_struct *napi = &channel->napi_str;
 
@@ -466,7 +467,8 @@ static void efx_rx_packet_lro(struct efx_channel *channel,
                skb->len = rx_buf->len;
                skb->data_len = rx_buf->len;
                skb->truesize += rx_buf->len;
-               skb->ip_summed = CHECKSUM_UNNECESSARY;
+               skb->ip_summed =
+                       checksummed ? CHECKSUM_UNNECESSARY : CHECKSUM_NONE;
 
                napi_gro_frags(napi);
 
@@ -475,6 +477,7 @@ out:
                rx_buf->page = NULL;
        } else {
                EFX_BUG_ON_PARANOID(!rx_buf->skb);
+               EFX_BUG_ON_PARANOID(!checksummed);
 
                napi_gro_receive(napi, rx_buf->skb);
                rx_buf->skb = NULL;
@@ -570,7 +573,7 @@ void __efx_rx_packet(struct efx_channel *channel,
        }
 
        if (likely(checksummed || rx_buf->page)) {
-               efx_rx_packet_lro(channel, rx_buf);
+               efx_rx_packet_lro(channel, rx_buf, checksummed);
                goto done;
        }
 
index f49d080..528b912 100644 (file)
@@ -30,6 +30,7 @@
 #include <linux/phy.h>
 #include <linux/cache.h>
 #include <linux/io.h>
+#include <asm/cacheflush.h>
 
 #include "sh_eth.h"
 
index 97949d0..c072f7f 100644 (file)
@@ -52,6 +52,7 @@
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/kernel.h>
+#include <linux/sched.h>
 #include <linux/string.h>
 #include <linux/timer.h>
 #include <linux/errno.h>
index 38a508b..b27156e 100644 (file)
@@ -73,6 +73,7 @@ static const char * const boot_msg =
 
 /* Include files */
 
+#include <linux/capability.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/errno.h>
index 01f6811..8f54143 100644 (file)
@@ -37,6 +37,7 @@
 #include <linux/crc32.h>
 #include <linux/dma-mapping.h>
 #include <linux/debugfs.h>
+#include <linux/sched.h>
 #include <linux/seq_file.h>
 #include <linux/mii.h>
 #include <asm/irq.h>
index 2ab5c39..6a10d7b 100644 (file)
@@ -4538,6 +4538,8 @@ static int __devinit sky2_probe(struct pci_dev *pdev,
                goto err_out_free_netdev;
        }
 
+       netif_carrier_off(dev);
+
        netif_napi_add(dev, &hw->napi, sky2_poll, NAPI_WEIGHT);
 
        err = request_irq(pdev->irq, sky2_intr,
index e17c535..fe3cebb 100644 (file)
@@ -67,6 +67,7 @@
 #include <asm/system.h>
 #include <asm/uaccess.h>
 #include <linux/bitops.h>
+#include <linux/sched.h>
 #include <linux/string.h>
 #include <linux/mm.h>
 #include <linux/interrupt.h>
diff --git a/drivers/net/stmmac/Kconfig b/drivers/net/stmmac/Kconfig
new file mode 100644 (file)
index 0000000..35eaa52
--- /dev/null
@@ -0,0 +1,53 @@
+config STMMAC_ETH
+       tristate "STMicroelectronics 10/100/1000 Ethernet driver"
+       select MII
+       select PHYLIB
+       depends on NETDEVICES && CPU_SUBTYPE_ST40
+       help
+         This is the driver for the ST MAC 10/100/1000 on-chip Ethernet
+         controllers. ST Ethernet IPs are built around a Synopsys IP Core.
+
+if STMMAC_ETH
+
+config STMMAC_DA
+       bool "STMMAC DMA arbitration scheme"
+       default n
+       help
+         Selecting this option, rx has priority over Tx (only for Giga
+         Ethernet device).
+         By default, the DMA arbitration scheme is based on Round-robin
+         (rx:tx priority is 1:1).
+
+config STMMAC_DUAL_MAC
+       bool "STMMAC: dual mac support (EXPERIMENTAL)"
+       default n
+        depends on EXPERIMENTAL && STMMAC_ETH && !STMMAC_TIMER
+       help
+         Some ST SoCs (for example the stx7141 and stx7200c2) have two
+         Ethernet Controllers. This option turns on the second Ethernet
+         device on this kind of platforms.
+
+config STMMAC_TIMER
+       bool "STMMAC Timer optimisation"
+       default n
+       help
+         Use an external timer for mitigating the number of network
+         interrupts.
+
+choice
+        prompt "Select Timer device"
+        depends on STMMAC_TIMER
+
+config STMMAC_TMU_TIMER
+        bool "TMU channel 2"
+        depends on CPU_SH4
+       help
+
+config STMMAC_RTC_TIMER
+        bool "Real time clock"
+        depends on RTC_CLASS
+       help
+
+endchoice
+
+endif
diff --git a/drivers/net/stmmac/Makefile b/drivers/net/stmmac/Makefile
new file mode 100644 (file)
index 0000000..b2d7a55
--- /dev/null
@@ -0,0 +1,4 @@
+obj-$(CONFIG_STMMAC_ETH) += stmmac.o
+stmmac-$(CONFIG_STMMAC_TIMER) += stmmac_timer.o
+stmmac-objs:= stmmac_main.o stmmac_ethtool.o stmmac_mdio.o \
+               mac100.o  gmac.o $(stmmac-y)
diff --git a/drivers/net/stmmac/common.h b/drivers/net/stmmac/common.h
new file mode 100644 (file)
index 0000000..e49e518
--- /dev/null
@@ -0,0 +1,330 @@
+/*******************************************************************************
+  STMMAC Common Header File
+
+  Copyright (C) 2007-2009  STMicroelectronics Ltd
+
+  This program is free software; you can redistribute it and/or modify it
+  under the terms and conditions of the GNU General Public License,
+  version 2, as published by the Free Software Foundation.
+
+  This program is distributed in the hope it will be useful, but WITHOUT
+  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+  more details.
+
+  You should have received a copy of the GNU General Public License along with
+  this program; if not, write to the Free Software Foundation, Inc.,
+  51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+
+  The full GNU General Public License is included in this distribution in
+  the file called "COPYING".
+
+  Author: Giuseppe Cavallaro <peppe.cavallaro@st.com>
+*******************************************************************************/
+
+#include "descs.h"
+#include <linux/io.h>
+
+/* *********************************************
+   DMA CRS Control and Status Register Mapping
+ * *********************************************/
+#define DMA_BUS_MODE           0x00001000      /* Bus Mode */
+#define DMA_XMT_POLL_DEMAND    0x00001004      /* Transmit Poll Demand */
+#define DMA_RCV_POLL_DEMAND    0x00001008      /* Received Poll Demand */
+#define DMA_RCV_BASE_ADDR      0x0000100c      /* Receive List Base */
+#define DMA_TX_BASE_ADDR       0x00001010      /* Transmit List Base */
+#define DMA_STATUS             0x00001014      /* Status Register */
+#define DMA_CONTROL            0x00001018      /* Ctrl (Operational Mode) */
+#define DMA_INTR_ENA           0x0000101c      /* Interrupt Enable */
+#define DMA_MISSED_FRAME_CTR   0x00001020      /* Missed Frame Counter */
+#define DMA_CUR_TX_BUF_ADDR    0x00001050      /* Current Host Tx Buffer */
+#define DMA_CUR_RX_BUF_ADDR    0x00001054      /* Current Host Rx Buffer */
+
+/* ********************************
+   DMA Control register defines
+ * ********************************/
+#define DMA_CONTROL_ST         0x00002000      /* Start/Stop Transmission */
+#define DMA_CONTROL_SR         0x00000002      /* Start/Stop Receive */
+
+/* **************************************
+   DMA Interrupt Enable register defines
+ * **************************************/
+/**** NORMAL INTERRUPT ****/
+#define DMA_INTR_ENA_NIE 0x00010000    /* Normal Summary */
+#define DMA_INTR_ENA_TIE 0x00000001    /* Transmit Interrupt */
+#define DMA_INTR_ENA_TUE 0x00000004    /* Transmit Buffer Unavailable */
+#define DMA_INTR_ENA_RIE 0x00000040    /* Receive Interrupt */
+#define DMA_INTR_ENA_ERE 0x00004000    /* Early Receive */
+
+#define DMA_INTR_NORMAL        (DMA_INTR_ENA_NIE | DMA_INTR_ENA_RIE | \
+                       DMA_INTR_ENA_TIE)
+
+/**** ABNORMAL INTERRUPT ****/
+#define DMA_INTR_ENA_AIE 0x00008000    /* Abnormal Summary */
+#define DMA_INTR_ENA_FBE 0x00002000    /* Fatal Bus Error */
+#define DMA_INTR_ENA_ETE 0x00000400    /* Early Transmit */
+#define DMA_INTR_ENA_RWE 0x00000200    /* Receive Watchdog */
+#define DMA_INTR_ENA_RSE 0x00000100    /* Receive Stopped */
+#define DMA_INTR_ENA_RUE 0x00000080    /* Receive Buffer Unavailable */
+#define DMA_INTR_ENA_UNE 0x00000020    /* Tx Underflow */
+#define DMA_INTR_ENA_OVE 0x00000010    /* Receive Overflow */
+#define DMA_INTR_ENA_TJE 0x00000008    /* Transmit Jabber */
+#define DMA_INTR_ENA_TSE 0x00000002    /* Transmit Stopped */
+
+#define DMA_INTR_ABNORMAL      (DMA_INTR_ENA_AIE | DMA_INTR_ENA_FBE | \
+                               DMA_INTR_ENA_UNE)
+
+/* DMA default interrupt mask */
+#define DMA_INTR_DEFAULT_MASK  (DMA_INTR_NORMAL | DMA_INTR_ABNORMAL)
+
+/* ****************************
+ *  DMA Status register defines
+ * ****************************/
+#define DMA_STATUS_GPI         0x10000000      /* PMT interrupt */
+#define DMA_STATUS_GMI         0x08000000      /* MMC interrupt */
+#define DMA_STATUS_GLI         0x04000000      /* GMAC Line interface int. */
+#define DMA_STATUS_GMI         0x08000000
+#define DMA_STATUS_GLI         0x04000000
+#define DMA_STATUS_EB_MASK     0x00380000      /* Error Bits Mask */
+#define DMA_STATUS_EB_TX_ABORT 0x00080000      /* Error Bits - TX Abort */
+#define DMA_STATUS_EB_RX_ABORT 0x00100000      /* Error Bits - RX Abort */
+#define DMA_STATUS_TS_MASK     0x00700000      /* Transmit Process State */
+#define DMA_STATUS_TS_SHIFT    20
+#define DMA_STATUS_RS_MASK     0x000e0000      /* Receive Process State */
+#define DMA_STATUS_RS_SHIFT    17
+#define DMA_STATUS_NIS 0x00010000      /* Normal Interrupt Summary */
+#define DMA_STATUS_AIS 0x00008000      /* Abnormal Interrupt Summary */
+#define DMA_STATUS_ERI 0x00004000      /* Early Receive Interrupt */
+#define DMA_STATUS_FBI 0x00002000      /* Fatal Bus Error Interrupt */
+#define DMA_STATUS_ETI 0x00000400      /* Early Transmit Interrupt */
+#define DMA_STATUS_RWT 0x00000200      /* Receive Watchdog Timeout */
+#define DMA_STATUS_RPS 0x00000100      /* Receive Process Stopped */
+#define DMA_STATUS_RU  0x00000080      /* Receive Buffer Unavailable */
+#define DMA_STATUS_RI  0x00000040      /* Receive Interrupt */
+#define DMA_STATUS_UNF 0x00000020      /* Transmit Underflow */
+#define DMA_STATUS_OVF 0x00000010      /* Receive Overflow */
+#define DMA_STATUS_TJT 0x00000008      /* Transmit Jabber Timeout */
+#define DMA_STATUS_TU  0x00000004      /* Transmit Buffer Unavailable */
+#define DMA_STATUS_TPS 0x00000002      /* Transmit Process Stopped */
+#define DMA_STATUS_TI  0x00000001      /* Transmit Interrupt */
+
+/* Other defines */
+#define HASH_TABLE_SIZE 64
+#define PAUSE_TIME 0x200
+
+/* Flow Control defines */
+#define FLOW_OFF       0
+#define FLOW_RX                1
+#define FLOW_TX                2
+#define FLOW_AUTO      (FLOW_TX | FLOW_RX)
+
+/* DMA STORE-AND-FORWARD Operation Mode */
+#define SF_DMA_MODE 1
+
+#define HW_CSUM 1
+#define NO_HW_CSUM 0
+
+/* GMAC TX FIFO is 8K, Rx FIFO is 16K */
+#define BUF_SIZE_16KiB 16384
+#define BUF_SIZE_8KiB 8192
+#define BUF_SIZE_4KiB 4096
+#define BUF_SIZE_2KiB 2048
+
+/* Power Down and WOL */
+#define PMT_NOT_SUPPORTED 0
+#define PMT_SUPPORTED 1
+
+/* Common MAC defines */
+#define MAC_CTRL_REG           0x00000000      /* MAC Control */
+#define MAC_ENABLE_TX          0x00000008      /* Transmitter Enable */
+#define MAC_RNABLE_RX          0x00000004      /* Receiver Enable */
+
+/* MAC Management Counters register */
+#define MMC_CONTROL            0x00000100      /* MMC Control */
+#define MMC_HIGH_INTR          0x00000104      /* MMC High Interrupt */
+#define MMC_LOW_INTR           0x00000108      /* MMC Low Interrupt */
+#define MMC_HIGH_INTR_MASK     0x0000010c      /* MMC High Interrupt Mask */
+#define MMC_LOW_INTR_MASK      0x00000110      /* MMC Low Interrupt Mask */
+
+#define MMC_CONTROL_MAX_FRM_MASK       0x0003ff8       /* Maximum Frame Size */
+#define MMC_CONTROL_MAX_FRM_SHIFT      3
+#define MMC_CONTROL_MAX_FRAME          0x7FF
+
+struct stmmac_extra_stats {
+       /* Transmit errors */
+       unsigned long tx_underflow ____cacheline_aligned;
+       unsigned long tx_carrier;
+       unsigned long tx_losscarrier;
+       unsigned long tx_heartbeat;
+       unsigned long tx_deferred;
+       unsigned long tx_vlan;
+       unsigned long tx_jabber;
+       unsigned long tx_frame_flushed;
+       unsigned long tx_payload_error;
+       unsigned long tx_ip_header_error;
+       /* Receive errors */
+       unsigned long rx_desc;
+       unsigned long rx_partial;
+       unsigned long rx_runt;
+       unsigned long rx_toolong;
+       unsigned long rx_collision;
+       unsigned long rx_crc;
+       unsigned long rx_lenght;
+       unsigned long rx_mii;
+       unsigned long rx_multicast;
+       unsigned long rx_gmac_overflow;
+       unsigned long rx_watchdog;
+       unsigned long da_rx_filter_fail;
+       unsigned long sa_rx_filter_fail;
+       unsigned long rx_missed_cntr;
+       unsigned long rx_overflow_cntr;
+       unsigned long rx_vlan;
+       /* Tx/Rx IRQ errors */
+       unsigned long tx_undeflow_irq;
+       unsigned long tx_process_stopped_irq;
+       unsigned long tx_jabber_irq;
+       unsigned long rx_overflow_irq;
+       unsigned long rx_buf_unav_irq;
+       unsigned long rx_process_stopped_irq;
+       unsigned long rx_watchdog_irq;
+       unsigned long tx_early_irq;
+       unsigned long fatal_bus_error_irq;
+       /* Extra info */
+       unsigned long threshold;
+       unsigned long tx_pkt_n;
+       unsigned long rx_pkt_n;
+       unsigned long poll_n;
+       unsigned long sched_timer_n;
+       unsigned long normal_irq_n;
+};
+
+/* GMAC core can compute the checksums in HW. */
+enum rx_frame_status {
+       good_frame = 0,
+       discard_frame = 1,
+       csum_none = 2,
+};
+
+static inline void stmmac_set_mac_addr(unsigned long ioaddr, u8 addr[6],
+                        unsigned int high, unsigned int low)
+{
+       unsigned long data;
+
+       data = (addr[5] << 8) | addr[4];
+       writel(data, ioaddr + high);
+       data = (addr[3] << 24) | (addr[2] << 16) | (addr[1] << 8) | addr[0];
+       writel(data, ioaddr + low);
+
+       return;
+}
+
+static inline void stmmac_get_mac_addr(unsigned long ioaddr,
+                               unsigned char *addr, unsigned int high,
+                               unsigned int low)
+{
+       unsigned int hi_addr, lo_addr;
+
+       /* Read the MAC address from the hardware */
+       hi_addr = readl(ioaddr + high);
+       lo_addr = readl(ioaddr + low);
+
+       /* Extract the MAC address from the high and low words */
+       addr[0] = lo_addr & 0xff;
+       addr[1] = (lo_addr >> 8) & 0xff;
+       addr[2] = (lo_addr >> 16) & 0xff;
+       addr[3] = (lo_addr >> 24) & 0xff;
+       addr[4] = hi_addr & 0xff;
+       addr[5] = (hi_addr >> 8) & 0xff;
+
+       return;
+}
+
+struct stmmac_ops {
+       /* MAC core initialization */
+       void (*core_init) (unsigned long ioaddr) ____cacheline_aligned;
+       /* DMA core initialization */
+       int (*dma_init) (unsigned long ioaddr, int pbl, u32 dma_tx, u32 dma_rx);
+       /* Dump MAC registers */
+       void (*dump_mac_regs) (unsigned long ioaddr);
+       /* Dump DMA registers */
+       void (*dump_dma_regs) (unsigned long ioaddr);
+       /* Set tx/rx threshold in the csr6 register
+        * An invalid value enables the store-and-forward mode */
+       void (*dma_mode) (unsigned long ioaddr, int txmode, int rxmode);
+       /* To track extra statistic (if supported) */
+       void (*dma_diagnostic_fr) (void *data, struct stmmac_extra_stats *x,
+                                  unsigned long ioaddr);
+       /* RX descriptor ring initialization */
+       void (*init_rx_desc) (struct dma_desc *p, unsigned int ring_size,
+                               int disable_rx_ic);
+       /* TX descriptor ring initialization */
+       void (*init_tx_desc) (struct dma_desc *p, unsigned int ring_size);
+
+       /* Invoked by the xmit function to prepare the tx descriptor */
+       void (*prepare_tx_desc) (struct dma_desc *p, int is_fs, int len,
+                                int csum_flag);
+       /* Set/get the owner of the descriptor */
+       void (*set_tx_owner) (struct dma_desc *p);
+       int (*get_tx_owner) (struct dma_desc *p);
+       /* Invoked by the xmit function to close the tx descriptor */
+       void (*close_tx_desc) (struct dma_desc *p);
+       /* Clean the tx descriptor as soon as the tx irq is received */
+       void (*release_tx_desc) (struct dma_desc *p);
+       /* Clear interrupt on tx frame completion. When this bit is
+        * set an interrupt happens as soon as the frame is transmitted */
+       void (*clear_tx_ic) (struct dma_desc *p);
+       /* Last tx segment reports the transmit status */
+       int (*get_tx_ls) (struct dma_desc *p);
+       /* Return the transmit status looking at the TDES1 */
+       int (*tx_status) (void *data, struct stmmac_extra_stats *x,
+                         struct dma_desc *p, unsigned long ioaddr);
+       /* Get the buffer size from the descriptor */
+       int (*get_tx_len) (struct dma_desc *p);
+       /* Handle extra events on specific interrupts hw dependent */
+       void (*host_irq_status) (unsigned long ioaddr);
+       int (*get_rx_owner) (struct dma_desc *p);
+       void (*set_rx_owner) (struct dma_desc *p);
+       /* Get the receive frame size */
+       int (*get_rx_frame_len) (struct dma_desc *p);
+       /* Return the reception status looking at the RDES1 */
+       int (*rx_status) (void *data, struct stmmac_extra_stats *x,
+                         struct dma_desc *p);
+       /* Multicast filter setting */
+       void (*set_filter) (struct net_device *dev);
+       /* Flow control setting */
+       void (*flow_ctrl) (unsigned long ioaddr, unsigned int duplex,
+                          unsigned int fc, unsigned int pause_time);
+       /* Set power management mode (e.g. magic frame) */
+       void (*pmt) (unsigned long ioaddr, unsigned long mode);
+       /* Set/Get Unicast MAC addresses */
+       void (*set_umac_addr) (unsigned long ioaddr, unsigned char *addr,
+                            unsigned int reg_n);
+       void (*get_umac_addr) (unsigned long ioaddr, unsigned char *addr,
+                            unsigned int reg_n);
+};
+
+struct mac_link {
+       int port;
+       int duplex;
+       int speed;
+};
+
+struct mii_regs {
+       unsigned int addr;      /* MII Address */
+       unsigned int data;      /* MII Data */
+};
+
+struct hw_cap {
+       unsigned int version;   /* Core Version register (GMAC) */
+       unsigned int pmt;       /* Power-Down mode (GMAC) */
+       struct mac_link link;
+       struct mii_regs mii;
+};
+
+struct mac_device_info {
+       struct hw_cap hw;
+       struct stmmac_ops *ops;
+};
+
+struct mac_device_info *gmac_setup(unsigned long addr);
+struct mac_device_info *mac100_setup(unsigned long addr);
diff --git a/drivers/net/stmmac/descs.h b/drivers/net/stmmac/descs.h
new file mode 100644 (file)
index 0000000..6d2a0b2
--- /dev/null
@@ -0,0 +1,163 @@
+/*******************************************************************************
+  Header File to describe the DMA descriptors
+  Use enhanced descriptors in case of GMAC Cores.
+
+  This program is free software; you can redistribute it and/or modify it
+  under the terms and conditions of the GNU General Public License,
+  version 2, as published by the Free Software Foundation.
+
+  This program is distributed in the hope it will be useful, but WITHOUT
+  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+  more details.
+
+  You should have received a copy of the GNU General Public License along with
+  this program; if not, write to the Free Software Foundation, Inc.,
+  51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+
+  The full GNU General Public License is included in this distribution in
+  the file called "COPYING".
+
+  Author: Giuseppe Cavallaro <peppe.cavallaro@st.com>
+*******************************************************************************/
+struct dma_desc {
+       /* Receive descriptor */
+       union {
+               struct {
+                       /* RDES0 */
+                       u32 reserved1:1;
+                       u32 crc_error:1;
+                       u32 dribbling:1;
+                       u32 mii_error:1;
+                       u32 receive_watchdog:1;
+                       u32 frame_type:1;
+                       u32 collision:1;
+                       u32 frame_too_long:1;
+                       u32 last_descriptor:1;
+                       u32 first_descriptor:1;
+                       u32 multicast_frame:1;
+                       u32 run_frame:1;
+                       u32 length_error:1;
+                       u32 partial_frame_error:1;
+                       u32 descriptor_error:1;
+                       u32 error_summary:1;
+                       u32 frame_length:14;
+                       u32 filtering_fail:1;
+                       u32 own:1;
+                       /* RDES1 */
+                       u32 buffer1_size:11;
+                       u32 buffer2_size:11;
+                       u32 reserved2:2;
+                       u32 second_address_chained:1;
+                       u32 end_ring:1;
+                       u32 reserved3:5;
+                       u32 disable_ic:1;
+               } rx;
+               struct {
+                       /* RDES0 */
+                       u32 payload_csum_error:1;
+                       u32 crc_error:1;
+                       u32 dribbling:1;
+                       u32 error_gmii:1;
+                       u32 receive_watchdog:1;
+                       u32 frame_type:1;
+                       u32 late_collision:1;
+                       u32 ipc_csum_error:1;
+                       u32 last_descriptor:1;
+                       u32 first_descriptor:1;
+                       u32 vlan_tag:1;
+                       u32 overflow_error:1;
+                       u32 length_error:1;
+                       u32 sa_filter_fail:1;
+                       u32 descriptor_error:1;
+                       u32 error_summary:1;
+                       u32 frame_length:14;
+                       u32 da_filter_fail:1;
+                       u32 own:1;
+                       /* RDES1 */
+                       u32 buffer1_size:13;
+                       u32 reserved1:1;
+                       u32 second_address_chained:1;
+                       u32 end_ring:1;
+                       u32 buffer2_size:13;
+                       u32 reserved2:2;
+                       u32 disable_ic:1;
+               } erx;          /* -- enhanced -- */
+
+               /* Transmit descriptor */
+               struct {
+                       /* TDES0 */
+                       u32 deferred:1;
+                       u32 underflow_error:1;
+                       u32 excessive_deferral:1;
+                       u32 collision_count:4;
+                       u32 heartbeat_fail:1;
+                       u32 excessive_collisions:1;
+                       u32 late_collision:1;
+                       u32 no_carrier:1;
+                       u32 loss_carrier:1;
+                       u32 reserved1:3;
+                       u32 error_summary:1;
+                       u32 reserved2:15;
+                       u32 own:1;
+                       /* TDES1 */
+                       u32 buffer1_size:11;
+                       u32 buffer2_size:11;
+                       u32 reserved3:1;
+                       u32 disable_padding:1;
+                       u32 second_address_chained:1;
+                       u32 end_ring:1;
+                       u32 crc_disable:1;
+                       u32 reserved4:2;
+                       u32 first_segment:1;
+                       u32 last_segment:1;
+                       u32 interrupt:1;
+               } tx;
+               struct {
+                       /* TDES0 */
+                       u32 deferred:1;
+                       u32 underflow_error:1;
+                       u32 excessive_deferral:1;
+                       u32 collision_count:4;
+                       u32 vlan_frame:1;
+                       u32 excessive_collisions:1;
+                       u32 late_collision:1;
+                       u32 no_carrier:1;
+                       u32 loss_carrier:1;
+                       u32 payload_error:1;
+                       u32 frame_flushed:1;
+                       u32 jabber_timeout:1;
+                       u32 error_summary:1;
+                       u32 ip_header_error:1;
+                       u32 time_stamp_status:1;
+                       u32 reserved1:2;
+                       u32 second_address_chained:1;
+                       u32 end_ring:1;
+                       u32 checksum_insertion:2;
+                       u32 reserved2:1;
+                       u32 time_stamp_enable:1;
+                       u32 disable_padding:1;
+                       u32 crc_disable:1;
+                       u32 first_segment:1;
+                       u32 last_segment:1;
+                       u32 interrupt:1;
+                       u32 own:1;
+                       /* TDES1 */
+                       u32 buffer1_size:13;
+                       u32 reserved3:3;
+                       u32 buffer2_size:13;
+                       u32 reserved4:3;
+               } etx;          /* -- enhanced -- */
+       } des01;
+       unsigned int des2;
+       unsigned int des3;
+};
+
+/* Transmit checksum insertion control */
+enum tdes_csum_insertion {
+       cic_disabled = 0,       /* Checksum Insertion Control */
+       cic_only_ip = 1,        /* Only IP header */
+       cic_no_pseudoheader = 2,        /* IP header but pseudoheader
+                                        * is not calculated */
+       cic_full = 3,           /* IP header and pseudoheader */
+};
diff --git a/drivers/net/stmmac/gmac.c b/drivers/net/stmmac/gmac.c
new file mode 100644 (file)
index 0000000..b624bb5
--- /dev/null
@@ -0,0 +1,693 @@
+/*******************************************************************************
+  This is the driver for the GMAC on-chip Ethernet controller for ST SoCs.
+  DWC Ether MAC 10/100/1000 Universal version 3.41a  has been used for
+  developing this code.
+
+  Copyright (C) 2007-2009  STMicroelectronics Ltd
+
+  This program is free software; you can redistribute it and/or modify it
+  under the terms and conditions of the GNU General Public License,
+  version 2, as published by the Free Software Foundation.
+
+  This program is distributed in the hope it will be useful, but WITHOUT
+  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+  more details.
+
+  You should have received a copy of the GNU General Public License along with
+  this program; if not, write to the Free Software Foundation, Inc.,
+  51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+
+  The full GNU General Public License is included in this distribution in
+  the file called "COPYING".
+
+  Author: Giuseppe Cavallaro <peppe.cavallaro@st.com>
+*******************************************************************************/
+
+#include <linux/netdevice.h>
+#include <linux/crc32.h>
+#include <linux/mii.h>
+#include <linux/phy.h>
+
+#include "stmmac.h"
+#include "gmac.h"
+
+#undef GMAC_DEBUG
+/*#define GMAC_DEBUG*/
+#undef FRAME_FILTER_DEBUG
+/*#define FRAME_FILTER_DEBUG*/
+#ifdef GMAC_DEBUG
+#define DBG(fmt, args...)  printk(fmt, ## args)
+#else
+#define DBG(fmt, args...)  do { } while (0)
+#endif
+
+static void gmac_dump_regs(unsigned long ioaddr)
+{
+       int i;
+       pr_info("\t----------------------------------------------\n"
+              "\t  GMAC registers (base addr = 0x%8x)\n"
+              "\t----------------------------------------------\n",
+              (unsigned int)ioaddr);
+
+       for (i = 0; i < 55; i++) {
+               int offset = i * 4;
+               pr_info("\tReg No. %d (offset 0x%x): 0x%08x\n", i,
+                      offset, readl(ioaddr + offset));
+       }
+       return;
+}
+
+static int gmac_dma_init(unsigned long ioaddr, int pbl, u32 dma_tx, u32 dma_rx)
+{
+       u32 value = readl(ioaddr + DMA_BUS_MODE);
+       /* DMA SW reset */
+       value |= DMA_BUS_MODE_SFT_RESET;
+       writel(value, ioaddr + DMA_BUS_MODE);
+       do {} while ((readl(ioaddr + DMA_BUS_MODE) & DMA_BUS_MODE_SFT_RESET));
+
+       value = /* DMA_BUS_MODE_FB | */ DMA_BUS_MODE_4PBL |
+           ((pbl << DMA_BUS_MODE_PBL_SHIFT) |
+            (pbl << DMA_BUS_MODE_RPBL_SHIFT));
+
+#ifdef CONFIG_STMMAC_DA
+       value |= DMA_BUS_MODE_DA;       /* Rx has priority over tx */
+#endif
+       writel(value, ioaddr + DMA_BUS_MODE);
+
+       /* Mask interrupts by writing to CSR7 */
+       writel(DMA_INTR_DEFAULT_MASK, ioaddr + DMA_INTR_ENA);
+
+       /* The base address of the RX/TX descriptor lists must be written into
+        * DMA CSR3 and CSR4, respectively. */
+       writel(dma_tx, ioaddr + DMA_TX_BASE_ADDR);
+       writel(dma_rx, ioaddr + DMA_RCV_BASE_ADDR);
+
+       return 0;
+}
+
+/* Transmit FIFO flush operation */
+static void gmac_flush_tx_fifo(unsigned long ioaddr)
+{
+       u32 csr6 = readl(ioaddr + DMA_CONTROL);
+       writel((csr6 | DMA_CONTROL_FTF), ioaddr + DMA_CONTROL);
+
+       do {} while ((readl(ioaddr + DMA_CONTROL) & DMA_CONTROL_FTF));
+}
+
+static void gmac_dma_operation_mode(unsigned long ioaddr, int txmode,
+                                   int rxmode)
+{
+       u32 csr6 = readl(ioaddr + DMA_CONTROL);
+
+       if (txmode == SF_DMA_MODE) {
+               DBG(KERN_DEBUG "GMAC: enabling TX store and forward mode\n");
+               /* Transmit COE type 2 cannot be done in cut-through mode. */
+               csr6 |= DMA_CONTROL_TSF;
+               /* Operating on second frame increase the performance
+                * especially when transmit store-and-forward is used.*/
+               csr6 |= DMA_CONTROL_OSF;
+       } else {
+               DBG(KERN_DEBUG "GMAC: disabling TX store and forward mode"
+                             " (threshold = %d)\n", txmode);
+               csr6 &= ~DMA_CONTROL_TSF;
+               csr6 &= DMA_CONTROL_TC_TX_MASK;
+               /* Set the transmit threashold */
+               if (txmode <= 32)
+                       csr6 |= DMA_CONTROL_TTC_32;
+               else if (txmode <= 64)
+                       csr6 |= DMA_CONTROL_TTC_64;
+               else if (txmode <= 128)
+                       csr6 |= DMA_CONTROL_TTC_128;
+               else if (txmode <= 192)
+                       csr6 |= DMA_CONTROL_TTC_192;
+               else
+                       csr6 |= DMA_CONTROL_TTC_256;
+       }
+
+       if (rxmode == SF_DMA_MODE) {
+               DBG(KERN_DEBUG "GMAC: enabling RX store and forward mode\n");
+               csr6 |= DMA_CONTROL_RSF;
+       } else {
+               DBG(KERN_DEBUG "GMAC: disabling RX store and forward mode"
+                             " (threshold = %d)\n", rxmode);
+               csr6 &= ~DMA_CONTROL_RSF;
+               csr6 &= DMA_CONTROL_TC_RX_MASK;
+               if (rxmode <= 32)
+                       csr6 |= DMA_CONTROL_RTC_32;
+               else if (rxmode <= 64)
+                       csr6 |= DMA_CONTROL_RTC_64;
+               else if (rxmode <= 96)
+                       csr6 |= DMA_CONTROL_RTC_96;
+               else
+                       csr6 |= DMA_CONTROL_RTC_128;
+       }
+
+       writel(csr6, ioaddr + DMA_CONTROL);
+       return;
+}
+
+/* Not yet implemented --- no RMON module */
+static void gmac_dma_diagnostic_fr(void *data, struct stmmac_extra_stats *x,
+                                  unsigned long ioaddr)
+{
+       return;
+}
+
+static void gmac_dump_dma_regs(unsigned long ioaddr)
+{
+       int i;
+       pr_info(" DMA registers\n");
+       for (i = 0; i < 22; i++) {
+               if ((i < 9) || (i > 17)) {
+                       int offset = i * 4;
+                       pr_err("\t Reg No. %d (offset 0x%x): 0x%08x\n", i,
+                              (DMA_BUS_MODE + offset),
+                              readl(ioaddr + DMA_BUS_MODE + offset));
+               }
+       }
+       return;
+}
+
+static int gmac_get_tx_frame_status(void *data, struct stmmac_extra_stats *x,
+                                   struct dma_desc *p, unsigned long ioaddr)
+{
+       int ret = 0;
+       struct net_device_stats *stats = (struct net_device_stats *)data;
+
+       if (unlikely(p->des01.etx.error_summary)) {
+               DBG(KERN_ERR "GMAC TX error... 0x%08x\n", p->des01.etx);
+               if (unlikely(p->des01.etx.jabber_timeout)) {
+                       DBG(KERN_ERR "\tjabber_timeout error\n");
+                       x->tx_jabber++;
+               }
+
+               if (unlikely(p->des01.etx.frame_flushed)) {
+                       DBG(KERN_ERR "\tframe_flushed error\n");
+                       x->tx_frame_flushed++;
+                       gmac_flush_tx_fifo(ioaddr);
+               }
+
+               if (unlikely(p->des01.etx.loss_carrier)) {
+                       DBG(KERN_ERR "\tloss_carrier error\n");
+                       x->tx_losscarrier++;
+                       stats->tx_carrier_errors++;
+               }
+               if (unlikely(p->des01.etx.no_carrier)) {
+                       DBG(KERN_ERR "\tno_carrier error\n");
+                       x->tx_carrier++;
+                       stats->tx_carrier_errors++;
+               }
+               if (unlikely(p->des01.etx.late_collision)) {
+                       DBG(KERN_ERR "\tlate_collision error\n");
+                       stats->collisions += p->des01.etx.collision_count;
+               }
+               if (unlikely(p->des01.etx.excessive_collisions)) {
+                       DBG(KERN_ERR "\texcessive_collisions\n");
+                       stats->collisions += p->des01.etx.collision_count;
+               }
+               if (unlikely(p->des01.etx.excessive_deferral)) {
+                       DBG(KERN_INFO "\texcessive tx_deferral\n");
+                       x->tx_deferred++;
+               }
+
+               if (unlikely(p->des01.etx.underflow_error)) {
+                       DBG(KERN_ERR "\tunderflow error\n");
+                       gmac_flush_tx_fifo(ioaddr);
+                       x->tx_underflow++;
+               }
+
+               if (unlikely(p->des01.etx.ip_header_error)) {
+                       DBG(KERN_ERR "\tTX IP header csum error\n");
+                       x->tx_ip_header_error++;
+               }
+
+               if (unlikely(p->des01.etx.payload_error)) {
+                       DBG(KERN_ERR "\tAddr/Payload csum error\n");
+                       x->tx_payload_error++;
+                       gmac_flush_tx_fifo(ioaddr);
+               }
+
+               ret = -1;
+       }
+
+       if (unlikely(p->des01.etx.deferred)) {
+               DBG(KERN_INFO "GMAC TX status: tx deferred\n");
+               x->tx_deferred++;
+       }
+#ifdef STMMAC_VLAN_TAG_USED
+       if (p->des01.etx.vlan_frame) {
+               DBG(KERN_INFO "GMAC TX status: VLAN frame\n");
+               x->tx_vlan++;
+       }
+#endif
+
+       return ret;
+}
+
+static int gmac_get_tx_len(struct dma_desc *p)
+{
+       return p->des01.etx.buffer1_size;
+}
+
+static int gmac_coe_rdes0(int ipc_err, int type, int payload_err)
+{
+       int ret = good_frame;
+       u32 status = (type << 2 | ipc_err << 1 | payload_err) & 0x7;
+
+       /* bits 5 7 0 | Frame status
+        * ----------------------------------------------------------
+        *      0 0 0 | IEEE 802.3 Type frame (lenght < 1536 octects)
+        *      1 0 0 | IPv4/6 No CSUM errorS.
+        *      1 0 1 | IPv4/6 CSUM PAYLOAD error
+        *      1 1 0 | IPv4/6 CSUM IP HR error
+        *      1 1 1 | IPv4/6 IP PAYLOAD AND HEADER errorS
+        *      0 0 1 | IPv4/6 unsupported IP PAYLOAD
+        *      0 1 1 | COE bypassed.. no IPv4/6 frame
+        *      0 1 0 | Reserved.
+        */
+       if (status == 0x0) {
+               DBG(KERN_INFO "RX Des0 status: IEEE 802.3 Type frame.\n");
+               ret = good_frame;
+       } else if (status == 0x4) {
+               DBG(KERN_INFO "RX Des0 status: IPv4/6 No CSUM errorS.\n");
+               ret = good_frame;
+       } else if (status == 0x5) {
+               DBG(KERN_ERR "RX Des0 status: IPv4/6 Payload Error.\n");
+               ret = csum_none;
+       } else if (status == 0x6) {
+               DBG(KERN_ERR "RX Des0 status: IPv4/6 Header Error.\n");
+               ret = csum_none;
+       } else if (status == 0x7) {
+               DBG(KERN_ERR
+                   "RX Des0 status: IPv4/6 Header and Payload Error.\n");
+               ret = csum_none;
+       } else if (status == 0x1) {
+               DBG(KERN_ERR
+                   "RX Des0 status: IPv4/6 unsupported IP PAYLOAD.\n");
+               ret = discard_frame;
+       } else if (status == 0x3) {
+               DBG(KERN_ERR "RX Des0 status: No IPv4, IPv6 frame.\n");
+               ret = discard_frame;
+       }
+       return ret;
+}
+
+static int gmac_get_rx_frame_status(void *data, struct stmmac_extra_stats *x,
+                                   struct dma_desc *p)
+{
+       int ret = good_frame;
+       struct net_device_stats *stats = (struct net_device_stats *)data;
+
+       if (unlikely(p->des01.erx.error_summary)) {
+               DBG(KERN_ERR "GMAC RX Error Summary... 0x%08x\n", p->des01.erx);
+               if (unlikely(p->des01.erx.descriptor_error)) {
+                       DBG(KERN_ERR "\tdescriptor error\n");
+                       x->rx_desc++;
+                       stats->rx_length_errors++;
+               }
+               if (unlikely(p->des01.erx.overflow_error)) {
+                       DBG(KERN_ERR "\toverflow error\n");
+                       x->rx_gmac_overflow++;
+               }
+
+               if (unlikely(p->des01.erx.ipc_csum_error))
+                       DBG(KERN_ERR "\tIPC Csum Error/Giant frame\n");
+
+               if (unlikely(p->des01.erx.late_collision)) {
+                       DBG(KERN_ERR "\tlate_collision error\n");
+                       stats->collisions++;
+                       stats->collisions++;
+               }
+               if (unlikely(p->des01.erx.receive_watchdog)) {
+                       DBG(KERN_ERR "\treceive_watchdog error\n");
+                       x->rx_watchdog++;
+               }
+               if (unlikely(p->des01.erx.error_gmii)) {
+                       DBG(KERN_ERR "\tReceive Error\n");
+                       x->rx_mii++;
+               }
+               if (unlikely(p->des01.erx.crc_error)) {
+                       DBG(KERN_ERR "\tCRC error\n");
+                       x->rx_crc++;
+                       stats->rx_crc_errors++;
+               }
+               ret = discard_frame;
+       }
+
+       /* After a payload csum error, the ES bit is set.
+        * It doesn't match with the information reported into the databook.
+        * At any rate, we need to understand if the CSUM hw computation is ok
+        * and report this info to the upper layers. */
+       ret = gmac_coe_rdes0(p->des01.erx.ipc_csum_error,
+               p->des01.erx.frame_type, p->des01.erx.payload_csum_error);
+
+       if (unlikely(p->des01.erx.dribbling)) {
+               DBG(KERN_ERR "GMAC RX: dribbling error\n");
+               ret = discard_frame;
+       }
+       if (unlikely(p->des01.erx.sa_filter_fail)) {
+               DBG(KERN_ERR "GMAC RX : Source Address filter fail\n");
+               x->sa_rx_filter_fail++;
+               ret = discard_frame;
+       }
+       if (unlikely(p->des01.erx.da_filter_fail)) {
+               DBG(KERN_ERR "GMAC RX : Destination Address filter fail\n");
+               x->da_rx_filter_fail++;
+               ret = discard_frame;
+       }
+       if (unlikely(p->des01.erx.length_error)) {
+               DBG(KERN_ERR "GMAC RX: length_error error\n");
+               x->rx_lenght++;
+               ret = discard_frame;
+       }
+#ifdef STMMAC_VLAN_TAG_USED
+       if (p->des01.erx.vlan_tag) {
+               DBG(KERN_INFO "GMAC RX: VLAN frame tagged\n");
+               x->rx_vlan++;
+       }
+#endif
+       return ret;
+}
+
+static void gmac_irq_status(unsigned long ioaddr)
+{
+       u32 intr_status = readl(ioaddr + GMAC_INT_STATUS);
+
+       /* Not used events (e.g. MMC interrupts) are not handled. */
+       if ((intr_status & mmc_tx_irq))
+               DBG(KERN_DEBUG "GMAC: MMC tx interrupt: 0x%08x\n",
+                   readl(ioaddr + GMAC_MMC_TX_INTR));
+       if (unlikely(intr_status & mmc_rx_irq))
+               DBG(KERN_DEBUG "GMAC: MMC rx interrupt: 0x%08x\n",
+                   readl(ioaddr + GMAC_MMC_RX_INTR));
+       if (unlikely(intr_status & mmc_rx_csum_offload_irq))
+               DBG(KERN_DEBUG "GMAC: MMC rx csum offload: 0x%08x\n",
+                   readl(ioaddr + GMAC_MMC_RX_CSUM_OFFLOAD));
+       if (unlikely(intr_status & pmt_irq)) {
+               DBG(KERN_DEBUG "GMAC: received Magic frame\n");
+               /* clear the PMT bits 5 and 6 by reading the PMT
+                * status register. */
+               readl(ioaddr + GMAC_PMT);
+       }
+
+       return;
+}
+
+static void gmac_core_init(unsigned long ioaddr)
+{
+       u32 value = readl(ioaddr + GMAC_CONTROL);
+       value |= GMAC_CORE_INIT;
+       writel(value, ioaddr + GMAC_CONTROL);
+
+       /* STBus Bridge Configuration */
+       /*writel(0xc5608, ioaddr + 0x00007000);*/
+
+       /* Freeze MMC counters */
+       writel(0x8, ioaddr + GMAC_MMC_CTRL);
+       /* Mask GMAC interrupts */
+       writel(0x207, ioaddr + GMAC_INT_MASK);
+
+#ifdef STMMAC_VLAN_TAG_USED
+       /* Tag detection without filtering */
+       writel(0x0, ioaddr + GMAC_VLAN_TAG);
+#endif
+       return;
+}
+
+static void gmac_set_umac_addr(unsigned long ioaddr, unsigned char *addr,
+                               unsigned int reg_n)
+{
+       stmmac_set_mac_addr(ioaddr, addr, GMAC_ADDR_HIGH(reg_n),
+                               GMAC_ADDR_LOW(reg_n));
+}
+
+static void gmac_get_umac_addr(unsigned long ioaddr, unsigned char *addr,
+                               unsigned int reg_n)
+{
+       stmmac_get_mac_addr(ioaddr, addr, GMAC_ADDR_HIGH(reg_n),
+                               GMAC_ADDR_LOW(reg_n));
+}
+
+static void gmac_set_filter(struct net_device *dev)
+{
+       unsigned long ioaddr = dev->base_addr;
+       unsigned int value = 0;
+
+       DBG(KERN_INFO "%s: # mcasts %d, # unicast %d\n",
+           __func__, dev->mc_count, dev->uc_count);
+
+       if (dev->flags & IFF_PROMISC)
+               value = GMAC_FRAME_FILTER_PR;
+       else if ((dev->mc_count > HASH_TABLE_SIZE)
+                  || (dev->flags & IFF_ALLMULTI)) {
+               value = GMAC_FRAME_FILTER_PM;   /* pass all multi */
+               writel(0xffffffff, ioaddr + GMAC_HASH_HIGH);
+               writel(0xffffffff, ioaddr + GMAC_HASH_LOW);
+       } else if (dev->mc_count > 0) {
+               int i;
+               u32 mc_filter[2];
+               struct dev_mc_list *mclist;
+
+               /* Hash filter for multicast */
+               value = GMAC_FRAME_FILTER_HMC;
+
+               memset(mc_filter, 0, sizeof(mc_filter));
+               for (i = 0, mclist = dev->mc_list;
+                    mclist && i < dev->mc_count; i++, mclist = mclist->next) {
+                       /* The upper 6 bits of the calculated CRC are used to
+                          index the contens of the hash table */
+                       int bit_nr =
+                           bitrev32(~crc32_le(~0, mclist->dmi_addr, 6)) >> 26;
+                       /* The most significant bit determines the register to
+                        * use (H/L) while the other 5 bits determine the bit
+                        * within the register. */
+                       mc_filter[bit_nr >> 5] |= 1 << (bit_nr & 31);
+               }
+               writel(mc_filter[0], ioaddr + GMAC_HASH_LOW);
+               writel(mc_filter[1], ioaddr + GMAC_HASH_HIGH);
+       }
+
+       /* Handle multiple unicast addresses (perfect filtering)*/
+       if (dev->uc_count > GMAC_MAX_UNICAST_ADDRESSES)
+               /* Switch to promiscuous mode is more than 16 addrs
+                  are required */
+               value |= GMAC_FRAME_FILTER_PR;
+       else {
+               int i;
+               struct dev_addr_list *uc_ptr = dev->uc_list;
+
+                       for (i = 0; i < dev->uc_count; i++) {
+                               gmac_set_umac_addr(ioaddr, uc_ptr->da_addr,
+                                               i + 1);
+
+                               DBG(KERN_INFO "\t%d "
+                               "- Unicast addr %02x:%02x:%02x:%02x:%02x:"
+                               "%02x\n", i + 1,
+                               uc_ptr->da_addr[0], uc_ptr->da_addr[1],
+                               uc_ptr->da_addr[2], uc_ptr->da_addr[3],
+                               uc_ptr->da_addr[4], uc_ptr->da_addr[5]);
+                               uc_ptr = uc_ptr->next;
+               }
+       }
+
+#ifdef FRAME_FILTER_DEBUG
+       /* Enable Receive all mode (to debug filtering_fail errors) */
+       value |= GMAC_FRAME_FILTER_RA;
+#endif
+       writel(value, ioaddr + GMAC_FRAME_FILTER);
+
+       DBG(KERN_INFO "\tFrame Filter reg: 0x%08x\n\tHash regs: "
+           "HI 0x%08x, LO 0x%08x\n", readl(ioaddr + GMAC_FRAME_FILTER),
+           readl(ioaddr + GMAC_HASH_HIGH), readl(ioaddr + GMAC_HASH_LOW));
+
+       return;
+}
+
+static void gmac_flow_ctrl(unsigned long ioaddr, unsigned int duplex,
+                          unsigned int fc, unsigned int pause_time)
+{
+       unsigned int flow = 0;
+
+       DBG(KERN_DEBUG "GMAC Flow-Control:\n");
+       if (fc & FLOW_RX) {
+               DBG(KERN_DEBUG "\tReceive Flow-Control ON\n");
+               flow |= GMAC_FLOW_CTRL_RFE;
+       }
+       if (fc & FLOW_TX) {
+               DBG(KERN_DEBUG "\tTransmit Flow-Control ON\n");
+               flow |= GMAC_FLOW_CTRL_TFE;
+       }
+
+       if (duplex) {
+               DBG(KERN_DEBUG "\tduplex mode: pause time: %d\n", pause_time);
+               flow |= (pause_time << GMAC_FLOW_CTRL_PT_SHIFT);
+       }
+
+       writel(flow, ioaddr + GMAC_FLOW_CTRL);
+       return;
+}
+
+static void gmac_pmt(unsigned long ioaddr, unsigned long mode)
+{
+       unsigned int pmt = 0;
+
+       if (mode == WAKE_MAGIC) {
+               DBG(KERN_DEBUG "GMAC: WOL Magic frame\n");
+               pmt |= power_down | magic_pkt_en;
+       } else if (mode == WAKE_UCAST) {
+               DBG(KERN_DEBUG "GMAC: WOL on global unicast\n");
+               pmt |= global_unicast;
+       }
+
+       writel(pmt, ioaddr + GMAC_PMT);
+       return;
+}
+
+static void gmac_init_rx_desc(struct dma_desc *p, unsigned int ring_size,
+                               int disable_rx_ic)
+{
+       int i;
+       for (i = 0; i < ring_size; i++) {
+               p->des01.erx.own = 1;
+               p->des01.erx.buffer1_size = BUF_SIZE_8KiB - 1;
+               /* To support jumbo frames */
+               p->des01.erx.buffer2_size = BUF_SIZE_8KiB - 1;
+               if (i == ring_size - 1)
+                       p->des01.erx.end_ring = 1;
+               if (disable_rx_ic)
+                       p->des01.erx.disable_ic = 1;
+               p++;
+       }
+       return;
+}
+
+static void gmac_init_tx_desc(struct dma_desc *p, unsigned int ring_size)
+{
+       int i;
+
+       for (i = 0; i < ring_size; i++) {
+               p->des01.etx.own = 0;
+               if (i == ring_size - 1)
+                       p->des01.etx.end_ring = 1;
+               p++;
+       }
+
+       return;
+}
+
+static int gmac_get_tx_owner(struct dma_desc *p)
+{
+       return p->des01.etx.own;
+}
+
+static int gmac_get_rx_owner(struct dma_desc *p)
+{
+       return p->des01.erx.own;
+}
+
+static void gmac_set_tx_owner(struct dma_desc *p)
+{
+       p->des01.etx.own = 1;
+}
+
+static void gmac_set_rx_owner(struct dma_desc *p)
+{
+       p->des01.erx.own = 1;
+}
+
+static int gmac_get_tx_ls(struct dma_desc *p)
+{
+       return p->des01.etx.last_segment;
+}
+
+static void gmac_release_tx_desc(struct dma_desc *p)
+{
+       int ter = p->des01.etx.end_ring;
+
+       memset(p, 0, sizeof(struct dma_desc));
+       p->des01.etx.end_ring = ter;
+
+       return;
+}
+
+static void gmac_prepare_tx_desc(struct dma_desc *p, int is_fs, int len,
+                                int csum_flag)
+{
+       p->des01.etx.first_segment = is_fs;
+       if (unlikely(len > BUF_SIZE_4KiB)) {
+               p->des01.etx.buffer1_size = BUF_SIZE_4KiB;
+               p->des01.etx.buffer2_size = len - BUF_SIZE_4KiB;
+       } else {
+               p->des01.etx.buffer1_size = len;
+       }
+       if (likely(csum_flag))
+               p->des01.etx.checksum_insertion = cic_full;
+}
+
+static void gmac_clear_tx_ic(struct dma_desc *p)
+{
+       p->des01.etx.interrupt = 0;
+}
+
+static void gmac_close_tx_desc(struct dma_desc *p)
+{
+       p->des01.etx.last_segment = 1;
+       p->des01.etx.interrupt = 1;
+}
+
+static int gmac_get_rx_frame_len(struct dma_desc *p)
+{
+       return p->des01.erx.frame_length;
+}
+
+struct stmmac_ops gmac_driver = {
+       .core_init = gmac_core_init,
+       .dump_mac_regs = gmac_dump_regs,
+       .dma_init = gmac_dma_init,
+       .dump_dma_regs = gmac_dump_dma_regs,
+       .dma_mode = gmac_dma_operation_mode,
+       .dma_diagnostic_fr = gmac_dma_diagnostic_fr,
+       .tx_status = gmac_get_tx_frame_status,
+       .rx_status = gmac_get_rx_frame_status,
+       .get_tx_len = gmac_get_tx_len,
+       .set_filter = gmac_set_filter,
+       .flow_ctrl = gmac_flow_ctrl,
+       .pmt = gmac_pmt,
+       .init_rx_desc = gmac_init_rx_desc,
+       .init_tx_desc = gmac_init_tx_desc,
+       .get_tx_owner = gmac_get_tx_owner,
+       .get_rx_owner = gmac_get_rx_owner,
+       .release_tx_desc = gmac_release_tx_desc,
+       .prepare_tx_desc = gmac_prepare_tx_desc,
+       .clear_tx_ic = gmac_clear_tx_ic,
+       .close_tx_desc = gmac_close_tx_desc,
+       .get_tx_ls = gmac_get_tx_ls,
+       .set_tx_owner = gmac_set_tx_owner,
+       .set_rx_owner = gmac_set_rx_owner,
+       .get_rx_frame_len = gmac_get_rx_frame_len,
+       .host_irq_status = gmac_irq_status,
+       .set_umac_addr = gmac_set_umac_addr,
+       .get_umac_addr = gmac_get_umac_addr,
+};
+
+struct mac_device_info *gmac_setup(unsigned long ioaddr)
+{
+       struct mac_device_info *mac;
+       u32 uid = readl(ioaddr + GMAC_VERSION);
+
+       pr_info("\tGMAC - user ID: 0x%x, Synopsys ID: 0x%x\n",
+              ((uid & 0x0000ff00) >> 8), (uid & 0x000000ff));
+
+       mac = kzalloc(sizeof(const struct mac_device_info), GFP_KERNEL);
+
+       mac->ops = &gmac_driver;
+       mac->hw.pmt = PMT_SUPPORTED;
+       mac->hw.link.port = GMAC_CONTROL_PS;
+       mac->hw.link.duplex = GMAC_CONTROL_DM;
+       mac->hw.link.speed = GMAC_CONTROL_FES;
+       mac->hw.mii.addr = GMAC_MII_ADDR;
+       mac->hw.mii.data = GMAC_MII_DATA;
+
+       return mac;
+}
diff --git a/drivers/net/stmmac/gmac.h b/drivers/net/stmmac/gmac.h
new file mode 100644 (file)
index 0000000..684a363
--- /dev/null
@@ -0,0 +1,204 @@
+/*******************************************************************************
+  Copyright (C) 2007-2009  STMicroelectronics Ltd
+
+  This program is free software; you can redistribute it and/or modify it
+  under the terms and conditions of the GNU General Public License,
+  version 2, as published by the Free Software Foundation.
+
+  This program is distributed in the hope it will be useful, but WITHOUT
+  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+  more details.
+
+  You should have received a copy of the GNU General Public License along with
+  this program; if not, write to the Free Software Foundation, Inc.,
+  51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+
+  The full GNU General Public License is included in this distribution in
+  the file called "COPYING".
+
+  Author: Giuseppe Cavallaro <peppe.cavallaro@st.com>
+*******************************************************************************/
+
+#define GMAC_CONTROL           0x00000000      /* Configuration */
+#define GMAC_FRAME_FILTER      0x00000004      /* Frame Filter */
+#define GMAC_HASH_HIGH         0x00000008      /* Multicast Hash Table High */
+#define GMAC_HASH_LOW          0x0000000c      /* Multicast Hash Table Low */
+#define GMAC_MII_ADDR          0x00000010      /* MII Address */
+#define GMAC_MII_DATA          0x00000014      /* MII Data */
+#define GMAC_FLOW_CTRL         0x00000018      /* Flow Control */
+#define GMAC_VLAN_TAG          0x0000001c      /* VLAN Tag */
+#define GMAC_VERSION           0x00000020      /* GMAC CORE Version */
+#define GMAC_WAKEUP_FILTER     0x00000028      /* Wake-up Frame Filter */
+
+#define GMAC_INT_STATUS                0x00000038      /* interrupt status register */
+enum gmac_irq_status {
+       time_stamp_irq = 0x0200,
+       mmc_rx_csum_offload_irq = 0x0080,
+       mmc_tx_irq = 0x0040,
+       mmc_rx_irq = 0x0020,
+       mmc_irq = 0x0010,
+       pmt_irq = 0x0008,
+       pcs_ane_irq = 0x0004,
+       pcs_link_irq = 0x0002,
+       rgmii_irq = 0x0001,
+};
+#define GMAC_INT_MASK          0x0000003c      /* interrupt mask register */
+
+/* PMT Control and Status */
+#define GMAC_PMT               0x0000002c
+enum power_event {
+       pointer_reset = 0x80000000,
+       global_unicast = 0x00000200,
+       wake_up_rx_frame = 0x00000040,
+       magic_frame = 0x00000020,
+       wake_up_frame_en = 0x00000004,
+       magic_pkt_en = 0x00000002,
+       power_down = 0x00000001,
+};
+
+/* GMAC HW ADDR regs */
+#define GMAC_ADDR_HIGH(reg)            (0x00000040+(reg * 8))
+#define GMAC_ADDR_LOW(reg)             (0x00000044+(reg * 8))
+#define GMAC_MAX_UNICAST_ADDRESSES     16
+
+#define GMAC_AN_CTRL   0x000000c0      /* AN control */
+#define GMAC_AN_STATUS 0x000000c4      /* AN status */
+#define GMAC_ANE_ADV   0x000000c8      /* Auto-Neg. Advertisement */
+#define GMAC_ANE_LINK  0x000000cc      /* Auto-Neg. link partener ability */
+#define GMAC_ANE_EXP   0x000000d0      /* ANE expansion */
+#define GMAC_TBI       0x000000d4      /* TBI extend status */
+#define GMAC_GMII_STATUS 0x000000d8    /* S/R-GMII status */
+
+/* GMAC Configuration defines */
+#define GMAC_CONTROL_TC        0x01000000      /* Transmit Conf. in RGMII/SGMII */
+#define GMAC_CONTROL_WD        0x00800000      /* Disable Watchdog on receive */
+#define GMAC_CONTROL_JD        0x00400000      /* Jabber disable */
+#define GMAC_CONTROL_BE        0x00200000      /* Frame Burst Enable */
+#define GMAC_CONTROL_JE        0x00100000      /* Jumbo frame */
+enum inter_frame_gap {
+       GMAC_CONTROL_IFG_88 = 0x00040000,
+       GMAC_CONTROL_IFG_80 = 0x00020000,
+       GMAC_CONTROL_IFG_40 = 0x000e0000,
+};
+#define GMAC_CONTROL_DCRS      0x00010000 /* Disable carrier sense during tx */
+#define GMAC_CONTROL_PS                0x00008000 /* Port Select 0:GMI 1:MII */
+#define GMAC_CONTROL_FES       0x00004000 /* Speed 0:10 1:100 */
+#define GMAC_CONTROL_DO                0x00002000 /* Disable Rx Own */
+#define GMAC_CONTROL_LM                0x00001000 /* Loop-back mode */
+#define GMAC_CONTROL_DM                0x00000800 /* Duplex Mode */
+#define GMAC_CONTROL_IPC       0x00000400 /* Checksum Offload */
+#define GMAC_CONTROL_DR                0x00000200 /* Disable Retry */
+#define GMAC_CONTROL_LUD       0x00000100 /* Link up/down */
+#define GMAC_CONTROL_ACS       0x00000080 /* Automatic Pad Stripping */
+#define GMAC_CONTROL_DC                0x00000010 /* Deferral Check */
+#define GMAC_CONTROL_TE                0x00000008 /* Transmitter Enable */
+#define GMAC_CONTROL_RE                0x00000004 /* Receiver Enable */
+
+#define GMAC_CORE_INIT (GMAC_CONTROL_JD | GMAC_CONTROL_PS | GMAC_CONTROL_ACS | \
+                       GMAC_CONTROL_IPC | GMAC_CONTROL_JE | GMAC_CONTROL_BE)
+
+/* GMAC Frame Filter defines */
+#define GMAC_FRAME_FILTER_PR   0x00000001      /* Promiscuous Mode */
+#define GMAC_FRAME_FILTER_HUC  0x00000002      /* Hash Unicast */
+#define GMAC_FRAME_FILTER_HMC  0x00000004      /* Hash Multicast */
+#define GMAC_FRAME_FILTER_DAIF 0x00000008      /* DA Inverse Filtering */
+#define GMAC_FRAME_FILTER_PM   0x00000010      /* Pass all multicast */
+#define GMAC_FRAME_FILTER_DBF  0x00000020      /* Disable Broadcast frames */
+#define GMAC_FRAME_FILTER_SAIF 0x00000100      /* Inverse Filtering */
+#define GMAC_FRAME_FILTER_SAF  0x00000200      /* Source Address Filter */
+#define GMAC_FRAME_FILTER_HPF  0x00000400      /* Hash or perfect Filter */
+#define GMAC_FRAME_FILTER_RA   0x80000000      /* Receive all mode */
+/* GMII ADDR  defines */
+#define GMAC_MII_ADDR_WRITE    0x00000002      /* MII Write */
+#define GMAC_MII_ADDR_BUSY     0x00000001      /* MII Busy */
+/* GMAC FLOW CTRL defines */
+#define GMAC_FLOW_CTRL_PT_MASK 0xffff0000      /* Pause Time Mask */
+#define GMAC_FLOW_CTRL_PT_SHIFT        16
+#define GMAC_FLOW_CTRL_RFE     0x00000004      /* Rx Flow Control Enable */
+#define GMAC_FLOW_CTRL_TFE     0x00000002      /* Tx Flow Control Enable */
+#define GMAC_FLOW_CTRL_FCB_BPA 0x00000001      /* Flow Control Busy ... */
+
+/*--- DMA BLOCK defines ---*/
+/* DMA Bus Mode register defines */
+#define DMA_BUS_MODE_SFT_RESET 0x00000001      /* Software Reset */
+#define DMA_BUS_MODE_DA                0x00000002      /* Arbitration scheme */
+#define DMA_BUS_MODE_DSL_MASK  0x0000007c      /* Descriptor Skip Length */
+#define DMA_BUS_MODE_DSL_SHIFT 2       /*   (in DWORDS)      */
+/* Programmable burst length (passed thorugh platform)*/
+#define DMA_BUS_MODE_PBL_MASK  0x00003f00      /* Programmable Burst Len */
+#define DMA_BUS_MODE_PBL_SHIFT 8
+
+enum rx_tx_priority_ratio {
+       double_ratio = 0x00004000,      /*2:1 */
+       triple_ratio = 0x00008000,      /*3:1 */
+       quadruple_ratio = 0x0000c000,   /*4:1 */
+};
+
+#define DMA_BUS_MODE_FB                0x00010000      /* Fixed burst */
+#define DMA_BUS_MODE_RPBL_MASK 0x003e0000      /* Rx-Programmable Burst Len */
+#define DMA_BUS_MODE_RPBL_SHIFT        17
+#define DMA_BUS_MODE_USP       0x00800000
+#define DMA_BUS_MODE_4PBL      0x01000000
+#define DMA_BUS_MODE_AAL       0x02000000
+
+/* DMA CRS Control and Status Register Mapping */
+#define DMA_HOST_TX_DESC         0x00001048    /* Current Host Tx descriptor */
+#define DMA_HOST_RX_DESC         0x0000104c    /* Current Host Rx descriptor */
+/*  DMA Bus Mode register defines */
+#define DMA_BUS_PR_RATIO_MASK    0x0000c000    /* Rx/Tx priority ratio */
+#define DMA_BUS_PR_RATIO_SHIFT   14
+#define DMA_BUS_FB               0x00010000    /* Fixed Burst */
+
+/* DMA operation mode defines (start/stop tx/rx are placed in common header)*/
+#define DMA_CONTROL_DT         0x04000000 /* Disable Drop TCP/IP csum error */
+#define DMA_CONTROL_RSF                0x02000000 /* Receive Store and Forward */
+#define DMA_CONTROL_DFF                0x01000000 /* Disaable flushing */
+/* Theshold for Activating the FC */
+enum rfa {
+       act_full_minus_1 = 0x00800000,
+       act_full_minus_2 = 0x00800200,
+       act_full_minus_3 = 0x00800400,
+       act_full_minus_4 = 0x00800600,
+};
+/* Theshold for Deactivating the FC */
+enum rfd {
+       deac_full_minus_1 = 0x00400000,
+       deac_full_minus_2 = 0x00400800,
+       deac_full_minus_3 = 0x00401000,
+       deac_full_minus_4 = 0x00401800,
+};
+#define DMA_CONTROL_TSF                0x00200000 /* Transmit  Store and Forward */
+#define DMA_CONTROL_FTF                0x00100000 /* Flush transmit FIFO */
+
+enum ttc_control {
+       DMA_CONTROL_TTC_64 = 0x00000000,
+       DMA_CONTROL_TTC_128 = 0x00004000,
+       DMA_CONTROL_TTC_192 = 0x00008000,
+       DMA_CONTROL_TTC_256 = 0x0000c000,
+       DMA_CONTROL_TTC_40 = 0x00010000,
+       DMA_CONTROL_TTC_32 = 0x00014000,
+       DMA_CONTROL_TTC_24 = 0x00018000,
+       DMA_CONTROL_TTC_16 = 0x0001c000,
+};
+#define DMA_CONTROL_TC_TX_MASK 0xfffe3fff
+
+#define DMA_CONTROL_EFC                0x00000100
+#define DMA_CONTROL_FEF                0x00000080
+#define DMA_CONTROL_FUF                0x00000040
+
+enum rtc_control {
+       DMA_CONTROL_RTC_64 = 0x00000000,
+       DMA_CONTROL_RTC_32 = 0x00000008,
+       DMA_CONTROL_RTC_96 = 0x00000010,
+       DMA_CONTROL_RTC_128 = 0x00000018,
+};
+#define DMA_CONTROL_TC_RX_MASK 0xffffffe7
+
+#define DMA_CONTROL_OSF        0x00000004      /* Operate on second frame */
+
+/* MMC registers offset */
+#define GMAC_MMC_CTRL      0x100
+#define GMAC_MMC_RX_INTR   0x104
+#define GMAC_MMC_TX_INTR   0x108
+#define GMAC_MMC_RX_CSUM_OFFLOAD   0x208
diff --git a/drivers/net/stmmac/mac100.c b/drivers/net/stmmac/mac100.c
new file mode 100644 (file)
index 0000000..625171b
--- /dev/null
@@ -0,0 +1,517 @@
+/*******************************************************************************
+  This is the driver for the MAC 10/100 on-chip Ethernet controller
+  currently tested on all the ST boards based on STb7109 and stx7200 SoCs.
+
+  DWC Ether MAC 10/100 Universal version 4.0 has been used for developing
+  this code.
+
+  Copyright (C) 2007-2009  STMicroelectronics Ltd
+
+  This program is free software; you can redistribute it and/or modify it
+  under the terms and conditions of the GNU General Public License,
+  version 2, as published by the Free Software Foundation.
+
+  This program is distributed in the hope it will be useful, but WITHOUT
+  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+  more details.
+
+  You should have received a copy of the GNU General Public License along with
+  this program; if not, write to the Free Software Foundation, Inc.,
+  51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+
+  The full GNU General Public License is included in this distribution in
+  the file called "COPYING".
+
+  Author: Giuseppe Cavallaro <peppe.cavallaro@st.com>
+*******************************************************************************/
+
+#include <linux/netdevice.h>
+#include <linux/crc32.h>
+#include <linux/mii.h>
+#include <linux/phy.h>
+
+#include "common.h"
+#include "mac100.h"
+
+#undef MAC100_DEBUG
+/*#define MAC100_DEBUG*/
+#ifdef MAC100_DEBUG
+#define DBG(fmt, args...)  printk(fmt, ## args)
+#else
+#define DBG(fmt, args...)  do { } while (0)
+#endif
+
+static void mac100_core_init(unsigned long ioaddr)
+{
+       u32 value = readl(ioaddr + MAC_CONTROL);
+
+       writel((value | MAC_CORE_INIT), ioaddr + MAC_CONTROL);
+
+#ifdef STMMAC_VLAN_TAG_USED
+       writel(ETH_P_8021Q, ioaddr + MAC_VLAN1);
+#endif
+       return;
+}
+
+static void mac100_dump_mac_regs(unsigned long ioaddr)
+{
+       pr_info("\t----------------------------------------------\n"
+              "\t  MAC100 CSR (base addr = 0x%8x)\n"
+              "\t----------------------------------------------\n",
+              (unsigned int)ioaddr);
+       pr_info("\tcontrol reg (offset 0x%x): 0x%08x\n", MAC_CONTROL,
+              readl(ioaddr + MAC_CONTROL));
+       pr_info("\taddr HI (offset 0x%x): 0x%08x\n ", MAC_ADDR_HIGH,
+              readl(ioaddr + MAC_ADDR_HIGH));
+       pr_info("\taddr LO (offset 0x%x): 0x%08x\n", MAC_ADDR_LOW,
+              readl(ioaddr + MAC_ADDR_LOW));
+       pr_info("\tmulticast hash HI (offset 0x%x): 0x%08x\n",
+                       MAC_HASH_HIGH, readl(ioaddr + MAC_HASH_HIGH));
+       pr_info("\tmulticast hash LO (offset 0x%x): 0x%08x\n",
+                       MAC_HASH_LOW, readl(ioaddr + MAC_HASH_LOW));
+       pr_info("\tflow control (offset 0x%x): 0x%08x\n",
+               MAC_FLOW_CTRL, readl(ioaddr + MAC_FLOW_CTRL));
+       pr_info("\tVLAN1 tag (offset 0x%x): 0x%08x\n", MAC_VLAN1,
+              readl(ioaddr + MAC_VLAN1));
+       pr_info("\tVLAN2 tag (offset 0x%x): 0x%08x\n", MAC_VLAN2,
+              readl(ioaddr + MAC_VLAN2));
+       pr_info("\n\tMAC management counter registers\n");
+       pr_info("\t MMC crtl (offset 0x%x): 0x%08x\n",
+              MMC_CONTROL, readl(ioaddr + MMC_CONTROL));
+       pr_info("\t MMC High Interrupt (offset 0x%x): 0x%08x\n",
+              MMC_HIGH_INTR, readl(ioaddr + MMC_HIGH_INTR));
+       pr_info("\t MMC Low Interrupt (offset 0x%x): 0x%08x\n",
+              MMC_LOW_INTR, readl(ioaddr + MMC_LOW_INTR));
+       pr_info("\t MMC High Interrupt Mask (offset 0x%x): 0x%08x\n",
+              MMC_HIGH_INTR_MASK, readl(ioaddr + MMC_HIGH_INTR_MASK));
+       pr_info("\t MMC Low Interrupt Mask (offset 0x%x): 0x%08x\n",
+              MMC_LOW_INTR_MASK, readl(ioaddr + MMC_LOW_INTR_MASK));
+       return;
+}
+
+static int mac100_dma_init(unsigned long ioaddr, int pbl, u32 dma_tx,
+                          u32 dma_rx)
+{
+       u32 value = readl(ioaddr + DMA_BUS_MODE);
+       /* DMA SW reset */
+       value |= DMA_BUS_MODE_SFT_RESET;
+       writel(value, ioaddr + DMA_BUS_MODE);
+       do {} while ((readl(ioaddr + DMA_BUS_MODE) & DMA_BUS_MODE_SFT_RESET));
+
+       /* Enable Application Access by writing to DMA CSR0 */
+       writel(DMA_BUS_MODE_DEFAULT | (pbl << DMA_BUS_MODE_PBL_SHIFT),
+              ioaddr + DMA_BUS_MODE);
+
+       /* Mask interrupts by writing to CSR7 */
+       writel(DMA_INTR_DEFAULT_MASK, ioaddr + DMA_INTR_ENA);
+
+       /* The base address of the RX/TX descriptor lists must be written into
+        * DMA CSR3 and CSR4, respectively. */
+       writel(dma_tx, ioaddr + DMA_TX_BASE_ADDR);
+       writel(dma_rx, ioaddr + DMA_RCV_BASE_ADDR);
+
+       return 0;
+}
+
+/* Store and Forward capability is not used at all..
+ * The transmit threshold can be programmed by
+ * setting the TTC bits in the DMA control register.*/
+static void mac100_dma_operation_mode(unsigned long ioaddr, int txmode,
+                                     int rxmode)
+{
+       u32 csr6 = readl(ioaddr + DMA_CONTROL);
+
+       if (txmode <= 32)
+               csr6 |= DMA_CONTROL_TTC_32;
+       else if (txmode <= 64)
+               csr6 |= DMA_CONTROL_TTC_64;
+       else
+               csr6 |= DMA_CONTROL_TTC_128;
+
+       writel(csr6, ioaddr + DMA_CONTROL);
+
+       return;
+}
+
+static void mac100_dump_dma_regs(unsigned long ioaddr)
+{
+       int i;
+
+       DBG(KERN_DEBUG "MAC100 DMA CSR \n");
+       for (i = 0; i < 9; i++)
+               pr_debug("\t CSR%d (offset 0x%x): 0x%08x\n", i,
+                      (DMA_BUS_MODE + i * 4),
+                      readl(ioaddr + DMA_BUS_MODE + i * 4));
+       DBG(KERN_DEBUG "\t CSR20 (offset 0x%x): 0x%08x\n",
+           DMA_CUR_TX_BUF_ADDR, readl(ioaddr + DMA_CUR_TX_BUF_ADDR));
+       DBG(KERN_DEBUG "\t CSR21 (offset 0x%x): 0x%08x\n",
+           DMA_CUR_RX_BUF_ADDR, readl(ioaddr + DMA_CUR_RX_BUF_ADDR));
+       return;
+}
+
+/* DMA controller has two counters to track the number of
+   the receive missed frames. */
+static void mac100_dma_diagnostic_fr(void *data, struct stmmac_extra_stats *x,
+                                    unsigned long ioaddr)
+{
+       struct net_device_stats *stats = (struct net_device_stats *)data;
+       u32 csr8 = readl(ioaddr + DMA_MISSED_FRAME_CTR);
+
+       if (unlikely(csr8)) {
+               if (csr8 & DMA_MISSED_FRAME_OVE) {
+                       stats->rx_over_errors += 0x800;
+                       x->rx_overflow_cntr += 0x800;
+               } else {
+                       unsigned int ove_cntr;
+                       ove_cntr = ((csr8 & DMA_MISSED_FRAME_OVE_CNTR) >> 17);
+                       stats->rx_over_errors += ove_cntr;
+                       x->rx_overflow_cntr += ove_cntr;
+               }
+
+               if (csr8 & DMA_MISSED_FRAME_OVE_M) {
+                       stats->rx_missed_errors += 0xffff;
+                       x->rx_missed_cntr += 0xffff;
+               } else {
+                       unsigned int miss_f = (csr8 & DMA_MISSED_FRAME_M_CNTR);
+                       stats->rx_missed_errors += miss_f;
+                       x->rx_missed_cntr += miss_f;
+               }
+       }
+       return;
+}
+
+static int mac100_get_tx_frame_status(void *data, struct stmmac_extra_stats *x,
+                                     struct dma_desc *p, unsigned long ioaddr)
+{
+       int ret = 0;
+       struct net_device_stats *stats = (struct net_device_stats *)data;
+
+       if (unlikely(p->des01.tx.error_summary)) {
+               if (unlikely(p->des01.tx.underflow_error)) {
+                       x->tx_underflow++;
+                       stats->tx_fifo_errors++;
+               }
+               if (unlikely(p->des01.tx.no_carrier)) {
+                       x->tx_carrier++;
+                       stats->tx_carrier_errors++;
+               }
+               if (unlikely(p->des01.tx.loss_carrier)) {
+                       x->tx_losscarrier++;
+                       stats->tx_carrier_errors++;
+               }
+               if (unlikely((p->des01.tx.excessive_deferral) ||
+                            (p->des01.tx.excessive_collisions) ||
+                            (p->des01.tx.late_collision)))
+                       stats->collisions += p->des01.tx.collision_count;
+               ret = -1;
+       }
+       if (unlikely(p->des01.tx.heartbeat_fail)) {
+               x->tx_heartbeat++;
+               stats->tx_heartbeat_errors++;
+               ret = -1;
+       }
+       if (unlikely(p->des01.tx.deferred))
+               x->tx_deferred++;
+
+       return ret;
+}
+
+static int mac100_get_tx_len(struct dma_desc *p)
+{
+       return p->des01.tx.buffer1_size;
+}
+
+/* This function verifies if each incoming frame has some errors
+ * and, if required, updates the multicast statistics.
+ * In case of success, it returns csum_none becasue the device
+ * is not able to compute the csum in HW. */
+static int mac100_get_rx_frame_status(void *data, struct stmmac_extra_stats *x,
+                                     struct dma_desc *p)
+{
+       int ret = csum_none;
+       struct net_device_stats *stats = (struct net_device_stats *)data;
+
+       if (unlikely(p->des01.rx.last_descriptor == 0)) {
+               pr_warning("mac100 Error: Oversized Ethernet "
+                          "frame spanned multiple buffers\n");
+               stats->rx_length_errors++;
+               return discard_frame;
+       }
+
+       if (unlikely(p->des01.rx.error_summary)) {
+               if (unlikely(p->des01.rx.descriptor_error))
+                       x->rx_desc++;
+               if (unlikely(p->des01.rx.partial_frame_error))
+                       x->rx_partial++;
+               if (unlikely(p->des01.rx.run_frame))
+                       x->rx_runt++;
+               if (unlikely(p->des01.rx.frame_too_long))
+                       x->rx_toolong++;
+               if (unlikely(p->des01.rx.collision)) {
+                       x->rx_collision++;
+                       stats->collisions++;
+               }
+               if (unlikely(p->des01.rx.crc_error)) {
+                       x->rx_crc++;
+                       stats->rx_crc_errors++;
+               }
+               ret = discard_frame;
+       }
+       if (unlikely(p->des01.rx.dribbling))
+               ret = discard_frame;
+
+       if (unlikely(p->des01.rx.length_error)) {
+               x->rx_lenght++;
+               ret = discard_frame;
+       }
+       if (unlikely(p->des01.rx.mii_error)) {
+               x->rx_mii++;
+               ret = discard_frame;
+       }
+       if (p->des01.rx.multicast_frame) {
+               x->rx_multicast++;
+               stats->multicast++;
+       }
+       return ret;
+}
+
+static void mac100_irq_status(unsigned long ioaddr)
+{
+       return;
+}
+
+static void mac100_set_umac_addr(unsigned long ioaddr, unsigned char *addr,
+                         unsigned int reg_n)
+{
+       stmmac_set_mac_addr(ioaddr, addr, MAC_ADDR_HIGH, MAC_ADDR_LOW);
+}
+
+static void mac100_get_umac_addr(unsigned long ioaddr, unsigned char *addr,
+                         unsigned int reg_n)
+{
+       stmmac_get_mac_addr(ioaddr, addr, MAC_ADDR_HIGH, MAC_ADDR_LOW);
+}
+
+static void mac100_set_filter(struct net_device *dev)
+{
+       unsigned long ioaddr = dev->base_addr;
+       u32 value = readl(ioaddr + MAC_CONTROL);
+
+       if (dev->flags & IFF_PROMISC) {
+               value |= MAC_CONTROL_PR;
+               value &= ~(MAC_CONTROL_PM | MAC_CONTROL_IF | MAC_CONTROL_HO |
+                          MAC_CONTROL_HP);
+       } else if ((dev->mc_count > HASH_TABLE_SIZE)
+                  || (dev->flags & IFF_ALLMULTI)) {
+               value |= MAC_CONTROL_PM;
+               value &= ~(MAC_CONTROL_PR | MAC_CONTROL_IF | MAC_CONTROL_HO);
+               writel(0xffffffff, ioaddr + MAC_HASH_HIGH);
+               writel(0xffffffff, ioaddr + MAC_HASH_LOW);
+       } else if (dev->mc_count == 0) {        /* no multicast */
+               value &= ~(MAC_CONTROL_PM | MAC_CONTROL_PR | MAC_CONTROL_IF |
+                          MAC_CONTROL_HO | MAC_CONTROL_HP);
+       } else {
+               int i;
+               u32 mc_filter[2];
+               struct dev_mc_list *mclist;
+
+               /* Perfect filter mode for physical address and Hash
+                  filter for multicast */
+               value |= MAC_CONTROL_HP;
+               value &= ~(MAC_CONTROL_PM | MAC_CONTROL_PR | MAC_CONTROL_IF
+                          | MAC_CONTROL_HO);
+
+               memset(mc_filter, 0, sizeof(mc_filter));
+               for (i = 0, mclist = dev->mc_list;
+                    mclist && i < dev->mc_count; i++, mclist = mclist->next) {
+                       /* The upper 6 bits of the calculated CRC are used to
+                        * index the contens of the hash table */
+                       int bit_nr =
+                           ether_crc(ETH_ALEN, mclist->dmi_addr) >> 26;
+                       /* The most significant bit determines the register to
+                        * use (H/L) while the other 5 bits determine the bit
+                        * within the register. */
+                       mc_filter[bit_nr >> 5] |= 1 << (bit_nr & 31);
+               }
+               writel(mc_filter[0], ioaddr + MAC_HASH_LOW);
+               writel(mc_filter[1], ioaddr + MAC_HASH_HIGH);
+       }
+
+       writel(value, ioaddr + MAC_CONTROL);
+
+       DBG(KERN_INFO "%s: CTRL reg: 0x%08x Hash regs: "
+           "HI 0x%08x, LO 0x%08x\n",
+           __func__, readl(ioaddr + MAC_CONTROL),
+           readl(ioaddr + MAC_HASH_HIGH), readl(ioaddr + MAC_HASH_LOW));
+       return;
+}
+
+static void mac100_flow_ctrl(unsigned long ioaddr, unsigned int duplex,
+                            unsigned int fc, unsigned int pause_time)
+{
+       unsigned int flow = MAC_FLOW_CTRL_ENABLE;
+
+       if (duplex)
+               flow |= (pause_time << MAC_FLOW_CTRL_PT_SHIFT);
+       writel(flow, ioaddr + MAC_FLOW_CTRL);
+
+       return;
+}
+
+/* No PMT module supported in our SoC  for the Ethernet Controller. */
+static void mac100_pmt(unsigned long ioaddr, unsigned long mode)
+{
+       return;
+}
+
+static void mac100_init_rx_desc(struct dma_desc *p, unsigned int ring_size,
+                               int disable_rx_ic)
+{
+       int i;
+       for (i = 0; i < ring_size; i++) {
+               p->des01.rx.own = 1;
+               p->des01.rx.buffer1_size = BUF_SIZE_2KiB - 1;
+               if (i == ring_size - 1)
+                       p->des01.rx.end_ring = 1;
+               if (disable_rx_ic)
+                       p->des01.rx.disable_ic = 1;
+               p++;
+       }
+       return;
+}
+
+static void mac100_init_tx_desc(struct dma_desc *p, unsigned int ring_size)
+{
+       int i;
+       for (i = 0; i < ring_size; i++) {
+               p->des01.tx.own = 0;
+               if (i == ring_size - 1)
+                       p->des01.tx.end_ring = 1;
+               p++;
+       }
+       return;
+}
+
+static int mac100_get_tx_owner(struct dma_desc *p)
+{
+       return p->des01.tx.own;
+}
+
+static int mac100_get_rx_owner(struct dma_desc *p)
+{
+       return p->des01.rx.own;
+}
+
+static void mac100_set_tx_owner(struct dma_desc *p)
+{
+       p->des01.tx.own = 1;
+}
+
+static void mac100_set_rx_owner(struct dma_desc *p)
+{
+       p->des01.rx.own = 1;
+}
+
+static int mac100_get_tx_ls(struct dma_desc *p)
+{
+       return p->des01.tx.last_segment;
+}
+
+static void mac100_release_tx_desc(struct dma_desc *p)
+{
+       int ter = p->des01.tx.end_ring;
+
+       /* clean field used within the xmit */
+       p->des01.tx.first_segment = 0;
+       p->des01.tx.last_segment = 0;
+       p->des01.tx.buffer1_size = 0;
+
+       /* clean status reported */
+       p->des01.tx.error_summary = 0;
+       p->des01.tx.underflow_error = 0;
+       p->des01.tx.no_carrier = 0;
+       p->des01.tx.loss_carrier = 0;
+       p->des01.tx.excessive_deferral = 0;
+       p->des01.tx.excessive_collisions = 0;
+       p->des01.tx.late_collision = 0;
+       p->des01.tx.heartbeat_fail = 0;
+       p->des01.tx.deferred = 0;
+
+       /* set termination field */
+       p->des01.tx.end_ring = ter;
+
+       return;
+}
+
+static void mac100_prepare_tx_desc(struct dma_desc *p, int is_fs, int len,
+                                  int csum_flag)
+{
+       p->des01.tx.first_segment = is_fs;
+       p->des01.tx.buffer1_size = len;
+}
+
+static void mac100_clear_tx_ic(struct dma_desc *p)
+{
+       p->des01.tx.interrupt = 0;
+}
+
+static void mac100_close_tx_desc(struct dma_desc *p)
+{
+       p->des01.tx.last_segment = 1;
+       p->des01.tx.interrupt = 1;
+}
+
+static int mac100_get_rx_frame_len(struct dma_desc *p)
+{
+       return p->des01.rx.frame_length;
+}
+
+struct stmmac_ops mac100_driver = {
+       .core_init = mac100_core_init,
+       .dump_mac_regs = mac100_dump_mac_regs,
+       .dma_init = mac100_dma_init,
+       .dump_dma_regs = mac100_dump_dma_regs,
+       .dma_mode = mac100_dma_operation_mode,
+       .dma_diagnostic_fr = mac100_dma_diagnostic_fr,
+       .tx_status = mac100_get_tx_frame_status,
+       .rx_status = mac100_get_rx_frame_status,
+       .get_tx_len = mac100_get_tx_len,
+       .set_filter = mac100_set_filter,
+       .flow_ctrl = mac100_flow_ctrl,
+       .pmt = mac100_pmt,
+       .init_rx_desc = mac100_init_rx_desc,
+       .init_tx_desc = mac100_init_tx_desc,
+       .get_tx_owner = mac100_get_tx_owner,
+       .get_rx_owner = mac100_get_rx_owner,
+       .release_tx_desc = mac100_release_tx_desc,
+       .prepare_tx_desc = mac100_prepare_tx_desc,
+       .clear_tx_ic = mac100_clear_tx_ic,
+       .close_tx_desc = mac100_close_tx_desc,
+       .get_tx_ls = mac100_get_tx_ls,
+       .set_tx_owner = mac100_set_tx_owner,
+       .set_rx_owner = mac100_set_rx_owner,
+       .get_rx_frame_len = mac100_get_rx_frame_len,
+       .host_irq_status = mac100_irq_status,
+       .set_umac_addr = mac100_set_umac_addr,
+       .get_umac_addr = mac100_get_umac_addr,
+};
+
+struct mac_device_info *mac100_setup(unsigned long ioaddr)
+{
+       struct mac_device_info *mac;
+
+       mac = kzalloc(sizeof(const struct mac_device_info), GFP_KERNEL);
+
+       pr_info("\tMAC 10/100\n");
+
+       mac->ops = &mac100_driver;
+       mac->hw.pmt = PMT_NOT_SUPPORTED;
+       mac->hw.link.port = MAC_CONTROL_PS;
+       mac->hw.link.duplex = MAC_CONTROL_F;
+       mac->hw.link.speed = 0;
+       mac->hw.mii.addr = MAC_MII_ADDR;
+       mac->hw.mii.data = MAC_MII_DATA;
+
+       return mac;
+}
diff --git a/drivers/net/stmmac/mac100.h b/drivers/net/stmmac/mac100.h
new file mode 100644 (file)
index 0000000..0f8f110
--- /dev/null
@@ -0,0 +1,116 @@
+/*******************************************************************************
+  MAC 10/100 Header File
+
+  Copyright (C) 2007-2009  STMicroelectronics Ltd
+
+  This program is free software; you can redistribute it and/or modify it
+  under the terms and conditions of the GNU General Public License,
+  version 2, as published by the Free Software Foundation.
+
+  This program is distributed in the hope it will be useful, but WITHOUT
+  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+  more details.
+
+  You should have received a copy of the GNU General Public License along with
+  this program; if not, write to the Free Software Foundation, Inc.,
+  51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+
+  The full GNU General Public License is included in this distribution in
+  the file called "COPYING".
+
+  Author: Giuseppe Cavallaro <peppe.cavallaro@st.com>
+*******************************************************************************/
+
+/*----------------------------------------------------------------------------
+ *                             MAC BLOCK defines
+ *---------------------------------------------------------------------------*/
+/* MAC CSR offset */
+#define MAC_CONTROL    0x00000000      /* MAC Control */
+#define MAC_ADDR_HIGH  0x00000004      /* MAC Address High */
+#define MAC_ADDR_LOW   0x00000008      /* MAC Address Low */
+#define MAC_HASH_HIGH  0x0000000c      /* Multicast Hash Table High */
+#define MAC_HASH_LOW   0x00000010      /* Multicast Hash Table Low */
+#define MAC_MII_ADDR   0x00000014      /* MII Address */
+#define MAC_MII_DATA   0x00000018      /* MII Data */
+#define MAC_FLOW_CTRL  0x0000001c      /* Flow Control */
+#define MAC_VLAN1      0x00000020      /* VLAN1 Tag */
+#define MAC_VLAN2      0x00000024      /* VLAN2 Tag */
+
+/* MAC CTRL defines */
+#define MAC_CONTROL_RA 0x80000000      /* Receive All Mode */
+#define MAC_CONTROL_BLE        0x40000000      /* Endian Mode */
+#define MAC_CONTROL_HBD        0x10000000      /* Heartbeat Disable */
+#define MAC_CONTROL_PS 0x08000000      /* Port Select */
+#define MAC_CONTROL_DRO        0x00800000      /* Disable Receive Own */
+#define MAC_CONTROL_EXT_LOOPBACK 0x00400000    /* Reserved (ext loopback?) */
+#define MAC_CONTROL_OM 0x00200000      /* Loopback Operating Mode */
+#define MAC_CONTROL_F  0x00100000      /* Full Duplex Mode */
+#define MAC_CONTROL_PM 0x00080000      /* Pass All Multicast */
+#define MAC_CONTROL_PR 0x00040000      /* Promiscuous Mode */
+#define MAC_CONTROL_IF 0x00020000      /* Inverse Filtering */
+#define MAC_CONTROL_PB 0x00010000      /* Pass Bad Frames */
+#define MAC_CONTROL_HO 0x00008000      /* Hash Only Filtering Mode */
+#define MAC_CONTROL_HP 0x00002000      /* Hash/Perfect Filtering Mode */
+#define MAC_CONTROL_LCC        0x00001000      /* Late Collision Control */
+#define MAC_CONTROL_DBF        0x00000800      /* Disable Broadcast Frames */
+#define MAC_CONTROL_DRTY       0x00000400      /* Disable Retry */
+#define MAC_CONTROL_ASTP       0x00000100      /* Automatic Pad Stripping */
+#define MAC_CONTROL_BOLMT_10   0x00000000      /* Back Off Limit 10 */
+#define MAC_CONTROL_BOLMT_8    0x00000040      /* Back Off Limit 8 */
+#define MAC_CONTROL_BOLMT_4    0x00000080      /* Back Off Limit 4 */
+#define MAC_CONTROL_BOLMT_1    0x000000c0      /* Back Off Limit 1 */
+#define MAC_CONTROL_DC         0x00000020      /* Deferral Check */
+#define MAC_CONTROL_TE         0x00000008      /* Transmitter Enable */
+#define MAC_CONTROL_RE         0x00000004      /* Receiver Enable */
+
+#define MAC_CORE_INIT (MAC_CONTROL_HBD | MAC_CONTROL_ASTP)
+
+/* MAC FLOW CTRL defines */
+#define MAC_FLOW_CTRL_PT_MASK  0xffff0000      /* Pause Time Mask */
+#define MAC_FLOW_CTRL_PT_SHIFT 16
+#define MAC_FLOW_CTRL_PASS     0x00000004      /* Pass Control Frames */
+#define MAC_FLOW_CTRL_ENABLE   0x00000002      /* Flow Control Enable */
+#define MAC_FLOW_CTRL_PAUSE    0x00000001      /* Flow Control Busy ... */
+
+/* MII ADDR  defines */
+#define MAC_MII_ADDR_WRITE     0x00000002      /* MII Write */
+#define MAC_MII_ADDR_BUSY      0x00000001      /* MII Busy */
+
+/*----------------------------------------------------------------------------
+ *                             DMA BLOCK defines
+ *---------------------------------------------------------------------------*/
+
+/* DMA Bus Mode register defines */
+#define DMA_BUS_MODE_DBO       0x00100000      /* Descriptor Byte Ordering */
+#define DMA_BUS_MODE_BLE       0x00000080      /* Big Endian/Little Endian */
+#define DMA_BUS_MODE_PBL_MASK  0x00003f00      /* Programmable Burst Len */
+#define DMA_BUS_MODE_PBL_SHIFT 8
+#define DMA_BUS_MODE_DSL_MASK  0x0000007c      /* Descriptor Skip Length */
+#define DMA_BUS_MODE_DSL_SHIFT 2       /*   (in DWORDS)      */
+#define DMA_BUS_MODE_BAR_BUS   0x00000002      /* Bar-Bus Arbitration */
+#define DMA_BUS_MODE_SFT_RESET 0x00000001      /* Software Reset */
+#define DMA_BUS_MODE_DEFAULT   0x00000000
+
+/* DMA Control register defines */
+#define DMA_CONTROL_SF         0x00200000      /* Store And Forward */
+
+/* Transmit Threshold Control */
+enum ttc_control {
+       DMA_CONTROL_TTC_DEFAULT = 0x00000000,   /* Threshold is 32 DWORDS */
+       DMA_CONTROL_TTC_64 = 0x00004000,        /* Threshold is 64 DWORDS */
+       DMA_CONTROL_TTC_128 = 0x00008000,       /* Threshold is 128 DWORDS */
+       DMA_CONTROL_TTC_256 = 0x0000c000,       /* Threshold is 256 DWORDS */
+       DMA_CONTROL_TTC_18 = 0x00400000,        /* Threshold is 18 DWORDS */
+       DMA_CONTROL_TTC_24 = 0x00404000,        /* Threshold is 24 DWORDS */
+       DMA_CONTROL_TTC_32 = 0x00408000,        /* Threshold is 32 DWORDS */
+       DMA_CONTROL_TTC_40 = 0x0040c000,        /* Threshold is 40 DWORDS */
+       DMA_CONTROL_SE = 0x00000008,    /* Stop On Empty */
+       DMA_CONTROL_OSF = 0x00000004,   /* Operate On 2nd Frame */
+};
+
+/* STMAC110 DMA Missed Frame Counter register defines */
+#define DMA_MISSED_FRAME_OVE   0x10000000      /* FIFO Overflow Overflow */
+#define DMA_MISSED_FRAME_OVE_CNTR 0x0ffe0000   /* Overflow Frame Counter */
+#define DMA_MISSED_FRAME_OVE_M 0x00010000      /* Missed Frame Overflow */
+#define DMA_MISSED_FRAME_M_CNTR        0x0000ffff      /* Missed Frame Couinter */
diff --git a/drivers/net/stmmac/stmmac.h b/drivers/net/stmmac/stmmac.h
new file mode 100644 (file)
index 0000000..6d2eae3
--- /dev/null
@@ -0,0 +1,98 @@
+/*******************************************************************************
+  Copyright (C) 2007-2009  STMicroelectronics Ltd
+
+  This program is free software; you can redistribute it and/or modify it
+  under the terms and conditions of the GNU General Public License,
+  version 2, as published by the Free Software Foundation.
+
+  This program is distributed in the hope it will be useful, but WITHOUT
+  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+  more details.
+
+  You should have received a copy of the GNU General Public License along with
+  this program; if not, write to the Free Software Foundation, Inc.,
+  51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+
+  The full GNU General Public License is included in this distribution in
+  the file called "COPYING".
+
+  Author: Giuseppe Cavallaro <peppe.cavallaro@st.com>
+*******************************************************************************/
+
+#define DRV_MODULE_VERSION     "Oct_09"
+
+#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE)
+#define STMMAC_VLAN_TAG_USED
+#include <linux/if_vlan.h>
+#endif
+
+#include "common.h"
+#ifdef CONFIG_STMMAC_TIMER
+#include "stmmac_timer.h"
+#endif
+
+struct stmmac_priv {
+       /* Frequently used values are kept adjacent for cache effect */
+       struct dma_desc *dma_tx ____cacheline_aligned;
+       dma_addr_t dma_tx_phy;
+       struct sk_buff **tx_skbuff;
+       unsigned int cur_tx;
+       unsigned int dirty_tx;
+       unsigned int dma_tx_size;
+       int tx_coe;
+       int tx_coalesce;
+
+       struct dma_desc *dma_rx ;
+       unsigned int cur_rx;
+       unsigned int dirty_rx;
+       struct sk_buff **rx_skbuff;
+       dma_addr_t *rx_skbuff_dma;
+       struct sk_buff_head rx_recycle;
+
+       struct net_device *dev;
+       int is_gmac;
+       dma_addr_t dma_rx_phy;
+       unsigned int dma_rx_size;
+       int rx_csum;
+       unsigned int dma_buf_sz;
+       struct device *device;
+       struct mac_device_info *mac_type;
+
+       struct stmmac_extra_stats xstats;
+       struct napi_struct napi;
+
+       phy_interface_t phy_interface;
+       int pbl;
+       int bus_id;
+       int phy_addr;
+       int phy_mask;
+       int (*phy_reset) (void *priv);
+       void (*fix_mac_speed) (void *priv, unsigned int speed);
+       void *bsp_priv;
+
+       int phy_irq;
+       struct phy_device *phydev;
+       int oldlink;
+       int speed;
+       int oldduplex;
+       unsigned int flow_ctrl;
+       unsigned int pause;
+       struct mii_bus *mii;
+
+       u32 msg_enable;
+       spinlock_t lock;
+       int wolopts;
+       int wolenabled;
+       int shutdown;
+#ifdef CONFIG_STMMAC_TIMER
+       struct stmmac_timer *tm;
+#endif
+#ifdef STMMAC_VLAN_TAG_USED
+       struct vlan_group *vlgrp;
+#endif
+};
+
+extern int stmmac_mdio_unregister(struct net_device *ndev);
+extern int stmmac_mdio_register(struct net_device *ndev);
+extern void stmmac_set_ethtool_ops(struct net_device *netdev);
diff --git a/drivers/net/stmmac/stmmac_ethtool.c b/drivers/net/stmmac/stmmac_ethtool.c
new file mode 100644 (file)
index 0000000..694ebe6
--- /dev/null
@@ -0,0 +1,395 @@
+/*******************************************************************************
+  STMMAC Ethtool support
+
+  Copyright (C) 2007-2009  STMicroelectronics Ltd
+
+  This program is free software; you can redistribute it and/or modify it
+  under the terms and conditions of the GNU General Public License,
+  version 2, as published by the Free Software Foundation.
+
+  This program is distributed in the hope it will be useful, but WITHOUT
+  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+  more details.
+
+  You should have received a copy of the GNU General Public License along with
+  this program; if not, write to the Free Software Foundation, Inc.,
+  51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+
+  The full GNU General Public License is included in this distribution in
+  the file called "COPYING".
+
+  Author: Giuseppe Cavallaro <peppe.cavallaro@st.com>
+*******************************************************************************/
+
+#include <linux/etherdevice.h>
+#include <linux/ethtool.h>
+#include <linux/mii.h>
+#include <linux/phy.h>
+
+#include "stmmac.h"
+
+#define REG_SPACE_SIZE 0x1054
+#define MAC100_ETHTOOL_NAME    "st_mac100"
+#define GMAC_ETHTOOL_NAME      "st_gmac"
+
+struct stmmac_stats {
+       char stat_string[ETH_GSTRING_LEN];
+       int sizeof_stat;
+       int stat_offset;
+};
+
+#define STMMAC_STAT(m) \
+       { #m, FIELD_SIZEOF(struct stmmac_extra_stats, m),       \
+       offsetof(struct stmmac_priv, xstats.m)}
+
+static const struct  stmmac_stats stmmac_gstrings_stats[] = {
+       STMMAC_STAT(tx_underflow),
+       STMMAC_STAT(tx_carrier),
+       STMMAC_STAT(tx_losscarrier),
+       STMMAC_STAT(tx_heartbeat),
+       STMMAC_STAT(tx_deferred),
+       STMMAC_STAT(tx_vlan),
+       STMMAC_STAT(rx_vlan),
+       STMMAC_STAT(tx_jabber),
+       STMMAC_STAT(tx_frame_flushed),
+       STMMAC_STAT(tx_payload_error),
+       STMMAC_STAT(tx_ip_header_error),
+       STMMAC_STAT(rx_desc),
+       STMMAC_STAT(rx_partial),
+       STMMAC_STAT(rx_runt),
+       STMMAC_STAT(rx_toolong),
+       STMMAC_STAT(rx_collision),
+       STMMAC_STAT(rx_crc),
+       STMMAC_STAT(rx_lenght),
+       STMMAC_STAT(rx_mii),
+       STMMAC_STAT(rx_multicast),
+       STMMAC_STAT(rx_gmac_overflow),
+       STMMAC_STAT(rx_watchdog),
+       STMMAC_STAT(da_rx_filter_fail),
+       STMMAC_STAT(sa_rx_filter_fail),
+       STMMAC_STAT(rx_missed_cntr),
+       STMMAC_STAT(rx_overflow_cntr),
+       STMMAC_STAT(tx_undeflow_irq),
+       STMMAC_STAT(tx_process_stopped_irq),
+       STMMAC_STAT(tx_jabber_irq),
+       STMMAC_STAT(rx_overflow_irq),
+       STMMAC_STAT(rx_buf_unav_irq),
+       STMMAC_STAT(rx_process_stopped_irq),
+       STMMAC_STAT(rx_watchdog_irq),
+       STMMAC_STAT(tx_early_irq),
+       STMMAC_STAT(fatal_bus_error_irq),
+       STMMAC_STAT(threshold),
+       STMMAC_STAT(tx_pkt_n),
+       STMMAC_STAT(rx_pkt_n),
+       STMMAC_STAT(poll_n),
+       STMMAC_STAT(sched_timer_n),
+       STMMAC_STAT(normal_irq_n),
+};
+#define STMMAC_STATS_LEN ARRAY_SIZE(stmmac_gstrings_stats)
+
+void stmmac_ethtool_getdrvinfo(struct net_device *dev,
+                              struct ethtool_drvinfo *info)
+{
+       struct stmmac_priv *priv = netdev_priv(dev);
+
+       if (!priv->is_gmac)
+               strcpy(info->driver, MAC100_ETHTOOL_NAME);
+       else
+               strcpy(info->driver, GMAC_ETHTOOL_NAME);
+
+       strcpy(info->version, DRV_MODULE_VERSION);
+       info->fw_version[0] = '\0';
+       info->n_stats = STMMAC_STATS_LEN;
+       return;
+}
+
+int stmmac_ethtool_getsettings(struct net_device *dev, struct ethtool_cmd *cmd)
+{
+       struct stmmac_priv *priv = netdev_priv(dev);
+       struct phy_device *phy = priv->phydev;
+       int rc;
+       if (phy == NULL) {
+               pr_err("%s: %s: PHY is not registered\n",
+                      __func__, dev->name);
+               return -ENODEV;
+       }
+       if (!netif_running(dev)) {
+               pr_err("%s: interface is disabled: we cannot track "
+               "link speed / duplex setting\n", dev->name);
+               return -EBUSY;
+       }
+       cmd->transceiver = XCVR_INTERNAL;
+       spin_lock_irq(&priv->lock);
+       rc = phy_ethtool_gset(phy, cmd);
+       spin_unlock_irq(&priv->lock);
+       return rc;
+}
+
+int stmmac_ethtool_setsettings(struct net_device *dev, struct ethtool_cmd *cmd)
+{
+       struct stmmac_priv *priv = netdev_priv(dev);
+       struct phy_device *phy = priv->phydev;
+       int rc;
+
+       spin_lock(&priv->lock);
+       rc = phy_ethtool_sset(phy, cmd);
+       spin_unlock(&priv->lock);
+
+       return rc;
+}
+
+u32 stmmac_ethtool_getmsglevel(struct net_device *dev)
+{
+       struct stmmac_priv *priv = netdev_priv(dev);
+       return priv->msg_enable;
+}
+
+void stmmac_ethtool_setmsglevel(struct net_device *dev, u32 level)
+{
+       struct stmmac_priv *priv = netdev_priv(dev);
+       priv->msg_enable = level;
+
+}
+
+int stmmac_check_if_running(struct net_device *dev)
+{
+       if (!netif_running(dev))
+               return -EBUSY;
+       return 0;
+}
+
+int stmmac_ethtool_get_regs_len(struct net_device *dev)
+{
+       return REG_SPACE_SIZE;
+}
+
+void stmmac_ethtool_gregs(struct net_device *dev,
+                         struct ethtool_regs *regs, void *space)
+{
+       int i;
+       u32 *reg_space = (u32 *) space;
+
+       struct stmmac_priv *priv = netdev_priv(dev);
+
+       memset(reg_space, 0x0, REG_SPACE_SIZE);
+
+       if (!priv->is_gmac) {
+               /* MAC registers */
+               for (i = 0; i < 12; i++)
+                       reg_space[i] = readl(dev->base_addr + (i * 4));
+               /* DMA registers */
+               for (i = 0; i < 9; i++)
+                       reg_space[i + 12] =
+                           readl(dev->base_addr + (DMA_BUS_MODE + (i * 4)));
+               reg_space[22] = readl(dev->base_addr + DMA_CUR_TX_BUF_ADDR);
+               reg_space[23] = readl(dev->base_addr + DMA_CUR_RX_BUF_ADDR);
+       } else {
+               /* MAC registers */
+               for (i = 0; i < 55; i++)
+                       reg_space[i] = readl(dev->base_addr + (i * 4));
+               /* DMA registers */
+               for (i = 0; i < 22; i++)
+                       reg_space[i + 55] =
+                           readl(dev->base_addr + (DMA_BUS_MODE + (i * 4)));
+       }
+
+       return;
+}
+
+int stmmac_ethtool_set_tx_csum(struct net_device *netdev, u32 data)
+{
+       if (data)
+               netdev->features |= NETIF_F_HW_CSUM;
+       else
+               netdev->features &= ~NETIF_F_HW_CSUM;
+
+       return 0;
+}
+
+u32 stmmac_ethtool_get_rx_csum(struct net_device *dev)
+{
+       struct stmmac_priv *priv = netdev_priv(dev);
+
+       return priv->rx_csum;
+}
+
+static void
+stmmac_get_pauseparam(struct net_device *netdev,
+                     struct ethtool_pauseparam *pause)
+{
+       struct stmmac_priv *priv = netdev_priv(netdev);
+
+       spin_lock(&priv->lock);
+
+       pause->rx_pause = 0;
+       pause->tx_pause = 0;
+       pause->autoneg = priv->phydev->autoneg;
+
+       if (priv->flow_ctrl & FLOW_RX)
+               pause->rx_pause = 1;
+       if (priv->flow_ctrl & FLOW_TX)
+               pause->tx_pause = 1;
+
+       spin_unlock(&priv->lock);
+       return;
+}
+
+static int
+stmmac_set_pauseparam(struct net_device *netdev,
+                     struct ethtool_pauseparam *pause)
+{
+       struct stmmac_priv *priv = netdev_priv(netdev);
+       struct phy_device *phy = priv->phydev;
+       int new_pause = FLOW_OFF;
+       int ret = 0;
+
+       spin_lock(&priv->lock);
+
+       if (pause->rx_pause)
+               new_pause |= FLOW_RX;
+       if (pause->tx_pause)
+               new_pause |= FLOW_TX;
+
+       priv->flow_ctrl = new_pause;
+
+       if (phy->autoneg) {
+               if (netif_running(netdev)) {
+                       struct ethtool_cmd cmd;
+                       /* auto-negotiation automatically restarted */
+                       cmd.cmd = ETHTOOL_NWAY_RST;
+                       cmd.supported = phy->supported;
+                       cmd.advertising = phy->advertising;
+                       cmd.autoneg = phy->autoneg;
+                       cmd.speed = phy->speed;
+                       cmd.duplex = phy->duplex;
+                       cmd.phy_address = phy->addr;
+                       ret = phy_ethtool_sset(phy, &cmd);
+               }
+       } else {
+               unsigned long ioaddr = netdev->base_addr;
+               priv->mac_type->ops->flow_ctrl(ioaddr, phy->duplex,
+                                              priv->flow_ctrl, priv->pause);
+       }
+       spin_unlock(&priv->lock);
+       return ret;
+}
+
+static void stmmac_get_ethtool_stats(struct net_device *dev,
+                                struct ethtool_stats *dummy, u64 *data)
+{
+       struct stmmac_priv *priv = netdev_priv(dev);
+       unsigned long ioaddr = dev->base_addr;
+       int i;
+
+       /* Update HW stats if supported */
+       priv->mac_type->ops->dma_diagnostic_fr(&dev->stats, &priv->xstats,
+                                              ioaddr);
+
+       for (i = 0; i < STMMAC_STATS_LEN; i++) {
+               char *p = (char *)priv + stmmac_gstrings_stats[i].stat_offset;
+               data[i] = (stmmac_gstrings_stats[i].sizeof_stat ==
+               sizeof(u64)) ? (*(u64 *)p) : (*(u32 *)p);
+       }
+
+       return;
+}
+
+static int stmmac_get_sset_count(struct net_device *netdev, int sset)
+{
+       switch (sset) {
+       case ETH_SS_STATS:
+               return STMMAC_STATS_LEN;
+       default:
+               return -EOPNOTSUPP;
+       }
+}
+
+static void stmmac_get_strings(struct net_device *dev, u32 stringset, u8 *data)
+{
+       int i;
+       u8 *p = data;
+
+       switch (stringset) {
+       case ETH_SS_STATS:
+               for (i = 0; i < STMMAC_STATS_LEN; i++) {
+                       memcpy(p, stmmac_gstrings_stats[i].stat_string,
+                               ETH_GSTRING_LEN);
+                       p += ETH_GSTRING_LEN;
+               }
+               break;
+       default:
+               WARN_ON(1);
+               break;
+       }
+       return;
+}
+
+/* Currently only support WOL through Magic packet. */
+static void stmmac_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
+{
+       struct stmmac_priv *priv = netdev_priv(dev);
+
+       spin_lock_irq(&priv->lock);
+       if (priv->wolenabled == PMT_SUPPORTED) {
+               wol->supported = WAKE_MAGIC;
+               wol->wolopts = priv->wolopts;
+       }
+       spin_unlock_irq(&priv->lock);
+}
+
+static int stmmac_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
+{
+       struct stmmac_priv *priv = netdev_priv(dev);
+       u32 support = WAKE_MAGIC;
+
+       if (priv->wolenabled == PMT_NOT_SUPPORTED)
+               return -EINVAL;
+
+       if (wol->wolopts & ~support)
+               return -EINVAL;
+
+       if (wol->wolopts == 0)
+               device_set_wakeup_enable(priv->device, 0);
+       else
+               device_set_wakeup_enable(priv->device, 1);
+
+       spin_lock_irq(&priv->lock);
+       priv->wolopts = wol->wolopts;
+       spin_unlock_irq(&priv->lock);
+
+       return 0;
+}
+
+static struct ethtool_ops stmmac_ethtool_ops = {
+       .begin = stmmac_check_if_running,
+       .get_drvinfo = stmmac_ethtool_getdrvinfo,
+       .get_settings = stmmac_ethtool_getsettings,
+       .set_settings = stmmac_ethtool_setsettings,
+       .get_msglevel = stmmac_ethtool_getmsglevel,
+       .set_msglevel = stmmac_ethtool_setmsglevel,
+       .get_regs = stmmac_ethtool_gregs,
+       .get_regs_len = stmmac_ethtool_get_regs_len,
+       .get_link = ethtool_op_get_link,
+       .get_rx_csum = stmmac_ethtool_get_rx_csum,
+       .get_tx_csum = ethtool_op_get_tx_csum,
+       .set_tx_csum = stmmac_ethtool_set_tx_csum,
+       .get_sg = ethtool_op_get_sg,
+       .set_sg = ethtool_op_set_sg,
+       .get_pauseparam = stmmac_get_pauseparam,
+       .set_pauseparam = stmmac_set_pauseparam,
+       .get_ethtool_stats = stmmac_get_ethtool_stats,
+       .get_strings = stmmac_get_strings,
+       .get_wol = stmmac_get_wol,
+       .set_wol = stmmac_set_wol,
+       .get_sset_count = stmmac_get_sset_count,
+#ifdef NETIF_F_TSO
+       .get_tso = ethtool_op_get_tso,
+       .set_tso = ethtool_op_set_tso,
+#endif
+};
+
+void stmmac_set_ethtool_ops(struct net_device *netdev)
+{
+       SET_ETHTOOL_OPS(netdev, &stmmac_ethtool_ops);
+}
diff --git a/drivers/net/stmmac/stmmac_main.c b/drivers/net/stmmac/stmmac_main.c
new file mode 100644 (file)
index 0000000..c2f14dc
--- /dev/null
@@ -0,0 +1,2204 @@
+/*******************************************************************************
+  This is the driver for the ST MAC 10/100/1000 on-chip Ethernet controllers.
+  ST Ethernet IPs are built around a Synopsys IP Core.
+
+  Copyright (C) 2007-2009  STMicroelectronics Ltd
+
+  This program is free software; you can redistribute it and/or modify it
+  under the terms and conditions of the GNU General Public License,
+  version 2, as published by the Free Software Foundation.
+
+  This program is distributed in the hope it will be useful, but WITHOUT
+  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+  more details.
+
+  You should have received a copy of the GNU General Public License along with
+  this program; if not, write to the Free Software Foundation, Inc.,
+  51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+
+  The full GNU General Public License is included in this distribution in
+  the file called "COPYING".
+
+  Author: Giuseppe Cavallaro <peppe.cavallaro@st.com>
+
+  Documentation available at:
+       http://www.stlinux.com
+  Support available at:
+       https://bugzilla.stlinux.com/
+*******************************************************************************/
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/interrupt.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/platform_device.h>
+#include <linux/ip.h>
+#include <linux/tcp.h>
+#include <linux/skbuff.h>
+#include <linux/ethtool.h>
+#include <linux/if_ether.h>
+#include <linux/crc32.h>
+#include <linux/mii.h>
+#include <linux/phy.h>
+#include <linux/if_vlan.h>
+#include <linux/dma-mapping.h>
+#include <linux/stm/soc.h>
+#include "stmmac.h"
+
+#define STMMAC_RESOURCE_NAME   "stmmaceth"
+#define PHY_RESOURCE_NAME      "stmmacphy"
+
+#undef STMMAC_DEBUG
+/*#define STMMAC_DEBUG*/
+#ifdef STMMAC_DEBUG
+#define DBG(nlevel, klevel, fmt, args...) \
+               ((void)(netif_msg_##nlevel(priv) && \
+               printk(KERN_##klevel fmt, ## args)))
+#else
+#define DBG(nlevel, klevel, fmt, args...) do { } while (0)
+#endif
+
+#undef STMMAC_RX_DEBUG
+/*#define STMMAC_RX_DEBUG*/
+#ifdef STMMAC_RX_DEBUG
+#define RX_DBG(fmt, args...)  printk(fmt, ## args)
+#else
+#define RX_DBG(fmt, args...)  do { } while (0)
+#endif
+
+#undef STMMAC_XMIT_DEBUG
+/*#define STMMAC_XMIT_DEBUG*/
+#ifdef STMMAC_TX_DEBUG
+#define TX_DBG(fmt, args...)  printk(fmt, ## args)
+#else
+#define TX_DBG(fmt, args...)  do { } while (0)
+#endif
+
+#define STMMAC_ALIGN(x)        L1_CACHE_ALIGN(x)
+#define JUMBO_LEN      9000
+
+/* Module parameters */
+#define TX_TIMEO 5000 /* default 5 seconds */
+static int watchdog = TX_TIMEO;
+module_param(watchdog, int, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(watchdog, "Transmit timeout in milliseconds");
+
+static int debug = -1;         /* -1: default, 0: no output, 16:  all */
+module_param(debug, int, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(debug, "Message Level (0: no output, 16: all)");
+
+static int phyaddr = -1;
+module_param(phyaddr, int, S_IRUGO);
+MODULE_PARM_DESC(phyaddr, "Physical device address");
+
+#define DMA_TX_SIZE 256
+static int dma_txsize = DMA_TX_SIZE;
+module_param(dma_txsize, int, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(dma_txsize, "Number of descriptors in the TX list");
+
+#define DMA_RX_SIZE 256
+static int dma_rxsize = DMA_RX_SIZE;
+module_param(dma_rxsize, int, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(dma_rxsize, "Number of descriptors in the RX list");
+
+static int flow_ctrl = FLOW_OFF;
+module_param(flow_ctrl, int, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(flow_ctrl, "Flow control ability [on/off]");
+
+static int pause = PAUSE_TIME;
+module_param(pause, int, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(pause, "Flow Control Pause Time");
+
+#define TC_DEFAULT 64
+static int tc = TC_DEFAULT;
+module_param(tc, int, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(tc, "DMA threshold control value");
+
+#define RX_NO_COALESCE 1       /* Always interrupt on completion */
+#define TX_NO_COALESCE -1      /* No moderation by default */
+
+/* Pay attention to tune this parameter; take care of both
+ * hardware capability and network stabitily/performance impact.
+ * Many tests showed that ~4ms latency seems to be good enough. */
+#ifdef CONFIG_STMMAC_TIMER
+#define DEFAULT_PERIODIC_RATE  256
+static int tmrate = DEFAULT_PERIODIC_RATE;
+module_param(tmrate, int, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(tmrate, "External timer freq. (default: 256Hz)");
+#endif
+
+#define DMA_BUFFER_SIZE        BUF_SIZE_2KiB
+static int buf_sz = DMA_BUFFER_SIZE;
+module_param(buf_sz, int, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(buf_sz, "DMA buffer size");
+
+/* In case of Giga ETH, we can enable/disable the COE for the
+ * transmit HW checksum computation.
+ * Note that, if tx csum is off in HW, SG will be still supported. */
+static int tx_coe = HW_CSUM;
+module_param(tx_coe, int, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(tx_coe, "GMAC COE type 2 [on/off]");
+
+static const u32 default_msg_level = (NETIF_MSG_DRV | NETIF_MSG_PROBE |
+                                     NETIF_MSG_LINK | NETIF_MSG_IFUP |
+                                     NETIF_MSG_IFDOWN | NETIF_MSG_TIMER);
+
+static irqreturn_t stmmac_interrupt(int irq, void *dev_id);
+static netdev_tx_t stmmac_xmit(struct sk_buff *skb, struct net_device *dev);
+
+/**
+ * stmmac_verify_args - verify the driver parameters.
+ * Description: it verifies if some wrong parameter is passed to the driver.
+ * Note that wrong parameters are replaced with the default values.
+ */
+static void stmmac_verify_args(void)
+{
+       if (unlikely(watchdog < 0))
+               watchdog = TX_TIMEO;
+       if (unlikely(dma_rxsize < 0))
+               dma_rxsize = DMA_RX_SIZE;
+       if (unlikely(dma_txsize < 0))
+               dma_txsize = DMA_TX_SIZE;
+       if (unlikely((buf_sz < DMA_BUFFER_SIZE) || (buf_sz > BUF_SIZE_16KiB)))
+               buf_sz = DMA_BUFFER_SIZE;
+       if (unlikely(flow_ctrl > 1))
+               flow_ctrl = FLOW_AUTO;
+       else if (likely(flow_ctrl < 0))
+               flow_ctrl = FLOW_OFF;
+       if (unlikely((pause < 0) || (pause > 0xffff)))
+               pause = PAUSE_TIME;
+
+       return;
+}
+
+#if defined(STMMAC_XMIT_DEBUG) || defined(STMMAC_RX_DEBUG)
+static void print_pkt(unsigned char *buf, int len)
+{
+       int j;
+       pr_info("len = %d byte, buf addr: 0x%p", len, buf);
+       for (j = 0; j < len; j++) {
+               if ((j % 16) == 0)
+                       pr_info("\n %03x:", j);
+               pr_info(" %02x", buf[j]);
+       }
+       pr_info("\n");
+       return;
+}
+#endif
+
+/* minimum number of free TX descriptors required to wake up TX process */
+#define STMMAC_TX_THRESH(x)    (x->dma_tx_size/4)
+
+static inline u32 stmmac_tx_avail(struct stmmac_priv *priv)
+{
+       return priv->dirty_tx + priv->dma_tx_size - priv->cur_tx - 1;
+}
+
+/**
+ * stmmac_adjust_link
+ * @dev: net device structure
+ * Description: it adjusts the link parameters.
+ */
+static void stmmac_adjust_link(struct net_device *dev)
+{
+       struct stmmac_priv *priv = netdev_priv(dev);
+       struct phy_device *phydev = priv->phydev;
+       unsigned long ioaddr = dev->base_addr;
+       unsigned long flags;
+       int new_state = 0;
+       unsigned int fc = priv->flow_ctrl, pause_time = priv->pause;
+
+       if (phydev == NULL)
+               return;
+
+       DBG(probe, DEBUG, "stmmac_adjust_link: called.  address %d link %d\n",
+           phydev->addr, phydev->link);
+
+       spin_lock_irqsave(&priv->lock, flags);
+       if (phydev->link) {
+               u32 ctrl = readl(ioaddr + MAC_CTRL_REG);
+
+               /* Now we make sure that we can be in full duplex mode.
+                * If not, we operate in half-duplex mode. */
+               if (phydev->duplex != priv->oldduplex) {
+                       new_state = 1;
+                       if (!(phydev->duplex))
+                               ctrl &= ~priv->mac_type->hw.link.duplex;
+                       else
+                               ctrl |= priv->mac_type->hw.link.duplex;
+                       priv->oldduplex = phydev->duplex;
+               }
+               /* Flow Control operation */
+               if (phydev->pause)
+                       priv->mac_type->ops->flow_ctrl(ioaddr, phydev->duplex,
+                                                      fc, pause_time);
+
+               if (phydev->speed != priv->speed) {
+                       new_state = 1;
+                       switch (phydev->speed) {
+                       case 1000:
+                               if (likely(priv->is_gmac))
+                                       ctrl &= ~priv->mac_type->hw.link.port;
+                               break;
+                       case 100:
+                       case 10:
+                               if (priv->is_gmac) {
+                                       ctrl |= priv->mac_type->hw.link.port;
+                                       if (phydev->speed == SPEED_100) {
+                                               ctrl |=
+                                                   priv->mac_type->hw.link.
+                                                   speed;
+                                       } else {
+                                               ctrl &=
+                                                   ~(priv->mac_type->hw.
+                                                     link.speed);
+                                       }
+                               } else {
+                                       ctrl &= ~priv->mac_type->hw.link.port;
+                               }
+                               priv->fix_mac_speed(priv->bsp_priv,
+                                                   phydev->speed);
+                               break;
+                       default:
+                               if (netif_msg_link(priv))
+                                       pr_warning("%s: Speed (%d) is not 10"
+                                      " or 100!\n", dev->name, phydev->speed);
+                               break;
+                       }
+
+                       priv->speed = phydev->speed;
+               }
+
+               writel(ctrl, ioaddr + MAC_CTRL_REG);
+
+               if (!priv->oldlink) {
+                       new_state = 1;
+                       priv->oldlink = 1;
+               }
+       } else if (priv->oldlink) {
+               new_state = 1;
+               priv->oldlink = 0;
+               priv->speed = 0;
+               priv->oldduplex = -1;
+       }
+
+       if (new_state && netif_msg_link(priv))
+               phy_print_status(phydev);
+
+       spin_unlock_irqrestore(&priv->lock, flags);
+
+       DBG(probe, DEBUG, "stmmac_adjust_link: exiting\n");
+}
+
+/**
+ * stmmac_init_phy - PHY initialization
+ * @dev: net device structure
+ * Description: it initializes the driver's PHY state, and attaches the PHY
+ * to the mac driver.
+ *  Return value:
+ *  0 on success
+ */
+static int stmmac_init_phy(struct net_device *dev)
+{
+       struct stmmac_priv *priv = netdev_priv(dev);
+       struct phy_device *phydev;
+       char phy_id[BUS_ID_SIZE];       /* PHY to connect */
+       char bus_id[BUS_ID_SIZE];
+
+       priv->oldlink = 0;
+       priv->speed = 0;
+       priv->oldduplex = -1;
+
+       if (priv->phy_addr == -1) {
+               /* We don't have a PHY, so do nothing */
+               return 0;
+       }
+
+       snprintf(bus_id, MII_BUS_ID_SIZE, "%x", priv->bus_id);
+       snprintf(phy_id, BUS_ID_SIZE, PHY_ID_FMT, bus_id, priv->phy_addr);
+       pr_debug("stmmac_init_phy:  trying to attach to %s\n", phy_id);
+
+       phydev = phy_connect(dev, phy_id, &stmmac_adjust_link, 0,
+                       priv->phy_interface);
+
+       if (IS_ERR(phydev)) {
+               pr_err("%s: Could not attach to PHY\n", dev->name);
+               return PTR_ERR(phydev);
+       }
+
+       /*
+        * Broken HW is sometimes missing the pull-up resistor on the
+        * MDIO line, which results in reads to non-existent devices returning
+        * 0 rather than 0xffff. Catch this here and treat 0 as a non-existent
+        * device as well.
+        * Note: phydev->phy_id is the result of reading the UID PHY registers.
+        */
+       if (phydev->phy_id == 0) {
+               phy_disconnect(phydev);
+               return -ENODEV;
+       }
+       pr_debug("stmmac_init_phy:  %s: attached to PHY (UID 0x%x)"
+              " Link = %d\n", dev->name, phydev->phy_id, phydev->link);
+
+       priv->phydev = phydev;
+
+       return 0;
+}
+
+static inline void stmmac_mac_enable_rx(unsigned long ioaddr)
+{
+       u32 value = readl(ioaddr + MAC_CTRL_REG);
+       value |= MAC_RNABLE_RX;
+       /* Set the RE (receive enable bit into the MAC CTRL register).  */
+       writel(value, ioaddr + MAC_CTRL_REG);
+}
+
+static inline void stmmac_mac_enable_tx(unsigned long ioaddr)
+{
+       u32 value = readl(ioaddr + MAC_CTRL_REG);
+       value |= MAC_ENABLE_TX;
+       /* Set the TE (transmit enable bit into the MAC CTRL register).  */
+       writel(value, ioaddr + MAC_CTRL_REG);
+}
+
+static inline void stmmac_mac_disable_rx(unsigned long ioaddr)
+{
+       u32 value = readl(ioaddr + MAC_CTRL_REG);
+       value &= ~MAC_RNABLE_RX;
+       writel(value, ioaddr + MAC_CTRL_REG);
+}
+
+static inline void stmmac_mac_disable_tx(unsigned long ioaddr)
+{
+       u32 value = readl(ioaddr + MAC_CTRL_REG);
+       value &= ~MAC_ENABLE_TX;
+       writel(value, ioaddr + MAC_CTRL_REG);
+}
+
+/**
+ * display_ring
+ * @p: pointer to the ring.
+ * @size: size of the ring.
+ * Description: display all the descriptors within the ring.
+ */
+static void display_ring(struct dma_desc *p, int size)
+{
+       struct tmp_s {
+               u64 a;
+               unsigned int b;
+               unsigned int c;
+       };
+       int i;
+       for (i = 0; i < size; i++) {
+               struct tmp_s *x = (struct tmp_s *)(p + i);
+               pr_info("\t%d [0x%x]: DES0=0x%x DES1=0x%x BUF1=0x%x BUF2=0x%x",
+                      i, (unsigned int)virt_to_phys(&p[i]),
+                      (unsigned int)(x->a), (unsigned int)((x->a) >> 32),
+                      x->b, x->c);
+               pr_info("\n");
+       }
+}
+
+/**
+ * init_dma_desc_rings - init the RX/TX descriptor rings
+ * @dev: net device structure
+ * Description:  this function initializes the DMA RX/TX descriptors
+ * and allocates the socket buffers.
+ */
+static void init_dma_desc_rings(struct net_device *dev)
+{
+       int i;
+       struct stmmac_priv *priv = netdev_priv(dev);
+       struct sk_buff *skb;
+       unsigned int txsize = priv->dma_tx_size;
+       unsigned int rxsize = priv->dma_rx_size;
+       unsigned int bfsize = priv->dma_buf_sz;
+       int buff2_needed = 0;
+       int dis_ic = 0;
+
+#ifdef CONFIG_STMMAC_TIMER
+       /* Using Timers disable interrupts on completion for the reception */
+       dis_ic = 1;
+#endif
+       /* Set the Buffer size according to the MTU;
+        * indeed, in case of jumbo we need to bump-up the buffer sizes.
+        */
+       if (unlikely(dev->mtu >= BUF_SIZE_8KiB))
+               bfsize = BUF_SIZE_16KiB;
+       else if (unlikely(dev->mtu >= BUF_SIZE_4KiB))
+               bfsize = BUF_SIZE_8KiB;
+       else if (unlikely(dev->mtu >= BUF_SIZE_2KiB))
+               bfsize = BUF_SIZE_4KiB;
+       else if (unlikely(dev->mtu >= DMA_BUFFER_SIZE))
+               bfsize = BUF_SIZE_2KiB;
+       else
+               bfsize = DMA_BUFFER_SIZE;
+
+       /* If the MTU exceeds 8k so use the second buffer in the chain */
+       if (bfsize >= BUF_SIZE_8KiB)
+               buff2_needed = 1;
+
+       DBG(probe, INFO, "stmmac: txsize %d, rxsize %d, bfsize %d\n",
+           txsize, rxsize, bfsize);
+
+       priv->rx_skbuff_dma = kmalloc(rxsize * sizeof(dma_addr_t), GFP_KERNEL);
+       priv->rx_skbuff =
+           kmalloc(sizeof(struct sk_buff *) * rxsize, GFP_KERNEL);
+       priv->dma_rx =
+           (struct dma_desc *)dma_alloc_coherent(priv->device,
+                                                 rxsize *
+                                                 sizeof(struct dma_desc),
+                                                 &priv->dma_rx_phy,
+                                                 GFP_KERNEL);
+       priv->tx_skbuff = kmalloc(sizeof(struct sk_buff *) * txsize,
+                                      GFP_KERNEL);
+       priv->dma_tx =
+           (struct dma_desc *)dma_alloc_coherent(priv->device,
+                                                 txsize *
+                                                 sizeof(struct dma_desc),
+                                                 &priv->dma_tx_phy,
+                                                 GFP_KERNEL);
+
+       if ((priv->dma_rx == NULL) || (priv->dma_tx == NULL)) {
+               pr_err("%s:ERROR allocating the DMA Tx/Rx desc\n", __func__);
+               return;
+       }
+
+       DBG(probe, INFO, "stmmac (%s) DMA desc rings: virt addr (Rx %p, "
+           "Tx %p)\n\tDMA phy addr (Rx 0x%08x, Tx 0x%08x)\n",
+           dev->name, priv->dma_rx, priv->dma_tx,
+           (unsigned int)priv->dma_rx_phy, (unsigned int)priv->dma_tx_phy);
+
+       /* RX INITIALIZATION */
+       DBG(probe, INFO, "stmmac: SKB addresses:\n"
+                        "skb\t\tskb data\tdma data\n");
+
+       for (i = 0; i < rxsize; i++) {
+               struct dma_desc *p = priv->dma_rx + i;
+
+               skb = netdev_alloc_skb_ip_align(dev, bfsize);
+               if (unlikely(skb == NULL)) {
+                       pr_err("%s: Rx init fails; skb is NULL\n", __func__);
+                       break;
+               }
+               priv->rx_skbuff[i] = skb;
+               priv->rx_skbuff_dma[i] = dma_map_single(priv->device, skb->data,
+                                               bfsize, DMA_FROM_DEVICE);
+
+               p->des2 = priv->rx_skbuff_dma[i];
+               if (unlikely(buff2_needed))
+                       p->des3 = p->des2 + BUF_SIZE_8KiB;
+               DBG(probe, INFO, "[%p]\t[%p]\t[%x]\n", priv->rx_skbuff[i],
+                       priv->rx_skbuff[i]->data, priv->rx_skbuff_dma[i]);
+       }
+       priv->cur_rx = 0;
+       priv->dirty_rx = (unsigned int)(i - rxsize);
+       priv->dma_buf_sz = bfsize;
+       buf_sz = bfsize;
+
+       /* TX INITIALIZATION */
+       for (i = 0; i < txsize; i++) {
+               priv->tx_skbuff[i] = NULL;
+               priv->dma_tx[i].des2 = 0;
+       }
+       priv->dirty_tx = 0;
+       priv->cur_tx = 0;
+
+       /* Clear the Rx/Tx descriptors */
+       priv->mac_type->ops->init_rx_desc(priv->dma_rx, rxsize, dis_ic);
+       priv->mac_type->ops->init_tx_desc(priv->dma_tx, txsize);
+
+       if (netif_msg_hw(priv)) {
+               pr_info("RX descriptor ring:\n");
+               display_ring(priv->dma_rx, rxsize);
+               pr_info("TX descriptor ring:\n");
+               display_ring(priv->dma_tx, txsize);
+       }
+       return;
+}
+
+static void dma_free_rx_skbufs(struct stmmac_priv *priv)
+{
+       int i;
+
+       for (i = 0; i < priv->dma_rx_size; i++) {
+               if (priv->rx_skbuff[i]) {
+                       dma_unmap_single(priv->device, priv->rx_skbuff_dma[i],
+                                        priv->dma_buf_sz, DMA_FROM_DEVICE);
+                       dev_kfree_skb_any(priv->rx_skbuff[i]);
+               }
+               priv->rx_skbuff[i] = NULL;
+       }
+       return;
+}
+
+static void dma_free_tx_skbufs(struct stmmac_priv *priv)
+{
+       int i;
+
+       for (i = 0; i < priv->dma_tx_size; i++) {
+               if (priv->tx_skbuff[i] != NULL) {
+                       struct dma_desc *p = priv->dma_tx + i;
+                       if (p->des2)
+                               dma_unmap_single(priv->device, p->des2,
+                                priv->mac_type->ops->get_tx_len(p),
+                                DMA_TO_DEVICE);
+                       dev_kfree_skb_any(priv->tx_skbuff[i]);
+                       priv->tx_skbuff[i] = NULL;
+               }
+       }
+       return;
+}
+
+static void free_dma_desc_resources(struct stmmac_priv *priv)
+{
+       /* Release the DMA TX/RX socket buffers */
+       dma_free_rx_skbufs(priv);
+       dma_free_tx_skbufs(priv);
+
+       /* Free the region of consistent memory previously allocated for
+        * the DMA */
+       dma_free_coherent(priv->device,
+                         priv->dma_tx_size * sizeof(struct dma_desc),
+                         priv->dma_tx, priv->dma_tx_phy);
+       dma_free_coherent(priv->device,
+                         priv->dma_rx_size * sizeof(struct dma_desc),
+                         priv->dma_rx, priv->dma_rx_phy);
+       kfree(priv->rx_skbuff_dma);
+       kfree(priv->rx_skbuff);
+       kfree(priv->tx_skbuff);
+
+       return;
+}
+
+/**
+ * stmmac_dma_start_tx
+ * @ioaddr: device I/O address
+ * Description:  this function starts the DMA tx process.
+ */
+static void stmmac_dma_start_tx(unsigned long ioaddr)
+{
+       u32 value = readl(ioaddr + DMA_CONTROL);
+       value |= DMA_CONTROL_ST;
+       writel(value, ioaddr + DMA_CONTROL);
+       return;
+}
+
+static void stmmac_dma_stop_tx(unsigned long ioaddr)
+{
+       u32 value = readl(ioaddr + DMA_CONTROL);
+       value &= ~DMA_CONTROL_ST;
+       writel(value, ioaddr + DMA_CONTROL);
+       return;
+}
+
+/**
+ * stmmac_dma_start_rx
+ * @ioaddr: device I/O address
+ * Description:  this function starts the DMA rx process.
+ */
+static void stmmac_dma_start_rx(unsigned long ioaddr)
+{
+       u32 value = readl(ioaddr + DMA_CONTROL);
+       value |= DMA_CONTROL_SR;
+       writel(value, ioaddr + DMA_CONTROL);
+
+       return;
+}
+
+static void stmmac_dma_stop_rx(unsigned long ioaddr)
+{
+       u32 value = readl(ioaddr + DMA_CONTROL);
+       value &= ~DMA_CONTROL_SR;
+       writel(value, ioaddr + DMA_CONTROL);
+
+       return;
+}
+
+/**
+ *  stmmac_dma_operation_mode - HW DMA operation mode
+ *  @priv : pointer to the private device structure.
+ *  Description: it sets the DMA operation mode: tx/rx DMA thresholds
+ *  or Store-And-Forward capability. It also verifies the COE for the
+ *  transmission in case of Giga ETH.
+ */
+static void stmmac_dma_operation_mode(struct stmmac_priv *priv)
+{
+       if (!priv->is_gmac) {
+               /* MAC 10/100 */
+               priv->mac_type->ops->dma_mode(priv->dev->base_addr, tc, 0);
+               priv->tx_coe = NO_HW_CSUM;
+       } else {
+               if ((priv->dev->mtu <= ETH_DATA_LEN) && (tx_coe)) {
+                       priv->mac_type->ops->dma_mode(priv->dev->base_addr,
+                                                     SF_DMA_MODE, SF_DMA_MODE);
+                       tc = SF_DMA_MODE;
+                       priv->tx_coe = HW_CSUM;
+               } else {
+                       /* Checksum computation is performed in software. */
+                       priv->mac_type->ops->dma_mode(priv->dev->base_addr, tc,
+                                                     SF_DMA_MODE);
+                       priv->tx_coe = NO_HW_CSUM;
+               }
+       }
+       tx_coe = priv->tx_coe;
+
+       return;
+}
+
+#ifdef STMMAC_DEBUG
+/**
+ * show_tx_process_state
+ * @status: tx descriptor status field
+ * Description: it shows the Transmit Process State for CSR5[22:20]
+ */
+static void show_tx_process_state(unsigned int status)
+{
+       unsigned int state;
+       state = (status & DMA_STATUS_TS_MASK) >> DMA_STATUS_TS_SHIFT;
+
+       switch (state) {
+       case 0:
+               pr_info("- TX (Stopped): Reset or Stop command\n");
+               break;
+       case 1:
+               pr_info("- TX (Running):Fetching the Tx desc\n");
+               break;
+       case 2:
+               pr_info("- TX (Running): Waiting for end of tx\n");
+               break;
+       case 3:
+               pr_info("- TX (Running): Reading the data "
+                      "and queuing the data into the Tx buf\n");
+               break;
+       case 6:
+               pr_info("- TX (Suspended): Tx Buff Underflow "
+                      "or an unavailable Transmit descriptor\n");
+               break;
+       case 7:
+               pr_info("- TX (Running): Closing Tx descriptor\n");
+               break;
+       default:
+               break;
+       }
+       return;
+}
+
+/**
+ * show_rx_process_state
+ * @status: rx descriptor status field
+ * Description: it shows the  Receive Process State for CSR5[19:17]
+ */
+static void show_rx_process_state(unsigned int status)
+{
+       unsigned int state;
+       state = (status & DMA_STATUS_RS_MASK) >> DMA_STATUS_RS_SHIFT;
+
+       switch (state) {
+       case 0:
+               pr_info("- RX (Stopped): Reset or Stop command\n");
+               break;
+       case 1:
+               pr_info("- RX (Running): Fetching the Rx desc\n");
+               break;
+       case 2:
+               pr_info("- RX (Running):Checking for end of pkt\n");
+               break;
+       case 3:
+               pr_info("- RX (Running): Waiting for Rx pkt\n");
+               break;
+       case 4:
+               pr_info("- RX (Suspended): Unavailable Rx buf\n");
+               break;
+       case 5:
+               pr_info("- RX (Running): Closing Rx descriptor\n");
+               break;
+       case 6:
+               pr_info("- RX(Running): Flushing the current frame"
+                      " from the Rx buf\n");
+               break;
+       case 7:
+               pr_info("- RX (Running): Queuing the Rx frame"
+                      " from the Rx buf into memory\n");
+               break;
+       default:
+               break;
+       }
+       return;
+}
+#endif
+
+/**
+ * stmmac_tx:
+ * @priv: private driver structure
+ * Description: it reclaims resources after transmission completes.
+ */
+static void stmmac_tx(struct stmmac_priv *priv)
+{
+       unsigned int txsize = priv->dma_tx_size;
+       unsigned long ioaddr = priv->dev->base_addr;
+
+       while (priv->dirty_tx != priv->cur_tx) {
+               int last;
+               unsigned int entry = priv->dirty_tx % txsize;
+               struct sk_buff *skb = priv->tx_skbuff[entry];
+               struct dma_desc *p = priv->dma_tx + entry;
+
+               /* Check if the descriptor is owned by the DMA. */
+               if (priv->mac_type->ops->get_tx_owner(p))
+                       break;
+
+               /* Verify tx error by looking at the last segment */
+               last = priv->mac_type->ops->get_tx_ls(p);
+               if (likely(last)) {
+                       int tx_error =
+                           priv->mac_type->ops->tx_status(&priv->dev->stats,
+                                                          &priv->xstats,
+                                                          p, ioaddr);
+                       if (likely(tx_error == 0)) {
+                               priv->dev->stats.tx_packets++;
+                               priv->xstats.tx_pkt_n++;
+                       } else
+                               priv->dev->stats.tx_errors++;
+               }
+               TX_DBG("%s: curr %d, dirty %d\n", __func__,
+                       priv->cur_tx, priv->dirty_tx);
+
+               if (likely(p->des2))
+                       dma_unmap_single(priv->device, p->des2,
+                                        priv->mac_type->ops->get_tx_len(p),
+                                        DMA_TO_DEVICE);
+               if (unlikely(p->des3))
+                       p->des3 = 0;
+
+               if (likely(skb != NULL)) {
+                       /*
+                        * If there's room in the queue (limit it to size)
+                        * we add this skb back into the pool,
+                        * if it's the right size.
+                        */
+                       if ((skb_queue_len(&priv->rx_recycle) <
+                               priv->dma_rx_size) &&
+                               skb_recycle_check(skb, priv->dma_buf_sz))
+                               __skb_queue_head(&priv->rx_recycle, skb);
+                       else
+                               dev_kfree_skb(skb);
+
+                       priv->tx_skbuff[entry] = NULL;
+               }
+
+               priv->mac_type->ops->release_tx_desc(p);
+
+               entry = (++priv->dirty_tx) % txsize;
+       }
+       if (unlikely(netif_queue_stopped(priv->dev) &&
+                    stmmac_tx_avail(priv) > STMMAC_TX_THRESH(priv))) {
+               netif_tx_lock(priv->dev);
+               if (netif_queue_stopped(priv->dev) &&
+                    stmmac_tx_avail(priv) > STMMAC_TX_THRESH(priv)) {
+                       TX_DBG("%s: restart transmit\n", __func__);
+                       netif_wake_queue(priv->dev);
+               }
+               netif_tx_unlock(priv->dev);
+       }
+       return;
+}
+
+static inline void stmmac_enable_irq(struct stmmac_priv *priv)
+{
+#ifndef CONFIG_STMMAC_TIMER
+       writel(DMA_INTR_DEFAULT_MASK, priv->dev->base_addr + DMA_INTR_ENA);
+#else
+       priv->tm->timer_start(tmrate);
+#endif
+}
+
+static inline void stmmac_disable_irq(struct stmmac_priv *priv)
+{
+#ifndef CONFIG_STMMAC_TIMER
+       writel(0, priv->dev->base_addr + DMA_INTR_ENA);
+#else
+       priv->tm->timer_stop();
+#endif
+}
+
+static int stmmac_has_work(struct stmmac_priv *priv)
+{
+       unsigned int has_work = 0;
+       int rxret, tx_work = 0;
+
+       rxret = priv->mac_type->ops->get_rx_owner(priv->dma_rx +
+               (priv->cur_rx % priv->dma_rx_size));
+
+       if (priv->dirty_tx != priv->cur_tx)
+               tx_work = 1;
+
+       if (likely(!rxret || tx_work))
+               has_work = 1;
+
+       return has_work;
+}
+
+static inline void _stmmac_schedule(struct stmmac_priv *priv)
+{
+       if (likely(stmmac_has_work(priv))) {
+               stmmac_disable_irq(priv);
+               napi_schedule(&priv->napi);
+       }
+}
+
+#ifdef CONFIG_STMMAC_TIMER
+void stmmac_schedule(struct net_device *dev)
+{
+       struct stmmac_priv *priv = netdev_priv(dev);
+
+       priv->xstats.sched_timer_n++;
+
+       _stmmac_schedule(priv);
+
+       return;
+}
+
+static void stmmac_no_timer_started(unsigned int x)
+{;
+};
+
+static void stmmac_no_timer_stopped(void)
+{;
+};
+#endif
+
+/**
+ * stmmac_tx_err:
+ * @priv: pointer to the private device structure
+ * Description: it cleans the descriptors and restarts the transmission
+ * in case of errors.
+ */
+static void stmmac_tx_err(struct stmmac_priv *priv)
+{
+       netif_stop_queue(priv->dev);
+
+       stmmac_dma_stop_tx(priv->dev->base_addr);
+       dma_free_tx_skbufs(priv);
+       priv->mac_type->ops->init_tx_desc(priv->dma_tx, priv->dma_tx_size);
+       priv->dirty_tx = 0;
+       priv->cur_tx = 0;
+       stmmac_dma_start_tx(priv->dev->base_addr);
+
+       priv->dev->stats.tx_errors++;
+       netif_wake_queue(priv->dev);
+
+       return;
+}
+
+/**
+ * stmmac_dma_interrupt - Interrupt handler for the driver
+ * @dev: net device structure
+ * Description: Interrupt handler for the driver (DMA).
+ */
+static void stmmac_dma_interrupt(struct net_device *dev)
+{
+       unsigned long ioaddr = dev->base_addr;
+       struct stmmac_priv *priv = netdev_priv(dev);
+       /* read the status register (CSR5) */
+       u32 intr_status = readl(ioaddr + DMA_STATUS);
+
+       DBG(intr, INFO, "%s: [CSR5: 0x%08x]\n", __func__, intr_status);
+
+#ifdef STMMAC_DEBUG
+       /* It displays the DMA transmit process state (CSR5 register) */
+       if (netif_msg_tx_done(priv))
+               show_tx_process_state(intr_status);
+       if (netif_msg_rx_status(priv))
+               show_rx_process_state(intr_status);
+#endif
+       /* ABNORMAL interrupts */
+       if (unlikely(intr_status & DMA_STATUS_AIS)) {
+               DBG(intr, INFO, "CSR5[15] DMA ABNORMAL IRQ: ");
+               if (unlikely(intr_status & DMA_STATUS_UNF)) {
+                       DBG(intr, INFO, "transmit underflow\n");
+                       if (unlikely(tc != SF_DMA_MODE)
+                           && (tc <= 256)) {
+                               /* Try to bump up the threshold */
+                               tc += 64;
+                               priv->mac_type->ops->dma_mode(ioaddr, tc,
+                                             SF_DMA_MODE);
+                               priv->xstats.threshold = tc;
+                       }
+                       stmmac_tx_err(priv);
+                       priv->xstats.tx_undeflow_irq++;
+               }
+               if (unlikely(intr_status & DMA_STATUS_TJT)) {
+                       DBG(intr, INFO, "transmit jabber\n");
+                       priv->xstats.tx_jabber_irq++;
+               }
+               if (unlikely(intr_status & DMA_STATUS_OVF)) {
+                       DBG(intr, INFO, "recv overflow\n");
+                       priv->xstats.rx_overflow_irq++;
+               }
+               if (unlikely(intr_status & DMA_STATUS_RU)) {
+                       DBG(intr, INFO, "receive buffer unavailable\n");
+                       priv->xstats.rx_buf_unav_irq++;
+               }
+               if (unlikely(intr_status & DMA_STATUS_RPS)) {
+                       DBG(intr, INFO, "receive process stopped\n");
+                       priv->xstats.rx_process_stopped_irq++;
+               }
+               if (unlikely(intr_status & DMA_STATUS_RWT)) {
+                       DBG(intr, INFO, "receive watchdog\n");
+                       priv->xstats.rx_watchdog_irq++;
+               }
+               if (unlikely(intr_status & DMA_STATUS_ETI)) {
+                       DBG(intr, INFO, "transmit early interrupt\n");
+                       priv->xstats.tx_early_irq++;
+               }
+               if (unlikely(intr_status & DMA_STATUS_TPS)) {
+                       DBG(intr, INFO, "transmit process stopped\n");
+                       priv->xstats.tx_process_stopped_irq++;
+                       stmmac_tx_err(priv);
+               }
+               if (unlikely(intr_status & DMA_STATUS_FBI)) {
+                       DBG(intr, INFO, "fatal bus error\n");
+                       priv->xstats.fatal_bus_error_irq++;
+                       stmmac_tx_err(priv);
+               }
+       }
+
+       /* TX/RX NORMAL interrupts */
+       if (intr_status & DMA_STATUS_NIS) {
+               priv->xstats.normal_irq_n++;
+               if (likely((intr_status & DMA_STATUS_RI) ||
+                        (intr_status & (DMA_STATUS_TI))))
+                               _stmmac_schedule(priv);
+       }
+
+       /* Optional hardware blocks, interrupts should be disabled */
+       if (unlikely(intr_status &
+                    (DMA_STATUS_GPI | DMA_STATUS_GMI | DMA_STATUS_GLI)))
+               pr_info("%s: unexpected status %08x\n", __func__, intr_status);
+
+       /* Clear the interrupt by writing a logic 1 to the CSR5[15-0] */
+       writel((intr_status & 0x1ffff), ioaddr + DMA_STATUS);
+
+       DBG(intr, INFO, "\n\n");
+
+       return;
+}
+
+/**
+ *  stmmac_open - open entry point of the driver
+ *  @dev : pointer to the device structure.
+ *  Description:
+ *  This function is the open entry point of the driver.
+ *  Return value:
+ *  0 on success and an appropriate (-)ve integer as defined in errno.h
+ *  file on failure.
+ */
+static int stmmac_open(struct net_device *dev)
+{
+       struct stmmac_priv *priv = netdev_priv(dev);
+       unsigned long ioaddr = dev->base_addr;
+       int ret;
+
+       /* Check that the MAC address is valid.  If its not, refuse
+        * to bring the device up. The user must specify an
+        * address using the following linux command:
+        *      ifconfig eth0 hw ether xx:xx:xx:xx:xx:xx  */
+       if (!is_valid_ether_addr(dev->dev_addr)) {
+               random_ether_addr(dev->dev_addr);
+               pr_warning("%s: generated random MAC address %pM\n", dev->name,
+                       dev->dev_addr);
+       }
+
+       stmmac_verify_args();
+
+       ret = stmmac_init_phy(dev);
+       if (unlikely(ret)) {
+               pr_err("%s: Cannot attach to PHY (error: %d)\n", __func__, ret);
+               return ret;
+       }
+
+       /* Request the IRQ lines */
+       ret = request_irq(dev->irq, &stmmac_interrupt,
+                         IRQF_SHARED, dev->name, dev);
+       if (unlikely(ret < 0)) {
+               pr_err("%s: ERROR: allocating the IRQ %d (error: %d)\n",
+                      __func__, dev->irq, ret);
+               return ret;
+       }
+
+#ifdef CONFIG_STMMAC_TIMER
+       priv->tm = kmalloc(sizeof(struct stmmac_timer *), GFP_KERNEL);
+       if (unlikely(priv->tm == NULL)) {
+               pr_err("%s: ERROR: timer memory alloc failed \n", __func__);
+               return -ENOMEM;
+       }
+       priv->tm->freq = tmrate;
+
+       /* Test if the HW timer can be actually used.
+        * In case of failure continue with no timer. */
+       if (unlikely((stmmac_open_ext_timer(dev, priv->tm)) < 0)) {
+               pr_warning("stmmaceth: cannot attach the HW timer\n");
+               tmrate = 0;
+               priv->tm->freq = 0;
+               priv->tm->timer_start = stmmac_no_timer_started;
+               priv->tm->timer_stop = stmmac_no_timer_stopped;
+       }
+#endif
+
+       /* Create and initialize the TX/RX descriptors chains. */
+       priv->dma_tx_size = STMMAC_ALIGN(dma_txsize);
+       priv->dma_rx_size = STMMAC_ALIGN(dma_rxsize);
+       priv->dma_buf_sz = STMMAC_ALIGN(buf_sz);
+       init_dma_desc_rings(dev);
+
+       /* DMA initialization and SW reset */
+       if (unlikely(priv->mac_type->ops->dma_init(ioaddr,
+               priv->pbl, priv->dma_tx_phy, priv->dma_rx_phy) < 0)) {
+
+               pr_err("%s: DMA initialization failed\n", __func__);
+               return -1;
+       }
+
+       /* Copy the MAC addr into the HW  */
+       priv->mac_type->ops->set_umac_addr(ioaddr, dev->dev_addr, 0);
+       /* Initialize the MAC Core */
+       priv->mac_type->ops->core_init(ioaddr);
+
+       priv->shutdown = 0;
+
+       /* Initialise the MMC (if present) to disable all interrupts. */
+       writel(0xffffffff, ioaddr + MMC_HIGH_INTR_MASK);
+       writel(0xffffffff, ioaddr + MMC_LOW_INTR_MASK);
+
+       /* Enable the MAC Rx/Tx */
+       stmmac_mac_enable_rx(ioaddr);
+       stmmac_mac_enable_tx(ioaddr);
+
+       /* Set the HW DMA mode and the COE */
+       stmmac_dma_operation_mode(priv);
+
+       /* Extra statistics */
+       memset(&priv->xstats, 0, sizeof(struct stmmac_extra_stats));
+       priv->xstats.threshold = tc;
+
+       /* Start the ball rolling... */
+       DBG(probe, DEBUG, "%s: DMA RX/TX processes started...\n", dev->name);
+       stmmac_dma_start_tx(ioaddr);
+       stmmac_dma_start_rx(ioaddr);
+
+#ifdef CONFIG_STMMAC_TIMER
+       priv->tm->timer_start(tmrate);
+#endif
+       /* Dump DMA/MAC registers */
+       if (netif_msg_hw(priv)) {
+               priv->mac_type->ops->dump_mac_regs(ioaddr);
+               priv->mac_type->ops->dump_dma_regs(ioaddr);
+       }
+
+       if (priv->phydev)
+               phy_start(priv->phydev);
+
+       napi_enable(&priv->napi);
+       skb_queue_head_init(&priv->rx_recycle);
+       netif_start_queue(dev);
+       return 0;
+}
+
+/**
+ *  stmmac_release - close entry point of the driver
+ *  @dev : device pointer.
+ *  Description:
+ *  This is the stop entry point of the driver.
+ */
+static int stmmac_release(struct net_device *dev)
+{
+       struct stmmac_priv *priv = netdev_priv(dev);
+
+       /* Stop and disconnect the PHY */
+       if (priv->phydev) {
+               phy_stop(priv->phydev);
+               phy_disconnect(priv->phydev);
+               priv->phydev = NULL;
+       }
+
+       netif_stop_queue(dev);
+
+#ifdef CONFIG_STMMAC_TIMER
+       /* Stop and release the timer */
+       stmmac_close_ext_timer();
+       if (priv->tm != NULL)
+               kfree(priv->tm);
+#endif
+       napi_disable(&priv->napi);
+       skb_queue_purge(&priv->rx_recycle);
+
+       /* Free the IRQ lines */
+       free_irq(dev->irq, dev);
+
+       /* Stop TX/RX DMA and clear the descriptors */
+       stmmac_dma_stop_tx(dev->base_addr);
+       stmmac_dma_stop_rx(dev->base_addr);
+
+       /* Release and free the Rx/Tx resources */
+       free_dma_desc_resources(priv);
+
+       /* Disable the MAC core */
+       stmmac_mac_disable_tx(dev->base_addr);
+       stmmac_mac_disable_rx(dev->base_addr);
+
+       netif_carrier_off(dev);
+
+       return 0;
+}
+
+/*
+ * To perform emulated hardware segmentation on skb.
+ */
+static int stmmac_sw_tso(struct stmmac_priv *priv, struct sk_buff *skb)
+{
+       struct sk_buff *segs, *curr_skb;
+       int gso_segs = skb_shinfo(skb)->gso_segs;
+
+       /* Estimate the number of fragments in the worst case */
+       if (unlikely(stmmac_tx_avail(priv) < gso_segs)) {
+               netif_stop_queue(priv->dev);
+               TX_DBG(KERN_ERR "%s: TSO BUG! Tx Ring full when queue awake\n",
+                      __func__);
+               if (stmmac_tx_avail(priv) < gso_segs)
+                       return NETDEV_TX_BUSY;
+
+               netif_wake_queue(priv->dev);
+       }
+       TX_DBG("\tstmmac_sw_tso: segmenting: skb %p (len %d)\n",
+              skb, skb->len);
+
+       segs = skb_gso_segment(skb, priv->dev->features & ~NETIF_F_TSO);
+       if (unlikely(IS_ERR(segs)))
+               goto sw_tso_end;
+
+       do {
+               curr_skb = segs;
+               segs = segs->next;
+               TX_DBG("\t\tcurrent skb->len: %d, *curr %p,"
+                      "*next %p\n", curr_skb->len, curr_skb, segs);
+               curr_skb->next = NULL;
+               stmmac_xmit(curr_skb, priv->dev);
+       } while (segs);
+
+sw_tso_end:
+       dev_kfree_skb(skb);
+
+       return NETDEV_TX_OK;
+}
+
+static unsigned int stmmac_handle_jumbo_frames(struct sk_buff *skb,
+                                              struct net_device *dev,
+                                              int csum_insertion)
+{
+       struct stmmac_priv *priv = netdev_priv(dev);
+       unsigned int nopaged_len = skb_headlen(skb);
+       unsigned int txsize = priv->dma_tx_size;
+       unsigned int entry = priv->cur_tx % txsize;
+       struct dma_desc *desc = priv->dma_tx + entry;
+
+       if (nopaged_len > BUF_SIZE_8KiB) {
+
+               int buf2_size = nopaged_len - BUF_SIZE_8KiB;
+
+               desc->des2 = dma_map_single(priv->device, skb->data,
+                                           BUF_SIZE_8KiB, DMA_TO_DEVICE);
+               desc->des3 = desc->des2 + BUF_SIZE_4KiB;
+               priv->mac_type->ops->prepare_tx_desc(desc, 1, BUF_SIZE_8KiB,
+                                                    csum_insertion);
+
+               entry = (++priv->cur_tx) % txsize;
+               desc = priv->dma_tx + entry;
+
+               desc->des2 = dma_map_single(priv->device,
+                                       skb->data + BUF_SIZE_8KiB,
+                                       buf2_size, DMA_TO_DEVICE);
+               desc->des3 = desc->des2 + BUF_SIZE_4KiB;
+               priv->mac_type->ops->prepare_tx_desc(desc, 0,
+                                                    buf2_size, csum_insertion);
+               priv->mac_type->ops->set_tx_owner(desc);
+               priv->tx_skbuff[entry] = NULL;
+       } else {
+               desc->des2 = dma_map_single(priv->device, skb->data,
+                                       nopaged_len, DMA_TO_DEVICE);
+               desc->des3 = desc->des2 + BUF_SIZE_4KiB;
+               priv->mac_type->ops->prepare_tx_desc(desc, 1, nopaged_len,
+                                                    csum_insertion);
+       }
+       return entry;
+}
+
+/**
+ *  stmmac_xmit:
+ *  @skb : the socket buffer
+ *  @dev : device pointer
+ *  Description : Tx entry point of the driver.
+ */
+static netdev_tx_t stmmac_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+       struct stmmac_priv *priv = netdev_priv(dev);
+       unsigned int txsize = priv->dma_tx_size;
+       unsigned int entry;
+       int i, csum_insertion = 0;
+       int nfrags = skb_shinfo(skb)->nr_frags;
+       struct dma_desc *desc, *first;
+
+       if (unlikely(stmmac_tx_avail(priv) < nfrags + 1)) {
+               if (!netif_queue_stopped(dev)) {
+                       netif_stop_queue(dev);
+                       /* This is a hard error, log it. */
+                       pr_err("%s: BUG! Tx Ring full when queue awake\n",
+                               __func__);
+               }
+               return NETDEV_TX_BUSY;
+       }
+
+       entry = priv->cur_tx % txsize;
+
+#ifdef STMMAC_XMIT_DEBUG
+       if ((skb->len > ETH_FRAME_LEN) || nfrags)
+               pr_info("stmmac xmit:\n"
+                      "\tskb addr %p - len: %d - nopaged_len: %d\n"
+                      "\tn_frags: %d - ip_summed: %d - %s gso\n",
+                      skb, skb->len, skb_headlen(skb), nfrags, skb->ip_summed,
+                      !skb_is_gso(skb) ? "isn't" : "is");
+#endif
+
+       if (unlikely(skb_is_gso(skb)))
+               return stmmac_sw_tso(priv, skb);
+
+       if (likely((skb->ip_summed == CHECKSUM_PARTIAL))) {
+               if (likely(priv->tx_coe == NO_HW_CSUM))
+                       skb_checksum_help(skb);
+               else
+                       csum_insertion = 1;
+       }
+
+       desc = priv->dma_tx + entry;
+       first = desc;
+
+#ifdef STMMAC_XMIT_DEBUG
+       if ((nfrags > 0) || (skb->len > ETH_FRAME_LEN))
+               pr_debug("stmmac xmit: skb len: %d, nopaged_len: %d,\n"
+                      "\t\tn_frags: %d, ip_summed: %d\n",
+                      skb->len, skb_headlen(skb), nfrags, skb->ip_summed);
+#endif
+       priv->tx_skbuff[entry] = skb;
+       if (unlikely(skb->len >= BUF_SIZE_4KiB)) {
+               entry = stmmac_handle_jumbo_frames(skb, dev, csum_insertion);
+               desc = priv->dma_tx + entry;
+       } else {
+               unsigned int nopaged_len = skb_headlen(skb);
+               desc->des2 = dma_map_single(priv->device, skb->data,
+                                       nopaged_len, DMA_TO_DEVICE);
+               priv->mac_type->ops->prepare_tx_desc(desc, 1, nopaged_len,
+                                                    csum_insertion);
+       }
+
+       for (i = 0; i < nfrags; i++) {
+               skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
+               int len = frag->size;
+
+               entry = (++priv->cur_tx) % txsize;
+               desc = priv->dma_tx + entry;
+
+               TX_DBG("\t[entry %d] segment len: %d\n", entry, len);
+               desc->des2 = dma_map_page(priv->device, frag->page,
+                                         frag->page_offset,
+                                         len, DMA_TO_DEVICE);
+               priv->tx_skbuff[entry] = NULL;
+               priv->mac_type->ops->prepare_tx_desc(desc, 0, len,
+                                                    csum_insertion);
+               priv->mac_type->ops->set_tx_owner(desc);
+       }
+
+       /* Interrupt on completition only for the latest segment */
+       priv->mac_type->ops->close_tx_desc(desc);
+#ifdef CONFIG_STMMAC_TIMER
+       /* Clean IC while using timers */
+       priv->mac_type->ops->clear_tx_ic(desc);
+#endif
+       /* To avoid raise condition */
+       priv->mac_type->ops->set_tx_owner(first);
+
+       priv->cur_tx++;
+
+#ifdef STMMAC_XMIT_DEBUG
+       if (netif_msg_pktdata(priv)) {
+               pr_info("stmmac xmit: current=%d, dirty=%d, entry=%d, "
+                      "first=%p, nfrags=%d\n",
+                      (priv->cur_tx % txsize), (priv->dirty_tx % txsize),
+                      entry, first, nfrags);
+               display_ring(priv->dma_tx, txsize);
+               pr_info(">>> frame to be transmitted: ");
+               print_pkt(skb->data, skb->len);
+       }
+#endif
+       if (unlikely(stmmac_tx_avail(priv) <= (MAX_SKB_FRAGS + 1))) {
+               TX_DBG("%s: stop transmitted packets\n", __func__);
+               netif_stop_queue(dev);
+       }
+
+       dev->stats.tx_bytes += skb->len;
+
+       /* CSR1 enables the transmit DMA to check for new descriptor */
+       writel(1, dev->base_addr + DMA_XMT_POLL_DEMAND);
+
+       return NETDEV_TX_OK;
+}
+
+static inline void stmmac_rx_refill(struct stmmac_priv *priv)
+{
+       unsigned int rxsize = priv->dma_rx_size;
+       int bfsize = priv->dma_buf_sz;
+       struct dma_desc *p = priv->dma_rx;
+
+       for (; priv->cur_rx - priv->dirty_rx > 0; priv->dirty_rx++) {
+               unsigned int entry = priv->dirty_rx % rxsize;
+               if (likely(priv->rx_skbuff[entry] == NULL)) {
+                       struct sk_buff *skb;
+
+                       skb = __skb_dequeue(&priv->rx_recycle);
+                       if (skb == NULL)
+                               skb = netdev_alloc_skb_ip_align(priv->dev,
+                                                               bfsize);
+
+                       if (unlikely(skb == NULL))
+                               break;
+
+                       priv->rx_skbuff[entry] = skb;
+                       priv->rx_skbuff_dma[entry] =
+                           dma_map_single(priv->device, skb->data, bfsize,
+                                          DMA_FROM_DEVICE);
+
+                       (p + entry)->des2 = priv->rx_skbuff_dma[entry];
+                       if (unlikely(priv->is_gmac)) {
+                               if (bfsize >= BUF_SIZE_8KiB)
+                                       (p + entry)->des3 =
+                                           (p + entry)->des2 + BUF_SIZE_8KiB;
+                       }
+                       RX_DBG(KERN_INFO "\trefill entry #%d\n", entry);
+               }
+               priv->mac_type->ops->set_rx_owner(p + entry);
+       }
+       return;
+}
+
+static int stmmac_rx(struct stmmac_priv *priv, int limit)
+{
+       unsigned int rxsize = priv->dma_rx_size;
+       unsigned int entry = priv->cur_rx % rxsize;
+       unsigned int next_entry;
+       unsigned int count = 0;
+       struct dma_desc *p = priv->dma_rx + entry;
+       struct dma_desc *p_next;
+
+#ifdef STMMAC_RX_DEBUG
+       if (netif_msg_hw(priv)) {
+               pr_debug(">>> stmmac_rx: descriptor ring:\n");
+               display_ring(priv->dma_rx, rxsize);
+       }
+#endif
+       count = 0;
+       while (!priv->mac_type->ops->get_rx_owner(p)) {
+               int status;
+
+               if (count >= limit)
+                       break;
+
+               count++;
+
+               next_entry = (++priv->cur_rx) % rxsize;
+               p_next = priv->dma_rx + next_entry;
+               prefetch(p_next);
+
+               /* read the status of the incoming frame */
+               status = (priv->mac_type->ops->rx_status(&priv->dev->stats,
+                                                        &priv->xstats, p));
+               if (unlikely(status == discard_frame))
+                       priv->dev->stats.rx_errors++;
+               else {
+                       struct sk_buff *skb;
+                       /* Length should omit the CRC */
+                       int frame_len =
+                           priv->mac_type->ops->get_rx_frame_len(p) - 4;
+
+#ifdef STMMAC_RX_DEBUG
+                       if (frame_len > ETH_FRAME_LEN)
+                               pr_debug("\tRX frame size %d, COE status: %d\n",
+                                       frame_len, status);
+
+                       if (netif_msg_hw(priv))
+                               pr_debug("\tdesc: %p [entry %d] buff=0x%x\n",
+                                       p, entry, p->des2);
+#endif
+                       skb = priv->rx_skbuff[entry];
+                       if (unlikely(!skb)) {
+                               pr_err("%s: Inconsistent Rx descriptor chain\n",
+                                       priv->dev->name);
+                               priv->dev->stats.rx_dropped++;
+                               break;
+                       }
+                       prefetch(skb->data - NET_IP_ALIGN);
+                       priv->rx_skbuff[entry] = NULL;
+
+                       skb_put(skb, frame_len);
+                       dma_unmap_single(priv->device,
+                                        priv->rx_skbuff_dma[entry],
+                                        priv->dma_buf_sz, DMA_FROM_DEVICE);
+#ifdef STMMAC_RX_DEBUG
+                       if (netif_msg_pktdata(priv)) {
+                               pr_info(" frame received (%dbytes)", frame_len);
+                               print_pkt(skb->data, frame_len);
+                       }
+#endif
+                       skb->protocol = eth_type_trans(skb, priv->dev);
+
+                       if (unlikely(status == csum_none)) {
+                               /* always for the old mac 10/100 */
+                               skb->ip_summed = CHECKSUM_NONE;
+                               netif_receive_skb(skb);
+                       } else {
+                               skb->ip_summed = CHECKSUM_UNNECESSARY;
+                               napi_gro_receive(&priv->napi, skb);
+                       }
+
+                       priv->dev->stats.rx_packets++;
+                       priv->dev->stats.rx_bytes += frame_len;
+                       priv->dev->last_rx = jiffies;
+               }
+               entry = next_entry;
+               p = p_next;     /* use prefetched values */
+       }
+
+       stmmac_rx_refill(priv);
+
+       priv->xstats.rx_pkt_n += count;
+
+       return count;
+}
+
+/**
+ *  stmmac_poll - stmmac poll method (NAPI)
+ *  @napi : pointer to the napi structure.
+ *  @budget : maximum number of packets that the current CPU can receive from
+ *           all interfaces.
+ *  Description :
+ *   This function implements the the reception process.
+ *   Also it runs the TX completion thread
+ */
+static int stmmac_poll(struct napi_struct *napi, int budget)
+{
+       struct stmmac_priv *priv = container_of(napi, struct stmmac_priv, napi);
+       int work_done = 0;
+
+       priv->xstats.poll_n++;
+       stmmac_tx(priv);
+       work_done = stmmac_rx(priv, budget);
+
+       if (work_done < budget) {
+               napi_complete(napi);
+               stmmac_enable_irq(priv);
+       }
+       return work_done;
+}
+
+/**
+ *  stmmac_tx_timeout
+ *  @dev : Pointer to net device structure
+ *  Description: this function is called when a packet transmission fails to
+ *   complete within a reasonable tmrate. The driver will mark the error in the
+ *   netdev structure and arrange for the device to be reset to a sane state
+ *   in order to transmit a new packet.
+ */
+static void stmmac_tx_timeout(struct net_device *dev)
+{
+       struct stmmac_priv *priv = netdev_priv(dev);
+
+       /* Clear Tx resources and restart transmitting again */
+       stmmac_tx_err(priv);
+       return;
+}
+
+/* Configuration changes (passed on by ifconfig) */
+static int stmmac_config(struct net_device *dev, struct ifmap *map)
+{
+       if (dev->flags & IFF_UP)        /* can't act on a running interface */
+               return -EBUSY;
+
+       /* Don't allow changing the I/O address */
+       if (map->base_addr != dev->base_addr) {
+               pr_warning("%s: can't change I/O address\n", dev->name);
+               return -EOPNOTSUPP;
+       }
+
+       /* Don't allow changing the IRQ */
+       if (map->irq != dev->irq) {
+               pr_warning("%s: can't change IRQ number %d\n",
+                      dev->name, dev->irq);
+               return -EOPNOTSUPP;
+       }
+
+       /* ignore other fields */
+       return 0;
+}
+
+/**
+ *  stmmac_multicast_list - entry point for multicast addressing
+ *  @dev : pointer to the device structure
+ *  Description:
+ *  This function is a driver entry point which gets called by the kernel
+ *  whenever multicast addresses must be enabled/disabled.
+ *  Return value:
+ *  void.
+ */
+static void stmmac_multicast_list(struct net_device *dev)
+{
+       struct stmmac_priv *priv = netdev_priv(dev);
+
+       spin_lock(&priv->lock);
+       priv->mac_type->ops->set_filter(dev);
+       spin_unlock(&priv->lock);
+       return;
+}
+
+/**
+ *  stmmac_change_mtu - entry point to change MTU size for the device.
+ *  @dev : device pointer.
+ *  @new_mtu : the new MTU size for the device.
+ *  Description: the Maximum Transfer Unit (MTU) is used by the network layer
+ *  to drive packet transmission. Ethernet has an MTU of 1500 octets
+ *  (ETH_DATA_LEN). This value can be changed with ifconfig.
+ *  Return value:
+ *  0 on success and an appropriate (-)ve integer as defined in errno.h
+ *  file on failure.
+ */
+static int stmmac_change_mtu(struct net_device *dev, int new_mtu)
+{
+       struct stmmac_priv *priv = netdev_priv(dev);
+       int max_mtu;
+
+       if (netif_running(dev)) {
+               pr_err("%s: must be stopped to change its MTU\n", dev->name);
+               return -EBUSY;
+       }
+
+       if (priv->is_gmac)
+               max_mtu = JUMBO_LEN;
+       else
+               max_mtu = ETH_DATA_LEN;
+
+       if ((new_mtu < 46) || (new_mtu > max_mtu)) {
+               pr_err("%s: invalid MTU, max MTU is: %d\n", dev->name, max_mtu);
+               return -EINVAL;
+       }
+
+       dev->mtu = new_mtu;
+
+       return 0;
+}
+
+static irqreturn_t stmmac_interrupt(int irq, void *dev_id)
+{
+       struct net_device *dev = (struct net_device *)dev_id;
+       struct stmmac_priv *priv = netdev_priv(dev);
+
+       if (unlikely(!dev)) {
+               pr_err("%s: invalid dev pointer\n", __func__);
+               return IRQ_NONE;
+       }
+
+       if (priv->is_gmac) {
+               unsigned long ioaddr = dev->base_addr;
+               /* To handle GMAC own interrupts */
+               priv->mac_type->ops->host_irq_status(ioaddr);
+       }
+       stmmac_dma_interrupt(dev);
+
+       return IRQ_HANDLED;
+}
+
+#ifdef CONFIG_NET_POLL_CONTROLLER
+/* Polling receive - used by NETCONSOLE and other diagnostic tools
+ * to allow network I/O with interrupts disabled. */
+static void stmmac_poll_controller(struct net_device *dev)
+{
+       disable_irq(dev->irq);
+       stmmac_interrupt(dev->irq, dev);
+       enable_irq(dev->irq);
+}
+#endif
+
+/**
+ *  stmmac_ioctl - Entry point for the Ioctl
+ *  @dev: Device pointer.
+ *  @rq: An IOCTL specefic structure, that can contain a pointer to
+ *  a proprietary structure used to pass information to the driver.
+ *  @cmd: IOCTL command
+ *  Description:
+ *  Currently there are no special functionality supported in IOCTL, just the
+ *  phy_mii_ioctl(...) can be invoked.
+ */
+static int stmmac_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
+{
+       struct stmmac_priv *priv = netdev_priv(dev);
+       int ret = -EOPNOTSUPP;
+
+       if (!netif_running(dev))
+               return -EINVAL;
+
+       switch (cmd) {
+       case SIOCGMIIPHY:
+       case SIOCGMIIREG:
+       case SIOCSMIIREG:
+               if (!priv->phydev)
+                       return -EINVAL;
+
+               spin_lock(&priv->lock);
+               ret = phy_mii_ioctl(priv->phydev, if_mii(rq), cmd);
+               spin_unlock(&priv->lock);
+       default:
+               break;
+       }
+       return ret;
+}
+
+#ifdef STMMAC_VLAN_TAG_USED
+static void stmmac_vlan_rx_register(struct net_device *dev,
+                                   struct vlan_group *grp)
+{
+       struct stmmac_priv *priv = netdev_priv(dev);
+
+       DBG(probe, INFO, "%s: Setting vlgrp to %p\n", dev->name, grp);
+
+       spin_lock(&priv->lock);
+       priv->vlgrp = grp;
+       spin_unlock(&priv->lock);
+
+       return;
+}
+#endif
+
+static const struct net_device_ops stmmac_netdev_ops = {
+       .ndo_open = stmmac_open,
+       .ndo_start_xmit = stmmac_xmit,
+       .ndo_stop = stmmac_release,
+       .ndo_change_mtu = stmmac_change_mtu,
+       .ndo_set_multicast_list = stmmac_multicast_list,
+       .ndo_tx_timeout = stmmac_tx_timeout,
+       .ndo_do_ioctl = stmmac_ioctl,
+       .ndo_set_config = stmmac_config,
+#ifdef STMMAC_VLAN_TAG_USED
+       .ndo_vlan_rx_register = stmmac_vlan_rx_register,
+#endif
+#ifdef CONFIG_NET_POLL_CONTROLLER
+       .ndo_poll_controller = stmmac_poll_controller,
+#endif
+       .ndo_set_mac_address = eth_mac_addr,
+};
+
+/**
+ * stmmac_probe - Initialization of the adapter .
+ * @dev : device pointer
+ * Description: The function initializes the network device structure for
+ * the STMMAC driver. It also calls the low level routines
+ * in order to init the HW (i.e. the DMA engine)
+ */
+static int stmmac_probe(struct net_device *dev)
+{
+       int ret = 0;
+       struct stmmac_priv *priv = netdev_priv(dev);
+
+       ether_setup(dev);
+
+       dev->netdev_ops = &stmmac_netdev_ops;
+       stmmac_set_ethtool_ops(dev);
+
+       dev->features |= (NETIF_F_SG | NETIF_F_HW_CSUM | NETIF_F_HIGHDMA);
+       dev->watchdog_timeo = msecs_to_jiffies(watchdog);
+#ifdef STMMAC_VLAN_TAG_USED
+       /* Both mac100 and gmac support receive VLAN tag detection */
+       dev->features |= NETIF_F_HW_VLAN_RX;
+#endif
+       priv->msg_enable = netif_msg_init(debug, default_msg_level);
+
+       if (priv->is_gmac)
+               priv->rx_csum = 1;
+
+       if (flow_ctrl)
+               priv->flow_ctrl = FLOW_AUTO;    /* RX/TX pause on */
+
+       priv->pause = pause;
+       netif_napi_add(dev, &priv->napi, stmmac_poll, 64);
+
+       /* Get the MAC address */
+       priv->mac_type->ops->get_umac_addr(dev->base_addr, dev->dev_addr, 0);
+
+       if (!is_valid_ether_addr(dev->dev_addr))
+               pr_warning("\tno valid MAC address;"
+                       "please, use ifconfig or nwhwconfig!\n");
+
+       ret = register_netdev(dev);
+       if (ret) {
+               pr_err("%s: ERROR %i registering the device\n",
+                      __func__, ret);
+               return -ENODEV;
+       }
+
+       DBG(probe, DEBUG, "%s: Scatter/Gather: %s - HW checksums: %s\n",
+           dev->name, (dev->features & NETIF_F_SG) ? "on" : "off",
+           (dev->features & NETIF_F_HW_CSUM) ? "on" : "off");
+
+       spin_lock_init(&priv->lock);
+
+       return ret;
+}
+
+/**
+ * stmmac_mac_device_setup
+ * @dev : device pointer
+ * Description: select and initialise the mac device (mac100 or Gmac).
+ */
+static int stmmac_mac_device_setup(struct net_device *dev)
+{
+       struct stmmac_priv *priv = netdev_priv(dev);
+       unsigned long ioaddr = dev->base_addr;
+
+       struct mac_device_info *device;
+
+       if (priv->is_gmac)
+               device = gmac_setup(ioaddr);
+       else
+               device = mac100_setup(ioaddr);
+
+       if (!device)
+               return -ENOMEM;
+
+       priv->mac_type = device;
+
+       priv->wolenabled = priv->mac_type->hw.pmt;      /* PMT supported */
+       if (priv->wolenabled == PMT_SUPPORTED)
+               priv->wolopts = WAKE_MAGIC;             /* Magic Frame */
+
+       return 0;
+}
+
+static int stmmacphy_dvr_probe(struct platform_device *pdev)
+{
+       struct plat_stmmacphy_data *plat_dat;
+       plat_dat = (struct plat_stmmacphy_data *)((pdev->dev).platform_data);
+
+       pr_debug("stmmacphy_dvr_probe: added phy for bus %d\n",
+              plat_dat->bus_id);
+
+       return 0;
+}
+
+static int stmmacphy_dvr_remove(struct platform_device *pdev)
+{
+       return 0;
+}
+
+static struct platform_driver stmmacphy_driver = {
+       .driver = {
+                  .name = PHY_RESOURCE_NAME,
+                  },
+       .probe = stmmacphy_dvr_probe,
+       .remove = stmmacphy_dvr_remove,
+};
+
+/**
+ * stmmac_associate_phy
+ * @dev: pointer to device structure
+ * @data: points to the private structure.
+ * Description: Scans through all the PHYs we have registered and checks if
+ * any are associated with our MAC.  If so, then just fill in
+ * the blanks in our local context structure
+ */
+static int stmmac_associate_phy(struct device *dev, void *data)
+{
+       struct stmmac_priv *priv = (struct stmmac_priv *)data;
+       struct plat_stmmacphy_data *plat_dat;
+
+       plat_dat = (struct plat_stmmacphy_data *)(dev->platform_data);
+
+       DBG(probe, DEBUG, "%s: checking phy for bus %d\n", __func__,
+               plat_dat->bus_id);
+
+       /* Check that this phy is for the MAC being initialised */
+       if (priv->bus_id != plat_dat->bus_id)
+               return 0;
+
+       /* OK, this PHY is connected to the MAC.
+          Go ahead and get the parameters */
+       DBG(probe, DEBUG, "%s: OK. Found PHY config\n", __func__);
+       priv->phy_irq =
+           platform_get_irq_byname(to_platform_device(dev), "phyirq");
+       DBG(probe, DEBUG, "%s: PHY irq on bus %d is %d\n", __func__,
+           plat_dat->bus_id, priv->phy_irq);
+
+       /* Override with kernel parameters if supplied XXX CRS XXX
+        * this needs to have multiple instances */
+       if ((phyaddr >= 0) && (phyaddr <= 31))
+               plat_dat->phy_addr = phyaddr;
+
+       priv->phy_addr = plat_dat->phy_addr;
+       priv->phy_mask = plat_dat->phy_mask;
+       priv->phy_interface = plat_dat->interface;
+       priv->phy_reset = plat_dat->phy_reset;
+
+       DBG(probe, DEBUG, "%s: exiting\n", __func__);
+       return 1;       /* forces exit of driver_for_each_device() */
+}
+
+/**
+ * stmmac_dvr_probe
+ * @pdev: platform device pointer
+ * Description: the driver is initialized through platform_device.
+ */
+static int stmmac_dvr_probe(struct platform_device *pdev)
+{
+       int ret = 0;
+       struct resource *res;
+       unsigned int *addr = NULL;
+       struct net_device *ndev = NULL;
+       struct stmmac_priv *priv;
+       struct plat_stmmacenet_data *plat_dat;
+
+       pr_info("STMMAC driver:\n\tplatform registration... ");
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (!res) {
+               ret = -ENODEV;
+               goto out;
+       }
+       pr_info("done!\n");
+
+       if (!request_mem_region(res->start, (res->end - res->start),
+                               pdev->name)) {
+               pr_err("%s: ERROR: memory allocation failed"
+                      "cannot get the I/O addr 0x%x\n",
+                      __func__, (unsigned int)res->start);
+               ret = -EBUSY;
+               goto out;
+       }
+
+       addr = ioremap(res->start, (res->end - res->start));
+       if (!addr) {
+               pr_err("%s: ERROR: memory mapping failed \n", __func__);
+               ret = -ENOMEM;
+               goto out;
+       }
+
+       ndev = alloc_etherdev(sizeof(struct stmmac_priv));
+       if (!ndev) {
+               pr_err("%s: ERROR: allocating the device\n", __func__);
+               ret = -ENOMEM;
+               goto out;
+       }
+
+       SET_NETDEV_DEV(ndev, &pdev->dev);
+
+       /* Get the MAC information */
+       ndev->irq = platform_get_irq_byname(pdev, "macirq");
+       if (ndev->irq == -ENXIO) {
+               pr_err("%s: ERROR: MAC IRQ configuration "
+                      "information not found\n", __func__);
+               ret = -ENODEV;
+               goto out;
+       }
+
+       priv = netdev_priv(ndev);
+       priv->device = &(pdev->dev);
+       priv->dev = ndev;
+       plat_dat = (struct plat_stmmacenet_data *)((pdev->dev).platform_data);
+       priv->bus_id = plat_dat->bus_id;
+       priv->pbl = plat_dat->pbl;      /* TLI */
+       priv->is_gmac = plat_dat->has_gmac;     /* GMAC is on board */
+
+       platform_set_drvdata(pdev, ndev);
+
+       /* Set the I/O base addr */
+       ndev->base_addr = (unsigned long)addr;
+
+       /* MAC HW revice detection */
+       ret = stmmac_mac_device_setup(ndev);
+       if (ret < 0)
+               goto out;
+
+       /* Network Device Registration */
+       ret = stmmac_probe(ndev);
+       if (ret < 0)
+               goto out;
+
+       /* associate a PHY - it is provided by another platform bus */
+       if (!driver_for_each_device
+           (&(stmmacphy_driver.driver), NULL, (void *)priv,
+            stmmac_associate_phy)) {
+               pr_err("No PHY device is associated with this MAC!\n");
+               ret = -ENODEV;
+               goto out;
+       }
+
+       priv->fix_mac_speed = plat_dat->fix_mac_speed;
+       priv->bsp_priv = plat_dat->bsp_priv;
+
+       pr_info("\t%s - (dev. name: %s - id: %d, IRQ #%d\n"
+              "\tIO base addr: 0x%08x)\n", ndev->name, pdev->name,
+              pdev->id, ndev->irq, (unsigned int)addr);
+
+       /* MDIO bus Registration */
+       pr_debug("\tMDIO bus (id: %d)...", priv->bus_id);
+       ret = stmmac_mdio_register(ndev);
+       if (ret < 0)
+               goto out;
+       pr_debug("registered!\n");
+
+out:
+       if (ret < 0) {
+               platform_set_drvdata(pdev, NULL);
+               release_mem_region(res->start, (res->end - res->start));
+               if (addr != NULL)
+                       iounmap(addr);
+       }
+
+       return ret;
+}
+
+/**
+ * stmmac_dvr_remove
+ * @pdev: platform device pointer
+ * Description: this function resets the TX/RX processes, disables the MAC RX/TX
+ * changes the link status, releases the DMA descriptor rings,
+ * unregisters the MDIO bus and unmaps the allocated memory.
+ */
+static int stmmac_dvr_remove(struct platform_device *pdev)
+{
+       struct net_device *ndev = platform_get_drvdata(pdev);
+       struct resource *res;
+
+       pr_info("%s:\n\tremoving driver", __func__);
+
+       stmmac_dma_stop_rx(ndev->base_addr);
+       stmmac_dma_stop_tx(ndev->base_addr);
+
+       stmmac_mac_disable_rx(ndev->base_addr);
+       stmmac_mac_disable_tx(ndev->base_addr);
+
+       netif_carrier_off(ndev);
+
+       stmmac_mdio_unregister(ndev);
+
+       platform_set_drvdata(pdev, NULL);
+       unregister_netdev(ndev);
+
+       iounmap((void *)ndev->base_addr);
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       release_mem_region(res->start, (res->end - res->start));
+
+       free_netdev(ndev);
+
+       return 0;
+}
+
+#ifdef CONFIG_PM
+static int stmmac_suspend(struct platform_device *pdev, pm_message_t state)
+{
+       struct net_device *dev = platform_get_drvdata(pdev);
+       struct stmmac_priv *priv = netdev_priv(dev);
+       int dis_ic = 0;
+
+       if (!dev || !netif_running(dev))
+               return 0;
+
+       spin_lock(&priv->lock);
+
+       if (state.event == PM_EVENT_SUSPEND) {
+               netif_device_detach(dev);
+               netif_stop_queue(dev);
+               if (priv->phydev)
+                       phy_stop(priv->phydev);
+
+#ifdef CONFIG_STMMAC_TIMER
+               priv->tm->timer_stop();
+               dis_ic = 1;
+#endif
+               napi_disable(&priv->napi);
+
+               /* Stop TX/RX DMA */
+               stmmac_dma_stop_tx(dev->base_addr);
+               stmmac_dma_stop_rx(dev->base_addr);
+               /* Clear the Rx/Tx descriptors */
+               priv->mac_type->ops->init_rx_desc(priv->dma_rx,
+                                                 priv->dma_rx_size, dis_ic);
+               priv->mac_type->ops->init_tx_desc(priv->dma_tx,
+                                                 priv->dma_tx_size);
+
+               stmmac_mac_disable_tx(dev->base_addr);
+
+               if (device_may_wakeup(&(pdev->dev))) {
+                       /* Enable Power down mode by programming the PMT regs */
+                       if (priv->wolenabled == PMT_SUPPORTED)
+                               priv->mac_type->ops->pmt(dev->base_addr,
+                                                        priv->wolopts);
+               } else {
+                       stmmac_mac_disable_rx(dev->base_addr);
+               }
+       } else {
+               priv->shutdown = 1;
+               /* Although this can appear slightly redundant it actually
+                * makes fast the standby operation and guarantees the driver
+                * working if hibernation is on media. */
+               stmmac_release(dev);
+       }
+
+       spin_unlock(&priv->lock);
+       return 0;
+}
+
+static int stmmac_resume(struct platform_device *pdev)
+{
+       struct net_device *dev = platform_get_drvdata(pdev);
+       struct stmmac_priv *priv = netdev_priv(dev);
+       unsigned long ioaddr = dev->base_addr;
+
+       if (!netif_running(dev))
+               return 0;
+
+       spin_lock(&priv->lock);
+
+       if (priv->shutdown) {
+               /* Re-open the interface and re-init the MAC/DMA
+                  and the rings. */
+               stmmac_open(dev);
+               goto out_resume;
+       }
+
+       /* Power Down bit, into the PM register, is cleared
+        * automatically as soon as a magic packet or a Wake-up frame
+        * is received. Anyway, it's better to manually clear
+        * this bit because it can generate problems while resuming
+        * from another devices (e.g. serial console). */
+       if (device_may_wakeup(&(pdev->dev)))
+               if (priv->wolenabled == PMT_SUPPORTED)
+                       priv->mac_type->ops->pmt(dev->base_addr, 0);
+
+       netif_device_attach(dev);
+
+       /* Enable the MAC and DMA */
+       stmmac_mac_enable_rx(ioaddr);
+       stmmac_mac_enable_tx(ioaddr);
+       stmmac_dma_start_tx(ioaddr);
+       stmmac_dma_start_rx(ioaddr);
+
+#ifdef CONFIG_STMMAC_TIMER
+       priv->tm->timer_start(tmrate);
+#endif
+       napi_enable(&priv->napi);
+
+       if (priv->phydev)
+               phy_start(priv->phydev);
+
+       netif_start_queue(dev);
+
+out_resume:
+       spin_unlock(&priv->lock);
+       return 0;
+}
+#endif
+
+static struct platform_driver stmmac_driver = {
+       .driver = {
+                  .name = STMMAC_RESOURCE_NAME,
+                  },
+       .probe = stmmac_dvr_probe,
+       .remove = stmmac_dvr_remove,
+#ifdef CONFIG_PM
+       .suspend = stmmac_suspend,
+       .resume = stmmac_resume,
+#endif
+
+};
+
+/**
+ * stmmac_init_module - Entry point for the driver
+ * Description: This function is the entry point for the driver.
+ */
+static int __init stmmac_init_module(void)
+{
+       int ret;
+
+       if (platform_driver_register(&stmmacphy_driver)) {
+               pr_err("No PHY devices registered!\n");
+               return -ENODEV;
+       }
+
+       ret = platform_driver_register(&stmmac_driver);
+       return ret;
+}
+
+/**
+ * stmmac_cleanup_module - Cleanup routine for the driver
+ * Description: This function is the cleanup routine for the driver.
+ */
+static void __exit stmmac_cleanup_module(void)
+{
+       platform_driver_unregister(&stmmacphy_driver);
+       platform_driver_unregister(&stmmac_driver);
+}
+
+#ifndef MODULE
+static int __init stmmac_cmdline_opt(char *str)
+{
+       char *opt;
+
+       if (!str || !*str)
+               return -EINVAL;
+       while ((opt = strsep(&str, ",")) != NULL) {
+               if (!strncmp(opt, "debug:", 6))
+                       strict_strtoul(opt + 6, 0, (unsigned long *)&debug);
+               else if (!strncmp(opt, "phyaddr:", 8))
+                       strict_strtoul(opt + 8, 0, (unsigned long *)&phyaddr);
+               else if (!strncmp(opt, "dma_txsize:", 11))
+                       strict_strtoul(opt + 11, 0,
+                                      (unsigned long *)&dma_txsize);
+               else if (!strncmp(opt, "dma_rxsize:", 11))
+                       strict_strtoul(opt + 11, 0,
+                                      (unsigned long *)&dma_rxsize);
+               else if (!strncmp(opt, "buf_sz:", 7))
+                       strict_strtoul(opt + 7, 0, (unsigned long *)&buf_sz);
+               else if (!strncmp(opt, "tc:", 3))
+                       strict_strtoul(opt + 3, 0, (unsigned long *)&tc);
+               else if (!strncmp(opt, "tx_coe:", 7))
+                       strict_strtoul(opt + 7, 0, (unsigned long *)&tx_coe);
+               else if (!strncmp(opt, "watchdog:", 9))
+                       strict_strtoul(opt + 9, 0, (unsigned long *)&watchdog);
+               else if (!strncmp(opt, "flow_ctrl:", 10))
+                       strict_strtoul(opt + 10, 0,
+                                      (unsigned long *)&flow_ctrl);
+               else if (!strncmp(opt, "pause:", 6))
+                       strict_strtoul(opt + 6, 0, (unsigned long *)&pause);
+#ifdef CONFIG_STMMAC_TIMER
+               else if (!strncmp(opt, "tmrate:", 7))
+                       strict_strtoul(opt + 7, 0, (unsigned long *)&tmrate);
+#endif
+       }
+       return 0;
+}
+
+__setup("stmmaceth=", stmmac_cmdline_opt);
+#endif
+
+module_init(stmmac_init_module);
+module_exit(stmmac_cleanup_module);
+
+MODULE_DESCRIPTION("STMMAC 10/100/1000 Ethernet driver");
+MODULE_AUTHOR("Giuseppe Cavallaro <peppe.cavallaro@st.com>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/net/stmmac/stmmac_mdio.c b/drivers/net/stmmac/stmmac_mdio.c
new file mode 100644 (file)
index 0000000..8498552
--- /dev/null
@@ -0,0 +1,217 @@
+/*******************************************************************************
+  STMMAC Ethernet Driver -- MDIO bus implementation
+  Provides Bus interface for MII registers
+
+  Copyright (C) 2007-2009  STMicroelectronics Ltd
+
+  This program is free software; you can redistribute it and/or modify it
+  under the terms and conditions of the GNU General Public License,
+  version 2, as published by the Free Software Foundation.
+
+  This program is distributed in the hope it will be useful, but WITHOUT
+  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+  more details.
+
+  You should have received a copy of the GNU General Public License along with
+  this program; if not, write to the Free Software Foundation, Inc.,
+  51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+
+  The full GNU General Public License is included in this distribution in
+  the file called "COPYING".
+
+  Author: Carl Shaw <carl.shaw@st.com>
+  Maintainer: Giuseppe Cavallaro <peppe.cavallaro@st.com>
+*******************************************************************************/
+
+#include <linux/netdevice.h>
+#include <linux/mii.h>
+#include <linux/phy.h>
+
+#include "stmmac.h"
+
+#define MII_BUSY 0x00000001
+#define MII_WRITE 0x00000002
+
+/**
+ * stmmac_mdio_read
+ * @bus: points to the mii_bus structure
+ * @phyaddr: MII addr reg bits 15-11
+ * @phyreg: MII addr reg bits 10-6
+ * Description: it reads data from the MII register from within the phy device.
+ * For the 7111 GMAC, we must set the bit 0 in the MII address register while
+ * accessing the PHY registers.
+ * Fortunately, it seems this has no drawback for the 7109 MAC.
+ */
+static int stmmac_mdio_read(struct mii_bus *bus, int phyaddr, int phyreg)
+{
+       struct net_device *ndev = bus->priv;
+       struct stmmac_priv *priv = netdev_priv(ndev);
+       unsigned long ioaddr = ndev->base_addr;
+       unsigned int mii_address = priv->mac_type->hw.mii.addr;
+       unsigned int mii_data = priv->mac_type->hw.mii.data;
+
+       int data;
+       u16 regValue = (((phyaddr << 11) & (0x0000F800)) |
+                       ((phyreg << 6) & (0x000007C0)));
+       regValue |= MII_BUSY;   /* in case of GMAC */
+
+       do {} while (((readl(ioaddr + mii_address)) & MII_BUSY) == 1);
+       writel(regValue, ioaddr + mii_address);
+       do {} while (((readl(ioaddr + mii_address)) & MII_BUSY) == 1);
+
+       /* Read the data from the MII data register */
+       data = (int)readl(ioaddr + mii_data);
+
+       return data;
+}
+
+/**
+ * stmmac_mdio_write
+ * @bus: points to the mii_bus structure
+ * @phyaddr: MII addr reg bits 15-11
+ * @phyreg: MII addr reg bits 10-6
+ * @phydata: phy data
+ * Description: it writes the data into the MII register from within the device.
+ */
+static int stmmac_mdio_write(struct mii_bus *bus, int phyaddr, int phyreg,
+                            u16 phydata)
+{
+       struct net_device *ndev = bus->priv;
+       struct stmmac_priv *priv = netdev_priv(ndev);
+       unsigned long ioaddr = ndev->base_addr;
+       unsigned int mii_address = priv->mac_type->hw.mii.addr;
+       unsigned int mii_data = priv->mac_type->hw.mii.data;
+
+       u16 value =
+           (((phyaddr << 11) & (0x0000F800)) | ((phyreg << 6) & (0x000007C0)))
+           | MII_WRITE;
+
+       value |= MII_BUSY;
+
+       /* Wait until any existing MII operation is complete */
+       do {} while (((readl(ioaddr + mii_address)) & MII_BUSY) == 1);
+
+       /* Set the MII address register to write */
+       writel(phydata, ioaddr + mii_data);
+       writel(value, ioaddr + mii_address);
+
+       /* Wait until any existing MII operation is complete */
+       do {} while (((readl(ioaddr + mii_address)) & MII_BUSY) == 1);
+
+       return 0;
+}
+
+/**
+ * stmmac_mdio_reset
+ * @bus: points to the mii_bus structure
+ * Description: reset the MII bus
+ */
+static int stmmac_mdio_reset(struct mii_bus *bus)
+{
+       struct net_device *ndev = bus->priv;
+       struct stmmac_priv *priv = netdev_priv(ndev);
+       unsigned long ioaddr = ndev->base_addr;
+       unsigned int mii_address = priv->mac_type->hw.mii.addr;
+
+       if (priv->phy_reset) {
+               pr_debug("stmmac_mdio_reset: calling phy_reset\n");
+               priv->phy_reset(priv->bsp_priv);
+       }
+
+       /* This is a workaround for problems with the STE101P PHY.
+        * It doesn't complete its reset until at least one clock cycle
+        * on MDC, so perform a dummy mdio read.
+        */
+       writel(0, ioaddr + mii_address);
+
+       return 0;
+}
+
+/**
+ * stmmac_mdio_register
+ * @ndev: net device structure
+ * Description: it registers the MII bus
+ */
+int stmmac_mdio_register(struct net_device *ndev)
+{
+       int err = 0;
+       struct mii_bus *new_bus;
+       int *irqlist;
+       struct stmmac_priv *priv = netdev_priv(ndev);
+       int addr, found;
+
+       new_bus = mdiobus_alloc();
+       if (new_bus == NULL)
+               return -ENOMEM;
+
+       irqlist = kzalloc(sizeof(int) * PHY_MAX_ADDR, GFP_KERNEL);
+       if (irqlist == NULL) {
+               err = -ENOMEM;
+               goto irqlist_alloc_fail;
+       }
+
+       /* Assign IRQ to phy at address phy_addr */
+       if (priv->phy_addr != -1)
+               irqlist[priv->phy_addr] = priv->phy_irq;
+
+       new_bus->name = "STMMAC MII Bus";
+       new_bus->read = &stmmac_mdio_read;
+       new_bus->write = &stmmac_mdio_write;
+       new_bus->reset = &stmmac_mdio_reset;
+       snprintf(new_bus->id, MII_BUS_ID_SIZE, "%x", priv->bus_id);
+       new_bus->priv = ndev;
+       new_bus->irq = irqlist;
+       new_bus->phy_mask = priv->phy_mask;
+       new_bus->parent = priv->device;
+       err = mdiobus_register(new_bus);
+       if (err != 0) {
+               pr_err("%s: Cannot register as MDIO bus\n", new_bus->name);
+               goto bus_register_fail;
+       }
+
+       priv->mii = new_bus;
+
+       found = 0;
+       for (addr = 0; addr < 32; addr++) {
+               struct phy_device *phydev = new_bus->phy_map[addr];
+               if (phydev) {
+                       if (priv->phy_addr == -1) {
+                               priv->phy_addr = addr;
+                               phydev->irq = priv->phy_irq;
+                               irqlist[addr] = priv->phy_irq;
+                       }
+                       pr_info("%s: PHY ID %08x at %d IRQ %d (%s)%s\n",
+                              ndev->name, phydev->phy_id, addr,
+                              phydev->irq, dev_name(&phydev->dev),
+                              (addr == priv->phy_addr) ? " active" : "");
+                       found = 1;
+               }
+       }
+
+       if (!found)
+               pr_warning("%s: No PHY found\n", ndev->name);
+
+       return 0;
+bus_register_fail:
+       kfree(irqlist);
+irqlist_alloc_fail:
+       kfree(new_bus);
+       return err;
+}
+
+/**
+ * stmmac_mdio_unregister
+ * @ndev: net device structure
+ * Description: it unregisters the MII bus
+ */
+int stmmac_mdio_unregister(struct net_device *ndev)
+{
+       struct stmmac_priv *priv = netdev_priv(ndev);
+
+       mdiobus_unregister(priv->mii);
+       priv->mii->priv = NULL;
+       kfree(priv->mii);
+
+       return 0;
+}
diff --git a/drivers/net/stmmac/stmmac_timer.c b/drivers/net/stmmac/stmmac_timer.c
new file mode 100644 (file)
index 0000000..b838c65
--- /dev/null
@@ -0,0 +1,140 @@
+/*******************************************************************************
+  STMMAC external timer support.
+
+  Copyright (C) 2007-2009  STMicroelectronics Ltd
+
+  This program is free software; you can redistribute it and/or modify it
+  under the terms and conditions of the GNU General Public License,
+  version 2, as published by the Free Software Foundation.
+
+  This program is distributed in the hope it will be useful, but WITHOUT
+  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+  more details.
+
+  You should have received a copy of the GNU General Public License along with
+  this program; if not, write to the Free Software Foundation, Inc.,
+  51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+
+  The full GNU General Public License is included in this distribution in
+  the file called "COPYING".
+
+  Author: Giuseppe Cavallaro <peppe.cavallaro@st.com>
+*******************************************************************************/
+
+#include <linux/kernel.h>
+#include <linux/etherdevice.h>
+#include "stmmac_timer.h"
+
+static void stmmac_timer_handler(void *data)
+{
+       struct net_device *dev = (struct net_device *)data;
+
+       stmmac_schedule(dev);
+
+       return;
+}
+
+#define STMMAC_TIMER_MSG(timer, freq) \
+printk(KERN_INFO "stmmac_timer: %s Timer ON (freq %dHz)\n", timer, freq);
+
+#if defined(CONFIG_STMMAC_RTC_TIMER)
+#include <linux/rtc.h>
+static struct rtc_device *stmmac_rtc;
+static rtc_task_t stmmac_task;
+
+static void stmmac_rtc_start(unsigned int new_freq)
+{
+       rtc_irq_set_freq(stmmac_rtc, &stmmac_task, new_freq);
+       rtc_irq_set_state(stmmac_rtc, &stmmac_task, 1);
+       return;
+}
+
+static void stmmac_rtc_stop(void)
+{
+       rtc_irq_set_state(stmmac_rtc, &stmmac_task, 0);
+       return;
+}
+
+int stmmac_open_ext_timer(struct net_device *dev, struct stmmac_timer *tm)
+{
+       stmmac_task.private_data = dev;
+       stmmac_task.func = stmmac_timer_handler;
+
+       stmmac_rtc = rtc_class_open(CONFIG_RTC_HCTOSYS_DEVICE);
+       if (stmmac_rtc == NULL) {
+               pr_error("open rtc device failed\n");
+               return -ENODEV;
+       }
+
+       rtc_irq_register(stmmac_rtc, &stmmac_task);
+
+       /* Periodic mode is not supported */
+       if ((rtc_irq_set_freq(stmmac_rtc, &stmmac_task, tm->freq) < 0)) {
+               pr_error("set periodic failed\n");
+               rtc_irq_unregister(stmmac_rtc, &stmmac_task);
+               rtc_class_close(stmmac_rtc);
+               return -1;
+       }
+
+       STMMAC_TIMER_MSG(CONFIG_RTC_HCTOSYS_DEVICE, tm->freq);
+
+       tm->timer_start = stmmac_rtc_start;
+       tm->timer_stop = stmmac_rtc_stop;
+
+       return 0;
+}
+
+int stmmac_close_ext_timer(void)
+{
+       rtc_irq_set_state(stmmac_rtc, &stmmac_task, 0);
+       rtc_irq_unregister(stmmac_rtc, &stmmac_task);
+       rtc_class_close(stmmac_rtc);
+       return 0;
+}
+
+#elif defined(CONFIG_STMMAC_TMU_TIMER)
+#include <linux/clk.h>
+#define TMU_CHANNEL "tmu2_clk"
+static struct clk *timer_clock;
+
+static void stmmac_tmu_start(unsigned int new_freq)
+{
+       clk_set_rate(timer_clock, new_freq);
+       clk_enable(timer_clock);
+       return;
+}
+
+static void stmmac_tmu_stop(void)
+{
+       clk_disable(timer_clock);
+       return;
+}
+
+int stmmac_open_ext_timer(struct net_device *dev, struct stmmac_timer *tm)
+{
+       timer_clock = clk_get(NULL, TMU_CHANNEL);
+
+       if (timer_clock == NULL)
+               return -1;
+
+       if (tmu2_register_user(stmmac_timer_handler, (void *)dev) < 0) {
+               timer_clock = NULL;
+               return -1;
+       }
+
+       STMMAC_TIMER_MSG("TMU2", tm->freq);
+       tm->timer_start = stmmac_tmu_start;
+       tm->timer_stop = stmmac_tmu_stop;
+
+       return 0;
+}
+
+int stmmac_close_ext_timer(void)
+{
+       clk_disable(timer_clock);
+       tmu2_unregister_user();
+       clk_put(timer_clock);
+       return 0;
+}
+#endif
diff --git a/drivers/net/stmmac/stmmac_timer.h b/drivers/net/stmmac/stmmac_timer.h
new file mode 100644 (file)
index 0000000..f795cae
--- /dev/null
@@ -0,0 +1,41 @@
+/*******************************************************************************
+  STMMAC external timer Header File.
+
+  Copyright (C) 2007-2009  STMicroelectronics Ltd
+
+  This program is free software; you can redistribute it and/or modify it
+  under the terms and conditions of the GNU General Public License,
+  version 2, as published by the Free Software Foundation.
+
+  This program is distributed in the hope it will be useful, but WITHOUT
+  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+  more details.
+
+  You should have received a copy of the GNU General Public License along with
+  this program; if not, write to the Free Software Foundation, Inc.,
+  51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+
+  The full GNU General Public License is included in this distribution in
+  the file called "COPYING".
+
+  Author: Giuseppe Cavallaro <peppe.cavallaro@st.com>
+*******************************************************************************/
+
+struct stmmac_timer {
+       void (*timer_start) (unsigned int new_freq);
+       void (*timer_stop) (void);
+       unsigned int freq;
+};
+
+/* Open the HW timer device and return 0 in case of success */
+int stmmac_open_ext_timer(struct net_device *dev, struct stmmac_timer *tm);
+/* Stop the timer and release it */
+int stmmac_close_ext_timer(void);
+/* Function used for scheduling task within the stmmac */
+void stmmac_schedule(struct net_device *dev);
+
+#if defined(CONFIG_STMMAC_TMU_TIMER)
+extern int tmu2_register_user(void *fnt, void *data);
+extern void tmu2_unregister_user(void);
+#endif
index 305ec3d..7019a0d 100644 (file)
@@ -38,6 +38,7 @@
 #include <linux/interrupt.h>
 #include <linux/ioport.h>
 #include <linux/in.h>
+#include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/string.h>
 #include <linux/delay.h>
index f09bc5d..ba5d3fe 100644 (file)
@@ -902,11 +902,12 @@ static int tg3_mdio_read(struct mii_bus *bp, int mii_id, int reg)
        struct tg3 *tp = bp->priv;
        u32 val;
 
-       if (tp->tg3_flags3 & TG3_FLG3_MDIOBUS_PAUSED)
-               return -EAGAIN;
+       spin_lock_bh(&tp->lock);
 
        if (tg3_readphy(tp, reg, &val))
-               return -EIO;
+               val = -EIO;
+
+       spin_unlock_bh(&tp->lock);
 
        return val;
 }
@@ -914,14 +915,16 @@ static int tg3_mdio_read(struct mii_bus *bp, int mii_id, int reg)
 static int tg3_mdio_write(struct mii_bus *bp, int mii_id, int reg, u16 val)
 {
        struct tg3 *tp = bp->priv;
+       u32 ret = 0;
 
-       if (tp->tg3_flags3 & TG3_FLG3_MDIOBUS_PAUSED)
-               return -EAGAIN;
+       spin_lock_bh(&tp->lock);
 
        if (tg3_writephy(tp, reg, val))
-               return -EIO;
+               ret = -EIO;
 
-       return 0;
+       spin_unlock_bh(&tp->lock);
+
+       return ret;
 }
 
 static int tg3_mdio_reset(struct mii_bus *bp)
@@ -1011,12 +1014,6 @@ static void tg3_mdio_config_5785(struct tg3 *tp)
 
 static void tg3_mdio_start(struct tg3 *tp)
 {
-       if (tp->tg3_flags3 & TG3_FLG3_MDIOBUS_INITED) {
-               mutex_lock(&tp->mdio_bus->mdio_lock);
-               tp->tg3_flags3 &= ~TG3_FLG3_MDIOBUS_PAUSED;
-               mutex_unlock(&tp->mdio_bus->mdio_lock);
-       }
-
        tp->mi_mode &= ~MAC_MI_MODE_AUTO_POLL;
        tw32_f(MAC_MI_MODE, tp->mi_mode);
        udelay(80);
@@ -1041,15 +1038,6 @@ static void tg3_mdio_start(struct tg3 *tp)
                tg3_mdio_config_5785(tp);
 }
 
-static void tg3_mdio_stop(struct tg3 *tp)
-{
-       if (tp->tg3_flags3 & TG3_FLG3_MDIOBUS_INITED) {
-               mutex_lock(&tp->mdio_bus->mdio_lock);
-               tp->tg3_flags3 |= TG3_FLG3_MDIOBUS_PAUSED;
-               mutex_unlock(&tp->mdio_bus->mdio_lock);
-       }
-}
-
 static int tg3_mdio_init(struct tg3 *tp)
 {
        int i;
@@ -1141,7 +1129,6 @@ static void tg3_mdio_fini(struct tg3 *tp)
                tp->tg3_flags3 &= ~TG3_FLG3_MDIOBUS_INITED;
                mdiobus_unregister(tp->mdio_bus);
                mdiobus_free(tp->mdio_bus);
-               tp->tg3_flags3 &= ~TG3_FLG3_MDIOBUS_PAUSED;
        }
 }
 
@@ -1363,7 +1350,7 @@ static void tg3_adjust_link(struct net_device *dev)
        struct tg3 *tp = netdev_priv(dev);
        struct phy_device *phydev = tp->mdio_bus->phy_map[PHY_ADDR];
 
-       spin_lock(&tp->lock);
+       spin_lock_bh(&tp->lock);
 
        mac_mode = tp->mac_mode & ~(MAC_MODE_PORT_MODE_MASK |
                                    MAC_MODE_HALF_DUPLEX);
@@ -1431,7 +1418,7 @@ static void tg3_adjust_link(struct net_device *dev)
        tp->link_config.active_speed = phydev->speed;
        tp->link_config.active_duplex = phydev->duplex;
 
-       spin_unlock(&tp->lock);
+       spin_unlock_bh(&tp->lock);
 
        if (linkmesg)
                tg3_link_report(tp);
@@ -6392,8 +6379,6 @@ static int tg3_chip_reset(struct tg3 *tp)
 
        tg3_nvram_lock(tp);
 
-       tg3_mdio_stop(tp);
-
        tg3_ape_lock(tp, TG3_APE_LOCK_GRC);
 
        /* No matching tg3_nvram_unlock() after this because
@@ -8698,6 +8683,8 @@ static int tg3_close(struct net_device *dev)
 
        del_timer_sync(&tp->timer);
 
+       tg3_phy_stop(tp);
+
        tg3_full_lock(tp, 1);
 #if 0
        tg3_dump_state(tp);
index 524691c..bab7940 100644 (file)
@@ -2748,7 +2748,6 @@ struct tg3 {
 #define TG3_FLG3_5701_DMA_BUG          0x00000008
 #define TG3_FLG3_USE_PHYLIB            0x00000010
 #define TG3_FLG3_MDIOBUS_INITED                0x00000020
-#define TG3_FLG3_MDIOBUS_PAUSED                0x00000040
 #define TG3_FLG3_PHY_CONNECTED         0x00000080
 #define TG3_FLG3_RGMII_STD_IBND_DISABLE        0x00000100
 #define TG3_FLG3_RGMII_EXT_IBND_RX_EN  0x00000200
index 525bbc5..75fa32e 100644 (file)
@@ -108,6 +108,7 @@ in the event that chatty debug messages are desired - jjs 12/30/98 */
 #define IBMTR_DEBUG_MESSAGES 0
 
 #include <linux/module.h>
+#include <linux/sched.h>
 
 #ifdef PCMCIA          /* required for ibmtr_cs.c to build */
 #undef MODULE          /* yes, really */
@@ -1143,9 +1144,16 @@ static void dir_open_adapter (struct net_device *dev)
                 } else {
                        char **prphase = printphase;
                        char **prerror = printerror;
+                       int pnr = err / 16 - 1;
+                       int enr = err % 16 - 1;
                        DPRINTK("TR Adapter misc open failure, error code = ");
-                       printk("0x%x, Phase: %s, Error: %s\n",
-                               err, prphase[err/16 -1], prerror[err%16 -1]);
+                       if (pnr < 0 || pnr >= ARRAY_SIZE(printphase) ||
+                                       enr < 0 ||
+                                       enr >= ARRAY_SIZE(printerror))
+                               printk("0x%x, invalid Phase/Error.", err);
+                       else
+                               printk("0x%x, Phase: %s, Error: %s\n", err,
+                                               prphase[pnr], prerror[enr]);
                        printk(" retrying after %ds delay...\n",
                                        TR_RETRY_INTERVAL/HZ);
                 }
index d6d3452..5921f5b 100644 (file)
@@ -108,6 +108,7 @@ static const int multicast_filter_limit = 32;
 
 #include <linux/module.h>
 #include <linux/kernel.h>
+#include <linux/sched.h>
 #include <linux/string.h>
 #include <linux/timer.h>
 #include <linux/errno.h>
index 72470f7..a2b30a1 100644 (file)
@@ -649,6 +649,10 @@ static const struct usb_device_id products[] = {
        USB_DEVICE(0x0fe6, 0x8101),     /* DM9601 USB to Fast Ethernet Adapter */
        .driver_info = (unsigned long)&dm9601_info,
         },
+       {
+        USB_DEVICE(0x0a46, 0x9000),    /* DM9000E */
+        .driver_info = (unsigned long)&dm9601_info,
+        },
        {},                     // END
 };
 
index 6fdaba8..ed4a508 100644 (file)
@@ -62,8 +62,11 @@ static char *devid=NULL;
 static struct usb_eth_dev usb_dev_id[] = {
 #define        PEGASUS_DEV(pn, vid, pid, flags)        \
        {.name = pn, .vendor = vid, .device = pid, .private = flags},
+#define PEGASUS_DEV_CLASS(pn, vid, pid, dclass, flags) \
+       PEGASUS_DEV(pn, vid, pid, flags)
 #include "pegasus.h"
 #undef PEGASUS_DEV
+#undef PEGASUS_DEV_CLASS
        {NULL, 0, 0, 0},
        {NULL, 0, 0, 0}
 };
@@ -71,8 +74,18 @@ static struct usb_eth_dev usb_dev_id[] = {
 static struct usb_device_id pegasus_ids[] = {
 #define        PEGASUS_DEV(pn, vid, pid, flags) \
        {.match_flags = USB_DEVICE_ID_MATCH_DEVICE, .idVendor = vid, .idProduct = pid},
+/*
+ * The Belkin F8T012xx1 bluetooth adaptor has the same vendor and product
+ * IDs as the Belkin F5D5050, so we need to teach the pegasus driver to
+ * ignore adaptors belonging to the "Wireless" class 0xE0. For this one
+ * case anyway, seeing as the pegasus is for "Wired" adaptors.
+ */
+#define PEGASUS_DEV_CLASS(pn, vid, pid, dclass, flags) \
+       {.match_flags = (USB_DEVICE_ID_MATCH_DEVICE | USB_DEVICE_ID_MATCH_DEV_CLASS), \
+       .idVendor = vid, .idProduct = pid, .bDeviceClass = dclass},
 #include "pegasus.h"
 #undef PEGASUS_DEV
+#undef PEGASUS_DEV_CLASS
        {},
        {}
 };
index f968c83..5d02f02 100644 (file)
@@ -202,7 +202,11 @@ PEGASUS_DEV( "AEI USB Fast Ethernet Adapter", VENDOR_AEILAB, 0x1701,
                DEFAULT_GPIO_RESET | PEGASUS_II )
 PEGASUS_DEV( "Allied Telesyn Int. AT-USB100", VENDOR_ALLIEDTEL, 0xb100,
                DEFAULT_GPIO_RESET | PEGASUS_II )
-PEGASUS_DEV( "Belkin F5D5050 USB Ethernet", VENDOR_BELKIN, 0x0121,
+/*
+ * Distinguish between this Belkin adaptor and the Belkin bluetooth adaptors
+ * with the same product IDs by checking the device class too.
+ */
+PEGASUS_DEV_CLASS( "Belkin F5D5050 USB Ethernet", VENDOR_BELKIN, 0x0121, 0x00,
                DEFAULT_GPIO_RESET | PEGASUS_II )
 PEGASUS_DEV( "Billionton USB-100", VENDOR_BILLIONTON, 0x0986,
                DEFAULT_GPIO_RESET )
index d032bba..f56dec6 100644 (file)
@@ -362,12 +362,12 @@ generic_rndis_bind(struct usbnet *dev, struct usb_interface *intf, int flags)
                        retval = -EINVAL;
                        goto halt_fail_and_release;
                }
-               dev->hard_mtu = tmp;
-               net->mtu = dev->hard_mtu - net->hard_header_len;
                dev_warn(&intf->dev,
                         "dev can't take %u byte packets (max %u), "
                         "adjusting MTU to %u\n",
-                        dev->hard_mtu, tmp, net->mtu);
+                        dev->hard_mtu, tmp, tmp - net->hard_header_len);
+               dev->hard_mtu = tmp;
+               net->mtu = dev->hard_mtu - net->hard_header_len;
        }
 
        /* REVISIT:  peripheral "alignment" request is ignored ... */
@@ -418,6 +418,7 @@ generic_rndis_bind(struct usbnet *dev, struct usb_interface *intf, int flags)
                goto halt_fail_and_release;
        }
        memcpy(net->dev_addr, bp, ETH_ALEN);
+       memcpy(net->perm_addr, bp, ETH_ALEN);
 
        /* set a nonzero filter to enable data transfers */
        memset(u.set, 0, sizeof *u.set);
index 8d00976..05630f2 100644 (file)
@@ -22,7 +22,6 @@
 #include <linux/ethtool.h>
 #include <linux/module.h>
 #include <linux/virtio.h>
-#include <linux/virtio_ids.h>
 #include <linux/virtio_net.h>
 #include <linux/scatterlist.h>
 #include <linux/if_vlan.h>
@@ -454,7 +453,7 @@ static unsigned int free_old_xmit_skbs(struct virtnet_info *vi)
                vi->dev->stats.tx_bytes += skb->len;
                vi->dev->stats.tx_packets++;
                tot_sgs += skb_vnet_hdr(skb)->num_sg;
-               kfree_skb(skb);
+               dev_kfree_skb_any(skb);
        }
        return tot_sgs;
 }
@@ -517,8 +516,7 @@ again:
        /* Free up any pending old buffers before queueing new ones. */
        free_old_xmit_skbs(vi);
 
-       /* Put new one in send queue and do transmit */
-       __skb_queue_head(&vi->send, skb);
+       /* Try to transmit */
        capacity = xmit_skb(vi, skb);
 
        /* This can happen with OOM and indirect buffers. */
@@ -532,8 +530,17 @@ again:
                }
                return NETDEV_TX_BUSY;
        }
-
        vi->svq->vq_ops->kick(vi->svq);
+
+       /*
+        * Put new one in send queue.  You'd expect we'd need this before
+        * xmit_skb calls add_buf(), since the callback can be triggered
+        * immediately after that.  But since the callback just triggers
+        * another call back here, normal network xmit locking prevents the
+        * race.
+        */
+       __skb_queue_head(&vi->send, skb);
+
        /* Don't wait up for transmitted skbs to be freed. */
        skb_orphan(skb);
        nf_reset(skb);
diff --git a/drivers/net/vmxnet3/Makefile b/drivers/net/vmxnet3/Makefile
new file mode 100644 (file)
index 0000000..880f509
--- /dev/null
@@ -0,0 +1,35 @@
+################################################################################
+#
+# Linux driver for VMware's vmxnet3 ethernet NIC.
+#
+# Copyright (C) 2007-2009, VMware, 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; version 2 of the License and no 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, GOOD TITLE or
+# NON INFRINGEMENT.  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.
+#
+# The full GNU General Public License is included in this distribution in
+# the file called "COPYING".
+#
+# Maintained by: Shreyas Bhatewara <pv-drivers@vmware.com>
+#
+#
+################################################################################
+
+#
+# Makefile for the VMware vmxnet3 ethernet NIC driver
+#
+
+obj-$(CONFIG_VMXNET3) += vmxnet3.o
+
+vmxnet3-objs := vmxnet3_drv.o vmxnet3_ethtool.o
diff --git a/drivers/net/vmxnet3/upt1_defs.h b/drivers/net/vmxnet3/upt1_defs.h
new file mode 100644 (file)
index 0000000..37108fb
--- /dev/null
@@ -0,0 +1,96 @@
+/*
+ * Linux driver for VMware's vmxnet3 ethernet NIC.
+ *
+ * Copyright (C) 2008-2009, VMware, 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; version 2 of the License and no 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, GOOD TITLE or
+ * NON INFRINGEMENT.  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.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Maintained by: Shreyas Bhatewara <pv-drivers@vmware.com>
+ *
+ */
+
+#ifndef _UPT1_DEFS_H
+#define _UPT1_DEFS_H
+
+struct UPT1_TxStats {
+       u64                     TSOPktsTxOK;  /* TSO pkts post-segmentation */
+       u64                     TSOBytesTxOK;
+       u64                     ucastPktsTxOK;
+       u64                     ucastBytesTxOK;
+       u64                     mcastPktsTxOK;
+       u64                     mcastBytesTxOK;
+       u64                     bcastPktsTxOK;
+       u64                     bcastBytesTxOK;
+       u64                     pktsTxError;
+       u64                     pktsTxDiscard;
+};
+
+struct UPT1_RxStats {
+       u64                     LROPktsRxOK;    /* LRO pkts */
+       u64                     LROBytesRxOK;   /* bytes from LRO pkts */
+       /* the following counters are for pkts from the wire, i.e., pre-LRO */
+       u64                     ucastPktsRxOK;
+       u64                     ucastBytesRxOK;
+       u64                     mcastPktsRxOK;
+       u64                     mcastBytesRxOK;
+       u64                     bcastPktsRxOK;
+       u64                     bcastBytesRxOK;
+       u64                     pktsRxOutOfBuf;
+       u64                     pktsRxError;
+};
+
+/* interrupt moderation level */
+enum {
+       UPT1_IML_NONE           = 0, /* no interrupt moderation */
+       UPT1_IML_HIGHEST        = 7, /* least intr generated */
+       UPT1_IML_ADAPTIVE       = 8, /* adpative intr moderation */
+};
+/* values for UPT1_RSSConf.hashFunc */
+enum {
+       UPT1_RSS_HASH_TYPE_NONE      = 0x0,
+       UPT1_RSS_HASH_TYPE_IPV4      = 0x01,
+       UPT1_RSS_HASH_TYPE_TCP_IPV4  = 0x02,
+       UPT1_RSS_HASH_TYPE_IPV6      = 0x04,
+       UPT1_RSS_HASH_TYPE_TCP_IPV6  = 0x08,
+};
+
+enum {
+       UPT1_RSS_HASH_FUNC_NONE      = 0x0,
+       UPT1_RSS_HASH_FUNC_TOEPLITZ  = 0x01,
+};
+
+#define UPT1_RSS_MAX_KEY_SIZE        40
+#define UPT1_RSS_MAX_IND_TABLE_SIZE  128
+
+struct UPT1_RSSConf {
+       u16                     hashType;
+       u16                     hashFunc;
+       u16                     hashKeySize;
+       u16                     indTableSize;
+       u8                      hashKey[UPT1_RSS_MAX_KEY_SIZE];
+       u8                      indTable[UPT1_RSS_MAX_IND_TABLE_SIZE];
+};
+
+/* features */
+enum {
+       UPT1_F_RXCSUM           = 0x0001,   /* rx csum verification */
+       UPT1_F_RSS              = 0x0002,
+       UPT1_F_RXVLAN           = 0x0004,   /* VLAN tag stripping */
+       UPT1_F_LRO              = 0x0008,
+};
+#endif
diff --git a/drivers/net/vmxnet3/vmxnet3_defs.h b/drivers/net/vmxnet3/vmxnet3_defs.h
new file mode 100644 (file)
index 0000000..dc8ee44
--- /dev/null
@@ -0,0 +1,535 @@
+/*
+ * Linux driver for VMware's vmxnet3 ethernet NIC.
+ *
+ * Copyright (C) 2008-2009, VMware, 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; version 2 of the License and no 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, GOOD TITLE or
+ * NON INFRINGEMENT.  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.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Maintained by: Shreyas Bhatewara <pv-drivers@vmware.com>
+ *
+ */
+
+#ifndef _VMXNET3_DEFS_H_
+#define _VMXNET3_DEFS_H_
+
+#include "upt1_defs.h"
+
+/* all registers are 32 bit wide */
+/* BAR 1 */
+enum {
+       VMXNET3_REG_VRRS        = 0x0,  /* Vmxnet3 Revision Report Selection */
+       VMXNET3_REG_UVRS        = 0x8,  /* UPT Version Report Selection */
+       VMXNET3_REG_DSAL        = 0x10, /* Driver Shared Address Low */
+       VMXNET3_REG_DSAH        = 0x18, /* Driver Shared Address High */
+       VMXNET3_REG_CMD         = 0x20, /* Command */
+       VMXNET3_REG_MACL        = 0x28, /* MAC Address Low */
+       VMXNET3_REG_MACH        = 0x30, /* MAC Address High */
+       VMXNET3_REG_ICR         = 0x38, /* Interrupt Cause Register */
+       VMXNET3_REG_ECR         = 0x40  /* Event Cause Register */
+};
+
+/* BAR 0 */
+enum {
+       VMXNET3_REG_IMR         = 0x0,   /* Interrupt Mask Register */
+       VMXNET3_REG_TXPROD      = 0x600, /* Tx Producer Index */
+       VMXNET3_REG_RXPROD      = 0x800, /* Rx Producer Index for ring 1 */
+       VMXNET3_REG_RXPROD2     = 0xA00  /* Rx Producer Index for ring 2 */
+};
+
+#define VMXNET3_PT_REG_SIZE     4096   /* BAR 0 */
+#define VMXNET3_VD_REG_SIZE     4096   /* BAR 1 */
+
+#define VMXNET3_REG_ALIGN       8      /* All registers are 8-byte aligned. */
+#define VMXNET3_REG_ALIGN_MASK  0x7
+
+/* I/O Mapped access to registers */
+#define VMXNET3_IO_TYPE_PT              0
+#define VMXNET3_IO_TYPE_VD              1
+#define VMXNET3_IO_ADDR(type, reg)      (((type) << 24) | ((reg) & 0xFFFFFF))
+#define VMXNET3_IO_TYPE(addr)           ((addr) >> 24)
+#define VMXNET3_IO_REG(addr)            ((addr) & 0xFFFFFF)
+
+enum {
+       VMXNET3_CMD_FIRST_SET = 0xCAFE0000,
+       VMXNET3_CMD_ACTIVATE_DEV = VMXNET3_CMD_FIRST_SET,
+       VMXNET3_CMD_QUIESCE_DEV,
+       VMXNET3_CMD_RESET_DEV,
+       VMXNET3_CMD_UPDATE_RX_MODE,
+       VMXNET3_CMD_UPDATE_MAC_FILTERS,
+       VMXNET3_CMD_UPDATE_VLAN_FILTERS,
+       VMXNET3_CMD_UPDATE_RSSIDT,
+       VMXNET3_CMD_UPDATE_IML,
+       VMXNET3_CMD_UPDATE_PMCFG,
+       VMXNET3_CMD_UPDATE_FEATURE,
+       VMXNET3_CMD_LOAD_PLUGIN,
+
+       VMXNET3_CMD_FIRST_GET = 0xF00D0000,
+       VMXNET3_CMD_GET_QUEUE_STATUS = VMXNET3_CMD_FIRST_GET,
+       VMXNET3_CMD_GET_STATS,
+       VMXNET3_CMD_GET_LINK,
+       VMXNET3_CMD_GET_PERM_MAC_LO,
+       VMXNET3_CMD_GET_PERM_MAC_HI,
+       VMXNET3_CMD_GET_DID_LO,
+       VMXNET3_CMD_GET_DID_HI,
+       VMXNET3_CMD_GET_DEV_EXTRA_INFO,
+       VMXNET3_CMD_GET_CONF_INTR
+};
+
+struct Vmxnet3_TxDesc {
+       u64             addr;
+
+       u32             len:14;
+       u32             gen:1;      /* generation bit */
+       u32             rsvd:1;
+       u32             dtype:1;    /* descriptor type */
+       u32             ext1:1;
+       u32             msscof:14;  /* MSS, checksum offset, flags */
+
+       u32             hlen:10;    /* header len */
+       u32             om:2;       /* offload mode */
+       u32             eop:1;      /* End Of Packet */
+       u32             cq:1;       /* completion request */
+       u32             ext2:1;
+       u32             ti:1;       /* VLAN Tag Insertion */
+       u32             tci:16;     /* Tag to Insert */
+};
+
+/* TxDesc.OM values */
+#define VMXNET3_OM_NONE                0
+#define VMXNET3_OM_CSUM                2
+#define VMXNET3_OM_TSO         3
+
+/* fields in TxDesc we access w/o using bit fields */
+#define VMXNET3_TXD_EOP_SHIFT  12
+#define VMXNET3_TXD_CQ_SHIFT   13
+#define VMXNET3_TXD_GEN_SHIFT  14
+
+#define VMXNET3_TXD_CQ         (1 << VMXNET3_TXD_CQ_SHIFT)
+#define VMXNET3_TXD_EOP                (1 << VMXNET3_TXD_EOP_SHIFT)
+#define VMXNET3_TXD_GEN                (1 << VMXNET3_TXD_GEN_SHIFT)
+
+#define VMXNET3_HDR_COPY_SIZE   128
+
+
+struct Vmxnet3_TxDataDesc {
+       u8              data[VMXNET3_HDR_COPY_SIZE];
+};
+
+
+struct Vmxnet3_TxCompDesc {
+       u32             txdIdx:12;    /* Index of the EOP TxDesc */
+       u32             ext1:20;
+
+       u32             ext2;
+       u32             ext3;
+
+       u32             rsvd:24;
+       u32             type:7;       /* completion type */
+       u32             gen:1;        /* generation bit */
+};
+
+
+struct Vmxnet3_RxDesc {
+       u64             addr;
+
+       u32             len:14;
+       u32             btype:1;      /* Buffer Type */
+       u32             dtype:1;      /* Descriptor type */
+       u32             rsvd:15;
+       u32             gen:1;        /* Generation bit */
+
+       u32             ext1;
+};
+
+/* values of RXD.BTYPE */
+#define VMXNET3_RXD_BTYPE_HEAD   0    /* head only */
+#define VMXNET3_RXD_BTYPE_BODY   1    /* body only */
+
+/* fields in RxDesc we access w/o using bit fields */
+#define VMXNET3_RXD_BTYPE_SHIFT  14
+#define VMXNET3_RXD_GEN_SHIFT    31
+
+
+struct Vmxnet3_RxCompDesc {
+       u32             rxdIdx:12;    /* Index of the RxDesc */
+       u32             ext1:2;
+       u32             eop:1;        /* End of Packet */
+       u32             sop:1;        /* Start of Packet */
+       u32             rqID:10;      /* rx queue/ring ID */
+       u32             rssType:4;    /* RSS hash type used */
+       u32             cnc:1;        /* Checksum Not Calculated */
+       u32             ext2:1;
+
+       u32             rssHash;      /* RSS hash value */
+
+       u32             len:14;       /* data length */
+       u32             err:1;        /* Error */
+       u32             ts:1;         /* Tag is stripped */
+       u32             tci:16;       /* Tag stripped */
+
+       u32             csum:16;
+       u32             tuc:1;        /* TCP/UDP Checksum Correct */
+       u32             udp:1;        /* UDP packet */
+       u32             tcp:1;        /* TCP packet */
+       u32             ipc:1;        /* IP Checksum Correct */
+       u32             v6:1;         /* IPv6 */
+       u32             v4:1;         /* IPv4 */
+       u32             frg:1;        /* IP Fragment */
+       u32             fcs:1;        /* Frame CRC correct */
+       u32             type:7;       /* completion type */
+       u32             gen:1;        /* generation bit */
+};
+
+/* fields in RxCompDesc we access via Vmxnet3_GenericDesc.dword[3] */
+#define VMXNET3_RCD_TUC_SHIFT  16
+#define VMXNET3_RCD_IPC_SHIFT  19
+
+/* fields in RxCompDesc we access via Vmxnet3_GenericDesc.qword[1] */
+#define VMXNET3_RCD_TYPE_SHIFT 56
+#define VMXNET3_RCD_GEN_SHIFT  63
+
+/* csum OK for TCP/UDP pkts over IP */
+#define VMXNET3_RCD_CSUM_OK (1 << VMXNET3_RCD_TUC_SHIFT | \
+                            1 << VMXNET3_RCD_IPC_SHIFT)
+
+/* value of RxCompDesc.rssType */
+enum {
+       VMXNET3_RCD_RSS_TYPE_NONE     = 0,
+       VMXNET3_RCD_RSS_TYPE_IPV4     = 1,
+       VMXNET3_RCD_RSS_TYPE_TCPIPV4  = 2,
+       VMXNET3_RCD_RSS_TYPE_IPV6     = 3,
+       VMXNET3_RCD_RSS_TYPE_TCPIPV6  = 4,
+};
+
+
+/* a union for accessing all cmd/completion descriptors */
+union Vmxnet3_GenericDesc {
+       u64                             qword[2];
+       u32                             dword[4];
+       u16                             word[8];
+       struct Vmxnet3_TxDesc           txd;
+       struct Vmxnet3_RxDesc           rxd;
+       struct Vmxnet3_TxCompDesc       tcd;
+       struct Vmxnet3_RxCompDesc       rcd;
+};
+
+#define VMXNET3_INIT_GEN       1
+
+/* Max size of a single tx buffer */
+#define VMXNET3_MAX_TX_BUF_SIZE  (1 << 14)
+
+/* # of tx desc needed for a tx buffer size */
+#define VMXNET3_TXD_NEEDED(size) (((size) + VMXNET3_MAX_TX_BUF_SIZE - 1) / \
+                                 VMXNET3_MAX_TX_BUF_SIZE)
+
+/* max # of tx descs for a non-tso pkt */
+#define VMXNET3_MAX_TXD_PER_PKT 16
+
+/* Max size of a single rx buffer */
+#define VMXNET3_MAX_RX_BUF_SIZE  ((1 << 14) - 1)
+/* Minimum size of a type 0 buffer */
+#define VMXNET3_MIN_T0_BUF_SIZE  128
+#define VMXNET3_MAX_CSUM_OFFSET  1024
+
+/* Ring base address alignment */
+#define VMXNET3_RING_BA_ALIGN   512
+#define VMXNET3_RING_BA_MASK    (VMXNET3_RING_BA_ALIGN - 1)
+
+/* Ring size must be a multiple of 32 */
+#define VMXNET3_RING_SIZE_ALIGN 32
+#define VMXNET3_RING_SIZE_MASK  (VMXNET3_RING_SIZE_ALIGN - 1)
+
+/* Max ring size */
+#define VMXNET3_TX_RING_MAX_SIZE   4096
+#define VMXNET3_TC_RING_MAX_SIZE   4096
+#define VMXNET3_RX_RING_MAX_SIZE   4096
+#define VMXNET3_RC_RING_MAX_SIZE   8192
+
+/* a list of reasons for queue stop */
+
+enum {
+ VMXNET3_ERR_NOEOP        = 0x80000000,  /* cannot find the EOP desc of a pkt */
+ VMXNET3_ERR_TXD_REUSE    = 0x80000001,  /* reuse TxDesc before tx completion */
+ VMXNET3_ERR_BIG_PKT      = 0x80000002,  /* too many TxDesc for a pkt */
+ VMXNET3_ERR_DESC_NOT_SPT = 0x80000003,  /* descriptor type not supported */
+ VMXNET3_ERR_SMALL_BUF    = 0x80000004,  /* type 0 buffer too small */
+ VMXNET3_ERR_STRESS       = 0x80000005,  /* stress option firing in vmkernel */
+ VMXNET3_ERR_SWITCH       = 0x80000006,  /* mode switch failure */
+ VMXNET3_ERR_TXD_INVALID  = 0x80000007,  /* invalid TxDesc */
+};
+
+/* completion descriptor types */
+#define VMXNET3_CDTYPE_TXCOMP      0    /* Tx Completion Descriptor */
+#define VMXNET3_CDTYPE_RXCOMP      3    /* Rx Completion Descriptor */
+
+enum {
+       VMXNET3_GOS_BITS_UNK    = 0,   /* unknown */
+       VMXNET3_GOS_BITS_32     = 1,
+       VMXNET3_GOS_BITS_64     = 2,
+};
+
+#define VMXNET3_GOS_TYPE_LINUX 1
+
+
+struct Vmxnet3_GOSInfo {
+       u32                             gosBits:2;      /* 32-bit or 64-bit? */
+       u32                             gosType:4;   /* which guest */
+       u32                             gosVer:16;   /* gos version */
+       u32                             gosMisc:10;  /* other info about gos */
+};
+
+
+struct Vmxnet3_DriverInfo {
+       u32                             version;
+       struct Vmxnet3_GOSInfo          gos;
+       u32                             vmxnet3RevSpt;
+       u32                             uptVerSpt;
+};
+
+
+#define VMXNET3_REV1_MAGIC  0xbabefee1
+
+/*
+ * QueueDescPA must be 128 bytes aligned. It points to an array of
+ * Vmxnet3_TxQueueDesc followed by an array of Vmxnet3_RxQueueDesc.
+ * The number of Vmxnet3_TxQueueDesc/Vmxnet3_RxQueueDesc are specified by
+ * Vmxnet3_MiscConf.numTxQueues/numRxQueues, respectively.
+ */
+#define VMXNET3_QUEUE_DESC_ALIGN  128
+
+
+struct Vmxnet3_MiscConf {
+       struct Vmxnet3_DriverInfo driverInfo;
+       u64             uptFeatures;
+       u64             ddPA;         /* driver data PA */
+       u64             queueDescPA;  /* queue descriptor table PA */
+       u32             ddLen;        /* driver data len */
+       u32             queueDescLen; /* queue desc. table len in bytes */
+       u32             mtu;
+       u16             maxNumRxSG;
+       u8              numTxQueues;
+       u8              numRxQueues;
+       u32             reserved[4];
+};
+
+
+struct Vmxnet3_TxQueueConf {
+       u64             txRingBasePA;
+       u64             dataRingBasePA;
+       u64             compRingBasePA;
+       u64             ddPA;         /* driver data */
+       u64             reserved;
+       u32             txRingSize;   /* # of tx desc */
+       u32             dataRingSize; /* # of data desc */
+       u32             compRingSize; /* # of comp desc */
+       u32             ddLen;        /* size of driver data */
+       u8              intrIdx;
+       u8              _pad[7];
+};
+
+
+struct Vmxnet3_RxQueueConf {
+       u64             rxRingBasePA[2];
+       u64             compRingBasePA;
+       u64             ddPA;            /* driver data */
+       u64             reserved;
+       u32             rxRingSize[2];   /* # of rx desc */
+       u32             compRingSize;    /* # of rx comp desc */
+       u32             ddLen;           /* size of driver data */
+       u8              intrIdx;
+       u8              _pad[7];
+};
+
+
+enum vmxnet3_intr_mask_mode {
+       VMXNET3_IMM_AUTO   = 0,
+       VMXNET3_IMM_ACTIVE = 1,
+       VMXNET3_IMM_LAZY   = 2
+};
+
+enum vmxnet3_intr_type {
+       VMXNET3_IT_AUTO = 0,
+       VMXNET3_IT_INTX = 1,
+       VMXNET3_IT_MSI  = 2,
+       VMXNET3_IT_MSIX = 3
+};
+
+#define VMXNET3_MAX_TX_QUEUES  8
+#define VMXNET3_MAX_RX_QUEUES  16
+/* addition 1 for events */
+#define VMXNET3_MAX_INTRS      25
+
+
+struct Vmxnet3_IntrConf {
+       bool            autoMask;
+       u8              numIntrs;      /* # of interrupts */
+       u8              eventIntrIdx;
+       u8              modLevels[VMXNET3_MAX_INTRS];   /* moderation level for
+                                                        * each intr */
+       u32             reserved[3];
+};
+
+/* one bit per VLAN ID, the size is in the units of u32        */
+#define VMXNET3_VFT_SIZE  (4096 / (sizeof(u32) * 8))
+
+
+struct Vmxnet3_QueueStatus {
+       bool            stopped;
+       u8              _pad[3];
+       u32             error;
+};
+
+
+struct Vmxnet3_TxQueueCtrl {
+       u32             txNumDeferred;
+       u32             txThreshold;
+       u64             reserved;
+};
+
+
+struct Vmxnet3_RxQueueCtrl {
+       bool            updateRxProd;
+       u8              _pad[7];
+       u64             reserved;
+};
+
+enum {
+       VMXNET3_RXM_UCAST     = 0x01,  /* unicast only */
+       VMXNET3_RXM_MCAST     = 0x02,  /* multicast passing the filters */
+       VMXNET3_RXM_BCAST     = 0x04,  /* broadcast only */
+       VMXNET3_RXM_ALL_MULTI = 0x08,  /* all multicast */
+       VMXNET3_RXM_PROMISC   = 0x10  /* promiscuous */
+};
+
+struct Vmxnet3_RxFilterConf {
+       u32             rxMode;       /* VMXNET3_RXM_xxx */
+       u16             mfTableLen;   /* size of the multicast filter table */
+       u16             _pad1;
+       u64             mfTablePA;    /* PA of the multicast filters table */
+       u32             vfTable[VMXNET3_VFT_SIZE]; /* vlan filter */
+};
+
+
+#define VMXNET3_PM_MAX_FILTERS        6
+#define VMXNET3_PM_MAX_PATTERN_SIZE   128
+#define VMXNET3_PM_MAX_MASK_SIZE      (VMXNET3_PM_MAX_PATTERN_SIZE / 8)
+
+#define VMXNET3_PM_WAKEUP_MAGIC       0x01  /* wake up on magic pkts */
+#define VMXNET3_PM_WAKEUP_FILTER      0x02  /* wake up on pkts matching
+                                            * filters */
+
+
+struct Vmxnet3_PM_PktFilter {
+       u8              maskSize;
+       u8              patternSize;
+       u8              mask[VMXNET3_PM_MAX_MASK_SIZE];
+       u8              pattern[VMXNET3_PM_MAX_PATTERN_SIZE];
+       u8              pad[6];
+};
+
+
+struct Vmxnet3_PMConf {
+       u16             wakeUpEvents;  /* VMXNET3_PM_WAKEUP_xxx */
+       u8              numFilters;
+       u8              pad[5];
+       struct Vmxnet3_PM_PktFilter filters[VMXNET3_PM_MAX_FILTERS];
+};
+
+
+struct Vmxnet3_VariableLenConfDesc {
+       u32             confVer;
+       u32             confLen;
+       u64             confPA;
+};
+
+
+struct Vmxnet3_TxQueueDesc {
+       struct Vmxnet3_TxQueueCtrl              ctrl;
+       struct Vmxnet3_TxQueueConf              conf;
+
+       /* Driver read after a GET command */
+       struct Vmxnet3_QueueStatus              status;
+       struct UPT1_TxStats                     stats;
+       u8                                      _pad[88]; /* 128 aligned */
+};
+
+
+struct Vmxnet3_RxQueueDesc {
+       struct Vmxnet3_RxQueueCtrl              ctrl;
+       struct Vmxnet3_RxQueueConf              conf;
+       /* Driver read after a GET commad */
+       struct Vmxnet3_QueueStatus              status;
+       struct UPT1_RxStats                     stats;
+       u8                                    __pad[88]; /* 128 aligned */
+};
+
+
+struct Vmxnet3_DSDevRead {
+       /* read-only region for device, read by dev in response to a SET cmd */
+       struct Vmxnet3_MiscConf                 misc;
+       struct Vmxnet3_IntrConf                 intrConf;
+       struct Vmxnet3_RxFilterConf             rxFilterConf;
+       struct Vmxnet3_VariableLenConfDesc      rssConfDesc;
+       struct Vmxnet3_VariableLenConfDesc      pmConfDesc;
+       struct Vmxnet3_VariableLenConfDesc      pluginConfDesc;
+};
+
+/* All structures in DriverShared are padded to multiples of 8 bytes */
+struct Vmxnet3_DriverShared {
+       u32                             magic;
+       /* make devRead start at 64bit boundaries */
+       u32                                     pad;
+       struct Vmxnet3_DSDevRead                devRead;
+       u32                                     ecr;
+       u32                                     reserved[5];
+};
+
+
+#define VMXNET3_ECR_RQERR       (1 << 0)
+#define VMXNET3_ECR_TQERR       (1 << 1)
+#define VMXNET3_ECR_LINK        (1 << 2)
+#define VMXNET3_ECR_DIC         (1 << 3)
+#define VMXNET3_ECR_DEBUG       (1 << 4)
+
+/* flip the gen bit of a ring */
+#define VMXNET3_FLIP_RING_GEN(gen) ((gen) = (gen) ^ 0x1)
+
+/* only use this if moving the idx won't affect the gen bit */
+#define VMXNET3_INC_RING_IDX_ONLY(idx, ring_size) \
+       do {\
+               (idx)++;\
+               if (unlikely((idx) == (ring_size))) {\
+                       (idx) = 0;\
+               } \
+       } while (0)
+
+#define VMXNET3_SET_VFTABLE_ENTRY(vfTable, vid) \
+       (vfTable[vid >> 5] |= (1 << (vid & 31)))
+#define VMXNET3_CLEAR_VFTABLE_ENTRY(vfTable, vid) \
+       (vfTable[vid >> 5] &= ~(1 << (vid & 31)))
+
+#define VMXNET3_VFTABLE_ENTRY_IS_SET(vfTable, vid) \
+       ((vfTable[vid >> 5] & (1 << (vid & 31))) != 0)
+
+#define VMXNET3_MAX_MTU     9000
+#define VMXNET3_MIN_MTU     60
+
+#define VMXNET3_LINK_UP         (10000 << 16 | 1)    /* 10 Gbps, up */
+#define VMXNET3_LINK_DOWN       0
+
+#endif /* _VMXNET3_DEFS_H_ */
diff --git a/drivers/net/vmxnet3/vmxnet3_drv.c b/drivers/net/vmxnet3/vmxnet3_drv.c
new file mode 100644 (file)
index 0000000..004353a
--- /dev/null
@@ -0,0 +1,2574 @@
+/*
+ * Linux driver for VMware's vmxnet3 ethernet NIC.
+ *
+ * Copyright (C) 2008-2009, VMware, 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; version 2 of the License and no 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, GOOD TITLE or
+ * NON INFRINGEMENT. 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.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Maintained by: Shreyas Bhatewara <pv-drivers@vmware.com>
+ *
+ */
+
+#include "vmxnet3_int.h"
+
+char vmxnet3_driver_name[] = "vmxnet3";
+#define VMXNET3_DRIVER_DESC "VMware vmxnet3 virtual NIC driver"
+
+
+/*
+ * PCI Device ID Table
+ * Last entry must be all 0s
+ */
+static const struct pci_device_id vmxnet3_pciid_table[] = {
+       {PCI_VDEVICE(VMWARE, PCI_DEVICE_ID_VMWARE_VMXNET3)},
+       {0}
+};
+
+MODULE_DEVICE_TABLE(pci, vmxnet3_pciid_table);
+
+static atomic_t devices_found;
+
+
+/*
+ *    Enable/Disable the given intr
+ */
+static void
+vmxnet3_enable_intr(struct vmxnet3_adapter *adapter, unsigned intr_idx)
+{
+       VMXNET3_WRITE_BAR0_REG(adapter, VMXNET3_REG_IMR + intr_idx * 8, 0);
+}
+
+
+static void
+vmxnet3_disable_intr(struct vmxnet3_adapter *adapter, unsigned intr_idx)
+{
+       VMXNET3_WRITE_BAR0_REG(adapter, VMXNET3_REG_IMR + intr_idx * 8, 1);
+}
+
+
+/*
+ *    Enable/Disable all intrs used by the device
+ */
+static void
+vmxnet3_enable_all_intrs(struct vmxnet3_adapter *adapter)
+{
+       int i;
+
+       for (i = 0; i < adapter->intr.num_intrs; i++)
+               vmxnet3_enable_intr(adapter, i);
+}
+
+
+static void
+vmxnet3_disable_all_intrs(struct vmxnet3_adapter *adapter)
+{
+       int i;
+
+       for (i = 0; i < adapter->intr.num_intrs; i++)
+               vmxnet3_disable_intr(adapter, i);
+}
+
+
+static void
+vmxnet3_ack_events(struct vmxnet3_adapter *adapter, u32 events)
+{
+       VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_ECR, events);
+}
+
+
+static bool
+vmxnet3_tq_stopped(struct vmxnet3_tx_queue *tq, struct vmxnet3_adapter *adapter)
+{
+       return netif_queue_stopped(adapter->netdev);
+}
+
+
+static void
+vmxnet3_tq_start(struct vmxnet3_tx_queue *tq, struct vmxnet3_adapter *adapter)
+{
+       tq->stopped = false;
+       netif_start_queue(adapter->netdev);
+}
+
+
+static void
+vmxnet3_tq_wake(struct vmxnet3_tx_queue *tq, struct vmxnet3_adapter *adapter)
+{
+       tq->stopped = false;
+       netif_wake_queue(adapter->netdev);
+}
+
+
+static void
+vmxnet3_tq_stop(struct vmxnet3_tx_queue *tq, struct vmxnet3_adapter *adapter)
+{
+       tq->stopped = true;
+       tq->num_stop++;
+       netif_stop_queue(adapter->netdev);
+}
+
+
+/*
+ * Check the link state. This may start or stop the tx queue.
+ */
+static void
+vmxnet3_check_link(struct vmxnet3_adapter *adapter)
+{
+       u32 ret;
+
+       VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_CMD, VMXNET3_CMD_GET_LINK);
+       ret = VMXNET3_READ_BAR1_REG(adapter, VMXNET3_REG_CMD);
+       adapter->link_speed = ret >> 16;
+       if (ret & 1) { /* Link is up. */
+               printk(KERN_INFO "%s: NIC Link is Up %d Mbps\n",
+                      adapter->netdev->name, adapter->link_speed);
+               if (!netif_carrier_ok(adapter->netdev))
+                       netif_carrier_on(adapter->netdev);
+
+               vmxnet3_tq_start(&adapter->tx_queue, adapter);
+       } else {
+               printk(KERN_INFO "%s: NIC Link is Down\n",
+                      adapter->netdev->name);
+               if (netif_carrier_ok(adapter->netdev))
+                       netif_carrier_off(adapter->netdev);
+
+               vmxnet3_tq_stop(&adapter->tx_queue, adapter);
+       }
+}
+
+
+static void
+vmxnet3_process_events(struct vmxnet3_adapter *adapter)
+{
+       u32 events = adapter->shared->ecr;
+       if (!events)
+               return;
+
+       vmxnet3_ack_events(adapter, events);
+
+       /* Check if link state has changed */
+       if (events & VMXNET3_ECR_LINK)
+               vmxnet3_check_link(adapter);
+
+       /* Check if there is an error on xmit/recv queues */
+       if (events & (VMXNET3_ECR_TQERR | VMXNET3_ECR_RQERR)) {
+               VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_CMD,
+                                      VMXNET3_CMD_GET_QUEUE_STATUS);
+
+               if (adapter->tqd_start->status.stopped) {
+                       printk(KERN_ERR "%s: tq error 0x%x\n",
+                              adapter->netdev->name,
+                              adapter->tqd_start->status.error);
+               }
+               if (adapter->rqd_start->status.stopped) {
+                       printk(KERN_ERR "%s: rq error 0x%x\n",
+                              adapter->netdev->name,
+                              adapter->rqd_start->status.error);
+               }
+
+               schedule_work(&adapter->work);
+       }
+}
+
+
+static void
+vmxnet3_unmap_tx_buf(struct vmxnet3_tx_buf_info *tbi,
+                    struct pci_dev *pdev)
+{
+       if (tbi->map_type == VMXNET3_MAP_SINGLE)
+               pci_unmap_single(pdev, tbi->dma_addr, tbi->len,
+                                PCI_DMA_TODEVICE);
+       else if (tbi->map_type == VMXNET3_MAP_PAGE)
+               pci_unmap_page(pdev, tbi->dma_addr, tbi->len,
+                              PCI_DMA_TODEVICE);
+       else
+               BUG_ON(tbi->map_type != VMXNET3_MAP_NONE);
+
+       tbi->map_type = VMXNET3_MAP_NONE; /* to help debugging */
+}
+
+
+static int
+vmxnet3_unmap_pkt(u32 eop_idx, struct vmxnet3_tx_queue *tq,
+                 struct pci_dev *pdev, struct vmxnet3_adapter *adapter)
+{
+       struct sk_buff *skb;
+       int entries = 0;
+
+       /* no out of order completion */
+       BUG_ON(tq->buf_info[eop_idx].sop_idx != tq->tx_ring.next2comp);
+       BUG_ON(tq->tx_ring.base[eop_idx].txd.eop != 1);
+
+       skb = tq->buf_info[eop_idx].skb;
+       BUG_ON(skb == NULL);
+       tq->buf_info[eop_idx].skb = NULL;
+
+       VMXNET3_INC_RING_IDX_ONLY(eop_idx, tq->tx_ring.size);
+
+       while (tq->tx_ring.next2comp != eop_idx) {
+               vmxnet3_unmap_tx_buf(tq->buf_info + tq->tx_ring.next2comp,
+                                    pdev);
+
+               /* update next2comp w/o tx_lock. Since we are marking more,
+                * instead of less, tx ring entries avail, the worst case is
+                * that the tx routine incorrectly re-queues a pkt due to
+                * insufficient tx ring entries.
+                */
+               vmxnet3_cmd_ring_adv_next2comp(&tq->tx_ring);
+               entries++;
+       }
+
+       dev_kfree_skb_any(skb);
+       return entries;
+}
+
+
+static int
+vmxnet3_tq_tx_complete(struct vmxnet3_tx_queue *tq,
+                       struct vmxnet3_adapter *adapter)
+{
+       int completed = 0;
+       union Vmxnet3_GenericDesc *gdesc;
+
+       gdesc = tq->comp_ring.base + tq->comp_ring.next2proc;
+       while (gdesc->tcd.gen == tq->comp_ring.gen) {
+               completed += vmxnet3_unmap_pkt(gdesc->tcd.txdIdx, tq,
+                                              adapter->pdev, adapter);
+
+               vmxnet3_comp_ring_adv_next2proc(&tq->comp_ring);
+               gdesc = tq->comp_ring.base + tq->comp_ring.next2proc;
+       }
+
+       if (completed) {
+               spin_lock(&tq->tx_lock);
+               if (unlikely(vmxnet3_tq_stopped(tq, adapter) &&
+                            vmxnet3_cmd_ring_desc_avail(&tq->tx_ring) >
+                            VMXNET3_WAKE_QUEUE_THRESHOLD(tq) &&
+                            netif_carrier_ok(adapter->netdev))) {
+                       vmxnet3_tq_wake(tq, adapter);
+               }
+               spin_unlock(&tq->tx_lock);
+       }
+       return completed;
+}
+
+
+static void
+vmxnet3_tq_cleanup(struct vmxnet3_tx_queue *tq,
+                  struct vmxnet3_adapter *adapter)
+{
+       int i;
+
+       while (tq->tx_ring.next2comp != tq->tx_ring.next2fill) {
+               struct vmxnet3_tx_buf_info *tbi;
+               union Vmxnet3_GenericDesc *gdesc;
+
+               tbi = tq->buf_info + tq->tx_ring.next2comp;
+               gdesc = tq->tx_ring.base + tq->tx_ring.next2comp;
+
+               vmxnet3_unmap_tx_buf(tbi, adapter->pdev);
+               if (tbi->skb) {
+                       dev_kfree_skb_any(tbi->skb);
+                       tbi->skb = NULL;
+               }
+               vmxnet3_cmd_ring_adv_next2comp(&tq->tx_ring);
+       }
+
+       /* sanity check, verify all buffers are indeed unmapped and freed */
+       for (i = 0; i < tq->tx_ring.size; i++) {
+               BUG_ON(tq->buf_info[i].skb != NULL ||
+                      tq->buf_info[i].map_type != VMXNET3_MAP_NONE);
+       }
+
+       tq->tx_ring.gen = VMXNET3_INIT_GEN;
+       tq->tx_ring.next2fill = tq->tx_ring.next2comp = 0;
+
+       tq->comp_ring.gen = VMXNET3_INIT_GEN;
+       tq->comp_ring.next2proc = 0;
+}
+
+
+void
+vmxnet3_tq_destroy(struct vmxnet3_tx_queue *tq,
+                  struct vmxnet3_adapter *adapter)
+{
+       if (tq->tx_ring.base) {
+               pci_free_consistent(adapter->pdev, tq->tx_ring.size *
+                                   sizeof(struct Vmxnet3_TxDesc),
+                                   tq->tx_ring.base, tq->tx_ring.basePA);
+               tq->tx_ring.base = NULL;
+       }
+       if (tq->data_ring.base) {
+               pci_free_consistent(adapter->pdev, tq->data_ring.size *
+                                   sizeof(struct Vmxnet3_TxDataDesc),
+                                   tq->data_ring.base, tq->data_ring.basePA);
+               tq->data_ring.base = NULL;
+       }
+       if (tq->comp_ring.base) {
+               pci_free_consistent(adapter->pdev, tq->comp_ring.size *
+                                   sizeof(struct Vmxnet3_TxCompDesc),
+                                   tq->comp_ring.base, tq->comp_ring.basePA);
+               tq->comp_ring.base = NULL;
+       }
+       kfree(tq->buf_info);
+       tq->buf_info = NULL;
+}
+
+
+static void
+vmxnet3_tq_init(struct vmxnet3_tx_queue *tq,
+               struct vmxnet3_adapter *adapter)
+{
+       int i;
+
+       /* reset the tx ring contents to 0 and reset the tx ring states */
+       memset(tq->tx_ring.base, 0, tq->tx_ring.size *
+              sizeof(struct Vmxnet3_TxDesc));
+       tq->tx_ring.next2fill = tq->tx_ring.next2comp = 0;
+       tq->tx_ring.gen = VMXNET3_INIT_GEN;
+
+       memset(tq->data_ring.base, 0, tq->data_ring.size *
+              sizeof(struct Vmxnet3_TxDataDesc));
+
+       /* reset the tx comp ring contents to 0 and reset comp ring states */
+       memset(tq->comp_ring.base, 0, tq->comp_ring.size *
+              sizeof(struct Vmxnet3_TxCompDesc));
+       tq->comp_ring.next2proc = 0;
+       tq->comp_ring.gen = VMXNET3_INIT_GEN;
+
+       /* reset the bookkeeping data */
+       memset(tq->buf_info, 0, sizeof(tq->buf_info[0]) * tq->tx_ring.size);
+       for (i = 0; i < tq->tx_ring.size; i++)
+               tq->buf_info[i].map_type = VMXNET3_MAP_NONE;
+
+       /* stats are not reset */
+}
+
+
+static int
+vmxnet3_tq_create(struct vmxnet3_tx_queue *tq,
+                 struct vmxnet3_adapter *adapter)
+{
+       BUG_ON(tq->tx_ring.base || tq->data_ring.base ||
+              tq->comp_ring.base || tq->buf_info);
+
+       tq->tx_ring.base = pci_alloc_consistent(adapter->pdev, tq->tx_ring.size
+                          * sizeof(struct Vmxnet3_TxDesc),
+                          &tq->tx_ring.basePA);
+       if (!tq->tx_ring.base) {
+               printk(KERN_ERR "%s: failed to allocate tx ring\n",
+                      adapter->netdev->name);
+               goto err;
+       }
+
+       tq->data_ring.base = pci_alloc_consistent(adapter->pdev,
+                            tq->data_ring.size *
+                            sizeof(struct Vmxnet3_TxDataDesc),
+                            &tq->data_ring.basePA);
+       if (!tq->data_ring.base) {
+               printk(KERN_ERR "%s: failed to allocate data ring\n",
+                      adapter->netdev->name);
+               goto err;
+       }
+
+       tq->comp_ring.base = pci_alloc_consistent(adapter->pdev,
+                            tq->comp_ring.size *
+                            sizeof(struct Vmxnet3_TxCompDesc),
+                            &tq->comp_ring.basePA);
+       if (!tq->comp_ring.base) {
+               printk(KERN_ERR "%s: failed to allocate tx comp ring\n",
+                      adapter->netdev->name);
+               goto err;
+       }
+
+       tq->buf_info = kcalloc(tq->tx_ring.size, sizeof(tq->buf_info[0]),
+                              GFP_KERNEL);
+       if (!tq->buf_info) {
+               printk(KERN_ERR "%s: failed to allocate tx bufinfo\n",
+                      adapter->netdev->name);
+               goto err;
+       }
+
+       return 0;
+
+err:
+       vmxnet3_tq_destroy(tq, adapter);
+       return -ENOMEM;
+}
+
+
+/*
+ *    starting from ring->next2fill, allocate rx buffers for the given ring
+ *    of the rx queue and update the rx desc. stop after @num_to_alloc buffers
+ *    are allocated or allocation fails
+ */
+
+static int
+vmxnet3_rq_alloc_rx_buf(struct vmxnet3_rx_queue *rq, u32 ring_idx,
+                       int num_to_alloc, struct vmxnet3_adapter *adapter)
+{
+       int num_allocated = 0;
+       struct vmxnet3_rx_buf_info *rbi_base = rq->buf_info[ring_idx];
+       struct vmxnet3_cmd_ring *ring = &rq->rx_ring[ring_idx];
+       u32 val;
+
+       while (num_allocated < num_to_alloc) {
+               struct vmxnet3_rx_buf_info *rbi;
+               union Vmxnet3_GenericDesc *gd;
+
+               rbi = rbi_base + ring->next2fill;
+               gd = ring->base + ring->next2fill;
+
+               if (rbi->buf_type == VMXNET3_RX_BUF_SKB) {
+                       if (rbi->skb == NULL) {
+                               rbi->skb = dev_alloc_skb(rbi->len +
+                                                        NET_IP_ALIGN);
+                               if (unlikely(rbi->skb == NULL)) {
+                                       rq->stats.rx_buf_alloc_failure++;
+                                       break;
+                               }
+                               rbi->skb->dev = adapter->netdev;
+
+                               skb_reserve(rbi->skb, NET_IP_ALIGN);
+                               rbi->dma_addr = pci_map_single(adapter->pdev,
+                                               rbi->skb->data, rbi->len,
+                                               PCI_DMA_FROMDEVICE);
+                       } else {
+                               /* rx buffer skipped by the device */
+                       }
+                       val = VMXNET3_RXD_BTYPE_HEAD << VMXNET3_RXD_BTYPE_SHIFT;
+               } else {
+                       BUG_ON(rbi->buf_type != VMXNET3_RX_BUF_PAGE ||
+                              rbi->len  != PAGE_SIZE);
+
+                       if (rbi->page == NULL) {
+                               rbi->page = alloc_page(GFP_ATOMIC);
+                               if (unlikely(rbi->page == NULL)) {
+                                       rq->stats.rx_buf_alloc_failure++;
+                                       break;
+                               }
+                               rbi->dma_addr = pci_map_page(adapter->pdev,
+                                               rbi->page, 0, PAGE_SIZE,
+                                               PCI_DMA_FROMDEVICE);
+                       } else {
+                               /* rx buffers skipped by the device */
+                       }
+                       val = VMXNET3_RXD_BTYPE_BODY << VMXNET3_RXD_BTYPE_SHIFT;
+               }
+
+               BUG_ON(rbi->dma_addr == 0);
+               gd->rxd.addr = rbi->dma_addr;
+               gd->dword[2] = (ring->gen << VMXNET3_RXD_GEN_SHIFT) | val |
+                               rbi->len;
+
+               num_allocated++;
+               vmxnet3_cmd_ring_adv_next2fill(ring);
+       }
+       rq->uncommitted[ring_idx] += num_allocated;
+
+       dev_dbg(&adapter->netdev->dev,
+               "alloc_rx_buf: %d allocated, next2fill %u, next2comp "
+               "%u, uncommited %u\n", num_allocated, ring->next2fill,
+               ring->next2comp, rq->uncommitted[ring_idx]);
+
+       /* so that the device can distinguish a full ring and an empty ring */
+       BUG_ON(num_allocated != 0 && ring->next2fill == ring->next2comp);
+
+       return num_allocated;
+}
+
+
+static void
+vmxnet3_append_frag(struct sk_buff *skb, struct Vmxnet3_RxCompDesc *rcd,
+                   struct vmxnet3_rx_buf_info *rbi)
+{
+       struct skb_frag_struct *frag = skb_shinfo(skb)->frags +
+               skb_shinfo(skb)->nr_frags;
+
+       BUG_ON(skb_shinfo(skb)->nr_frags >= MAX_SKB_FRAGS);
+
+       frag->page = rbi->page;
+       frag->page_offset = 0;
+       frag->size = rcd->len;
+       skb->data_len += frag->size;
+       skb_shinfo(skb)->nr_frags++;
+}
+
+
+static void
+vmxnet3_map_pkt(struct sk_buff *skb, struct vmxnet3_tx_ctx *ctx,
+               struct vmxnet3_tx_queue *tq, struct pci_dev *pdev,
+               struct vmxnet3_adapter *adapter)
+{
+       u32 dw2, len;
+       unsigned long buf_offset;
+       int i;
+       union Vmxnet3_GenericDesc *gdesc;
+       struct vmxnet3_tx_buf_info *tbi = NULL;
+
+       BUG_ON(ctx->copy_size > skb_headlen(skb));
+
+       /* use the previous gen bit for the SOP desc */
+       dw2 = (tq->tx_ring.gen ^ 0x1) << VMXNET3_TXD_GEN_SHIFT;
+
+       ctx->sop_txd = tq->tx_ring.base + tq->tx_ring.next2fill;
+       gdesc = ctx->sop_txd; /* both loops below can be skipped */
+
+       /* no need to map the buffer if headers are copied */
+       if (ctx->copy_size) {
+               ctx->sop_txd->txd.addr = tq->data_ring.basePA +
+                                       tq->tx_ring.next2fill *
+                                       sizeof(struct Vmxnet3_TxDataDesc);
+               ctx->sop_txd->dword[2] = dw2 | ctx->copy_size;
+               ctx->sop_txd->dword[3] = 0;
+
+               tbi = tq->buf_info + tq->tx_ring.next2fill;
+               tbi->map_type = VMXNET3_MAP_NONE;
+
+               dev_dbg(&adapter->netdev->dev,
+                       "txd[%u]: 0x%Lx 0x%x 0x%x\n",
+                       tq->tx_ring.next2fill, ctx->sop_txd->txd.addr,
+                       ctx->sop_txd->dword[2], ctx->sop_txd->dword[3]);
+               vmxnet3_cmd_ring_adv_next2fill(&tq->tx_ring);
+
+               /* use the right gen for non-SOP desc */
+               dw2 = tq->tx_ring.gen << VMXNET3_TXD_GEN_SHIFT;
+       }
+
+       /* linear part can use multiple tx desc if it's big */
+       len = skb_headlen(skb) - ctx->copy_size;
+       buf_offset = ctx->copy_size;
+       while (len) {
+               u32 buf_size;
+
+               buf_size = len > VMXNET3_MAX_TX_BUF_SIZE ?
+                          VMXNET3_MAX_TX_BUF_SIZE : len;
+
+               tbi = tq->buf_info + tq->tx_ring.next2fill;
+               tbi->map_type = VMXNET3_MAP_SINGLE;
+               tbi->dma_addr = pci_map_single(adapter->pdev,
+                               skb->data + buf_offset, buf_size,
+                               PCI_DMA_TODEVICE);
+
+               tbi->len = buf_size; /* this automatically convert 2^14 to 0 */
+
+               gdesc = tq->tx_ring.base + tq->tx_ring.next2fill;
+               BUG_ON(gdesc->txd.gen == tq->tx_ring.gen);
+
+               gdesc->txd.addr = tbi->dma_addr;
+               gdesc->dword[2] = dw2 | buf_size;
+               gdesc->dword[3] = 0;
+
+               dev_dbg(&adapter->netdev->dev,
+                       "txd[%u]: 0x%Lx 0x%x 0x%x\n",
+                       tq->tx_ring.next2fill, gdesc->txd.addr,
+                       gdesc->dword[2], gdesc->dword[3]);
+               vmxnet3_cmd_ring_adv_next2fill(&tq->tx_ring);
+               dw2 = tq->tx_ring.gen << VMXNET3_TXD_GEN_SHIFT;
+
+               len -= buf_size;
+               buf_offset += buf_size;
+       }
+
+       for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
+               struct skb_frag_struct *frag = &skb_shinfo(skb)->frags[i];
+
+               tbi = tq->buf_info + tq->tx_ring.next2fill;
+               tbi->map_type = VMXNET3_MAP_PAGE;
+               tbi->dma_addr = pci_map_page(adapter->pdev, frag->page,
+                                            frag->page_offset, frag->size,
+                                            PCI_DMA_TODEVICE);
+
+               tbi->len = frag->size;
+
+               gdesc = tq->tx_ring.base + tq->tx_ring.next2fill;
+               BUG_ON(gdesc->txd.gen == tq->tx_ring.gen);
+
+               gdesc->txd.addr = tbi->dma_addr;
+               gdesc->dword[2] = dw2 | frag->size;
+               gdesc->dword[3] = 0;
+
+               dev_dbg(&adapter->netdev->dev,
+                       "txd[%u]: 0x%llu %u %u\n",
+                       tq->tx_ring.next2fill, gdesc->txd.addr,
+                       gdesc->dword[2], gdesc->dword[3]);
+               vmxnet3_cmd_ring_adv_next2fill(&tq->tx_ring);
+               dw2 = tq->tx_ring.gen << VMXNET3_TXD_GEN_SHIFT;
+       }
+
+       ctx->eop_txd = gdesc;
+
+       /* set the last buf_info for the pkt */
+       tbi->skb = skb;
+       tbi->sop_idx = ctx->sop_txd - tq->tx_ring.base;
+}
+
+
+/*
+ *    parse and copy relevant protocol headers:
+ *      For a tso pkt, relevant headers are L2/3/4 including options
+ *      For a pkt requesting csum offloading, they are L2/3 and may include L4
+ *      if it's a TCP/UDP pkt
+ *
+ * Returns:
+ *    -1:  error happens during parsing
+ *     0:  protocol headers parsed, but too big to be copied
+ *     1:  protocol headers parsed and copied
+ *
+ * Other effects:
+ *    1. related *ctx fields are updated.
+ *    2. ctx->copy_size is # of bytes copied
+ *    3. the portion copied is guaranteed to be in the linear part
+ *
+ */
+static int
+vmxnet3_parse_and_copy_hdr(struct sk_buff *skb, struct vmxnet3_tx_queue *tq,
+                          struct vmxnet3_tx_ctx *ctx,
+                          struct vmxnet3_adapter *adapter)
+{
+       struct Vmxnet3_TxDataDesc *tdd;
+
+       if (ctx->mss) {
+               ctx->eth_ip_hdr_size = skb_transport_offset(skb);
+               ctx->l4_hdr_size = ((struct tcphdr *)
+                                  skb_transport_header(skb))->doff * 4;
+               ctx->copy_size = ctx->eth_ip_hdr_size + ctx->l4_hdr_size;
+       } else {
+               unsigned int pull_size;
+
+               if (skb->ip_summed == CHECKSUM_PARTIAL) {
+                       ctx->eth_ip_hdr_size = skb_transport_offset(skb);
+
+                       if (ctx->ipv4) {
+                               struct iphdr *iph = (struct iphdr *)
+                                                   skb_network_header(skb);
+                               if (iph->protocol == IPPROTO_TCP) {
+                                       pull_size = ctx->eth_ip_hdr_size +
+                                                   sizeof(struct tcphdr);
+
+                                       if (unlikely(!pskb_may_pull(skb,
+                                                               pull_size))) {
+                                               goto err;
+                                       }
+                                       ctx->l4_hdr_size = ((struct tcphdr *)
+                                          skb_transport_header(skb))->doff * 4;
+                               } else if (iph->protocol == IPPROTO_UDP) {
+                                       ctx->l4_hdr_size =
+                                                       sizeof(struct udphdr);
+                               } else {
+                                       ctx->l4_hdr_size = 0;
+                               }
+                       } else {
+                               /* for simplicity, don't copy L4 headers */
+                               ctx->l4_hdr_size = 0;
+                       }
+                       ctx->copy_size = ctx->eth_ip_hdr_size +
+                                        ctx->l4_hdr_size;
+               } else {
+                       ctx->eth_ip_hdr_size = 0;
+                       ctx->l4_hdr_size = 0;
+                       /* copy as much as allowed */
+                       ctx->copy_size = min((unsigned int)VMXNET3_HDR_COPY_SIZE
+                                            , skb_headlen(skb));
+               }
+
+               /* make sure headers are accessible directly */
+               if (unlikely(!pskb_may_pull(skb, ctx->copy_size)))
+                       goto err;
+       }
+
+       if (unlikely(ctx->copy_size > VMXNET3_HDR_COPY_SIZE)) {
+               tq->stats.oversized_hdr++;
+               ctx->copy_size = 0;
+               return 0;
+       }
+
+       tdd = tq->data_ring.base + tq->tx_ring.next2fill;
+
+       memcpy(tdd->data, skb->data, ctx->copy_size);
+       dev_dbg(&adapter->netdev->dev,
+               "copy %u bytes to dataRing[%u]\n",
+               ctx->copy_size, tq->tx_ring.next2fill);
+       return 1;
+
+err:
+       return -1;
+}
+
+
+static void
+vmxnet3_prepare_tso(struct sk_buff *skb,
+                   struct vmxnet3_tx_ctx *ctx)
+{
+       struct tcphdr *tcph = (struct tcphdr *)skb_transport_header(skb);
+       if (ctx->ipv4) {
+               struct iphdr *iph = (struct iphdr *)skb_network_header(skb);
+               iph->check = 0;
+               tcph->check = ~csum_tcpudp_magic(iph->saddr, iph->daddr, 0,
+                                                IPPROTO_TCP, 0);
+       } else {
+               struct ipv6hdr *iph = (struct ipv6hdr *)skb_network_header(skb);
+               tcph->check = ~csum_ipv6_magic(&iph->saddr, &iph->daddr, 0,
+                                              IPPROTO_TCP, 0);
+       }
+}
+
+
+/*
+ * Transmits a pkt thru a given tq
+ * Returns:
+ *    NETDEV_TX_OK:      descriptors are setup successfully
+ *    NETDEV_TX_OK:      error occured, the pkt is dropped
+ *    NETDEV_TX_BUSY:    tx ring is full, queue is stopped
+ *
+ * Side-effects:
+ *    1. tx ring may be changed
+ *    2. tq stats may be updated accordingly
+ *    3. shared->txNumDeferred may be updated
+ */
+
+static int
+vmxnet3_tq_xmit(struct sk_buff *skb, struct vmxnet3_tx_queue *tq,
+               struct vmxnet3_adapter *adapter, struct net_device *netdev)
+{
+       int ret;
+       u32 count;
+       unsigned long flags;
+       struct vmxnet3_tx_ctx ctx;
+       union Vmxnet3_GenericDesc *gdesc;
+
+       /* conservatively estimate # of descriptors to use */
+       count = VMXNET3_TXD_NEEDED(skb_headlen(skb)) +
+               skb_shinfo(skb)->nr_frags + 1;
+
+       ctx.ipv4 = (skb->protocol == __constant_ntohs(ETH_P_IP));
+
+       ctx.mss = skb_shinfo(skb)->gso_size;
+       if (ctx.mss) {
+               if (skb_header_cloned(skb)) {
+                       if (unlikely(pskb_expand_head(skb, 0, 0,
+                                                     GFP_ATOMIC) != 0)) {
+                               tq->stats.drop_tso++;
+                               goto drop_pkt;
+                       }
+                       tq->stats.copy_skb_header++;
+               }
+               vmxnet3_prepare_tso(skb, &ctx);
+       } else {
+               if (unlikely(count > VMXNET3_MAX_TXD_PER_PKT)) {
+
+                       /* non-tso pkts must not use more than
+                        * VMXNET3_MAX_TXD_PER_PKT entries
+                        */
+                       if (skb_linearize(skb) != 0) {
+                               tq->stats.drop_too_many_frags++;
+                               goto drop_pkt;
+                       }
+                       tq->stats.linearized++;
+
+                       /* recalculate the # of descriptors to use */
+                       count = VMXNET3_TXD_NEEDED(skb_headlen(skb)) + 1;
+               }
+       }
+
+       ret = vmxnet3_parse_and_copy_hdr(skb, tq, &ctx, adapter);
+       if (ret >= 0) {
+               BUG_ON(ret <= 0 && ctx.copy_size != 0);
+               /* hdrs parsed, check against other limits */
+               if (ctx.mss) {
+                       if (unlikely(ctx.eth_ip_hdr_size + ctx.l4_hdr_size >
+                                    VMXNET3_MAX_TX_BUF_SIZE)) {
+                               goto hdr_too_big;
+                       }
+               } else {
+                       if (skb->ip_summed == CHECKSUM_PARTIAL) {
+                               if (unlikely(ctx.eth_ip_hdr_size +
+                                            skb->csum_offset >
+                                            VMXNET3_MAX_CSUM_OFFSET)) {
+                                       goto hdr_too_big;
+                               }
+                       }
+               }
+       } else {
+               tq->stats.drop_hdr_inspect_err++;
+               goto drop_pkt;
+       }
+
+       spin_lock_irqsave(&tq->tx_lock, flags);
+
+       if (count > vmxnet3_cmd_ring_desc_avail(&tq->tx_ring)) {
+               tq->stats.tx_ring_full++;
+               dev_dbg(&adapter->netdev->dev,
+                       "tx queue stopped on %s, next2comp %u"
+                       " next2fill %u\n", adapter->netdev->name,
+                       tq->tx_ring.next2comp, tq->tx_ring.next2fill);
+
+               vmxnet3_tq_stop(tq, adapter);
+               spin_unlock_irqrestore(&tq->tx_lock, flags);
+               return NETDEV_TX_BUSY;
+       }
+
+       /* fill tx descs related to addr & len */
+       vmxnet3_map_pkt(skb, &ctx, tq, adapter->pdev, adapter);
+
+       /* setup the EOP desc */
+       ctx.eop_txd->dword[3] = VMXNET3_TXD_CQ | VMXNET3_TXD_EOP;
+
+       /* setup the SOP desc */
+       gdesc = ctx.sop_txd;
+       if (ctx.mss) {
+               gdesc->txd.hlen = ctx.eth_ip_hdr_size + ctx.l4_hdr_size;
+               gdesc->txd.om = VMXNET3_OM_TSO;
+               gdesc->txd.msscof = ctx.mss;
+               tq->shared->txNumDeferred += (skb->len - gdesc->txd.hlen +
+                                            ctx.mss - 1) / ctx.mss;
+       } else {
+               if (skb->ip_summed == CHECKSUM_PARTIAL) {
+                       gdesc->txd.hlen = ctx.eth_ip_hdr_size;
+                       gdesc->txd.om = VMXNET3_OM_CSUM;
+                       gdesc->txd.msscof = ctx.eth_ip_hdr_size +
+                                           skb->csum_offset;
+               } else {
+                       gdesc->txd.om = 0;
+                       gdesc->txd.msscof = 0;
+               }
+               tq->shared->txNumDeferred++;
+       }
+
+       if (vlan_tx_tag_present(skb)) {
+               gdesc->txd.ti = 1;
+               gdesc->txd.tci = vlan_tx_tag_get(skb);
+       }
+
+       wmb();
+
+       /* finally flips the GEN bit of the SOP desc */
+       gdesc->dword[2] ^= VMXNET3_TXD_GEN;
+       dev_dbg(&adapter->netdev->dev,
+               "txd[%u]: SOP 0x%Lx 0x%x 0x%x\n",
+               (u32)((union Vmxnet3_GenericDesc *)ctx.sop_txd -
+               tq->tx_ring.base), gdesc->txd.addr, gdesc->dword[2],
+               gdesc->dword[3]);
+
+       spin_unlock_irqrestore(&tq->tx_lock, flags);
+
+       if (tq->shared->txNumDeferred >= tq->shared->txThreshold) {
+               tq->shared->txNumDeferred = 0;
+               VMXNET3_WRITE_BAR0_REG(adapter, VMXNET3_REG_TXPROD,
+                                      tq->tx_ring.next2fill);
+       }
+       netdev->trans_start = jiffies;
+
+       return NETDEV_TX_OK;
+
+hdr_too_big:
+       tq->stats.drop_oversized_hdr++;
+drop_pkt:
+       tq->stats.drop_total++;
+       dev_kfree_skb(skb);
+       return NETDEV_TX_OK;
+}
+
+
+static netdev_tx_t
+vmxnet3_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
+{
+       struct vmxnet3_adapter *adapter = netdev_priv(netdev);
+       struct vmxnet3_tx_queue *tq = &adapter->tx_queue;
+
+       return vmxnet3_tq_xmit(skb, tq, adapter, netdev);
+}
+
+
+static void
+vmxnet3_rx_csum(struct vmxnet3_adapter *adapter,
+               struct sk_buff *skb,
+               union Vmxnet3_GenericDesc *gdesc)
+{
+       if (!gdesc->rcd.cnc && adapter->rxcsum) {
+               /* typical case: TCP/UDP over IP and both csums are correct */
+               if ((gdesc->dword[3] & VMXNET3_RCD_CSUM_OK) ==
+                                                       VMXNET3_RCD_CSUM_OK) {
+                       skb->ip_summed = CHECKSUM_UNNECESSARY;
+                       BUG_ON(!(gdesc->rcd.tcp || gdesc->rcd.udp));
+                       BUG_ON(!(gdesc->rcd.v4  || gdesc->rcd.v6));
+                       BUG_ON(gdesc->rcd.frg);
+               } else {
+                       if (gdesc->rcd.csum) {
+                               skb->csum = htons(gdesc->rcd.csum);
+                               skb->ip_summed = CHECKSUM_PARTIAL;
+                       } else {
+                               skb->ip_summed = CHECKSUM_NONE;
+                       }
+               }
+       } else {
+               skb->ip_summed = CHECKSUM_NONE;
+       }
+}
+
+
+static void
+vmxnet3_rx_error(struct vmxnet3_rx_queue *rq, struct Vmxnet3_RxCompDesc *rcd,
+                struct vmxnet3_rx_ctx *ctx,  struct vmxnet3_adapter *adapter)
+{
+       rq->stats.drop_err++;
+       if (!rcd->fcs)
+               rq->stats.drop_fcs++;
+
+       rq->stats.drop_total++;
+
+       /*
+        * We do not unmap and chain the rx buffer to the skb.
+        * We basically pretend this buffer is not used and will be recycled
+        * by vmxnet3_rq_alloc_rx_buf()
+        */
+
+       /*
+        * ctx->skb may be NULL if this is the first and the only one
+        * desc for the pkt
+        */
+       if (ctx->skb)
+               dev_kfree_skb_irq(ctx->skb);
+
+       ctx->skb = NULL;
+}
+
+
+static int
+vmxnet3_rq_rx_complete(struct vmxnet3_rx_queue *rq,
+                      struct vmxnet3_adapter *adapter, int quota)
+{
+       static u32 rxprod_reg[2] = {VMXNET3_REG_RXPROD, VMXNET3_REG_RXPROD2};
+       u32 num_rxd = 0;
+       struct Vmxnet3_RxCompDesc *rcd;
+       struct vmxnet3_rx_ctx *ctx = &rq->rx_ctx;
+
+       rcd = &rq->comp_ring.base[rq->comp_ring.next2proc].rcd;
+       while (rcd->gen == rq->comp_ring.gen) {
+               struct vmxnet3_rx_buf_info *rbi;
+               struct sk_buff *skb;
+               int num_to_alloc;
+               struct Vmxnet3_RxDesc *rxd;
+               u32 idx, ring_idx;
+
+               if (num_rxd >= quota) {
+                       /* we may stop even before we see the EOP desc of
+                        * the current pkt
+                        */
+                       break;
+               }
+               num_rxd++;
+
+               idx = rcd->rxdIdx;
+               ring_idx = rcd->rqID == rq->qid ? 0 : 1;
+
+               rxd = &rq->rx_ring[ring_idx].base[idx].rxd;
+               rbi = rq->buf_info[ring_idx] + idx;
+
+               BUG_ON(rxd->addr != rbi->dma_addr || rxd->len != rbi->len);
+
+               if (unlikely(rcd->eop && rcd->err)) {
+                       vmxnet3_rx_error(rq, rcd, ctx, adapter);
+                       goto rcd_done;
+               }
+
+               if (rcd->sop) { /* first buf of the pkt */
+                       BUG_ON(rxd->btype != VMXNET3_RXD_BTYPE_HEAD ||
+                              rcd->rqID != rq->qid);
+
+                       BUG_ON(rbi->buf_type != VMXNET3_RX_BUF_SKB);
+                       BUG_ON(ctx->skb != NULL || rbi->skb == NULL);
+
+                       if (unlikely(rcd->len == 0)) {
+                               /* Pretend the rx buffer is skipped. */
+                               BUG_ON(!(rcd->sop && rcd->eop));
+                               dev_dbg(&adapter->netdev->dev,
+                                       "rxRing[%u][%u] 0 length\n",
+                                       ring_idx, idx);
+                               goto rcd_done;
+                       }
+
+                       ctx->skb = rbi->skb;
+                       rbi->skb = NULL;
+
+                       pci_unmap_single(adapter->pdev, rbi->dma_addr, rbi->len,
+                                        PCI_DMA_FROMDEVICE);
+
+                       skb_put(ctx->skb, rcd->len);
+               } else {
+                       BUG_ON(ctx->skb == NULL);
+                       /* non SOP buffer must be type 1 in most cases */
+                       if (rbi->buf_type == VMXNET3_RX_BUF_PAGE) {
+                               BUG_ON(rxd->btype != VMXNET3_RXD_BTYPE_BODY);
+
+                               if (rcd->len) {
+                                       pci_unmap_page(adapter->pdev,
+                                                      rbi->dma_addr, rbi->len,
+                                                      PCI_DMA_FROMDEVICE);
+
+                                       vmxnet3_append_frag(ctx->skb, rcd, rbi);
+                                       rbi->page = NULL;
+                               }
+                       } else {
+                               /*
+                                * The only time a non-SOP buffer is type 0 is
+                                * when it's EOP and error flag is raised, which
+                                * has already been handled.
+                                */
+                               BUG_ON(true);
+                       }
+               }
+
+               skb = ctx->skb;
+               if (rcd->eop) {
+                       skb->len += skb->data_len;
+                       skb->truesize += skb->data_len;
+
+                       vmxnet3_rx_csum(adapter, skb,
+                                       (union Vmxnet3_GenericDesc *)rcd);
+                       skb->protocol = eth_type_trans(skb, adapter->netdev);
+
+                       if (unlikely(adapter->vlan_grp && rcd->ts)) {
+                               vlan_hwaccel_receive_skb(skb,
+                                               adapter->vlan_grp, rcd->tci);
+                       } else {
+                               netif_receive_skb(skb);
+                       }
+
+                       adapter->netdev->last_rx = jiffies;
+                       ctx->skb = NULL;
+               }
+
+rcd_done:
+               /* device may skip some rx descs */
+               rq->rx_ring[ring_idx].next2comp = idx;
+               VMXNET3_INC_RING_IDX_ONLY(rq->rx_ring[ring_idx].next2comp,
+                                         rq->rx_ring[ring_idx].size);
+
+               /* refill rx buffers frequently to avoid starving the h/w */
+               num_to_alloc = vmxnet3_cmd_ring_desc_avail(rq->rx_ring +
+                                                          ring_idx);
+               if (unlikely(num_to_alloc > VMXNET3_RX_ALLOC_THRESHOLD(rq,
+                                                       ring_idx, adapter))) {
+                       vmxnet3_rq_alloc_rx_buf(rq, ring_idx, num_to_alloc,
+                                               adapter);
+
+                       /* if needed, update the register */
+                       if (unlikely(rq->shared->updateRxProd)) {
+                               VMXNET3_WRITE_BAR0_REG(adapter,
+                                       rxprod_reg[ring_idx] + rq->qid * 8,
+                                       rq->rx_ring[ring_idx].next2fill);
+                               rq->uncommitted[ring_idx] = 0;
+                       }
+               }
+
+               vmxnet3_comp_ring_adv_next2proc(&rq->comp_ring);
+               rcd = &rq->comp_ring.base[rq->comp_ring.next2proc].rcd;
+       }
+
+       return num_rxd;
+}
+
+
+static void
+vmxnet3_rq_cleanup(struct vmxnet3_rx_queue *rq,
+                  struct vmxnet3_adapter *adapter)
+{
+       u32 i, ring_idx;
+       struct Vmxnet3_RxDesc *rxd;
+
+       for (ring_idx = 0; ring_idx < 2; ring_idx++) {
+               for (i = 0; i < rq->rx_ring[ring_idx].size; i++) {
+                       rxd = &rq->rx_ring[ring_idx].base[i].rxd;
+
+                       if (rxd->btype == VMXNET3_RXD_BTYPE_HEAD &&
+                                       rq->buf_info[ring_idx][i].skb) {
+                               pci_unmap_single(adapter->pdev, rxd->addr,
+                                                rxd->len, PCI_DMA_FROMDEVICE);
+                               dev_kfree_skb(rq->buf_info[ring_idx][i].skb);
+                               rq->buf_info[ring_idx][i].skb = NULL;
+                       } else if (rxd->btype == VMXNET3_RXD_BTYPE_BODY &&
+                                       rq->buf_info[ring_idx][i].page) {
+                               pci_unmap_page(adapter->pdev, rxd->addr,
+                                              rxd->len, PCI_DMA_FROMDEVICE);
+                               put_page(rq->buf_info[ring_idx][i].page);
+                               rq->buf_info[ring_idx][i].page = NULL;
+                       }
+               }
+
+               rq->rx_ring[ring_idx].gen = VMXNET3_INIT_GEN;
+               rq->rx_ring[ring_idx].next2fill =
+                                       rq->rx_ring[ring_idx].next2comp = 0;
+               rq->uncommitted[ring_idx] = 0;
+       }
+
+       rq->comp_ring.gen = VMXNET3_INIT_GEN;
+       rq->comp_ring.next2proc = 0;
+}
+
+
+void vmxnet3_rq_destroy(struct vmxnet3_rx_queue *rq,
+                       struct vmxnet3_adapter *adapter)
+{
+       int i;
+       int j;
+
+       /* all rx buffers must have already been freed */
+       for (i = 0; i < 2; i++) {
+               if (rq->buf_info[i]) {
+                       for (j = 0; j < rq->rx_ring[i].size; j++)
+                               BUG_ON(rq->buf_info[i][j].page != NULL);
+               }
+       }
+
+
+       kfree(rq->buf_info[0]);
+
+       for (i = 0; i < 2; i++) {
+               if (rq->rx_ring[i].base) {
+                       pci_free_consistent(adapter->pdev, rq->rx_ring[i].size
+                                           * sizeof(struct Vmxnet3_RxDesc),
+                                           rq->rx_ring[i].base,
+                                           rq->rx_ring[i].basePA);
+                       rq->rx_ring[i].base = NULL;
+               }
+               rq->buf_info[i] = NULL;
+       }
+
+       if (rq->comp_ring.base) {
+               pci_free_consistent(adapter->pdev, rq->comp_ring.size *
+                                   sizeof(struct Vmxnet3_RxCompDesc),
+                                   rq->comp_ring.base, rq->comp_ring.basePA);
+               rq->comp_ring.base = NULL;
+       }
+}
+
+
+static int
+vmxnet3_rq_init(struct vmxnet3_rx_queue *rq,
+               struct vmxnet3_adapter  *adapter)
+{
+       int i;
+
+       /* initialize buf_info */
+       for (i = 0; i < rq->rx_ring[0].size; i++) {
+
+               /* 1st buf for a pkt is skbuff */
+               if (i % adapter->rx_buf_per_pkt == 0) {
+                       rq->buf_info[0][i].buf_type = VMXNET3_RX_BUF_SKB;
+                       rq->buf_info[0][i].len = adapter->skb_buf_size;
+               } else { /* subsequent bufs for a pkt is frag */
+                       rq->buf_info[0][i].buf_type = VMXNET3_RX_BUF_PAGE;
+                       rq->buf_info[0][i].len = PAGE_SIZE;
+               }
+       }
+       for (i = 0; i < rq->rx_ring[1].size; i++) {
+               rq->buf_info[1][i].buf_type = VMXNET3_RX_BUF_PAGE;
+               rq->buf_info[1][i].len = PAGE_SIZE;
+       }
+
+       /* reset internal state and allocate buffers for both rings */
+       for (i = 0; i < 2; i++) {
+               rq->rx_ring[i].next2fill = rq->rx_ring[i].next2comp = 0;
+               rq->uncommitted[i] = 0;
+
+               memset(rq->rx_ring[i].base, 0, rq->rx_ring[i].size *
+                      sizeof(struct Vmxnet3_RxDesc));
+               rq->rx_ring[i].gen = VMXNET3_INIT_GEN;
+       }
+       if (vmxnet3_rq_alloc_rx_buf(rq, 0, rq->rx_ring[0].size - 1,
+                                   adapter) == 0) {
+               /* at least has 1 rx buffer for the 1st ring */
+               return -ENOMEM;
+       }
+       vmxnet3_rq_alloc_rx_buf(rq, 1, rq->rx_ring[1].size - 1, adapter);
+
+       /* reset the comp ring */
+       rq->comp_ring.next2proc = 0;
+       memset(rq->comp_ring.base, 0, rq->comp_ring.size *
+              sizeof(struct Vmxnet3_RxCompDesc));
+       rq->comp_ring.gen = VMXNET3_INIT_GEN;
+
+       /* reset rxctx */
+       rq->rx_ctx.skb = NULL;
+
+       /* stats are not reset */
+       return 0;
+}
+
+
+static int
+vmxnet3_rq_create(struct vmxnet3_rx_queue *rq, struct vmxnet3_adapter *adapter)
+{
+       int i;
+       size_t sz;
+       struct vmxnet3_rx_buf_info *bi;
+
+       for (i = 0; i < 2; i++) {
+
+               sz = rq->rx_ring[i].size * sizeof(struct Vmxnet3_RxDesc);
+               rq->rx_ring[i].base = pci_alloc_consistent(adapter->pdev, sz,
+                                                       &rq->rx_ring[i].basePA);
+               if (!rq->rx_ring[i].base) {
+                       printk(KERN_ERR "%s: failed to allocate rx ring %d\n",
+                              adapter->netdev->name, i);
+                       goto err;
+               }
+       }
+
+       sz = rq->comp_ring.size * sizeof(struct Vmxnet3_RxCompDesc);
+       rq->comp_ring.base = pci_alloc_consistent(adapter->pdev, sz,
+                                                 &rq->comp_ring.basePA);
+       if (!rq->comp_ring.base) {
+               printk(KERN_ERR "%s: failed to allocate rx comp ring\n",
+                      adapter->netdev->name);
+               goto err;
+       }
+
+       sz = sizeof(struct vmxnet3_rx_buf_info) * (rq->rx_ring[0].size +
+                                                  rq->rx_ring[1].size);
+       bi = kmalloc(sz, GFP_KERNEL);
+       if (!bi) {
+               printk(KERN_ERR "%s: failed to allocate rx bufinfo\n",
+                      adapter->netdev->name);
+               goto err;
+       }
+       memset(bi, 0, sz);
+       rq->buf_info[0] = bi;
+       rq->buf_info[1] = bi + rq->rx_ring[0].size;
+
+       return 0;
+
+err:
+       vmxnet3_rq_destroy(rq, adapter);
+       return -ENOMEM;
+}
+
+
+static int
+vmxnet3_do_poll(struct vmxnet3_adapter *adapter, int budget)
+{
+       if (unlikely(adapter->shared->ecr))
+               vmxnet3_process_events(adapter);
+
+       vmxnet3_tq_tx_complete(&adapter->tx_queue, adapter);
+       return vmxnet3_rq_rx_complete(&adapter->rx_queue, adapter, budget);
+}
+
+
+static int
+vmxnet3_poll(struct napi_struct *napi, int budget)
+{
+       struct vmxnet3_adapter *adapter = container_of(napi,
+                                         struct vmxnet3_adapter, napi);
+       int rxd_done;
+
+       rxd_done = vmxnet3_do_poll(adapter, budget);
+
+       if (rxd_done < budget) {
+               napi_complete(napi);
+               vmxnet3_enable_intr(adapter, 0);
+       }
+       return rxd_done;
+}
+
+
+/* Interrupt handler for vmxnet3  */
+static irqreturn_t
+vmxnet3_intr(int irq, void *dev_id)
+{
+       struct net_device *dev = dev_id;
+       struct vmxnet3_adapter *adapter = netdev_priv(dev);
+
+       if (unlikely(adapter->intr.type == VMXNET3_IT_INTX)) {
+               u32 icr = VMXNET3_READ_BAR1_REG(adapter, VMXNET3_REG_ICR);
+               if (unlikely(icr == 0))
+                       /* not ours */
+                       return IRQ_NONE;
+       }
+
+
+       /* disable intr if needed */
+       if (adapter->intr.mask_mode == VMXNET3_IMM_ACTIVE)
+               vmxnet3_disable_intr(adapter, 0);
+
+       napi_schedule(&adapter->napi);
+
+       return IRQ_HANDLED;
+}
+
+#ifdef CONFIG_NET_POLL_CONTROLLER
+
+
+/* netpoll callback. */
+static void
+vmxnet3_netpoll(struct net_device *netdev)
+{
+       struct vmxnet3_adapter *adapter = netdev_priv(netdev);
+       int irq;
+
+#ifdef CONFIG_PCI_MSI
+       if (adapter->intr.type == VMXNET3_IT_MSIX)
+               irq = adapter->intr.msix_entries[0].vector;
+       else
+#endif
+               irq = adapter->pdev->irq;
+
+       disable_irq(irq);
+       vmxnet3_intr(irq, netdev);
+       enable_irq(irq);
+}
+#endif
+
+static int
+vmxnet3_request_irqs(struct vmxnet3_adapter *adapter)
+{
+       int err;
+
+#ifdef CONFIG_PCI_MSI
+       if (adapter->intr.type == VMXNET3_IT_MSIX) {
+               /* we only use 1 MSI-X vector */
+               err = request_irq(adapter->intr.msix_entries[0].vector,
+                                 vmxnet3_intr, 0, adapter->netdev->name,
+                                 adapter->netdev);
+       } else
+#endif
+       if (adapter->intr.type == VMXNET3_IT_MSI) {
+               err = request_irq(adapter->pdev->irq, vmxnet3_intr, 0,
+                                 adapter->netdev->name, adapter->netdev);
+       } else {
+               err = request_irq(adapter->pdev->irq, vmxnet3_intr,
+                                 IRQF_SHARED, adapter->netdev->name,
+                                 adapter->netdev);
+       }
+
+       if (err)
+               printk(KERN_ERR "Failed to request irq %s (intr type:%d), error"
+                      ":%d\n", adapter->netdev->name, adapter->intr.type, err);
+
+
+       if (!err) {
+               int i;
+               /* init our intr settings */
+               for (i = 0; i < adapter->intr.num_intrs; i++)
+                       adapter->intr.mod_levels[i] = UPT1_IML_ADAPTIVE;
+
+               /* next setup intr index for all intr sources */
+               adapter->tx_queue.comp_ring.intr_idx = 0;
+               adapter->rx_queue.comp_ring.intr_idx = 0;
+               adapter->intr.event_intr_idx = 0;
+
+               printk(KERN_INFO "%s: intr type %u, mode %u, %u vectors "
+                      "allocated\n", adapter->netdev->name, adapter->intr.type,
+                      adapter->intr.mask_mode, adapter->intr.num_intrs);
+       }
+
+       return err;
+}
+
+
+static void
+vmxnet3_free_irqs(struct vmxnet3_adapter *adapter)
+{
+       BUG_ON(adapter->intr.type == VMXNET3_IT_AUTO ||
+              adapter->intr.num_intrs <= 0);
+
+       switch (adapter->intr.type) {
+#ifdef CONFIG_PCI_MSI
+       case VMXNET3_IT_MSIX:
+       {
+               int i;
+
+               for (i = 0; i < adapter->intr.num_intrs; i++)
+                       free_irq(adapter->intr.msix_entries[i].vector,
+                                adapter->netdev);
+               break;
+       }
+#endif
+       case VMXNET3_IT_MSI:
+               free_irq(adapter->pdev->irq, adapter->netdev);
+               break;
+       case VMXNET3_IT_INTX:
+               free_irq(adapter->pdev->irq, adapter->netdev);
+               break;
+       default:
+               BUG_ON(true);
+       }
+}
+
+
+static void
+vmxnet3_vlan_rx_register(struct net_device *netdev, struct vlan_group *grp)
+{
+       struct vmxnet3_adapter *adapter = netdev_priv(netdev);
+       struct Vmxnet3_DriverShared *shared = adapter->shared;
+       u32 *vfTable = adapter->shared->devRead.rxFilterConf.vfTable;
+
+       if (grp) {
+               /* add vlan rx stripping. */
+               if (adapter->netdev->features & NETIF_F_HW_VLAN_RX) {
+                       int i;
+                       struct Vmxnet3_DSDevRead *devRead = &shared->devRead;
+                       adapter->vlan_grp = grp;
+
+                       /* update FEATURES to device */
+                       devRead->misc.uptFeatures |= UPT1_F_RXVLAN;
+                       VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_CMD,
+                                              VMXNET3_CMD_UPDATE_FEATURE);
+                       /*
+                        *  Clear entire vfTable; then enable untagged pkts.
+                        *  Note: setting one entry in vfTable to non-zero turns
+                        *  on VLAN rx filtering.
+                        */
+                       for (i = 0; i < VMXNET3_VFT_SIZE; i++)
+                               vfTable[i] = 0;
+
+                       VMXNET3_SET_VFTABLE_ENTRY(vfTable, 0);
+                       VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_CMD,
+                                              VMXNET3_CMD_UPDATE_VLAN_FILTERS);
+               } else {
+                       printk(KERN_ERR "%s: vlan_rx_register when device has "
+                              "no NETIF_F_HW_VLAN_RX\n", netdev->name);
+               }
+       } else {
+               /* remove vlan rx stripping. */
+               struct Vmxnet3_DSDevRead *devRead = &shared->devRead;
+               adapter->vlan_grp = NULL;
+
+               if (devRead->misc.uptFeatures & UPT1_F_RXVLAN) {
+                       int i;
+
+                       for (i = 0; i < VMXNET3_VFT_SIZE; i++) {
+                               /* clear entire vfTable; this also disables
+                                * VLAN rx filtering
+                                */
+                               vfTable[i] = 0;
+                       }
+                       VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_CMD,
+                                              VMXNET3_CMD_UPDATE_VLAN_FILTERS);
+
+                       /* update FEATURES to device */
+                       devRead->misc.uptFeatures &= ~UPT1_F_RXVLAN;
+                       VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_CMD,
+                                              VMXNET3_CMD_UPDATE_FEATURE);
+               }
+       }
+}
+
+
+static void
+vmxnet3_restore_vlan(struct vmxnet3_adapter *adapter)
+{
+       if (adapter->vlan_grp) {
+               u16 vid;
+               u32 *vfTable = adapter->shared->devRead.rxFilterConf.vfTable;
+               bool activeVlan = false;
+
+               for (vid = 0; vid < VLAN_GROUP_ARRAY_LEN; vid++) {
+                       if (vlan_group_get_device(adapter->vlan_grp, vid)) {
+                               VMXNET3_SET_VFTABLE_ENTRY(vfTable, vid);
+                               activeVlan = true;
+                       }
+               }
+               if (activeVlan) {
+                       /* continue to allow untagged pkts */
+                       VMXNET3_SET_VFTABLE_ENTRY(vfTable, 0);
+               }
+       }
+}
+
+
+static void
+vmxnet3_vlan_rx_add_vid(struct net_device *netdev, u16 vid)
+{
+       struct vmxnet3_adapter *adapter = netdev_priv(netdev);
+       u32 *vfTable = adapter->shared->devRead.rxFilterConf.vfTable;
+
+       VMXNET3_SET_VFTABLE_ENTRY(vfTable, vid);
+       VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_CMD,
+                              VMXNET3_CMD_UPDATE_VLAN_FILTERS);
+}
+
+
+static void
+vmxnet3_vlan_rx_kill_vid(struct net_device *netdev, u16 vid)
+{
+       struct vmxnet3_adapter *adapter = netdev_priv(netdev);
+       u32 *vfTable = adapter->shared->devRead.rxFilterConf.vfTable;
+
+       VMXNET3_CLEAR_VFTABLE_ENTRY(vfTable, vid);
+       VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_CMD,
+                              VMXNET3_CMD_UPDATE_VLAN_FILTERS);
+}
+
+
+static u8 *
+vmxnet3_copy_mc(struct net_device *netdev)
+{
+       u8 *buf = NULL;
+       u32 sz = netdev->mc_count * ETH_ALEN;
+
+       /* struct Vmxnet3_RxFilterConf.mfTableLen is u16. */
+       if (sz <= 0xffff) {
+               /* We may be called with BH disabled */
+               buf = kmalloc(sz, GFP_ATOMIC);
+               if (buf) {
+                       int i;
+                       struct dev_mc_list *mc = netdev->mc_list;
+
+                       for (i = 0; i < netdev->mc_count; i++) {
+                               BUG_ON(!mc);
+                               memcpy(buf + i * ETH_ALEN, mc->dmi_addr,
+                                      ETH_ALEN);
+                               mc = mc->next;
+                       }
+               }
+       }
+       return buf;
+}
+
+
+static void
+vmxnet3_set_mc(struct net_device *netdev)
+{
+       struct vmxnet3_adapter *adapter = netdev_priv(netdev);
+       struct Vmxnet3_RxFilterConf *rxConf =
+                                       &adapter->shared->devRead.rxFilterConf;
+       u8 *new_table = NULL;
+       u32 new_mode = VMXNET3_RXM_UCAST;
+
+       if (netdev->flags & IFF_PROMISC)
+               new_mode |= VMXNET3_RXM_PROMISC;
+
+       if (netdev->flags & IFF_BROADCAST)
+               new_mode |= VMXNET3_RXM_BCAST;
+
+       if (netdev->flags & IFF_ALLMULTI)
+               new_mode |= VMXNET3_RXM_ALL_MULTI;
+       else
+               if (netdev->mc_count > 0) {
+                       new_table = vmxnet3_copy_mc(netdev);
+                       if (new_table) {
+                               new_mode |= VMXNET3_RXM_MCAST;
+                               rxConf->mfTableLen = netdev->mc_count *
+                                                    ETH_ALEN;
+                               rxConf->mfTablePA = virt_to_phys(new_table);
+                       } else {
+                               printk(KERN_INFO "%s: failed to copy mcast list"
+                                      ", setting ALL_MULTI\n", netdev->name);
+                               new_mode |= VMXNET3_RXM_ALL_MULTI;
+                       }
+               }
+
+
+       if (!(new_mode & VMXNET3_RXM_MCAST)) {
+               rxConf->mfTableLen = 0;
+               rxConf->mfTablePA = 0;
+       }
+
+       if (new_mode != rxConf->rxMode) {
+               rxConf->rxMode = new_mode;
+               VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_CMD,
+                                      VMXNET3_CMD_UPDATE_RX_MODE);
+       }
+
+       VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_CMD,
+                              VMXNET3_CMD_UPDATE_MAC_FILTERS);
+
+       kfree(new_table);
+}
+
+
+/*
+ *   Set up driver_shared based on settings in adapter.
+ */
+
+static void
+vmxnet3_setup_driver_shared(struct vmxnet3_adapter *adapter)
+{
+       struct Vmxnet3_DriverShared *shared = adapter->shared;
+       struct Vmxnet3_DSDevRead *devRead = &shared->devRead;
+       struct Vmxnet3_TxQueueConf *tqc;
+       struct Vmxnet3_RxQueueConf *rqc;
+       int i;
+
+       memset(shared, 0, sizeof(*shared));
+
+       /* driver settings */
+       shared->magic = VMXNET3_REV1_MAGIC;
+       devRead->misc.driverInfo.version = VMXNET3_DRIVER_VERSION_NUM;
+       devRead->misc.driverInfo.gos.gosBits = (sizeof(void *) == 4 ?
+                               VMXNET3_GOS_BITS_32 : VMXNET3_GOS_BITS_64);
+       devRead->misc.driverInfo.gos.gosType = VMXNET3_GOS_TYPE_LINUX;
+       devRead->misc.driverInfo.vmxnet3RevSpt = 1;
+       devRead->misc.driverInfo.uptVerSpt = 1;
+
+       devRead->misc.ddPA = virt_to_phys(adapter);
+       devRead->misc.ddLen = sizeof(struct vmxnet3_adapter);
+
+       /* set up feature flags */
+       if (adapter->rxcsum)
+               devRead->misc.uptFeatures |= UPT1_F_RXCSUM;
+
+       if (adapter->lro) {
+               devRead->misc.uptFeatures |= UPT1_F_LRO;
+               devRead->misc.maxNumRxSG = 1 + MAX_SKB_FRAGS;
+       }
+       if ((adapter->netdev->features & NETIF_F_HW_VLAN_RX)
+                       && adapter->vlan_grp) {
+               devRead->misc.uptFeatures |= UPT1_F_RXVLAN;
+       }
+
+       devRead->misc.mtu = adapter->netdev->mtu;
+       devRead->misc.queueDescPA = adapter->queue_desc_pa;
+       devRead->misc.queueDescLen = sizeof(struct Vmxnet3_TxQueueDesc) +
+                                    sizeof(struct Vmxnet3_RxQueueDesc);
+
+       /* tx queue settings */
+       BUG_ON(adapter->tx_queue.tx_ring.base == NULL);
+
+       devRead->misc.numTxQueues = 1;
+       tqc = &adapter->tqd_start->conf;
+       tqc->txRingBasePA   = adapter->tx_queue.tx_ring.basePA;
+       tqc->dataRingBasePA = adapter->tx_queue.data_ring.basePA;
+       tqc->compRingBasePA = adapter->tx_queue.comp_ring.basePA;
+       tqc->ddPA           = virt_to_phys(adapter->tx_queue.buf_info);
+       tqc->txRingSize     = adapter->tx_queue.tx_ring.size;
+       tqc->dataRingSize   = adapter->tx_queue.data_ring.size;
+       tqc->compRingSize   = adapter->tx_queue.comp_ring.size;
+       tqc->ddLen          = sizeof(struct vmxnet3_tx_buf_info) *
+                             tqc->txRingSize;
+       tqc->intrIdx        = adapter->tx_queue.comp_ring.intr_idx;
+
+       /* rx queue settings */
+       devRead->misc.numRxQueues = 1;
+       rqc = &adapter->rqd_start->conf;
+       rqc->rxRingBasePA[0] = adapter->rx_queue.rx_ring[0].basePA;
+       rqc->rxRingBasePA[1] = adapter->rx_queue.rx_ring[1].basePA;
+       rqc->compRingBasePA  = adapter->rx_queue.comp_ring.basePA;
+       rqc->ddPA            = virt_to_phys(adapter->rx_queue.buf_info);
+       rqc->rxRingSize[0]   = adapter->rx_queue.rx_ring[0].size;
+       rqc->rxRingSize[1]   = adapter->rx_queue.rx_ring[1].size;
+       rqc->compRingSize    = adapter->rx_queue.comp_ring.size;
+       rqc->ddLen           = sizeof(struct vmxnet3_rx_buf_info) *
+                              (rqc->rxRingSize[0] + rqc->rxRingSize[1]);
+       rqc->intrIdx         = adapter->rx_queue.comp_ring.intr_idx;
+
+       /* intr settings */
+       devRead->intrConf.autoMask = adapter->intr.mask_mode ==
+                                    VMXNET3_IMM_AUTO;
+       devRead->intrConf.numIntrs = adapter->intr.num_intrs;
+       for (i = 0; i < adapter->intr.num_intrs; i++)
+               devRead->intrConf.modLevels[i] = adapter->intr.mod_levels[i];
+
+       devRead->intrConf.eventIntrIdx = adapter->intr.event_intr_idx;
+
+       /* rx filter settings */
+       devRead->rxFilterConf.rxMode = 0;
+       vmxnet3_restore_vlan(adapter);
+       /* the rest are already zeroed */
+}
+
+
+int
+vmxnet3_activate_dev(struct vmxnet3_adapter *adapter)
+{
+       int err;
+       u32 ret;
+
+       dev_dbg(&adapter->netdev->dev,
+               "%s: skb_buf_size %d, rx_buf_per_pkt %d, ring sizes"
+               " %u %u %u\n", adapter->netdev->name, adapter->skb_buf_size,
+               adapter->rx_buf_per_pkt, adapter->tx_queue.tx_ring.size,
+               adapter->rx_queue.rx_ring[0].size,
+               adapter->rx_queue.rx_ring[1].size);
+
+       vmxnet3_tq_init(&adapter->tx_queue, adapter);
+       err = vmxnet3_rq_init(&adapter->rx_queue, adapter);
+       if (err) {
+               printk(KERN_ERR "Failed to init rx queue for %s: error %d\n",
+                      adapter->netdev->name, err);
+               goto rq_err;
+       }
+
+       err = vmxnet3_request_irqs(adapter);
+       if (err) {
+               printk(KERN_ERR "Failed to setup irq for %s: error %d\n",
+                      adapter->netdev->name, err);
+               goto irq_err;
+       }
+
+       vmxnet3_setup_driver_shared(adapter);
+
+       VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_DSAL,
+                              VMXNET3_GET_ADDR_LO(adapter->shared_pa));
+       VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_DSAH,
+                              VMXNET3_GET_ADDR_HI(adapter->shared_pa));
+
+       VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_CMD,
+                              VMXNET3_CMD_ACTIVATE_DEV);
+       ret = VMXNET3_READ_BAR1_REG(adapter, VMXNET3_REG_CMD);
+
+       if (ret != 0) {
+               printk(KERN_ERR "Failed to activate dev %s: error %u\n",
+                      adapter->netdev->name, ret);
+               err = -EINVAL;
+               goto activate_err;
+       }
+       VMXNET3_WRITE_BAR0_REG(adapter, VMXNET3_REG_RXPROD,
+                              adapter->rx_queue.rx_ring[0].next2fill);
+       VMXNET3_WRITE_BAR0_REG(adapter, VMXNET3_REG_RXPROD2,
+                              adapter->rx_queue.rx_ring[1].next2fill);
+
+       /* Apply the rx filter settins last. */
+       vmxnet3_set_mc(adapter->netdev);
+
+       /*
+        * Check link state when first activating device. It will start the
+        * tx queue if the link is up.
+        */
+       vmxnet3_check_link(adapter);
+
+       napi_enable(&adapter->napi);
+       vmxnet3_enable_all_intrs(adapter);
+       clear_bit(VMXNET3_STATE_BIT_QUIESCED, &adapter->state);
+       return 0;
+
+activate_err:
+       VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_DSAL, 0);
+       VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_DSAH, 0);
+       vmxnet3_free_irqs(adapter);
+irq_err:
+rq_err:
+       /* free up buffers we allocated */
+       vmxnet3_rq_cleanup(&adapter->rx_queue, adapter);
+       return err;
+}
+
+
+void
+vmxnet3_reset_dev(struct vmxnet3_adapter *adapter)
+{
+       VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_CMD, VMXNET3_CMD_RESET_DEV);
+}
+
+
+int
+vmxnet3_quiesce_dev(struct vmxnet3_adapter *adapter)
+{
+       if (test_and_set_bit(VMXNET3_STATE_BIT_QUIESCED, &adapter->state))
+               return 0;
+
+
+       VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_CMD,
+                              VMXNET3_CMD_QUIESCE_DEV);
+       vmxnet3_disable_all_intrs(adapter);
+
+       napi_disable(&adapter->napi);
+       netif_tx_disable(adapter->netdev);
+       adapter->link_speed = 0;
+       netif_carrier_off(adapter->netdev);
+
+       vmxnet3_tq_cleanup(&adapter->tx_queue, adapter);
+       vmxnet3_rq_cleanup(&adapter->rx_queue, adapter);
+       vmxnet3_free_irqs(adapter);
+       return 0;
+}
+
+
+static void
+vmxnet3_write_mac_addr(struct vmxnet3_adapter *adapter, u8 *mac)
+{
+       u32 tmp;
+
+       tmp = *(u32 *)mac;
+       VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_MACL, tmp);
+
+       tmp = (mac[5] << 8) | mac[4];
+       VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_MACH, tmp);
+}
+
+
+static int
+vmxnet3_set_mac_addr(struct net_device *netdev, void *p)
+{
+       struct sockaddr *addr = p;
+       struct vmxnet3_adapter *adapter = netdev_priv(netdev);
+
+       memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len);
+       vmxnet3_write_mac_addr(adapter, addr->sa_data);
+
+       return 0;
+}
+
+
+/* ==================== initialization and cleanup routines ============ */
+
+static int
+vmxnet3_alloc_pci_resources(struct vmxnet3_adapter *adapter, bool *dma64)
+{
+       int err;
+       unsigned long mmio_start, mmio_len;
+       struct pci_dev *pdev = adapter->pdev;
+
+       err = pci_enable_device(pdev);
+       if (err) {
+               printk(KERN_ERR "Failed to enable adapter %s: error %d\n",
+                      pci_name(pdev), err);
+               return err;
+       }
+
+       if (pci_set_dma_mask(pdev, DMA_BIT_MASK(64)) == 0) {
+               if (pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64)) != 0) {
+                       printk(KERN_ERR "pci_set_consistent_dma_mask failed "
+                              "for adapter %s\n", pci_name(pdev));
+                       err = -EIO;
+                       goto err_set_mask;
+               }
+               *dma64 = true;
+       } else {
+               if (pci_set_dma_mask(pdev, DMA_BIT_MASK(32)) != 0) {
+                       printk(KERN_ERR "pci_set_dma_mask failed for adapter "
+                              "%s\n",  pci_name(pdev));
+                       err = -EIO;
+                       goto err_set_mask;
+               }
+               *dma64 = false;
+       }
+
+       err = pci_request_selected_regions(pdev, (1 << 2) - 1,
+                                          vmxnet3_driver_name);
+       if (err) {
+               printk(KERN_ERR "Failed to request region for adapter %s: "
+                      "error %d\n", pci_name(pdev), err);
+               goto err_set_mask;
+       }
+
+       pci_set_master(pdev);
+
+       mmio_start = pci_resource_start(pdev, 0);
+       mmio_len = pci_resource_len(pdev, 0);
+       adapter->hw_addr0 = ioremap(mmio_start, mmio_len);
+       if (!adapter->hw_addr0) {
+               printk(KERN_ERR "Failed to map bar0 for adapter %s\n",
+                      pci_name(pdev));
+               err = -EIO;
+               goto err_ioremap;
+       }
+
+       mmio_start = pci_resource_start(pdev, 1);
+       mmio_len = pci_resource_len(pdev, 1);
+       adapter->hw_addr1 = ioremap(mmio_start, mmio_len);
+       if (!adapter->hw_addr1) {
+               printk(KERN_ERR "Failed to map bar1 for adapter %s\n",
+                      pci_name(pdev));
+               err = -EIO;
+               goto err_bar1;
+       }
+       return 0;
+
+err_bar1:
+       iounmap(adapter->hw_addr0);
+err_ioremap:
+       pci_release_selected_regions(pdev, (1 << 2) - 1);
+err_set_mask:
+       pci_disable_device(pdev);
+       return err;
+}
+
+
+static void
+vmxnet3_free_pci_resources(struct vmxnet3_adapter *adapter)
+{
+       BUG_ON(!adapter->pdev);
+
+       iounmap(adapter->hw_addr0);
+       iounmap(adapter->hw_addr1);
+       pci_release_selected_regions(adapter->pdev, (1 << 2) - 1);
+       pci_disable_device(adapter->pdev);
+}
+
+
+static void
+vmxnet3_adjust_rx_ring_size(struct vmxnet3_adapter *adapter)
+{
+       size_t sz;
+
+       if (adapter->netdev->mtu <= VMXNET3_MAX_SKB_BUF_SIZE -
+                                   VMXNET3_MAX_ETH_HDR_SIZE) {
+               adapter->skb_buf_size = adapter->netdev->mtu +
+                                       VMXNET3_MAX_ETH_HDR_SIZE;
+               if (adapter->skb_buf_size < VMXNET3_MIN_T0_BUF_SIZE)
+                       adapter->skb_buf_size = VMXNET3_MIN_T0_BUF_SIZE;
+
+               adapter->rx_buf_per_pkt = 1;
+       } else {
+               adapter->skb_buf_size = VMXNET3_MAX_SKB_BUF_SIZE;
+               sz = adapter->netdev->mtu - VMXNET3_MAX_SKB_BUF_SIZE +
+                                           VMXNET3_MAX_ETH_HDR_SIZE;
+               adapter->rx_buf_per_pkt = 1 + (sz + PAGE_SIZE - 1) / PAGE_SIZE;
+       }
+
+       /*
+        * for simplicity, force the ring0 size to be a multiple of
+        * rx_buf_per_pkt * VMXNET3_RING_SIZE_ALIGN
+        */
+       sz = adapter->rx_buf_per_pkt * VMXNET3_RING_SIZE_ALIGN;
+       adapter->rx_queue.rx_ring[0].size = (adapter->rx_queue.rx_ring[0].size +
+                                            sz - 1) / sz * sz;
+       adapter->rx_queue.rx_ring[0].size = min_t(u32,
+                                           adapter->rx_queue.rx_ring[0].size,
+                                           VMXNET3_RX_RING_MAX_SIZE / sz * sz);
+}
+
+
+int
+vmxnet3_create_queues(struct vmxnet3_adapter *adapter, u32 tx_ring_size,
+                     u32 rx_ring_size, u32 rx_ring2_size)
+{
+       int err;
+
+       adapter->tx_queue.tx_ring.size   = tx_ring_size;
+       adapter->tx_queue.data_ring.size = tx_ring_size;
+       adapter->tx_queue.comp_ring.size = tx_ring_size;
+       adapter->tx_queue.shared = &adapter->tqd_start->ctrl;
+       adapter->tx_queue.stopped = true;
+       err = vmxnet3_tq_create(&adapter->tx_queue, adapter);
+       if (err)
+               return err;
+
+       adapter->rx_queue.rx_ring[0].size = rx_ring_size;
+       adapter->rx_queue.rx_ring[1].size = rx_ring2_size;
+       vmxnet3_adjust_rx_ring_size(adapter);
+       adapter->rx_queue.comp_ring.size  = adapter->rx_queue.rx_ring[0].size +
+                                           adapter->rx_queue.rx_ring[1].size;
+       adapter->rx_queue.qid  = 0;
+       adapter->rx_queue.qid2 = 1;
+       adapter->rx_queue.shared = &adapter->rqd_start->ctrl;
+       err = vmxnet3_rq_create(&adapter->rx_queue, adapter);
+       if (err)
+               vmxnet3_tq_destroy(&adapter->tx_queue, adapter);
+
+       return err;
+}
+
+static int
+vmxnet3_open(struct net_device *netdev)
+{
+       struct vmxnet3_adapter *adapter;
+       int err;
+
+       adapter = netdev_priv(netdev);
+
+       spin_lock_init(&adapter->tx_queue.tx_lock);
+
+       err = vmxnet3_create_queues(adapter, VMXNET3_DEF_TX_RING_SIZE,
+                                   VMXNET3_DEF_RX_RING_SIZE,
+                                   VMXNET3_DEF_RX_RING_SIZE);
+       if (err)
+               goto queue_err;
+
+       err = vmxnet3_activate_dev(adapter);
+       if (err)
+               goto activate_err;
+
+       return 0;
+
+activate_err:
+       vmxnet3_rq_destroy(&adapter->rx_queue, adapter);
+       vmxnet3_tq_destroy(&adapter->tx_queue, adapter);
+queue_err:
+       return err;
+}
+
+
+static int
+vmxnet3_close(struct net_device *netdev)
+{
+       struct vmxnet3_adapter *adapter = netdev_priv(netdev);
+
+       /*
+        * Reset_work may be in the middle of resetting the device, wait for its
+        * completion.
+        */
+       while (test_and_set_bit(VMXNET3_STATE_BIT_RESETTING, &adapter->state))
+               msleep(1);
+
+       vmxnet3_quiesce_dev(adapter);
+
+       vmxnet3_rq_destroy(&adapter->rx_queue, adapter);
+       vmxnet3_tq_destroy(&adapter->tx_queue, adapter);
+
+       clear_bit(VMXNET3_STATE_BIT_RESETTING, &adapter->state);
+
+
+       return 0;
+}
+
+
+void
+vmxnet3_force_close(struct vmxnet3_adapter *adapter)
+{
+       /*
+        * we must clear VMXNET3_STATE_BIT_RESETTING, otherwise
+        * vmxnet3_close() will deadlock.
+        */
+       BUG_ON(test_bit(VMXNET3_STATE_BIT_RESETTING, &adapter->state));
+
+       /* we need to enable NAPI, otherwise dev_close will deadlock */
+       napi_enable(&adapter->napi);
+       dev_close(adapter->netdev);
+}
+
+
+static int
+vmxnet3_change_mtu(struct net_device *netdev, int new_mtu)
+{
+       struct vmxnet3_adapter *adapter = netdev_priv(netdev);
+       int err = 0;
+
+       if (new_mtu < VMXNET3_MIN_MTU || new_mtu > VMXNET3_MAX_MTU)
+               return -EINVAL;
+
+       if (new_mtu > 1500 && !adapter->jumbo_frame)
+               return -EINVAL;
+
+       netdev->mtu = new_mtu;
+
+       /*
+        * Reset_work may be in the middle of resetting the device, wait for its
+        * completion.
+        */
+       while (test_and_set_bit(VMXNET3_STATE_BIT_RESETTING, &adapter->state))
+               msleep(1);
+
+       if (netif_running(netdev)) {
+               vmxnet3_quiesce_dev(adapter);
+               vmxnet3_reset_dev(adapter);
+
+               /* we need to re-create the rx queue based on the new mtu */
+               vmxnet3_rq_destroy(&adapter->rx_queue, adapter);
+               vmxnet3_adjust_rx_ring_size(adapter);
+               adapter->rx_queue.comp_ring.size  =
+                                       adapter->rx_queue.rx_ring[0].size +
+                                       adapter->rx_queue.rx_ring[1].size;
+               err = vmxnet3_rq_create(&adapter->rx_queue, adapter);
+               if (err) {
+                       printk(KERN_ERR "%s: failed to re-create rx queue,"
+                               " error %d. Closing it.\n", netdev->name, err);
+                       goto out;
+               }
+
+               err = vmxnet3_activate_dev(adapter);
+               if (err) {
+                       printk(KERN_ERR "%s: failed to re-activate, error %d. "
+                               "Closing it\n", netdev->name, err);
+                       goto out;
+               }
+       }
+
+out:
+       clear_bit(VMXNET3_STATE_BIT_RESETTING, &adapter->state);
+       if (err)
+               vmxnet3_force_close(adapter);
+
+       return err;
+}
+
+
+static void
+vmxnet3_declare_features(struct vmxnet3_adapter *adapter, bool dma64)
+{
+       struct net_device *netdev = adapter->netdev;
+
+       netdev->features = NETIF_F_SG |
+               NETIF_F_HW_CSUM |
+               NETIF_F_HW_VLAN_TX |
+               NETIF_F_HW_VLAN_RX |
+               NETIF_F_HW_VLAN_FILTER |
+               NETIF_F_TSO |
+               NETIF_F_TSO6 |
+               NETIF_F_LRO;
+
+       printk(KERN_INFO "features: sg csum vlan jf tso tsoIPv6 lro");
+
+       adapter->rxcsum = true;
+       adapter->jumbo_frame = true;
+       adapter->lro = true;
+
+       if (dma64) {
+               netdev->features |= NETIF_F_HIGHDMA;
+               printk(" highDMA");
+       }
+
+       netdev->vlan_features = netdev->features;
+       printk("\n");
+}
+
+
+static void
+vmxnet3_read_mac_addr(struct vmxnet3_adapter *adapter, u8 *mac)
+{
+       u32 tmp;
+
+       tmp = VMXNET3_READ_BAR1_REG(adapter, VMXNET3_REG_MACL);
+       *(u32 *)mac = tmp;
+
+       tmp = VMXNET3_READ_BAR1_REG(adapter, VMXNET3_REG_MACH);
+       mac[4] = tmp & 0xff;
+       mac[5] = (tmp >> 8) & 0xff;
+}
+
+
+static void
+vmxnet3_alloc_intr_resources(struct vmxnet3_adapter *adapter)
+{
+       u32 cfg;
+
+       /* intr settings */
+       VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_CMD,
+                              VMXNET3_CMD_GET_CONF_INTR);
+       cfg = VMXNET3_READ_BAR1_REG(adapter, VMXNET3_REG_CMD);
+       adapter->intr.type = cfg & 0x3;
+       adapter->intr.mask_mode = (cfg >> 2) & 0x3;
+
+       if (adapter->intr.type == VMXNET3_IT_AUTO) {
+               int err;
+
+#ifdef CONFIG_PCI_MSI
+               adapter->intr.msix_entries[0].entry = 0;
+               err = pci_enable_msix(adapter->pdev, adapter->intr.msix_entries,
+                                     VMXNET3_LINUX_MAX_MSIX_VECT);
+               if (!err) {
+                       adapter->intr.num_intrs = 1;
+                       adapter->intr.type = VMXNET3_IT_MSIX;
+                       return;
+               }
+#endif
+
+               err = pci_enable_msi(adapter->pdev);
+               if (!err) {
+                       adapter->intr.num_intrs = 1;
+                       adapter->intr.type = VMXNET3_IT_MSI;
+                       return;
+               }
+       }
+
+       adapter->intr.type = VMXNET3_IT_INTX;
+
+       /* INT-X related setting */
+       adapter->intr.num_intrs = 1;
+}
+
+
+static void
+vmxnet3_free_intr_resources(struct vmxnet3_adapter *adapter)
+{
+       if (adapter->intr.type == VMXNET3_IT_MSIX)
+               pci_disable_msix(adapter->pdev);
+       else if (adapter->intr.type == VMXNET3_IT_MSI)
+               pci_disable_msi(adapter->pdev);
+       else
+               BUG_ON(adapter->intr.type != VMXNET3_IT_INTX);
+}
+
+
+static void
+vmxnet3_tx_timeout(struct net_device *netdev)
+{
+       struct vmxnet3_adapter *adapter = netdev_priv(netdev);
+       adapter->tx_timeout_count++;
+
+       printk(KERN_ERR "%s: tx hang\n", adapter->netdev->name);
+       schedule_work(&adapter->work);
+}
+
+
+static void
+vmxnet3_reset_work(struct work_struct *data)
+{
+       struct vmxnet3_adapter *adapter;
+
+       adapter = container_of(data, struct vmxnet3_adapter, work);
+
+       /* if another thread is resetting the device, no need to proceed */
+       if (test_and_set_bit(VMXNET3_STATE_BIT_RESETTING, &adapter->state))
+               return;
+
+       /* if the device is closed, we must leave it alone */
+       if (netif_running(adapter->netdev)) {
+               printk(KERN_INFO "%s: resetting\n", adapter->netdev->name);
+               vmxnet3_quiesce_dev(adapter);
+               vmxnet3_reset_dev(adapter);
+               vmxnet3_activate_dev(adapter);
+       } else {
+               printk(KERN_INFO "%s: already closed\n", adapter->netdev->name);
+       }
+
+       clear_bit(VMXNET3_STATE_BIT_RESETTING, &adapter->state);
+}
+
+
+static int __devinit
+vmxnet3_probe_device(struct pci_dev *pdev,
+                    const struct pci_device_id *id)
+{
+       static const struct net_device_ops vmxnet3_netdev_ops = {
+               .ndo_open = vmxnet3_open,
+               .ndo_stop = vmxnet3_close,
+               .ndo_start_xmit = vmxnet3_xmit_frame,
+               .ndo_set_mac_address = vmxnet3_set_mac_addr,
+               .ndo_change_mtu = vmxnet3_change_mtu,
+               .ndo_get_stats = vmxnet3_get_stats,
+               .ndo_tx_timeout = vmxnet3_tx_timeout,
+               .ndo_set_multicast_list = vmxnet3_set_mc,
+               .ndo_vlan_rx_register = vmxnet3_vlan_rx_register,
+               .ndo_vlan_rx_add_vid = vmxnet3_vlan_rx_add_vid,
+               .ndo_vlan_rx_kill_vid = vmxnet3_vlan_rx_kill_vid,
+#ifdef CONFIG_NET_POLL_CONTROLLER
+               .ndo_poll_controller = vmxnet3_netpoll,
+#endif
+       };
+       int err;
+       bool dma64 = false; /* stupid gcc */
+       u32 ver;
+       struct net_device *netdev;
+       struct vmxnet3_adapter *adapter;
+       u8 mac[ETH_ALEN];
+
+       netdev = alloc_etherdev(sizeof(struct vmxnet3_adapter));
+       if (!netdev) {
+               printk(KERN_ERR "Failed to alloc ethernet device for adapter "
+                       "%s\n", pci_name(pdev));
+               return -ENOMEM;
+       }
+
+       pci_set_drvdata(pdev, netdev);
+       adapter = netdev_priv(netdev);
+       adapter->netdev = netdev;
+       adapter->pdev = pdev;
+
+       adapter->shared = pci_alloc_consistent(adapter->pdev,
+                         sizeof(struct Vmxnet3_DriverShared),
+                         &adapter->shared_pa);
+       if (!adapter->shared) {
+               printk(KERN_ERR "Failed to allocate memory for %s\n",
+                       pci_name(pdev));
+               err = -ENOMEM;
+               goto err_alloc_shared;
+       }
+
+       adapter->tqd_start = pci_alloc_consistent(adapter->pdev,
+                            sizeof(struct Vmxnet3_TxQueueDesc) +
+                            sizeof(struct Vmxnet3_RxQueueDesc),
+                            &adapter->queue_desc_pa);
+
+       if (!adapter->tqd_start) {
+               printk(KERN_ERR "Failed to allocate memory for %s\n",
+                       pci_name(pdev));
+               err = -ENOMEM;
+               goto err_alloc_queue_desc;
+       }
+       adapter->rqd_start = (struct Vmxnet3_RxQueueDesc *)(adapter->tqd_start
+                                                           + 1);
+
+       adapter->pm_conf = kmalloc(sizeof(struct Vmxnet3_PMConf), GFP_KERNEL);
+       if (adapter->pm_conf == NULL) {
+               printk(KERN_ERR "Failed to allocate memory for %s\n",
+                       pci_name(pdev));
+               err = -ENOMEM;
+               goto err_alloc_pm;
+       }
+
+       err = vmxnet3_alloc_pci_resources(adapter, &dma64);
+       if (err < 0)
+               goto err_alloc_pci;
+
+       ver = VMXNET3_READ_BAR1_REG(adapter, VMXNET3_REG_VRRS);
+       if (ver & 1) {
+               VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_VRRS, 1);
+       } else {
+               printk(KERN_ERR "Incompatible h/w version (0x%x) for adapter"
+                      " %s\n", ver, pci_name(pdev));
+               err = -EBUSY;
+               goto err_ver;
+       }
+
+       ver = VMXNET3_READ_BAR1_REG(adapter, VMXNET3_REG_UVRS);
+       if (ver & 1) {
+               VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_UVRS, 1);
+       } else {
+               printk(KERN_ERR "Incompatible upt version (0x%x) for "
+                      "adapter %s\n", ver, pci_name(pdev));
+               err = -EBUSY;
+               goto err_ver;
+       }
+
+       vmxnet3_declare_features(adapter, dma64);
+
+       adapter->dev_number = atomic_read(&devices_found);
+       vmxnet3_alloc_intr_resources(adapter);
+
+       vmxnet3_read_mac_addr(adapter, mac);
+       memcpy(netdev->dev_addr,  mac, netdev->addr_len);
+
+       netdev->netdev_ops = &vmxnet3_netdev_ops;
+       netdev->watchdog_timeo = 5 * HZ;
+       vmxnet3_set_ethtool_ops(netdev);
+
+       INIT_WORK(&adapter->work, vmxnet3_reset_work);
+
+       netif_napi_add(netdev, &adapter->napi, vmxnet3_poll, 64);
+       SET_NETDEV_DEV(netdev, &pdev->dev);
+       err = register_netdev(netdev);
+
+       if (err) {
+               printk(KERN_ERR "Failed to register adapter %s\n",
+                       pci_name(pdev));
+               goto err_register;
+       }
+
+       set_bit(VMXNET3_STATE_BIT_QUIESCED, &adapter->state);
+       atomic_inc(&devices_found);
+       return 0;
+
+err_register:
+       vmxnet3_free_intr_resources(adapter);
+err_ver:
+       vmxnet3_free_pci_resources(adapter);
+err_alloc_pci:
+       kfree(adapter->pm_conf);
+err_alloc_pm:
+       pci_free_consistent(adapter->pdev, sizeof(struct Vmxnet3_TxQueueDesc) +
+                           sizeof(struct Vmxnet3_RxQueueDesc),
+                           adapter->tqd_start, adapter->queue_desc_pa);
+err_alloc_queue_desc:
+       pci_free_consistent(adapter->pdev, sizeof(struct Vmxnet3_DriverShared),
+                           adapter->shared, adapter->shared_pa);
+err_alloc_shared:
+       pci_set_drvdata(pdev, NULL);
+       free_netdev(netdev);
+       return err;
+}
+
+
+static void __devexit
+vmxnet3_remove_device(struct pci_dev *pdev)
+{
+       struct net_device *netdev = pci_get_drvdata(pdev);
+       struct vmxnet3_adapter *adapter = netdev_priv(netdev);
+
+       flush_scheduled_work();
+
+       unregister_netdev(netdev);
+
+       vmxnet3_free_intr_resources(adapter);
+       vmxnet3_free_pci_resources(adapter);
+       kfree(adapter->pm_conf);
+       pci_free_consistent(adapter->pdev, sizeof(struct Vmxnet3_TxQueueDesc) +
+                           sizeof(struct Vmxnet3_RxQueueDesc),
+                           adapter->tqd_start, adapter->queue_desc_pa);
+       pci_free_consistent(adapter->pdev, sizeof(struct Vmxnet3_DriverShared),
+                           adapter->shared, adapter->shared_pa);
+       free_netdev(netdev);
+}
+
+
+#ifdef CONFIG_PM
+
+static int
+vmxnet3_suspend(struct device *device)
+{
+       struct pci_dev *pdev = to_pci_dev(device);
+       struct net_device *netdev = pci_get_drvdata(pdev);
+       struct vmxnet3_adapter *adapter = netdev_priv(netdev);
+       struct Vmxnet3_PMConf *pmConf;
+       struct ethhdr *ehdr;
+       struct arphdr *ahdr;
+       u8 *arpreq;
+       struct in_device *in_dev;
+       struct in_ifaddr *ifa;
+       int i = 0;
+
+       if (!netif_running(netdev))
+               return 0;
+
+       vmxnet3_disable_all_intrs(adapter);
+       vmxnet3_free_irqs(adapter);
+       vmxnet3_free_intr_resources(adapter);
+
+       netif_device_detach(netdev);
+       netif_stop_queue(netdev);
+
+       /* Create wake-up filters. */
+       pmConf = adapter->pm_conf;
+       memset(pmConf, 0, sizeof(*pmConf));
+
+       if (adapter->wol & WAKE_UCAST) {
+               pmConf->filters[i].patternSize = ETH_ALEN;
+               pmConf->filters[i].maskSize = 1;
+               memcpy(pmConf->filters[i].pattern, netdev->dev_addr, ETH_ALEN);
+               pmConf->filters[i].mask[0] = 0x3F; /* LSB ETH_ALEN bits */
+
+               pmConf->wakeUpEvents |= VMXNET3_PM_WAKEUP_FILTER;
+               i++;
+       }
+
+       if (adapter->wol & WAKE_ARP) {
+               in_dev = in_dev_get(netdev);
+               if (!in_dev)
+                       goto skip_arp;
+
+               ifa = (struct in_ifaddr *)in_dev->ifa_list;
+               if (!ifa)
+                       goto skip_arp;
+
+               pmConf->filters[i].patternSize = ETH_HLEN + /* Ethernet header*/
+                       sizeof(struct arphdr) +         /* ARP header */
+                       2 * ETH_ALEN +          /* 2 Ethernet addresses*/
+                       2 * sizeof(u32);        /*2 IPv4 addresses */
+               pmConf->filters[i].maskSize =
+                       (pmConf->filters[i].patternSize - 1) / 8 + 1;
+
+               /* ETH_P_ARP in Ethernet header. */
+               ehdr = (struct ethhdr *)pmConf->filters[i].pattern;
+               ehdr->h_proto = htons(ETH_P_ARP);
+
+               /* ARPOP_REQUEST in ARP header. */
+               ahdr = (struct arphdr *)&pmConf->filters[i].pattern[ETH_HLEN];
+               ahdr->ar_op = htons(ARPOP_REQUEST);
+               arpreq = (u8 *)(ahdr + 1);
+
+               /* The Unicast IPv4 address in 'tip' field. */
+               arpreq += 2 * ETH_ALEN + sizeof(u32);
+               *(u32 *)arpreq = ifa->ifa_address;
+
+               /* The mask for the relevant bits. */
+               pmConf->filters[i].mask[0] = 0x00;
+               pmConf->filters[i].mask[1] = 0x30; /* ETH_P_ARP */
+               pmConf->filters[i].mask[2] = 0x30; /* ARPOP_REQUEST */
+               pmConf->filters[i].mask[3] = 0x00;
+               pmConf->filters[i].mask[4] = 0xC0; /* IPv4 TIP */
+               pmConf->filters[i].mask[5] = 0x03; /* IPv4 TIP */
+               in_dev_put(in_dev);
+
+               pmConf->wakeUpEvents |= VMXNET3_PM_WAKEUP_FILTER;
+               i++;
+       }
+
+skip_arp:
+       if (adapter->wol & WAKE_MAGIC)
+               pmConf->wakeUpEvents |= VMXNET3_PM_WAKEUP_MAGIC;
+
+       pmConf->numFilters = i;
+
+       adapter->shared->devRead.pmConfDesc.confVer = 1;
+       adapter->shared->devRead.pmConfDesc.confLen = sizeof(*pmConf);
+       adapter->shared->devRead.pmConfDesc.confPA = virt_to_phys(pmConf);
+
+       VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_CMD,
+                              VMXNET3_CMD_UPDATE_PMCFG);
+
+       pci_save_state(pdev);
+       pci_enable_wake(pdev, pci_choose_state(pdev, PMSG_SUSPEND),
+                       adapter->wol);
+       pci_disable_device(pdev);
+       pci_set_power_state(pdev, pci_choose_state(pdev, PMSG_SUSPEND));
+
+       return 0;
+}
+
+
+static int
+vmxnet3_resume(struct device *device)
+{
+       int err;
+       struct pci_dev *pdev = to_pci_dev(device);
+       struct net_device *netdev = pci_get_drvdata(pdev);
+       struct vmxnet3_adapter *adapter = netdev_priv(netdev);
+       struct Vmxnet3_PMConf *pmConf;
+
+       if (!netif_running(netdev))
+               return 0;
+
+       /* Destroy wake-up filters. */
+       pmConf = adapter->pm_conf;
+       memset(pmConf, 0, sizeof(*pmConf));
+
+       adapter->shared->devRead.pmConfDesc.confVer = 1;
+       adapter->shared->devRead.pmConfDesc.confLen = sizeof(*pmConf);
+       adapter->shared->devRead.pmConfDesc.confPA = virt_to_phys(pmConf);
+
+       netif_device_attach(netdev);
+       pci_set_power_state(pdev, PCI_D0);
+       pci_restore_state(pdev);
+       err = pci_enable_device_mem(pdev);
+       if (err != 0)
+               return err;
+
+       pci_enable_wake(pdev, PCI_D0, 0);
+
+       VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_CMD,
+                              VMXNET3_CMD_UPDATE_PMCFG);
+       vmxnet3_alloc_intr_resources(adapter);
+       vmxnet3_request_irqs(adapter);
+       vmxnet3_enable_all_intrs(adapter);
+
+       return 0;
+}
+
+static struct dev_pm_ops vmxnet3_pm_ops = {
+       .suspend = vmxnet3_suspend,
+       .resume = vmxnet3_resume,
+};
+#endif
+
+static struct pci_driver vmxnet3_driver = {
+       .name           = vmxnet3_driver_name,
+       .id_table       = vmxnet3_pciid_table,
+       .probe          = vmxnet3_probe_device,
+       .remove         = __devexit_p(vmxnet3_remove_device),
+#ifdef CONFIG_PM
+       .driver.pm      = &vmxnet3_pm_ops,
+#endif
+};
+
+
+static int __init
+vmxnet3_init_module(void)
+{
+       printk(KERN_INFO "%s - version %s\n", VMXNET3_DRIVER_DESC,
+               VMXNET3_DRIVER_VERSION_REPORT);
+       return pci_register_driver(&vmxnet3_driver);
+}
+
+module_init(vmxnet3_init_module);
+
+
+static void
+vmxnet3_exit_module(void)
+{
+       pci_unregister_driver(&vmxnet3_driver);
+}
+
+module_exit(vmxnet3_exit_module);
+
+MODULE_AUTHOR("VMware, Inc.");
+MODULE_DESCRIPTION(VMXNET3_DRIVER_DESC);
+MODULE_LICENSE("GPL v2");
+MODULE_VERSION(VMXNET3_DRIVER_VERSION_STRING);
diff --git a/drivers/net/vmxnet3/vmxnet3_ethtool.c b/drivers/net/vmxnet3/vmxnet3_ethtool.c
new file mode 100644 (file)
index 0000000..c2c15e4
--- /dev/null
@@ -0,0 +1,566 @@
+/*
+ * Linux driver for VMware's vmxnet3 ethernet NIC.
+ *
+ * Copyright (C) 2008-2009, VMware, 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; version 2 of the License and no 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, GOOD TITLE or
+ * NON INFRINGEMENT.  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.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Maintained by: Shreyas Bhatewara <pv-drivers@vmware.com>
+ *
+ */
+
+
+#include "vmxnet3_int.h"
+
+struct vmxnet3_stat_desc {
+       char desc[ETH_GSTRING_LEN];
+       int  offset;
+};
+
+
+static u32
+vmxnet3_get_rx_csum(struct net_device *netdev)
+{
+       struct vmxnet3_adapter *adapter = netdev_priv(netdev);
+       return adapter->rxcsum;
+}
+
+
+static int
+vmxnet3_set_rx_csum(struct net_device *netdev, u32 val)
+{
+       struct vmxnet3_adapter *adapter = netdev_priv(netdev);
+
+       if (adapter->rxcsum != val) {
+               adapter->rxcsum = val;
+               if (netif_running(netdev)) {
+                       if (val)
+                               adapter->shared->devRead.misc.uptFeatures |=
+                                                               UPT1_F_RXCSUM;
+                       else
+                               adapter->shared->devRead.misc.uptFeatures &=
+                                                               ~UPT1_F_RXCSUM;
+
+                       VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_CMD,
+                                              VMXNET3_CMD_UPDATE_FEATURE);
+               }
+       }
+       return 0;
+}
+
+
+/* per tq stats maintained by the device */
+static const struct vmxnet3_stat_desc
+vmxnet3_tq_dev_stats[] = {
+       /* description,         offset */
+       { "TSO pkts tx",        offsetof(struct UPT1_TxStats, TSOPktsTxOK) },
+       { "TSO bytes tx",       offsetof(struct UPT1_TxStats, TSOBytesTxOK) },
+       { "ucast pkts tx",      offsetof(struct UPT1_TxStats, ucastPktsTxOK) },
+       { "ucast bytes tx",     offsetof(struct UPT1_TxStats, ucastBytesTxOK) },
+       { "mcast pkts tx",      offsetof(struct UPT1_TxStats, mcastPktsTxOK) },
+       { "mcast bytes tx",     offsetof(struct UPT1_TxStats, mcastBytesTxOK) },
+       { "bcast pkts tx",      offsetof(struct UPT1_TxStats, bcastPktsTxOK) },
+       { "bcast bytes tx",     offsetof(struct UPT1_TxStats, bcastBytesTxOK) },
+       { "pkts tx err",        offsetof(struct UPT1_TxStats, pktsTxError) },
+       { "pkts tx discard",    offsetof(struct UPT1_TxStats, pktsTxDiscard) },
+};
+
+/* per tq stats maintained by the driver */
+static const struct vmxnet3_stat_desc
+vmxnet3_tq_driver_stats[] = {
+       /* description,         offset */
+       {"drv dropped tx total", offsetof(struct vmxnet3_tq_driver_stats,
+                                       drop_total) },
+       { "   too many frags",  offsetof(struct vmxnet3_tq_driver_stats,
+                                       drop_too_many_frags) },
+       { "   giant hdr",       offsetof(struct vmxnet3_tq_driver_stats,
+                                       drop_oversized_hdr) },
+       { "   hdr err",         offsetof(struct vmxnet3_tq_driver_stats,
+                                       drop_hdr_inspect_err) },
+       { "   tso",             offsetof(struct vmxnet3_tq_driver_stats,
+                                       drop_tso) },
+       { "ring full",          offsetof(struct vmxnet3_tq_driver_stats,
+                                       tx_ring_full) },
+       { "pkts linearized",    offsetof(struct vmxnet3_tq_driver_stats,
+                                       linearized) },
+       { "hdr cloned",         offsetof(struct vmxnet3_tq_driver_stats,
+                                       copy_skb_header) },
+       { "giant hdr",          offsetof(struct vmxnet3_tq_driver_stats,
+                                       oversized_hdr) },
+};
+
+/* per rq stats maintained by the device */
+static const struct vmxnet3_stat_desc
+vmxnet3_rq_dev_stats[] = {
+       { "LRO pkts rx",        offsetof(struct UPT1_RxStats, LROPktsRxOK) },
+       { "LRO byte rx",        offsetof(struct UPT1_RxStats, LROBytesRxOK) },
+       { "ucast pkts rx",      offsetof(struct UPT1_RxStats, ucastPktsRxOK) },
+       { "ucast bytes rx",     offsetof(struct UPT1_RxStats, ucastBytesRxOK) },
+       { "mcast pkts rx",      offsetof(struct UPT1_RxStats, mcastPktsRxOK) },
+       { "mcast bytes rx",     offsetof(struct UPT1_RxStats, mcastBytesRxOK) },
+       { "bcast pkts rx",      offsetof(struct UPT1_RxStats, bcastPktsRxOK) },
+       { "bcast bytes rx",     offsetof(struct UPT1_RxStats, bcastBytesRxOK) },
+       { "pkts rx out of buf", offsetof(struct UPT1_RxStats, pktsRxOutOfBuf) },
+       { "pkts rx err",        offsetof(struct UPT1_RxStats, pktsRxError) },
+};
+
+/* per rq stats maintained by the driver */
+static const struct vmxnet3_stat_desc
+vmxnet3_rq_driver_stats[] = {
+       /* description,         offset */
+       { "drv dropped rx total", offsetof(struct vmxnet3_rq_driver_stats,
+                                          drop_total) },
+       { "   err",            offsetof(struct vmxnet3_rq_driver_stats,
+                                       drop_err) },
+       { "   fcs",            offsetof(struct vmxnet3_rq_driver_stats,
+                                       drop_fcs) },
+       { "rx buf alloc fail", offsetof(struct vmxnet3_rq_driver_stats,
+                                       rx_buf_alloc_failure) },
+};
+
+/* gloabl stats maintained by the driver */
+static const struct vmxnet3_stat_desc
+vmxnet3_global_stats[] = {
+       /* description,         offset */
+       { "tx timeout count",   offsetof(struct vmxnet3_adapter,
+                                        tx_timeout_count) }
+};
+
+
+struct net_device_stats *
+vmxnet3_get_stats(struct net_device *netdev)
+{
+       struct vmxnet3_adapter *adapter;
+       struct vmxnet3_tq_driver_stats *drvTxStats;
+       struct vmxnet3_rq_driver_stats *drvRxStats;
+       struct UPT1_TxStats *devTxStats;
+       struct UPT1_RxStats *devRxStats;
+       struct net_device_stats *net_stats = &netdev->stats;
+
+       adapter = netdev_priv(netdev);
+
+       /* Collect the dev stats into the shared area */
+       VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_CMD, VMXNET3_CMD_GET_STATS);
+
+       /* Assuming that we have a single queue device */
+       devTxStats = &adapter->tqd_start->stats;
+       devRxStats = &adapter->rqd_start->stats;
+
+       /* Get access to the driver stats per queue */
+       drvTxStats = &adapter->tx_queue.stats;
+       drvRxStats = &adapter->rx_queue.stats;
+
+       memset(net_stats, 0, sizeof(*net_stats));
+
+       net_stats->rx_packets = devRxStats->ucastPktsRxOK +
+                               devRxStats->mcastPktsRxOK +
+                               devRxStats->bcastPktsRxOK;
+
+       net_stats->tx_packets = devTxStats->ucastPktsTxOK +
+                               devTxStats->mcastPktsTxOK +
+                               devTxStats->bcastPktsTxOK;
+
+       net_stats->rx_bytes = devRxStats->ucastBytesRxOK +
+                             devRxStats->mcastBytesRxOK +
+                             devRxStats->bcastBytesRxOK;
+
+       net_stats->tx_bytes = devTxStats->ucastBytesTxOK +
+                             devTxStats->mcastBytesTxOK +
+                             devTxStats->bcastBytesTxOK;
+
+       net_stats->rx_errors = devRxStats->pktsRxError;
+       net_stats->tx_errors = devTxStats->pktsTxError;
+       net_stats->rx_dropped = drvRxStats->drop_total;
+       net_stats->tx_dropped = drvTxStats->drop_total;
+       net_stats->multicast =  devRxStats->mcastPktsRxOK;
+
+       return net_stats;
+}
+
+static int
+vmxnet3_get_sset_count(struct net_device *netdev, int sset)
+{
+       switch (sset) {
+       case ETH_SS_STATS:
+               return ARRAY_SIZE(vmxnet3_tq_dev_stats) +
+                       ARRAY_SIZE(vmxnet3_tq_driver_stats) +
+                       ARRAY_SIZE(vmxnet3_rq_dev_stats) +
+                       ARRAY_SIZE(vmxnet3_rq_driver_stats) +
+                       ARRAY_SIZE(vmxnet3_global_stats);
+       default:
+               return -EOPNOTSUPP;
+       }
+}
+
+
+static int
+vmxnet3_get_regs_len(struct net_device *netdev)
+{
+       return 20 * sizeof(u32);
+}
+
+
+static void
+vmxnet3_get_drvinfo(struct net_device *netdev, struct ethtool_drvinfo *drvinfo)
+{
+       struct vmxnet3_adapter *adapter = netdev_priv(netdev);
+
+       strlcpy(drvinfo->driver, vmxnet3_driver_name, sizeof(drvinfo->driver));
+       drvinfo->driver[sizeof(drvinfo->driver) - 1] = '\0';
+
+       strlcpy(drvinfo->version, VMXNET3_DRIVER_VERSION_REPORT,
+               sizeof(drvinfo->version));
+       drvinfo->driver[sizeof(drvinfo->version) - 1] = '\0';
+
+       strlcpy(drvinfo->fw_version, "N/A", sizeof(drvinfo->fw_version));
+       drvinfo->fw_version[sizeof(drvinfo->fw_version) - 1] = '\0';
+
+       strlcpy(drvinfo->bus_info, pci_name(adapter->pdev),
+               ETHTOOL_BUSINFO_LEN);
+       drvinfo->n_stats = vmxnet3_get_sset_count(netdev, ETH_SS_STATS);
+       drvinfo->testinfo_len = 0;
+       drvinfo->eedump_len   = 0;
+       drvinfo->regdump_len  = vmxnet3_get_regs_len(netdev);
+}
+
+
+static void
+vmxnet3_get_strings(struct net_device *netdev, u32 stringset, u8 *buf)
+{
+       if (stringset == ETH_SS_STATS) {
+               int i;
+
+               for (i = 0; i < ARRAY_SIZE(vmxnet3_tq_dev_stats); i++) {
+                       memcpy(buf, vmxnet3_tq_dev_stats[i].desc,
+                              ETH_GSTRING_LEN);
+                       buf += ETH_GSTRING_LEN;
+               }
+               for (i = 0; i < ARRAY_SIZE(vmxnet3_tq_driver_stats); i++) {
+                       memcpy(buf, vmxnet3_tq_driver_stats[i].desc,
+                              ETH_GSTRING_LEN);
+                       buf += ETH_GSTRING_LEN;
+               }
+               for (i = 0; i < ARRAY_SIZE(vmxnet3_rq_dev_stats); i++) {
+                       memcpy(buf, vmxnet3_rq_dev_stats[i].desc,
+                              ETH_GSTRING_LEN);
+                       buf += ETH_GSTRING_LEN;
+               }
+               for (i = 0; i < ARRAY_SIZE(vmxnet3_rq_driver_stats); i++) {
+                       memcpy(buf, vmxnet3_rq_driver_stats[i].desc,
+                              ETH_GSTRING_LEN);
+                       buf += ETH_GSTRING_LEN;
+               }
+               for (i = 0; i < ARRAY_SIZE(vmxnet3_global_stats); i++) {
+                       memcpy(buf, vmxnet3_global_stats[i].desc,
+                               ETH_GSTRING_LEN);
+                       buf += ETH_GSTRING_LEN;
+               }
+       }
+}
+
+static u32
+vmxnet3_get_flags(struct net_device *netdev) {
+       return netdev->features;
+}
+
+static int
+vmxnet3_set_flags(struct net_device *netdev, u32 data) {
+       struct vmxnet3_adapter *adapter = netdev_priv(netdev);
+       u8 lro_requested = (data & ETH_FLAG_LRO) == 0 ? 0 : 1;
+       u8 lro_present = (netdev->features & NETIF_F_LRO) == 0 ? 0 : 1;
+
+       if (lro_requested ^ lro_present) {
+               /* toggle the LRO feature*/
+               netdev->features ^= NETIF_F_LRO;
+
+               /* update harware LRO capability accordingly */
+               if (lro_requested)
+                       adapter->shared->devRead.misc.uptFeatures &= UPT1_F_LRO;
+               else
+                       adapter->shared->devRead.misc.uptFeatures &=
+                                                               ~UPT1_F_LRO;
+               VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_CMD,
+                                      VMXNET3_CMD_UPDATE_FEATURE);
+       }
+       return 0;
+}
+
+static void
+vmxnet3_get_ethtool_stats(struct net_device *netdev,
+                         struct ethtool_stats *stats, u64  *buf)
+{
+       struct vmxnet3_adapter *adapter = netdev_priv(netdev);
+       u8 *base;
+       int i;
+
+       VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_CMD, VMXNET3_CMD_GET_STATS);
+
+       /* this does assume each counter is 64-bit wide */
+
+       base = (u8 *)&adapter->tqd_start->stats;
+       for (i = 0; i < ARRAY_SIZE(vmxnet3_tq_dev_stats); i++)
+               *buf++ = *(u64 *)(base + vmxnet3_tq_dev_stats[i].offset);
+
+       base = (u8 *)&adapter->tx_queue.stats;
+       for (i = 0; i < ARRAY_SIZE(vmxnet3_tq_driver_stats); i++)
+               *buf++ = *(u64 *)(base + vmxnet3_tq_driver_stats[i].offset);
+
+       base = (u8 *)&adapter->rqd_start->stats;
+       for (i = 0; i < ARRAY_SIZE(vmxnet3_rq_dev_stats); i++)
+               *buf++ = *(u64 *)(base + vmxnet3_rq_dev_stats[i].offset);
+
+       base = (u8 *)&adapter->rx_queue.stats;
+       for (i = 0; i < ARRAY_SIZE(vmxnet3_rq_driver_stats); i++)
+               *buf++ = *(u64 *)(base + vmxnet3_rq_driver_stats[i].offset);
+
+       base = (u8 *)adapter;
+       for (i = 0; i < ARRAY_SIZE(vmxnet3_global_stats); i++)
+               *buf++ = *(u64 *)(base + vmxnet3_global_stats[i].offset);
+}
+
+
+static void
+vmxnet3_get_regs(struct net_device *netdev, struct ethtool_regs *regs, void *p)
+{
+       struct vmxnet3_adapter *adapter = netdev_priv(netdev);
+       u32 *buf = p;
+
+       memset(p, 0, vmxnet3_get_regs_len(netdev));
+
+       regs->version = 1;
+
+       /* Update vmxnet3_get_regs_len if we want to dump more registers */
+
+       /* make each ring use multiple of 16 bytes */
+       buf[0] = adapter->tx_queue.tx_ring.next2fill;
+       buf[1] = adapter->tx_queue.tx_ring.next2comp;
+       buf[2] = adapter->tx_queue.tx_ring.gen;
+       buf[3] = 0;
+
+       buf[4] = adapter->tx_queue.comp_ring.next2proc;
+       buf[5] = adapter->tx_queue.comp_ring.gen;
+       buf[6] = adapter->tx_queue.stopped;
+       buf[7] = 0;
+
+       buf[8] = adapter->rx_queue.rx_ring[0].next2fill;
+       buf[9] = adapter->rx_queue.rx_ring[0].next2comp;
+       buf[10] = adapter->rx_queue.rx_ring[0].gen;
+       buf[11] = 0;
+
+       buf[12] = adapter->rx_queue.rx_ring[1].next2fill;
+       buf[13] = adapter->rx_queue.rx_ring[1].next2comp;
+       buf[14] = adapter->rx_queue.rx_ring[1].gen;
+       buf[15] = 0;
+
+       buf[16] = adapter->rx_queue.comp_ring.next2proc;
+       buf[17] = adapter->rx_queue.comp_ring.gen;
+       buf[18] = 0;
+       buf[19] = 0;
+}
+
+
+static void
+vmxnet3_get_wol(struct net_device *netdev, struct ethtool_wolinfo *wol)
+{
+       struct vmxnet3_adapter *adapter = netdev_priv(netdev);
+
+       wol->supported = WAKE_UCAST | WAKE_ARP | WAKE_MAGIC;
+       wol->wolopts = adapter->wol;
+}
+
+
+static int
+vmxnet3_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol)
+{
+       struct vmxnet3_adapter *adapter = netdev_priv(netdev);
+
+       if (wol->wolopts & (WAKE_PHY | WAKE_MCAST | WAKE_BCAST |
+                           WAKE_MAGICSECURE)) {
+               return -EOPNOTSUPP;
+       }
+
+       adapter->wol = wol->wolopts;
+
+       device_set_wakeup_enable(&adapter->pdev->dev, adapter->wol);
+
+       return 0;
+}
+
+
+static int
+vmxnet3_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd)
+{
+       struct vmxnet3_adapter *adapter = netdev_priv(netdev);
+
+       ecmd->supported = SUPPORTED_10000baseT_Full | SUPPORTED_1000baseT_Full |
+                         SUPPORTED_TP;
+       ecmd->advertising = ADVERTISED_TP;
+       ecmd->port = PORT_TP;
+       ecmd->transceiver = XCVR_INTERNAL;
+
+       if (adapter->link_speed) {
+               ecmd->speed = adapter->link_speed;
+               ecmd->duplex = DUPLEX_FULL;
+       } else {
+               ecmd->speed = -1;
+               ecmd->duplex = -1;
+       }
+       return 0;
+}
+
+
+static void
+vmxnet3_get_ringparam(struct net_device *netdev,
+                     struct ethtool_ringparam *param)
+{
+       struct vmxnet3_adapter *adapter = netdev_priv(netdev);
+
+       param->rx_max_pending = VMXNET3_RX_RING_MAX_SIZE;
+       param->tx_max_pending = VMXNET3_TX_RING_MAX_SIZE;
+       param->rx_mini_max_pending = 0;
+       param->rx_jumbo_max_pending = 0;
+
+       param->rx_pending = adapter->rx_queue.rx_ring[0].size;
+       param->tx_pending = adapter->tx_queue.tx_ring.size;
+       param->rx_mini_pending = 0;
+       param->rx_jumbo_pending = 0;
+}
+
+
+static int
+vmxnet3_set_ringparam(struct net_device *netdev,
+                     struct ethtool_ringparam *param)
+{
+       struct vmxnet3_adapter *adapter = netdev_priv(netdev);
+       u32 new_tx_ring_size, new_rx_ring_size;
+       u32 sz;
+       int err = 0;
+
+       if (param->tx_pending == 0 || param->tx_pending >
+                                               VMXNET3_TX_RING_MAX_SIZE)
+               return -EINVAL;
+
+       if (param->rx_pending == 0 || param->rx_pending >
+                                               VMXNET3_RX_RING_MAX_SIZE)
+               return -EINVAL;
+
+
+       /* round it up to a multiple of VMXNET3_RING_SIZE_ALIGN */
+       new_tx_ring_size = (param->tx_pending + VMXNET3_RING_SIZE_MASK) &
+                                                       ~VMXNET3_RING_SIZE_MASK;
+       new_tx_ring_size = min_t(u32, new_tx_ring_size,
+                                VMXNET3_TX_RING_MAX_SIZE);
+       if (new_tx_ring_size > VMXNET3_TX_RING_MAX_SIZE || (new_tx_ring_size %
+                                               VMXNET3_RING_SIZE_ALIGN) != 0)
+               return -EINVAL;
+
+       /* ring0 has to be a multiple of
+        * rx_buf_per_pkt * VMXNET3_RING_SIZE_ALIGN
+        */
+       sz = adapter->rx_buf_per_pkt * VMXNET3_RING_SIZE_ALIGN;
+       new_rx_ring_size = (param->rx_pending + sz - 1) / sz * sz;
+       new_rx_ring_size = min_t(u32, new_rx_ring_size,
+                                VMXNET3_RX_RING_MAX_SIZE / sz * sz);
+       if (new_rx_ring_size > VMXNET3_RX_RING_MAX_SIZE || (new_rx_ring_size %
+                                                          sz) != 0)
+               return -EINVAL;
+
+       if (new_tx_ring_size == adapter->tx_queue.tx_ring.size &&
+                       new_rx_ring_size == adapter->rx_queue.rx_ring[0].size) {
+               return 0;
+       }
+
+       /*
+        * Reset_work may be in the middle of resetting the device, wait for its
+        * completion.
+        */
+       while (test_and_set_bit(VMXNET3_STATE_BIT_RESETTING, &adapter->state))
+               msleep(1);
+
+       if (netif_running(netdev)) {
+               vmxnet3_quiesce_dev(adapter);
+               vmxnet3_reset_dev(adapter);
+
+               /* recreate the rx queue and the tx queue based on the
+                * new sizes */
+               vmxnet3_tq_destroy(&adapter->tx_queue, adapter);
+               vmxnet3_rq_destroy(&adapter->rx_queue, adapter);
+
+               err = vmxnet3_create_queues(adapter, new_tx_ring_size,
+                       new_rx_ring_size, VMXNET3_DEF_RX_RING_SIZE);
+               if (err) {
+                       /* failed, most likely because of OOM, try default
+                        * size */
+                       printk(KERN_ERR "%s: failed to apply new sizes, try the"
+                               " default ones\n", netdev->name);
+                       err = vmxnet3_create_queues(adapter,
+                                                   VMXNET3_DEF_TX_RING_SIZE,
+                                                   VMXNET3_DEF_RX_RING_SIZE,
+                                                   VMXNET3_DEF_RX_RING_SIZE);
+                       if (err) {
+                               printk(KERN_ERR "%s: failed to create queues "
+                                       "with default sizes. Closing it\n",
+                                       netdev->name);
+                               goto out;
+                       }
+               }
+
+               err = vmxnet3_activate_dev(adapter);
+               if (err)
+                       printk(KERN_ERR "%s: failed to re-activate, error %d."
+                               " Closing it\n", netdev->name, err);
+       }
+
+out:
+       clear_bit(VMXNET3_STATE_BIT_RESETTING, &adapter->state);
+       if (err)
+               vmxnet3_force_close(adapter);
+
+       return err;
+}
+
+
+static struct ethtool_ops vmxnet3_ethtool_ops = {
+       .get_settings      = vmxnet3_get_settings,
+       .get_drvinfo       = vmxnet3_get_drvinfo,
+       .get_regs_len      = vmxnet3_get_regs_len,
+       .get_regs          = vmxnet3_get_regs,
+       .get_wol           = vmxnet3_get_wol,
+       .set_wol           = vmxnet3_set_wol,
+       .get_link          = ethtool_op_get_link,
+       .get_rx_csum       = vmxnet3_get_rx_csum,
+       .set_rx_csum       = vmxnet3_set_rx_csum,
+       .get_tx_csum       = ethtool_op_get_tx_csum,
+       .set_tx_csum       = ethtool_op_set_tx_hw_csum,
+       .get_sg            = ethtool_op_get_sg,
+       .set_sg            = ethtool_op_set_sg,
+       .get_tso           = ethtool_op_get_tso,
+       .set_tso           = ethtool_op_set_tso,
+       .get_strings       = vmxnet3_get_strings,
+       .get_flags         = vmxnet3_get_flags,
+       .set_flags         = vmxnet3_set_flags,
+       .get_sset_count    = vmxnet3_get_sset_count,
+       .get_ethtool_stats = vmxnet3_get_ethtool_stats,
+       .get_ringparam     = vmxnet3_get_ringparam,
+       .set_ringparam     = vmxnet3_set_ringparam,
+};
+
+void vmxnet3_set_ethtool_ops(struct net_device *netdev)
+{
+       SET_ETHTOOL_OPS(netdev, &vmxnet3_ethtool_ops);
+}
diff --git a/drivers/net/vmxnet3/vmxnet3_int.h b/drivers/net/vmxnet3/vmxnet3_int.h
new file mode 100644 (file)
index 0000000..3c0d70d
--- /dev/null
@@ -0,0 +1,389 @@
+/*
+ * Linux driver for VMware's vmxnet3 ethernet NIC.
+ *
+ * Copyright (C) 2008-2009, VMware, 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; version 2 of the License and no 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, GOOD TITLE or
+ * NON INFRINGEMENT.  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.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Maintained by: Shreyas Bhatewara <pv-drivers@vmware.com>
+ *
+ */
+
+#ifndef _VMXNET3_INT_H
+#define _VMXNET3_INT_H
+
+#include <linux/types.h>
+#include <linux/ethtool.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/netdevice.h>
+#include <linux/pci.h>
+#include <linux/ethtool.h>
+#include <linux/compiler.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+#include <linux/ioport.h>
+#include <linux/highmem.h>
+#include <linux/init.h>
+#include <linux/timer.h>
+#include <linux/skbuff.h>
+#include <linux/interrupt.h>
+#include <linux/workqueue.h>
+#include <linux/uaccess.h>
+#include <asm/dma.h>
+#include <asm/page.h>
+
+#include <linux/tcp.h>
+#include <linux/udp.h>
+#include <linux/ip.h>
+#include <linux/ipv6.h>
+#include <linux/in.h>
+#include <linux/etherdevice.h>
+#include <asm/checksum.h>
+#include <linux/if_vlan.h>
+#include <linux/if_arp.h>
+#include <linux/inetdevice.h>
+
+#include "vmxnet3_defs.h"
+
+#ifdef DEBUG
+# define VMXNET3_DRIVER_VERSION_REPORT VMXNET3_DRIVER_VERSION_STRING"-NAPI(debug)"
+#else
+# define VMXNET3_DRIVER_VERSION_REPORT VMXNET3_DRIVER_VERSION_STRING"-NAPI"
+#endif
+
+
+/*
+ * Version numbers
+ */
+#define VMXNET3_DRIVER_VERSION_STRING   "1.0.5.0-k"
+
+/* a 32-bit int, each byte encode a verion number in VMXNET3_DRIVER_VERSION */
+#define VMXNET3_DRIVER_VERSION_NUM      0x01000500
+
+
+/*
+ * Capabilities
+ */
+
+enum {
+       VMNET_CAP_SG            = 0x0001, /* Can do scatter-gather transmits. */
+       VMNET_CAP_IP4_CSUM      = 0x0002, /* Can checksum only TCP/UDP over
+                                          * IPv4 */
+       VMNET_CAP_HW_CSUM       = 0x0004, /* Can checksum all packets. */
+       VMNET_CAP_HIGH_DMA      = 0x0008, /* Can DMA to high memory. */
+       VMNET_CAP_TOE           = 0x0010, /* Supports TCP/IP offload. */
+       VMNET_CAP_TSO           = 0x0020, /* Supports TCP Segmentation
+                                          * offload */
+       VMNET_CAP_SW_TSO        = 0x0040, /* Supports SW TCP Segmentation */
+       VMNET_CAP_VMXNET_APROM  = 0x0080, /* Vmxnet APROM support */
+       VMNET_CAP_HW_TX_VLAN    = 0x0100, /* Can we do VLAN tagging in HW */
+       VMNET_CAP_HW_RX_VLAN    = 0x0200, /* Can we do VLAN untagging in HW */
+       VMNET_CAP_SW_VLAN       = 0x0400, /* VLAN tagging/untagging in SW */
+       VMNET_CAP_WAKE_PCKT_RCV = 0x0800, /* Can wake on network packet recv? */
+       VMNET_CAP_ENABLE_INT_INLINE = 0x1000,  /* Enable Interrupt Inline */
+       VMNET_CAP_ENABLE_HEADER_COPY = 0x2000,  /* copy header for vmkernel */
+       VMNET_CAP_TX_CHAIN      = 0x4000, /* Guest can use multiple tx entries
+                                         * for a pkt */
+       VMNET_CAP_RX_CHAIN      = 0x8000, /* pkt can span multiple rx entries */
+       VMNET_CAP_LPD           = 0x10000, /* large pkt delivery */
+       VMNET_CAP_BPF           = 0x20000, /* BPF Support in VMXNET Virtual HW*/
+       VMNET_CAP_SG_SPAN_PAGES = 0x40000, /* Scatter-gather can span multiple*/
+                                          /* pages transmits */
+       VMNET_CAP_IP6_CSUM      = 0x80000, /* Can do IPv6 csum offload. */
+       VMNET_CAP_TSO6         = 0x100000, /* TSO seg. offload for IPv6 pkts. */
+       VMNET_CAP_TSO256k      = 0x200000, /* Can do TSO seg offload for */
+                                          /* pkts up to 256kB. */
+       VMNET_CAP_UPT          = 0x400000  /* Support UPT */
+};
+
+/*
+ * PCI vendor and device IDs.
+ */
+#define PCI_VENDOR_ID_VMWARE            0x15AD
+#define PCI_DEVICE_ID_VMWARE_VMXNET3    0x07B0
+#define MAX_ETHERNET_CARDS             10
+#define MAX_PCI_PASSTHRU_DEVICE                6
+
+struct vmxnet3_cmd_ring {
+       union Vmxnet3_GenericDesc *base;
+       u32             size;
+       u32             next2fill;
+       u32             next2comp;
+       u8              gen;
+       dma_addr_t      basePA;
+};
+
+static inline void
+vmxnet3_cmd_ring_adv_next2fill(struct vmxnet3_cmd_ring *ring)
+{
+       ring->next2fill++;
+       if (unlikely(ring->next2fill == ring->size)) {
+               ring->next2fill = 0;
+               VMXNET3_FLIP_RING_GEN(ring->gen);
+       }
+}
+
+static inline void
+vmxnet3_cmd_ring_adv_next2comp(struct vmxnet3_cmd_ring *ring)
+{
+       VMXNET3_INC_RING_IDX_ONLY(ring->next2comp, ring->size);
+}
+
+static inline int
+vmxnet3_cmd_ring_desc_avail(struct vmxnet3_cmd_ring *ring)
+{
+       return (ring->next2comp > ring->next2fill ? 0 : ring->size) +
+               ring->next2comp - ring->next2fill - 1;
+}
+
+struct vmxnet3_comp_ring {
+       union Vmxnet3_GenericDesc *base;
+       u32               size;
+       u32               next2proc;
+       u8                gen;
+       u8                intr_idx;
+       dma_addr_t           basePA;
+};
+
+static inline void
+vmxnet3_comp_ring_adv_next2proc(struct vmxnet3_comp_ring *ring)
+{
+       ring->next2proc++;
+       if (unlikely(ring->next2proc == ring->size)) {
+               ring->next2proc = 0;
+               VMXNET3_FLIP_RING_GEN(ring->gen);
+       }
+}
+
+struct vmxnet3_tx_data_ring {
+       struct Vmxnet3_TxDataDesc *base;
+       u32              size;
+       dma_addr_t          basePA;
+};
+
+enum vmxnet3_buf_map_type {
+       VMXNET3_MAP_INVALID = 0,
+       VMXNET3_MAP_NONE,
+       VMXNET3_MAP_SINGLE,
+       VMXNET3_MAP_PAGE,
+};
+
+struct vmxnet3_tx_buf_info {
+       u32      map_type;
+       u16      len;
+       u16      sop_idx;
+       dma_addr_t  dma_addr;
+       struct sk_buff *skb;
+};
+
+struct vmxnet3_tq_driver_stats {
+       u64 drop_total;     /* # of pkts dropped by the driver, the
+                               * counters below track droppings due to
+                               * different reasons
+                               */
+       u64 drop_too_many_frags;
+       u64 drop_oversized_hdr;
+       u64 drop_hdr_inspect_err;
+       u64 drop_tso;
+
+       u64 tx_ring_full;
+       u64 linearized;         /* # of pkts linearized */
+       u64 copy_skb_header;    /* # of times we have to copy skb header */
+       u64 oversized_hdr;
+};
+
+struct vmxnet3_tx_ctx {
+       bool   ipv4;
+       u16 mss;
+       u32 eth_ip_hdr_size; /* only valid for pkts requesting tso or csum
+                                * offloading
+                                */
+       u32 l4_hdr_size;     /* only valid if mss != 0 */
+       u32 copy_size;       /* # of bytes copied into the data ring */
+       union Vmxnet3_GenericDesc *sop_txd;
+       union Vmxnet3_GenericDesc *eop_txd;
+};
+
+struct vmxnet3_tx_queue {
+       spinlock_t                      tx_lock;
+       struct vmxnet3_cmd_ring         tx_ring;
+       struct vmxnet3_tx_buf_info     *buf_info;
+       struct vmxnet3_tx_data_ring     data_ring;
+       struct vmxnet3_comp_ring        comp_ring;
+       struct Vmxnet3_TxQueueCtrl            *shared;
+       struct vmxnet3_tq_driver_stats  stats;
+       bool                            stopped;
+       int                             num_stop;  /* # of times the queue is
+                                                   * stopped */
+} __attribute__((__aligned__(SMP_CACHE_BYTES)));
+
+enum vmxnet3_rx_buf_type {
+       VMXNET3_RX_BUF_NONE = 0,
+       VMXNET3_RX_BUF_SKB = 1,
+       VMXNET3_RX_BUF_PAGE = 2
+};
+
+struct vmxnet3_rx_buf_info {
+       enum vmxnet3_rx_buf_type buf_type;
+       u16     len;
+       union {
+               struct sk_buff *skb;
+               struct page    *page;
+       };
+       dma_addr_t dma_addr;
+};
+
+struct vmxnet3_rx_ctx {
+       struct sk_buff *skb;
+       u32 sop_idx;
+};
+
+struct vmxnet3_rq_driver_stats {
+       u64 drop_total;
+       u64 drop_err;
+       u64 drop_fcs;
+       u64 rx_buf_alloc_failure;
+};
+
+struct vmxnet3_rx_queue {
+       struct vmxnet3_cmd_ring   rx_ring[2];
+       struct vmxnet3_comp_ring  comp_ring;
+       struct vmxnet3_rx_ctx     rx_ctx;
+       u32 qid;            /* rqID in RCD for buffer from 1st ring */
+       u32 qid2;           /* rqID in RCD for buffer from 2nd ring */
+       u32 uncommitted[2]; /* # of buffers allocated since last RXPROD
+                               * update */
+       struct vmxnet3_rx_buf_info     *buf_info[2];
+       struct Vmxnet3_RxQueueCtrl            *shared;
+       struct vmxnet3_rq_driver_stats  stats;
+} __attribute__((__aligned__(SMP_CACHE_BYTES)));
+
+#define VMXNET3_LINUX_MAX_MSIX_VECT     1
+
+struct vmxnet3_intr {
+       enum vmxnet3_intr_mask_mode  mask_mode;
+       enum vmxnet3_intr_type       type;      /* MSI-X, MSI, or INTx? */
+       u8  num_intrs;                  /* # of intr vectors */
+       u8  event_intr_idx;             /* idx of the intr vector for event */
+       u8  mod_levels[VMXNET3_LINUX_MAX_MSIX_VECT]; /* moderation level */
+#ifdef CONFIG_PCI_MSI
+       struct msix_entry msix_entries[VMXNET3_LINUX_MAX_MSIX_VECT];
+#endif
+};
+
+#define VMXNET3_STATE_BIT_RESETTING   0
+#define VMXNET3_STATE_BIT_QUIESCED    1
+struct vmxnet3_adapter {
+       struct vmxnet3_tx_queue         tx_queue;
+       struct vmxnet3_rx_queue         rx_queue;
+       struct napi_struct              napi;
+       struct vlan_group              *vlan_grp;
+
+       struct vmxnet3_intr             intr;
+
+       struct Vmxnet3_DriverShared    *shared;
+       struct Vmxnet3_PMConf          *pm_conf;
+       struct Vmxnet3_TxQueueDesc     *tqd_start;     /* first tx queue desc */
+       struct Vmxnet3_RxQueueDesc     *rqd_start;     /* first rx queue desc */
+       struct net_device              *netdev;
+       struct pci_dev                 *pdev;
+
+       u8                              *hw_addr0; /* for BAR 0 */
+       u8                              *hw_addr1; /* for BAR 1 */
+
+       /* feature control */
+       bool                            rxcsum;
+       bool                            lro;
+       bool                            jumbo_frame;
+
+       /* rx buffer related */
+       unsigned                        skb_buf_size;
+       int             rx_buf_per_pkt;  /* only apply to the 1st ring */
+       dma_addr_t                      shared_pa;
+       dma_addr_t queue_desc_pa;
+
+       /* Wake-on-LAN */
+       u32     wol;
+
+       /* Link speed */
+       u32     link_speed; /* in mbps */
+
+       u64     tx_timeout_count;
+       struct work_struct work;
+
+       unsigned long  state;    /* VMXNET3_STATE_BIT_xxx */
+
+       int dev_number;
+};
+
+#define VMXNET3_WRITE_BAR0_REG(adapter, reg, val)  \
+       writel((val), (adapter)->hw_addr0 + (reg))
+#define VMXNET3_READ_BAR0_REG(adapter, reg)        \
+       readl((adapter)->hw_addr0 + (reg))
+
+#define VMXNET3_WRITE_BAR1_REG(adapter, reg, val)  \
+       writel((val), (adapter)->hw_addr1 + (reg))
+#define VMXNET3_READ_BAR1_REG(adapter, reg)        \
+       readl((adapter)->hw_addr1 + (reg))
+
+#define VMXNET3_WAKE_QUEUE_THRESHOLD(tq)  (5)
+#define VMXNET3_RX_ALLOC_THRESHOLD(rq, ring_idx, adapter) \
+       ((rq)->rx_ring[ring_idx].size >> 3)
+
+#define VMXNET3_GET_ADDR_LO(dma)   ((u32)(dma))
+#define VMXNET3_GET_ADDR_HI(dma)   ((u32)(((u64)(dma)) >> 32))
+
+/* must be a multiple of VMXNET3_RING_SIZE_ALIGN */
+#define VMXNET3_DEF_TX_RING_SIZE    512
+#define VMXNET3_DEF_RX_RING_SIZE    256
+
+#define VMXNET3_MAX_ETH_HDR_SIZE    22
+#define VMXNET3_MAX_SKB_BUF_SIZE    (3*1024)
+
+int
+vmxnet3_quiesce_dev(struct vmxnet3_adapter *adapter);
+
+int
+vmxnet3_activate_dev(struct vmxnet3_adapter *adapter);
+
+void
+vmxnet3_force_close(struct vmxnet3_adapter *adapter);
+
+void
+vmxnet3_reset_dev(struct vmxnet3_adapter *adapter);
+
+void
+vmxnet3_tq_destroy(struct vmxnet3_tx_queue *tq,
+                  struct vmxnet3_adapter *adapter);
+
+void
+vmxnet3_rq_destroy(struct vmxnet3_rx_queue *rq,
+                  struct vmxnet3_adapter *adapter);
+
+int
+vmxnet3_create_queues(struct vmxnet3_adapter *adapter,
+                     u32 tx_ring_size, u32 rx_ring_size, u32 rx_ring2_size);
+
+extern void vmxnet3_set_ethtool_ops(struct net_device *netdev);
+extern struct net_device_stats *vmxnet3_get_stats(struct net_device *netdev);
+
+extern char vmxnet3_driver_name[];
+#endif
index 9693b0f..0bd898c 100644 (file)
@@ -16,6 +16,7 @@
 
 #include <linux/module.h>
 #include <linux/kernel.h>
+#include <linux/capability.h>
 #include <linux/slab.h>
 #include <linux/types.h>
 #include <linux/string.h>
index 66360a2..e2c33c0 100644 (file)
@@ -76,6 +76,7 @@
 
 #include <linux/module.h>
 #include <linux/kernel.h>
+#include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/poll.h>
 #include <linux/fs.h>
index 2573c18..cd8cb95 100644 (file)
@@ -84,6 +84,7 @@
 #include <linux/kernel.h>      /* printk(), and other useful stuff */
 #include <linux/module.h>
 #include <linux/string.h>      /* inline memset(), etc. */
+#include <linux/sched.h>
 #include <linux/slab.h>                /* kmalloc(), kfree() */
 #include <linux/stddef.h>      /* offsetof(), etc. */
 #include <linux/wanrouter.h>   /* WAN router definitions */
index 81c8aec..07d00b4 100644 (file)
@@ -81,6 +81,7 @@
  */
 
 #include <linux/module.h>
+#include <linux/sched.h>
 #include <linux/types.h>
 #include <linux/errno.h>
 #include <linux/list.h>
index 3e90eb8..beda387 100644 (file)
@@ -19,6 +19,7 @@
 #include <linux/kernel.h>
 #include <linux/version.h>
 #include <linux/pci.h>
+#include <linux/sched.h>
 #include <linux/ioport.h>
 #include <linux/init.h>
 #include <linux/if.h>
index cf5fd17..f1bff98 100644 (file)
@@ -58,8 +58,7 @@ struct cisco_state {
        spinlock_t lock;
        unsigned long last_poll;
        int up;
-       int request_sent;
-       u32 txseq; /* TX sequence number */
+       u32 txseq; /* TX sequence number, 0 = none */
        u32 rxseq; /* RX sequence number */
 };
 
@@ -163,6 +162,7 @@ static int cisco_rx(struct sk_buff *skb)
        struct cisco_packet *cisco_data;
        struct in_device *in_dev;
        __be32 addr, mask;
+       u32 ack;
 
        if (skb->len < sizeof(struct hdlc_header))
                goto rx_error;
@@ -223,8 +223,10 @@ static int cisco_rx(struct sk_buff *skb)
                case CISCO_KEEPALIVE_REQ:
                        spin_lock(&st->lock);
                        st->rxseq = ntohl(cisco_data->par1);
-                       if (st->request_sent &&
-                           ntohl(cisco_data->par2) == st->txseq) {
+                       ack = ntohl(cisco_data->par2);
+                       if (ack && (ack == st->txseq ||
+                                   /* our current REQ may be in transit */
+                                   ack == st->txseq - 1)) {
                                st->last_poll = jiffies;
                                if (!st->up) {
                                        u32 sec, min, hrs, days;
@@ -275,7 +277,6 @@ static void cisco_timer(unsigned long arg)
 
        cisco_keepalive_send(dev, CISCO_KEEPALIVE_REQ, htonl(++st->txseq),
                             htonl(st->rxseq));
-       st->request_sent = 1;
        spin_unlock(&st->lock);
 
        st->timer.expires = jiffies + st->settings.interval * HZ;
@@ -293,9 +294,7 @@ static void cisco_start(struct net_device *dev)
        unsigned long flags;
 
        spin_lock_irqsave(&st->lock, flags);
-       st->up = 0;
-       st->request_sent = 0;
-       st->txseq = st->rxseq = 0;
+       st->up = st->txseq = st->rxseq = 0;
        spin_unlock_irqrestore(&st->lock, flags);
 
        init_timer(&st->timer);
@@ -317,8 +316,7 @@ static void cisco_stop(struct net_device *dev)
 
        spin_lock_irqsave(&st->lock, flags);
        netif_dormant_on(dev);
-       st->up = 0;
-       st->request_sent = 0;
+       st->up = st->txseq = 0;
        spin_unlock_irqrestore(&st->lock, flags);
 }
 
index 83da596..58c6681 100644 (file)
@@ -18,6 +18,7 @@
 
 #include <linux/module.h>
 #include <linux/kernel.h>
+#include <linux/capability.h>
 #include <linux/slab.h>
 #include <linux/types.h>
 #include <linux/fcntl.h>
index a52f29c..f1340fa 100644 (file)
@@ -16,6 +16,7 @@
 
 #include <linux/module.h>
 #include <linux/kernel.h>
+#include <linux/capability.h>
 #include <linux/slab.h>
 #include <linux/types.h>
 #include <linux/fcntl.h>
index 4f6ab13..b07e4d3 100644 (file)
@@ -266,7 +266,7 @@ do {                                                                \
 #define ADM8211_SYNCTL_CS1     (1 << 28)
 #define ADM8211_SYNCTL_CAL     (1 << 27)
 #define ADM8211_SYNCTL_SELCAL  (1 << 26)
-#define ADM8211_SYNCTL_RFtype  ((1 << 24) || (1 << 23) || (1 << 22))
+#define ADM8211_SYNCTL_RFtype  ((1 << 24) | (1 << 23) | (1 << 22))
 #define ADM8211_SYNCTL_RFMD    (1 << 22)
 #define ADM8211_SYNCTL_GENERAL (0x7 << 22)
 /* SYNCTL 21:0 Data (Si4126: 18-bit data, 4-bit address) */
index 7116a1a..abf896a 100644 (file)
@@ -4790,9 +4790,8 @@ static int proc_stats_rid_open( struct inode *inode,
 static int get_dec_u16( char *buffer, int *start, int limit ) {
        u16 value;
        int valid = 0;
-       for( value = 0; buffer[*start] >= '0' &&
-                    buffer[*start] <= '9' &&
-                    *start < limit; (*start)++ ) {
+       for (value = 0; *start < limit && buffer[*start] >= '0' &&
+                       buffer[*start] <= '9'; (*start)++) {
                valid = 1;
                value *= 10;
                value += buffer[*start] - '0';
index 16a2717..1895d63 100644 (file)
@@ -679,7 +679,7 @@ static u8 ath_rc_get_highest_rix(struct ath_softc *sc,
                return rate;
 
        if (rate_table->info[rate].valid_single_stream &&
-           !(ath_rc_priv->ht_cap & WLAN_RC_DS_FLAG));
+           !(ath_rc_priv->ht_cap & WLAN_RC_DS_FLAG))
                return rate;
 
        /* This should not happen */
index fa1549a..6607162 100644 (file)
@@ -607,82 +607,7 @@ struct b43_qos_params {
        struct ieee80211_tx_queue_params p;
 };
 
-struct b43_wldev;
-
-/* Data structure for the WLAN parts (802.11 cores) of the b43 chip. */
-struct b43_wl {
-       /* Pointer to the active wireless device on this chip */
-       struct b43_wldev *current_dev;
-       /* Pointer to the ieee80211 hardware data structure */
-       struct ieee80211_hw *hw;
-
-       /* Global driver mutex. Every operation must run with this mutex locked. */
-       struct mutex mutex;
-       /* Hard-IRQ spinlock. This lock protects things used in the hard-IRQ
-        * handler, only. This basically is just the IRQ mask register. */
-       spinlock_t hardirq_lock;
-
-       /* The number of queues that were registered with the mac80211 subsystem
-        * initially. This is a backup copy of hw->queues in case hw->queues has
-        * to be dynamically lowered at runtime (Firmware does not support QoS).
-        * hw->queues has to be restored to the original value before unregistering
-        * from the mac80211 subsystem. */
-       u16 mac80211_initially_registered_queues;
-
-       /* We can only have one operating interface (802.11 core)
-        * at a time. General information about this interface follows.
-        */
-
-       struct ieee80211_vif *vif;
-       /* The MAC address of the operating interface. */
-       u8 mac_addr[ETH_ALEN];
-       /* Current BSSID */
-       u8 bssid[ETH_ALEN];
-       /* Interface type. (NL80211_IFTYPE_XXX) */
-       int if_type;
-       /* Is the card operating in AP, STA or IBSS mode? */
-       bool operating;
-       /* filter flags */
-       unsigned int filter_flags;
-       /* Stats about the wireless interface */
-       struct ieee80211_low_level_stats ieee_stats;
-
-#ifdef CONFIG_B43_HWRNG
-       struct hwrng rng;
-       bool rng_initialized;
-       char rng_name[30 + 1];
-#endif /* CONFIG_B43_HWRNG */
-
-       /* List of all wireless devices on this chip */
-       struct list_head devlist;
-       u8 nr_devs;
-
-       bool radiotap_enabled;
-       bool radio_enabled;
-
-       /* The beacon we are currently using (AP or IBSS mode). */
-       struct sk_buff *current_beacon;
-       bool beacon0_uploaded;
-       bool beacon1_uploaded;
-       bool beacon_templates_virgin; /* Never wrote the templates? */
-       struct work_struct beacon_update_trigger;
-
-       /* The current QOS parameters for the 4 queues. */
-       struct b43_qos_params qos_params[4];
-
-       /* Work for adjustment of the transmission power.
-        * This is scheduled when we determine that the actual TX output
-        * power doesn't match what we want. */
-       struct work_struct txpower_adjust_work;
-
-       /* Packet transmit work */
-       struct work_struct tx_work;
-       /* Queue of packets to be transmitted. */
-       struct sk_buff_head tx_queue;
-
-       /* The device LEDs. */
-       struct b43_leds leds;
-};
+struct b43_wl;
 
 /* The type of the firmware file. */
 enum b43_firmware_file_type {
@@ -824,6 +749,97 @@ struct b43_wldev {
 #endif
 };
 
+/*
+ * Include goes here to avoid a dependency problem.
+ * A better fix would be to integrate xmit.h into b43.h.
+ */
+#include "xmit.h"
+
+/* Data structure for the WLAN parts (802.11 cores) of the b43 chip. */
+struct b43_wl {
+       /* Pointer to the active wireless device on this chip */
+       struct b43_wldev *current_dev;
+       /* Pointer to the ieee80211 hardware data structure */
+       struct ieee80211_hw *hw;
+
+       /* Global driver mutex. Every operation must run with this mutex locked. */
+       struct mutex mutex;
+       /* Hard-IRQ spinlock. This lock protects things used in the hard-IRQ
+        * handler, only. This basically is just the IRQ mask register. */
+       spinlock_t hardirq_lock;
+
+       /* The number of queues that were registered with the mac80211 subsystem
+        * initially. This is a backup copy of hw->queues in case hw->queues has
+        * to be dynamically lowered at runtime (Firmware does not support QoS).
+        * hw->queues has to be restored to the original value before unregistering
+        * from the mac80211 subsystem. */
+       u16 mac80211_initially_registered_queues;
+
+       /* We can only have one operating interface (802.11 core)
+        * at a time. General information about this interface follows.
+        */
+
+       struct ieee80211_vif *vif;
+       /* The MAC address of the operating interface. */
+       u8 mac_addr[ETH_ALEN];
+       /* Current BSSID */
+       u8 bssid[ETH_ALEN];
+       /* Interface type. (NL80211_IFTYPE_XXX) */
+       int if_type;
+       /* Is the card operating in AP, STA or IBSS mode? */
+       bool operating;
+       /* filter flags */
+       unsigned int filter_flags;
+       /* Stats about the wireless interface */
+       struct ieee80211_low_level_stats ieee_stats;
+
+#ifdef CONFIG_B43_HWRNG
+       struct hwrng rng;
+       bool rng_initialized;
+       char rng_name[30 + 1];
+#endif /* CONFIG_B43_HWRNG */
+
+       /* List of all wireless devices on this chip */
+       struct list_head devlist;
+       u8 nr_devs;
+
+       bool radiotap_enabled;
+       bool radio_enabled;
+
+       /* The beacon we are currently using (AP or IBSS mode). */
+       struct sk_buff *current_beacon;
+       bool beacon0_uploaded;
+       bool beacon1_uploaded;
+       bool beacon_templates_virgin; /* Never wrote the templates? */
+       struct work_struct beacon_update_trigger;
+
+       /* The current QOS parameters for the 4 queues. */
+       struct b43_qos_params qos_params[4];
+
+       /* Work for adjustment of the transmission power.
+        * This is scheduled when we determine that the actual TX output
+        * power doesn't match what we want. */
+       struct work_struct txpower_adjust_work;
+
+       /* Packet transmit work */
+       struct work_struct tx_work;
+       /* Queue of packets to be transmitted. */
+       struct sk_buff_head tx_queue;
+
+       /* The device LEDs. */
+       struct b43_leds leds;
+
+#ifdef CONFIG_B43_PIO
+       /*
+        * RX/TX header/tail buffers used by the frame transmit functions.
+        */
+       struct b43_rxhdr_fw4 rxhdr;
+       struct b43_txhdr txhdr;
+       u8 rx_tail[4];
+       u8 tx_tail[4];
+#endif /* CONFIG_B43_PIO */
+};
+
 static inline struct b43_wl *hw_to_b43_wl(struct ieee80211_hw *hw)
 {
        return hw->priv;
index 8701034..de4e804 100644 (file)
@@ -1157,8 +1157,9 @@ struct b43_dmaring *parse_cookie(struct b43_wldev *dev, u16 cookie, int *slot)
 }
 
 static int dma_tx_fragment(struct b43_dmaring *ring,
-                          struct sk_buff *skb)
+                          struct sk_buff **in_skb)
 {
+       struct sk_buff *skb = *in_skb;
        const struct b43_dma_ops *ops = ring->ops;
        struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
        u8 *header;
@@ -1224,8 +1225,14 @@ static int dma_tx_fragment(struct b43_dmaring *ring,
                }
 
                memcpy(skb_put(bounce_skb, skb->len), skb->data, skb->len);
+               memcpy(bounce_skb->cb, skb->cb, sizeof(skb->cb));
+               bounce_skb->dev = skb->dev;
+               skb_set_queue_mapping(bounce_skb, skb_get_queue_mapping(skb));
+               info = IEEE80211_SKB_CB(bounce_skb);
+
                dev_kfree_skb_any(skb);
                skb = bounce_skb;
+               *in_skb = bounce_skb;
                meta->skb = skb;
                meta->dmaaddr = map_descbuffer(ring, skb->data, skb->len, 1);
                if (b43_dma_mapping_error(ring, meta->dmaaddr, skb->len, 1)) {
@@ -1355,7 +1362,11 @@ int b43_dma_tx(struct b43_wldev *dev, struct sk_buff *skb)
         * static, so we don't need to store it per frame. */
        ring->queue_prio = skb_get_queue_mapping(skb);
 
-       err = dma_tx_fragment(ring, skb);
+       /* dma_tx_fragment might reallocate the skb, so invalidate pointers pointing
+        * into the skb data or cb now. */
+       hdr = NULL;
+       info = NULL;
+       err = dma_tx_fragment(ring, &skb);
        if (unlikely(err == -ENOKEY)) {
                /* Drop this packet, as we don't have the encryption key
                 * anymore and must not transmit it unencrypted. */
index fbe3d4f..1e8dba4 100644 (file)
@@ -348,9 +348,9 @@ void b43_leds_register(struct b43_wldev *dev)
        }
 }
 
-void b43_leds_unregister(struct b43_wldev *dev)
+void b43_leds_unregister(struct b43_wl *wl)
 {
-       struct b43_leds *leds = &dev->wl->leds;
+       struct b43_leds *leds = &wl->leds;
 
        b43_unregister_led(&leds->led_tx);
        b43_unregister_led(&leds->led_rx);
index 9592e4c..32b66d5 100644 (file)
@@ -1,6 +1,7 @@
 #ifndef B43_LEDS_H_
 #define B43_LEDS_H_
 
+struct b43_wl;
 struct b43_wldev;
 
 #ifdef CONFIG_B43_LEDS
@@ -60,7 +61,7 @@ enum b43_led_behaviour {
 };
 
 void b43_leds_register(struct b43_wldev *dev);
-void b43_leds_unregister(struct b43_wldev *dev);
+void b43_leds_unregister(struct b43_wl *wl);
 void b43_leds_init(struct b43_wldev *dev);
 void b43_leds_exit(struct b43_wldev *dev);
 void b43_leds_stop(struct b43_wldev *dev);
@@ -76,7 +77,7 @@ struct b43_leds {
 static inline void b43_leds_register(struct b43_wldev *dev)
 {
 }
-static inline void b43_leds_unregister(struct b43_wldev *dev)
+static inline void b43_leds_unregister(struct b43_wl *wl)
 {
 }
 static inline void b43_leds_init(struct b43_wldev *dev)
index 9b907a3..86f3582 100644 (file)
@@ -3874,6 +3874,7 @@ static struct b43_wldev * b43_wireless_core_stop(struct b43_wldev *dev)
 {
        struct b43_wl *wl = dev->wl;
        struct b43_wldev *orig_dev;
+       u32 mask;
 
 redo:
        if (!dev || b43_status(dev) < B43_STAT_STARTED)
@@ -3920,7 +3921,8 @@ redo:
                        goto redo;
                return dev;
        }
-       B43_WARN_ON(b43_read32(dev, B43_MMIO_GEN_IRQ_MASK));
+       mask = b43_read32(dev, B43_MMIO_GEN_IRQ_MASK);
+       B43_WARN_ON(mask != 0xFFFFFFFF && mask);
 
        /* Drain the TX queue */
        while (skb_queue_len(&wl->tx_queue))
@@ -4997,7 +4999,7 @@ static void b43_remove(struct ssb_device *dev)
 
        if (list_empty(&wl->devlist)) {
                b43_rng_exit(wl);
-               b43_leds_unregister(wldev);
+               b43_leds_unregister(wl);
                /* Last core on the chip unregistered.
                 * We can destroy common struct b43_wl.
                 */
index 9c13979..9b90444 100644 (file)
@@ -30,6 +30,7 @@
 #include "xmit.h"
 
 #include <linux/delay.h>
+#include <linux/sched.h>
 
 
 static u16 generate_cookie(struct b43_pio_txqueue *q,
@@ -331,6 +332,7 @@ static u16 tx_write_2byte_queue(struct b43_pio_txqueue *q,
                                unsigned int data_len)
 {
        struct b43_wldev *dev = q->dev;
+       struct b43_wl *wl = dev->wl;
        const u8 *data = _data;
 
        ctl |= B43_PIO_TXCTL_WRITELO | B43_PIO_TXCTL_WRITEHI;
@@ -340,13 +342,12 @@ static u16 tx_write_2byte_queue(struct b43_pio_txqueue *q,
                        q->mmio_base + B43_PIO_TXDATA,
                        sizeof(u16));
        if (data_len & 1) {
-               u8 tail[2] = { 0, };
-
                /* Write the last byte. */
                ctl &= ~B43_PIO_TXCTL_WRITEHI;
                b43_piotx_write16(q, B43_PIO_TXCTL, ctl);
-               tail[0] = data[data_len - 1];
-               ssb_block_write(dev->dev, tail, 2,
+               wl->tx_tail[0] = data[data_len - 1];
+               wl->tx_tail[1] = 0;
+               ssb_block_write(dev->dev, wl->tx_tail, 2,
                                q->mmio_base + B43_PIO_TXDATA,
                                sizeof(u16));
        }
@@ -381,6 +382,7 @@ static u32 tx_write_4byte_queue(struct b43_pio_txqueue *q,
                                unsigned int data_len)
 {
        struct b43_wldev *dev = q->dev;
+       struct b43_wl *wl = dev->wl;
        const u8 *data = _data;
 
        ctl |= B43_PIO8_TXCTL_0_7 | B43_PIO8_TXCTL_8_15 |
@@ -391,29 +393,31 @@ static u32 tx_write_4byte_queue(struct b43_pio_txqueue *q,
                        q->mmio_base + B43_PIO8_TXDATA,
                        sizeof(u32));
        if (data_len & 3) {
-               u8 tail[4] = { 0, };
-
+               wl->tx_tail[3] = 0;
                /* Write the last few bytes. */
                ctl &= ~(B43_PIO8_TXCTL_8_15 | B43_PIO8_TXCTL_16_23 |
                         B43_PIO8_TXCTL_24_31);
                switch (data_len & 3) {
                case 3:
                        ctl |= B43_PIO8_TXCTL_16_23 | B43_PIO8_TXCTL_8_15;
-                       tail[0] = data[data_len - 3];
-                       tail[1] = data[data_len - 2];
-                       tail[2] = data[data_len - 1];
+                       wl->tx_tail[0] = data[data_len - 3];
+                       wl->tx_tail[1] = data[data_len - 2];
+                       wl->tx_tail[2] = data[data_len - 1];
                        break;
                case 2:
                        ctl |= B43_PIO8_TXCTL_8_15;
-                       tail[0] = data[data_len - 2];
-                       tail[1] = data[data_len - 1];
+                       wl->tx_tail[0] = data[data_len - 2];
+                       wl->tx_tail[1] = data[data_len - 1];
+                       wl->tx_tail[2] = 0;
                        break;
                case 1:
-                       tail[0] = data[data_len - 1];
+                       wl->tx_tail[0] = data[data_len - 1];
+                       wl->tx_tail[1] = 0;
+                       wl->tx_tail[2] = 0;
                        break;
                }
                b43_piotx_write32(q, B43_PIO8_TXCTL, ctl);
-               ssb_block_write(dev->dev, tail, 4,
+               ssb_block_write(dev->dev, wl->tx_tail, 4,
                                q->mmio_base + B43_PIO8_TXDATA,
                                sizeof(u32));
        }
@@ -445,8 +449,9 @@ static void pio_tx_frame_4byte_queue(struct b43_pio_txpacket *pack,
 static int pio_tx_frame(struct b43_pio_txqueue *q,
                        struct sk_buff *skb)
 {
+       struct b43_wldev *dev = q->dev;
+       struct b43_wl *wl = dev->wl;
        struct b43_pio_txpacket *pack;
-       struct b43_txhdr txhdr;
        u16 cookie;
        int err;
        unsigned int hdrlen;
@@ -457,8 +462,8 @@ static int pio_tx_frame(struct b43_pio_txqueue *q,
                          struct b43_pio_txpacket, list);
 
        cookie = generate_cookie(q, pack);
-       hdrlen = b43_txhdr_size(q->dev);
-       err = b43_generate_txhdr(q->dev, (u8 *)&txhdr, skb,
+       hdrlen = b43_txhdr_size(dev);
+       err = b43_generate_txhdr(dev, (u8 *)&wl->txhdr, skb,
                                 info, cookie);
        if (err)
                return err;
@@ -466,15 +471,15 @@ static int pio_tx_frame(struct b43_pio_txqueue *q,
        if (info->flags & IEEE80211_TX_CTL_SEND_AFTER_DTIM) {
                /* Tell the firmware about the cookie of the last
                 * mcast frame, so it can clear the more-data bit in it. */
-               b43_shm_write16(q->dev, B43_SHM_SHARED,
+               b43_shm_write16(dev, B43_SHM_SHARED,
                                B43_SHM_SH_MCASTCOOKIE, cookie);
        }
 
        pack->skb = skb;
        if (q->rev >= 8)
-               pio_tx_frame_4byte_queue(pack, (const u8 *)&txhdr, hdrlen);
+               pio_tx_frame_4byte_queue(pack, (const u8 *)&wl->txhdr, hdrlen);
        else
-               pio_tx_frame_2byte_queue(pack, (const u8 *)&txhdr, hdrlen);
+               pio_tx_frame_2byte_queue(pack, (const u8 *)&wl->txhdr, hdrlen);
 
        /* Remove it from the list of available packet slots.
         * It will be put back when we receive the status report. */
@@ -614,14 +619,14 @@ void b43_pio_get_tx_stats(struct b43_wldev *dev,
 static bool pio_rx_frame(struct b43_pio_rxqueue *q)
 {
        struct b43_wldev *dev = q->dev;
-       struct b43_rxhdr_fw4 rxhdr;
+       struct b43_wl *wl = dev->wl;
        u16 len;
        u32 macstat;
        unsigned int i, padding;
        struct sk_buff *skb;
        const char *err_msg = NULL;
 
-       memset(&rxhdr, 0, sizeof(rxhdr));
+       memset(&wl->rxhdr, 0, sizeof(wl->rxhdr));
 
        /* Check if we have data and wait for it to get ready. */
        if (q->rev >= 8) {
@@ -659,16 +664,16 @@ data_ready:
 
        /* Get the preamble (RX header) */
        if (q->rev >= 8) {
-               ssb_block_read(dev->dev, &rxhdr, sizeof(rxhdr),
+               ssb_block_read(dev->dev, &wl->rxhdr, sizeof(wl->rxhdr),
                               q->mmio_base + B43_PIO8_RXDATA,
                               sizeof(u32));
        } else {
-               ssb_block_read(dev->dev, &rxhdr, sizeof(rxhdr),
+               ssb_block_read(dev->dev, &wl->rxhdr, sizeof(wl->rxhdr),
                               q->mmio_base + B43_PIO_RXDATA,
                               sizeof(u16));
        }
        /* Sanity checks. */
-       len = le16_to_cpu(rxhdr.frame_len);
+       len = le16_to_cpu(wl->rxhdr.frame_len);
        if (unlikely(len > 0x700)) {
                err_msg = "len > 0x700";
                goto rx_error;
@@ -678,7 +683,7 @@ data_ready:
                goto rx_error;
        }
 
-       macstat = le32_to_cpu(rxhdr.mac_status);
+       macstat = le32_to_cpu(wl->rxhdr.mac_status);
        if (macstat & B43_RX_MAC_FCSERR) {
                if (!(q->dev->wl->filter_flags & FIF_FCSFAIL)) {
                        /* Drop frames with failed FCS. */
@@ -703,24 +708,22 @@ data_ready:
                               q->mmio_base + B43_PIO8_RXDATA,
                               sizeof(u32));
                if (len & 3) {
-                       u8 tail[4] = { 0, };
-
                        /* Read the last few bytes. */
-                       ssb_block_read(dev->dev, tail, 4,
+                       ssb_block_read(dev->dev, wl->rx_tail, 4,
                                       q->mmio_base + B43_PIO8_RXDATA,
                                       sizeof(u32));
                        switch (len & 3) {
                        case 3:
-                               skb->data[len + padding - 3] = tail[0];
-                               skb->data[len + padding - 2] = tail[1];
-                               skb->data[len + padding - 1] = tail[2];
+                               skb->data[len + padding - 3] = wl->rx_tail[0];
+                               skb->data[len + padding - 2] = wl->rx_tail[1];
+                               skb->data[len + padding - 1] = wl->rx_tail[2];
                                break;
                        case 2:
-                               skb->data[len + padding - 2] = tail[0];
-                               skb->data[len + padding - 1] = tail[1];
+                               skb->data[len + padding - 2] = wl->rx_tail[0];
+                               skb->data[len + padding - 1] = wl->rx_tail[1];
                                break;
                        case 1:
-                               skb->data[len + padding - 1] = tail[0];
+                               skb->data[len + padding - 1] = wl->rx_tail[0];
                                break;
                        }
                }
@@ -729,17 +732,15 @@ data_ready:
                               q->mmio_base + B43_PIO_RXDATA,
                               sizeof(u16));
                if (len & 1) {
-                       u8 tail[2] = { 0, };
-
                        /* Read the last byte. */
-                       ssb_block_read(dev->dev, tail, 2,
+                       ssb_block_read(dev->dev, wl->rx_tail, 2,
                                       q->mmio_base + B43_PIO_RXDATA,
                                       sizeof(u16));
-                       skb->data[len + padding - 1] = tail[0];
+                       skb->data[len + padding - 1] = wl->rx_tail[0];
                }
        }
 
-       b43_rx(q->dev, skb, &rxhdr);
+       b43_rx(q->dev, skb, &wl->rxhdr);
 
        return 1;
 
index 7a3218c..ffdce6f 100644 (file)
@@ -33,7 +33,8 @@ bool b43_is_hw_radio_enabled(struct b43_wldev *dev)
                      & B43_MMIO_RADIO_HWENABLED_HI_MASK))
                        return 1;
        } else {
-               if (b43_read16(dev, B43_MMIO_RADIO_HWENABLED_LO)
+               if (b43_status(dev) >= B43_STAT_STARTED &&
+                   b43_read16(dev, B43_MMIO_RADIO_HWENABLED_LO)
                    & B43_MMIO_RADIO_HWENABLED_LO_MASK)
                        return 1;
        }
index ac9f600..f4e9695 100644 (file)
@@ -27,7 +27,7 @@
 
 */
 
-#include "xmit.h"
+#include "b43.h"
 #include "phy_common.h"
 #include "dma.h"
 #include "pio.h"
@@ -690,7 +690,10 @@ void b43_rx(struct b43_wldev *dev, struct sk_buff *skb, const void *_rxhdr)
        }
 
        memcpy(IEEE80211_SKB_RXCB(skb), &status, sizeof(status));
+
+       local_bh_disable();
        ieee80211_rx(dev->wl->hw, skb);
+       local_bh_enable();
 
 #if B43_DEBUG
        dev->rx_count++;
index 1d9223b..4b60148 100644 (file)
@@ -37,6 +37,7 @@
 #include <linux/firmware.h>
 #include <linux/wireless.h>
 #include <linux/workqueue.h>
+#include <linux/sched.h>
 #include <linux/skbuff.h>
 #include <linux/dma-mapping.h>
 #include <net/dst.h>
index 11319ec..aaf2272 100644 (file)
@@ -31,6 +31,7 @@
 
 #include <linux/delay.h>
 #include <linux/pci.h>
+#include <linux/sched.h>
 #include <linux/types.h>
 
 #include "b43legacy.h"
index 6fa14a4..4dfb40a 100644 (file)
@@ -1,6 +1,7 @@
 /* Host AP driver Info Frame processing (part of hostap.o module) */
 
 #include <linux/if_arp.h>
+#include <linux/sched.h>
 #include "hostap_wlan.h"
 #include "hostap.h"
 #include "hostap_ap.h"
index 3f2bda8..9419ceb 100644 (file)
@@ -1,6 +1,7 @@
 /* ioctl() (mostly Linux Wireless Extensions) routines for Host AP driver */
 
 #include <linux/types.h>
+#include <linux/sched.h>
 #include <linux/ethtool.h>
 #include <linux/if_arp.h>
 #include <net/lib80211.h>
index 240cff1..a741d37 100644 (file)
@@ -6325,8 +6325,10 @@ static int ipw2100_pci_init_one(struct pci_dev *pci_dev,
 
       fail:
        if (dev) {
-               if (registered)
+               if (registered) {
+                       unregister_ieee80211(priv->ieee);
                        unregister_netdev(dev);
+               }
 
                ipw2100_hw_stop_adapter(priv);
 
@@ -6383,6 +6385,7 @@ static void __devexit ipw2100_pci_remove_one(struct pci_dev *pci_dev)
                /* Unregister the device first - this results in close()
                 * being called if the device is open.  If we free storage
                 * first, then close() will crash. */
+               unregister_ieee80211(priv->ieee);
                unregister_netdev(dev);
 
                /* ipw2100_down will ensure that there is no more pending work
index 8d58e6e..9b0f2c0 100644 (file)
@@ -30,6 +30,7 @@
 
 ******************************************************************************/
 
+#include <linux/sched.h>
 #include "ipw2200.h"
 
 
@@ -11821,6 +11822,7 @@ static int __devinit ipw_pci_probe(struct pci_dev *pdev,
                if (err) {
                        IPW_ERROR("Failed to register promiscuous network "
                                  "device (error %d).\n", err);
+                       unregister_ieee80211(priv->ieee);
                        unregister_netdev(priv->net_dev);
                        goto out_remove_sysfs;
                }
@@ -11871,6 +11873,7 @@ static void __devexit ipw_pci_remove(struct pci_dev *pdev)
 
        mutex_unlock(&priv->mutex);
 
+       unregister_ieee80211(priv->ieee);
        unregister_netdev(priv->net_dev);
 
        if (priv->rxq) {
index bf45391..f42ade6 100644 (file)
@@ -1020,6 +1020,7 @@ static inline int libipw_is_cck_rate(u8 rate)
 /* ieee80211.c */
 extern void free_ieee80211(struct net_device *dev, int monitor);
 extern struct net_device *alloc_ieee80211(int sizeof_priv, int monitor);
+extern void unregister_ieee80211(struct libipw_device *ieee);
 extern int libipw_change_mtu(struct net_device *dev, int new_mtu);
 
 extern void libipw_networks_age(struct libipw_device *ieee,
index a0e9f6a..be5b809 100644 (file)
@@ -235,16 +235,19 @@ void free_ieee80211(struct net_device *dev, int monitor)
        libipw_networks_free(ieee);
 
        /* free cfg80211 resources */
-       if (!monitor) {
-               wiphy_unregister(ieee->wdev.wiphy);
-               kfree(ieee->a_band.channels);
-               kfree(ieee->bg_band.channels);
+       if (!monitor)
                wiphy_free(ieee->wdev.wiphy);
-       }
 
        free_netdev(dev);
 }
 
+void unregister_ieee80211(struct libipw_device *ieee)
+{
+       wiphy_unregister(ieee->wdev.wiphy);
+       kfree(ieee->a_band.channels);
+       kfree(ieee->bg_band.channels);
+}
+
 #ifdef CONFIG_LIBIPW_DEBUG
 
 static int debug = 0;
@@ -330,3 +333,4 @@ module_init(libipw_init);
 
 EXPORT_SYMBOL(alloc_ieee80211);
 EXPORT_SYMBOL(free_ieee80211);
+EXPORT_SYMBOL(unregister_ieee80211);
index a16bd41..cbb0585 100644 (file)
@@ -702,7 +702,7 @@ static void rs_get_rate(void *priv_r, struct ieee80211_sta *sta,
                u8 sta_id = iwl_find_station(priv, hdr->addr1);
 
                if (sta_id == IWL_INVALID_STATION) {
-                       IWL_DEBUG_RATE(priv, "LQ: ADD station %pm\n",
+                       IWL_DEBUG_RATE(priv, "LQ: ADD station %pM\n",
                                       hdr->addr1);
                        sta_id = iwl_add_station(priv, hdr->addr1, false,
                                CMD_ASYNC, NULL);
index e70c5b0..f059b49 100644 (file)
@@ -30,6 +30,7 @@
 #include <linux/pci.h>
 #include <linux/dma-mapping.h>
 #include <linux/delay.h>
+#include <linux/sched.h>
 #include <linux/skbuff.h>
 #include <linux/netdevice.h>
 #include <linux/wireless.h>
@@ -610,7 +611,7 @@ static void iwl3945_rx_reply_rx(struct iwl_priv *priv,
        if (rx_status.band == IEEE80211_BAND_5GHZ)
                rx_status.rate_idx -= IWL_FIRST_OFDM_RATE;
 
-       rx_status.antenna = le16_to_cpu(rx_hdr->phy_flags &
+       rx_status.antenna = (le16_to_cpu(rx_hdr->phy_flags) &
                                        RX_RES_PHY_FLAGS_ANTENNA_MSK) >> 4;
 
        /* set the preamble flag if appropriate */
index a22a050..6f703a0 100644 (file)
@@ -30,6 +30,7 @@
 #include <linux/pci.h>
 #include <linux/dma-mapping.h>
 #include <linux/delay.h>
+#include <linux/sched.h>
 #include <linux/skbuff.h>
 #include <linux/netdevice.h>
 #include <linux/wireless.h>
index eb08f44..6e6f516 100644 (file)
@@ -29,6 +29,7 @@
 #include <linux/pci.h>
 #include <linux/dma-mapping.h>
 #include <linux/delay.h>
+#include <linux/sched.h>
 #include <linux/skbuff.h>
 #include <linux/netdevice.h>
 #include <linux/wireless.h>
@@ -317,7 +318,7 @@ static void iwl5000_gain_computation(struct iwl_priv *priv,
                        (s32)average_noise[i])) / 1500;
                /* bound gain by 2 bits value max, 3rd bit is sign */
                data->delta_gain_code[i] =
-                       min(abs(delta_g), CHAIN_NOISE_MAX_DELTA_GAIN_CODE);
+                       min(abs(delta_g), (long) CHAIN_NOISE_MAX_DELTA_GAIN_CODE);
 
                if (delta_g < 0)
                        /* set negative sign */
index cdc07c4..eaafae0 100644 (file)
@@ -33,6 +33,7 @@
 #include <linux/pci.h>
 #include <linux/dma-mapping.h>
 #include <linux/delay.h>
+#include <linux/sched.h>
 #include <linux/skbuff.h>
 #include <linux/netdevice.h>
 #include <linux/wireless.h>
@@ -3105,8 +3106,8 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
  out_pci_disable_device:
        pci_disable_device(pdev);
  out_ieee80211_free_hw:
-       ieee80211_free_hw(priv->hw);
        iwl_free_traffic_mem(priv);
+       ieee80211_free_hw(priv->hw);
  out:
        return err;
 }
index 2c5c88f..4afaf77 100644 (file)
@@ -1154,7 +1154,7 @@ struct iwl_wep_cmd {
 #define RX_RES_PHY_FLAGS_MOD_CCK_MSK           cpu_to_le16(1 << 1)
 #define RX_RES_PHY_FLAGS_SHORT_PREAMBLE_MSK    cpu_to_le16(1 << 2)
 #define RX_RES_PHY_FLAGS_NARROW_BAND_MSK       cpu_to_le16(1 << 3)
-#define RX_RES_PHY_FLAGS_ANTENNA_MSK           cpu_to_le16(0xf0)
+#define RX_RES_PHY_FLAGS_ANTENNA_MSK           0xf0
 #define RX_RES_PHY_FLAGS_ANTENNA_POS           4
 
 #define RX_RES_STATUS_SEC_TYPE_MSK     (0x7 << 8)
index 484d5c1..2dc9287 100644 (file)
@@ -29,6 +29,7 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/etherdevice.h>
+#include <linux/sched.h>
 #include <net/mac80211.h>
 
 #include "iwl-eeprom.h"
index 3d2b93a..e14c995 100644 (file)
@@ -410,7 +410,6 @@ static int iwl_find_otp_image(struct iwl_priv *priv,
                                        u16 *validblockaddr)
 {
        u16 next_link_addr = 0, link_value = 0, valid_addr;
-       int ret = 0;
        int usedblocks = 0;
 
        /* set addressing mode to absolute to traverse the link list */
@@ -430,29 +429,29 @@ static int iwl_find_otp_image(struct iwl_priv *priv,
                 * check for more block on the link list
                 */
                valid_addr = next_link_addr;
-               next_link_addr = link_value;
+               next_link_addr = link_value * sizeof(u16);
                IWL_DEBUG_INFO(priv, "OTP blocks %d addr 0x%x\n",
                               usedblocks, next_link_addr);
                if (iwl_read_otp_word(priv, next_link_addr, &link_value))
                        return -EINVAL;
                if (!link_value) {
                        /*
-                        * reach the end of link list,
+                        * reach the end of link list, return success and
                         * set address point to the starting address
                         * of the image
                         */
-                       goto done;
+                       *validblockaddr = valid_addr;
+                       /* skip first 2 bytes (link list pointer) */
+                       *validblockaddr += 2;
+                       return 0;
                }
                /* more in the link list, continue */
                usedblocks++;
-       } while (usedblocks < priv->cfg->max_ll_items);
-       /* OTP full, use last block */
-       IWL_DEBUG_INFO(priv, "OTP is full, use last block\n");
-done:
-       *validblockaddr = valid_addr;
-       /* skip first 2 bytes (link list pointer) */
-       *validblockaddr += 2;
-       return ret;
+       } while (usedblocks <= priv->cfg->max_ll_items);
+
+       /* OTP has no valid blocks */
+       IWL_DEBUG_INFO(priv, "OTP has no valid blocks\n");
+       return -EINVAL;
 }
 
 /**
index 6b68db7..80b9e45 100644 (file)
@@ -220,35 +220,35 @@ struct iwl_eeprom_enhanced_txpwr {
  * Section 10: 2.4 GHz 40MHz channels: 132, 44 (_above_)
  */
 /* 2.4 GHz band: CCK */
-#define EEPROM_LB_CCK_20_COMMON       ((0xAA)\
+#define EEPROM_LB_CCK_20_COMMON       ((0xA8)\
                | INDIRECT_ADDRESS | INDIRECT_REGULATORY)   /* 8 bytes */
 /* 2.4 GHz band: 20MHz-Legacy, 20MHz-HT, 40MHz-HT */
-#define EEPROM_LB_OFDM_COMMON       ((0xB2)\
+#define EEPROM_LB_OFDM_COMMON       ((0xB0)\
                | INDIRECT_ADDRESS | INDIRECT_REGULATORY)   /* 24 bytes */
 /* 5.2 GHz band: 20MHz-Legacy, 20MHz-HT, 40MHz-HT */
-#define EEPROM_HB_OFDM_COMMON       ((0xCA)\
+#define EEPROM_HB_OFDM_COMMON       ((0xC8)\
                | INDIRECT_ADDRESS | INDIRECT_REGULATORY)   /* 24 bytes */
 /* 2.4GHz band channels:
  *     1Legacy, 1HT, 2Legacy, 2HT, 10Legacy, 10HT, 11Legacy, 11HT */
-#define EEPROM_LB_OFDM_20_BAND       ((0xE2)\
+#define EEPROM_LB_OFDM_20_BAND       ((0xE0)\
                | INDIRECT_ADDRESS | INDIRECT_REGULATORY)   /* 64 bytes */
 /* 2.4 GHz band HT40 channels: (1,+1) (2,+1) (6,+1) (7,+1) (9,+1) */
-#define EEPROM_LB_OFDM_HT40_BAND       ((0x122)\
+#define EEPROM_LB_OFDM_HT40_BAND       ((0x120)\
                | INDIRECT_ADDRESS | INDIRECT_REGULATORY)   /* 40 bytes */
 /* 5.2GHz band channels: 36Legacy, 36HT, 64Legacy, 64HT, 100Legacy, 100HT */
-#define EEPROM_HB_OFDM_20_BAND       ((0x14A)\
+#define EEPROM_HB_OFDM_20_BAND       ((0x148)\
                | INDIRECT_ADDRESS | INDIRECT_REGULATORY)   /* 48 bytes */
 /* 5.2 GHz band HT40 channels: (36,+1) (60,+1) (100,+1) */
-#define EEPROM_HB_OFDM_HT40_BAND       ((0x17A)\
+#define EEPROM_HB_OFDM_HT40_BAND       ((0x178)\
                | INDIRECT_ADDRESS | INDIRECT_REGULATORY)   /* 24 bytes */
 /* 2.4 GHz band, channnel 13: Legacy, HT */
-#define EEPROM_LB_OFDM_20_CHANNEL_13       ((0x192)\
+#define EEPROM_LB_OFDM_20_CHANNEL_13       ((0x190)\
                | INDIRECT_ADDRESS | INDIRECT_REGULATORY)   /* 16 bytes */
 /* 5.2 GHz band, channnel 140: Legacy, HT */
-#define EEPROM_HB_OFDM_20_CHANNEL_140       ((0x1A2)\
+#define EEPROM_HB_OFDM_20_CHANNEL_140       ((0x1A0)\
                | INDIRECT_ADDRESS | INDIRECT_REGULATORY)   /* 16 bytes */
 /* 5.2 GHz band, HT40 channnels (132,+1) (44,+1) */
-#define EEPROM_HB_OFDM_HT40_BAND_1       ((0x1B2)\
+#define EEPROM_HB_OFDM_HT40_BAND_1       ((0x1B0)\
                | INDIRECT_ADDRESS | INDIRECT_REGULATORY)   /* 16 bytes */
 
 
index 532c8d6..a6856da 100644 (file)
@@ -28,6 +28,7 @@
 
 #include <linux/kernel.h>
 #include <linux/module.h>
+#include <linux/sched.h>
 #include <net/mac80211.h>
 
 #include "iwl-dev.h" /* FIXME: remove */
index 8e1bb53..493626b 100644 (file)
@@ -1044,7 +1044,7 @@ void iwl_rx_reply_rx(struct iwl_priv *priv,
         * as a bitmask.
         */
        rx_status.antenna =
-               le16_to_cpu(phy_res->phy_flags & RX_RES_PHY_FLAGS_ANTENNA_MSK)
+               (le16_to_cpu(phy_res->phy_flags) & RX_RES_PHY_FLAGS_ANTENNA_MSK)
                >> RX_RES_PHY_FLAGS_ANTENNA_POS;
 
        /* set the preamble flag if appropriate */
index c189075..fb9bcfa 100644 (file)
@@ -28,6 +28,7 @@
  *****************************************************************************/
 
 #include <linux/etherdevice.h>
+#include <linux/sched.h>
 #include <net/mac80211.h>
 #include "iwl-eeprom.h"
 #include "iwl-dev.h"
index c390dbd..d00a803 100644 (file)
@@ -33,6 +33,7 @@
 #include <linux/pci.h>
 #include <linux/dma-mapping.h>
 #include <linux/delay.h>
+#include <linux/sched.h>
 #include <linux/skbuff.h>
 #include <linux/netdevice.h>
 #include <linux/wireless.h>
@@ -4096,8 +4097,8 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
        pci_set_drvdata(pdev, NULL);
        pci_disable_device(pdev);
  out_ieee80211_free_hw:
-       ieee80211_free_hw(priv->hw);
        iwl_free_traffic_mem(priv);
+       ieee80211_free_hw(priv->hw);
  out:
        return err;
 }
index a56a2b0..f3c5565 100644 (file)
@@ -23,6 +23,7 @@
 
 #include <linux/kernel.h>
 #include <linux/netdevice.h>
+#include <linux/sched.h>
 #include <linux/etherdevice.h>
 #include <linux/wireless.h>
 #include <linux/ieee80211.h>
index 23b52fa..84158b6 100644 (file)
@@ -40,6 +40,7 @@
 #include <linux/wireless.h>
 #include <linux/etherdevice.h>
 #include <linux/ieee80211.h>
+#include <linux/sched.h>
 
 #include "iwm.h"
 #include "bus.h"
index d668e47..222eb2c 100644 (file)
@@ -38,6 +38,7 @@
 
 #include <linux/kernel.h>
 #include <linux/netdevice.h>
+#include <linux/sched.h>
 #include <linux/ieee80211.h>
 #include <linux/wireless.h>
 
index 40dbcbc..771a301 100644 (file)
@@ -38,6 +38,7 @@
 
 #include <linux/kernel.h>
 #include <linux/netdevice.h>
+#include <linux/sched.h>
 #include <linux/etherdevice.h>
 #include <linux/wireless.h>
 #include <linux/ieee80211.h>
index 6850981..0a324dc 100644 (file)
@@ -6,6 +6,7 @@
 #include <net/iw_handler.h>
 #include <net/lib80211.h>
 #include <linux/kfifo.h>
+#include <linux/sched.h>
 #include "host.h"
 #include "hostcmd.h"
 #include "decl.h"
index c42d3fa..23f6843 100644 (file)
@@ -3,6 +3,7 @@
   * responses as well as events generated by firmware.
   */
 #include <linux/delay.h>
+#include <linux/sched.h>
 #include <linux/if_arp.h>
 #include <linux/netdevice.h>
 #include <asm/unaligned.h>
index cb8be8d..5b3672c 100644 (file)
@@ -134,7 +134,7 @@ static void spu_transaction_finish(struct if_spi_card *card)
 static int spu_write(struct if_spi_card *card, u16 reg, const u8 *buf, int len)
 {
        int err = 0;
-       u16 reg_out = cpu_to_le16(reg | IF_SPI_WRITE_OPERATION_MASK);
+       __le16 reg_out = cpu_to_le16(reg | IF_SPI_WRITE_OPERATION_MASK);
        struct spi_message m;
        struct spi_transfer reg_trans;
        struct spi_transfer data_trans;
@@ -166,7 +166,7 @@ static int spu_write(struct if_spi_card *card, u16 reg, const u8 *buf, int len)
 
 static inline int spu_write_u16(struct if_spi_card *card, u16 reg, u16 val)
 {
-       u16 buff;
+       __le16 buff;
 
        buff = cpu_to_le16(val);
        return spu_write(card, reg, (u8 *)&buff, sizeof(u16));
@@ -188,7 +188,7 @@ static int spu_read(struct if_spi_card *card, u16 reg, u8 *buf, int len)
 {
        unsigned int delay;
        int err = 0;
-       u16 reg_out = cpu_to_le16(reg | IF_SPI_READ_OPERATION_MASK);
+       __le16 reg_out = cpu_to_le16(reg | IF_SPI_READ_OPERATION_MASK);
        struct spi_message m;
        struct spi_transfer reg_trans;
        struct spi_transfer dummy_trans;
@@ -235,7 +235,7 @@ static int spu_read(struct if_spi_card *card, u16 reg, u8 *buf, int len)
 /* Read 16 bits from an SPI register */
 static inline int spu_read_u16(struct if_spi_card *card, u16 reg, u16 *val)
 {
-       u16 buf;
+       __le16 buf;
        int ret;
 
        ret = spu_read(card, reg, (u8 *)&buf, sizeof(buf));
@@ -248,7 +248,7 @@ static inline int spu_read_u16(struct if_spi_card *card, u16 reg, u16 *val)
  * The low 16 bits are read first. */
 static int spu_read_u32(struct if_spi_card *card, u16 reg, u32 *val)
 {
-       u32 buf;
+       __le32 buf;
        int err;
 
        err = spu_read(card, reg, (u8 *)&buf, sizeof(buf));
index 92bc8c5..3fac4ef 100644 (file)
@@ -508,7 +508,7 @@ static int __if_usb_submit_rx_urb(struct if_usb_card *cardp,
        /* Fill the receive configuration URB and initialise the Rx call back */
        usb_fill_bulk_urb(cardp->rx_urb, cardp->udev,
                          usb_rcvbulkpipe(cardp->udev, cardp->ep_in),
-                         (void *) (skb->tail + (size_t) IPFIELD_ALIGN_OFFSET),
+                         skb->data + IPFIELD_ALIGN_OFFSET,
                          MRVDRV_ETH_RX_PACKET_BUFFER_SIZE, callbackfn,
                          cardp);
 
index 4c018f7..8c3766a 100644 (file)
@@ -3,6 +3,7 @@
   */
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
+#include <linux/sched.h>
 
 #include "hostcmd.h"
 #include "radiotap.h"
index 4c97c6a..bc08464 100644 (file)
@@ -19,6 +19,7 @@
  *
  */
 
+#include <linux/capability.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/if_arp.h>
index e26d7b3..2505be5 100644 (file)
@@ -23,6 +23,7 @@
 #include <linux/netdevice.h>
 #include <linux/ethtool.h>
 #include <linux/pci.h>
+#include <linux/sched.h>
 #include <linux/etherdevice.h>
 #include <linux/delay.h>
 #include <linux/if_arp.h>
index f7c677e..69d2f88 100644 (file)
@@ -20,6 +20,7 @@
 #include <linux/netdevice.h>
 #include <linux/module.h>
 #include <linux/pci.h>
+#include <linux/sched.h>
 
 #include <asm/io.h>
 #include <asm/system.h>
index 88cd58e..1c88c2e 100644 (file)
@@ -2879,7 +2879,7 @@ static int write_essid(struct file *file, const char __user *buffer,
                       unsigned long count, void *data)
 {
        static char proc_essid[33];
-       int len = count;
+       unsigned int len = count;
 
        if (len > 32)
                len = 32;
index a084077..9fe770f 100644 (file)
@@ -1994,7 +1994,7 @@ static void rt2800usb_write_tx_desc(struct rt2x00_dev *rt2x00dev,
        rt2x00_set_field32(&word, TXWI_W1_BW_WIN_SIZE, txdesc->ba_size);
        rt2x00_set_field32(&word, TXWI_W1_WIRELESS_CLI_ID,
                           test_bit(ENTRY_TXD_ENCRYPT, &txdesc->flags) ?
-                              (skbdesc->entry->entry_idx + 1) : 0xff);
+                          txdesc->key_idx : 0xff);
        rt2x00_set_field32(&word, TXWI_W1_MPDU_TOTAL_BYTE_COUNT,
                           skb->len - txdesc->l2pad);
        rt2x00_set_field32(&word, TXWI_W1_PACKETID,
index 7b3ee8c..68bc9bb 100644 (file)
@@ -27,6 +27,7 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/poll.h>
+#include <linux/sched.h>
 #include <linux/uaccess.h>
 
 #include "rt2x00.h"
index b8f5ee3..14e7bb2 100644 (file)
@@ -2389,10 +2389,13 @@ static struct usb_device_id rt73usb_device_table[] = {
        { USB_DEVICE(0x13b1, 0x0023), USB_DEVICE_DATA(&rt73usb_ops) },
        { USB_DEVICE(0x13b1, 0x0028), USB_DEVICE_DATA(&rt73usb_ops) },
        /* MSI */
+       { USB_DEVICE(0x0db0, 0x4600), USB_DEVICE_DATA(&rt73usb_ops) },
        { USB_DEVICE(0x0db0, 0x6877), USB_DEVICE_DATA(&rt73usb_ops) },
        { USB_DEVICE(0x0db0, 0x6874), USB_DEVICE_DATA(&rt73usb_ops) },
        { USB_DEVICE(0x0db0, 0xa861), USB_DEVICE_DATA(&rt73usb_ops) },
        { USB_DEVICE(0x0db0, 0xa874), USB_DEVICE_DATA(&rt73usb_ops) },
+       /* Ovislink */
+       { USB_DEVICE(0x1b75, 0x7318), USB_DEVICE_DATA(&rt73usb_ops) },
        /* Ralink */
        { USB_DEVICE(0x04bb, 0x093d), USB_DEVICE_DATA(&rt73usb_ops) },
        { USB_DEVICE(0x148f, 0x2573), USB_DEVICE_DATA(&rt73usb_ops) },
@@ -2420,6 +2423,8 @@ static struct usb_device_id rt73usb_device_table[] = {
        /* Planex */
        { USB_DEVICE(0x2019, 0xab01), USB_DEVICE_DATA(&rt73usb_ops) },
        { USB_DEVICE(0x2019, 0xab50), USB_DEVICE_DATA(&rt73usb_ops) },
+       /* WideTell */
+       { USB_DEVICE(0x7167, 0x3840), USB_DEVICE_DATA(&rt73usb_ops) },
        /* Zcom */
        { USB_DEVICE(0x0cde, 0x001c), USB_DEVICE_DATA(&rt73usb_ops) },
        /* ZyXEL */
index a0384b6..b423473 100644 (file)
@@ -169,7 +169,6 @@ static void znet_tx_timeout (struct net_device *dev);
 static int znet_request_resources (struct net_device *dev)
 {
        struct znet_private *znet = netdev_priv(dev);
-       unsigned long flags;
 
        if (request_irq (dev->irq, &znet_interrupt, 0, "ZNet", dev))
                goto failed;
@@ -187,13 +186,9 @@ static int znet_request_resources (struct net_device *dev)
  free_sia:
        release_region (znet->sia_base, znet->sia_size);
  free_tx_dma:
-       flags = claim_dma_lock();
        free_dma (znet->tx_dma);
-       release_dma_lock (flags);
  free_rx_dma:
-       flags = claim_dma_lock();
        free_dma (znet->rx_dma);
-       release_dma_lock (flags);
  free_irq:
        free_irq (dev->irq, dev);
  failed:
@@ -203,14 +198,11 @@ static int znet_request_resources (struct net_device *dev)
 static void znet_release_resources (struct net_device *dev)
 {
        struct znet_private *znet = netdev_priv(dev);
-       unsigned long flags;
 
        release_region (znet->sia_base, znet->sia_size);
        release_region (dev->base_addr, znet->io_size);
-       flags = claim_dma_lock();
        free_dma (znet->tx_dma);
        free_dma (znet->rx_dma);
-       release_dma_lock (flags);
        free_irq (dev->irq, dev);
 }
 
index bacaa53..4b22ba5 100644 (file)
@@ -97,6 +97,12 @@ int of_mdiobus_register(struct mii_bus *mdio, struct device_node *np)
 }
 EXPORT_SYMBOL(of_mdiobus_register);
 
+/* Helper function for of_phy_find_device */
+static int of_phy_match(struct device *dev, void *phy_np)
+{
+       return dev_archdata_get_node(&dev->archdata) == phy_np;
+}
+
 /**
  * of_phy_find_device - Give a PHY node, find the phy_device
  * @phy_np: Pointer to the phy's device tree node
@@ -106,15 +112,10 @@ EXPORT_SYMBOL(of_mdiobus_register);
 struct phy_device *of_phy_find_device(struct device_node *phy_np)
 {
        struct device *d;
-       int match(struct device *dev, void *phy_np)
-       {
-               return dev_archdata_get_node(&dev->archdata) == phy_np;
-       }
-
        if (!phy_np)
                return NULL;
 
-       d = bus_find_device(&mdio_bus_type, NULL, phy_np, match);
+       d = bus_find_device(&mdio_bus_type, NULL, phy_np, of_phy_match);
        return d ? to_phy_device(d) : NULL;
 }
 EXPORT_SYMBOL(of_phy_find_device);
index 2b7ae36..5df60a6 100644 (file)
@@ -35,12 +35,23 @@ static size_t buffer_pos;
 /* atomic_t because wait_event checks it outside of buffer_mutex */
 static atomic_t buffer_ready = ATOMIC_INIT(0);
 
-/* Add an entry to the event buffer. When we
- * get near to the end we wake up the process
- * sleeping on the read() of the file.
+/*
+ * Add an entry to the event buffer. When we get near to the end we
+ * wake up the process sleeping on the read() of the file. To protect
+ * the event_buffer this function may only be called when buffer_mutex
+ * is set.
  */
 void add_event_entry(unsigned long value)
 {
+       /*
+        * This shouldn't happen since all workqueues or handlers are
+        * canceled or flushed before the event buffer is freed.
+        */
+       if (!event_buffer) {
+               WARN_ON_ONCE(1);
+               return;
+       }
+
        if (buffer_pos == buffer_size) {
                atomic_inc(&oprofile_stats.event_lost_overflow);
                return;
@@ -69,7 +80,6 @@ void wake_up_buffer_waiter(void)
 
 int alloc_event_buffer(void)
 {
-       int err = -ENOMEM;
        unsigned long flags;
 
        spin_lock_irqsave(&oprofilefs_lock, flags);
@@ -80,21 +90,22 @@ int alloc_event_buffer(void)
        if (buffer_watershed >= buffer_size)
                return -EINVAL;
 
+       buffer_pos = 0;
        event_buffer = vmalloc(sizeof(unsigned long) * buffer_size);
        if (!event_buffer)
-               goto out;
+               return -ENOMEM;
 
-       err = 0;
-out:
-       return err;
+       return 0;
 }
 
 
 void free_event_buffer(void)
 {
+       mutex_lock(&buffer_mutex);
        vfree(event_buffer);
-
+       buffer_pos = 0;
        event_buffer = NULL;
+       mutex_unlock(&buffer_mutex);
 }
 
 
@@ -167,6 +178,12 @@ static ssize_t event_buffer_read(struct file *file, char __user *buf,
 
        mutex_lock(&buffer_mutex);
 
+       /* May happen if the buffer is freed during pending reads. */
+       if (!event_buffer) {
+               retval = -EINTR;
+               goto out;
+       }
+
        atomic_set(&buffer_ready, 0);
 
        retval = -EFAULT;
index 14bbaa1..22b02c6 100644 (file)
@@ -354,6 +354,7 @@ dmar_table_print_dmar_entry(struct acpi_dmar_header *header)
        struct acpi_dmar_hardware_unit *drhd;
        struct acpi_dmar_reserved_memory *rmrr;
        struct acpi_dmar_atsr *atsr;
+       struct acpi_dmar_rhsa *rhsa;
 
        switch (header->type) {
        case ACPI_DMAR_TYPE_HARDWARE_UNIT:
@@ -375,6 +376,12 @@ dmar_table_print_dmar_entry(struct acpi_dmar_header *header)
                atsr = container_of(header, struct acpi_dmar_atsr, header);
                printk(KERN_INFO PREFIX "ATSR flags: %#x\n", atsr->flags);
                break;
+       case ACPI_DMAR_HARDWARE_AFFINITY:
+               rhsa = container_of(header, struct acpi_dmar_rhsa, header);
+               printk(KERN_INFO PREFIX "RHSA base: %#016Lx proximity domain: %#x\n",
+                      (unsigned long long)rhsa->base_address,
+                      rhsa->proximity_domain);
+               break;
        }
 }
 
@@ -459,9 +466,13 @@ parse_dmar_table(void)
                        ret = dmar_parse_one_atsr(entry_header);
 #endif
                        break;
+               case ACPI_DMAR_HARDWARE_AFFINITY:
+                       /* We don't do anything with RHSA (yet?) */
+                       break;
                default:
                        printk(KERN_WARNING PREFIX
-                               "Unknown DMAR structure type\n");
+                               "Unknown DMAR structure type %d\n",
+                               entry_header->type);
                        ret = 0; /* for forward compatibility */
                        break;
                }
index 5383600..9c6a9fd 100644 (file)
@@ -32,6 +32,7 @@
 #include <asm/io.h>            /* for read? and write? functions */
 #include <linux/delay.h>       /* for delays */
 #include <linux/mutex.h>
+#include <linux/sched.h>       /* for signal_pending() */
 
 #define MY_NAME        "cpqphp"
 
index 855dd7c..b1e97e6 100644 (file)
@@ -48,6 +48,7 @@
 
 #define IS_GFX_DEVICE(pdev) ((pdev->class >> 16) == PCI_BASE_CLASS_DISPLAY)
 #define IS_ISA_DEVICE(pdev) ((pdev->class >> 8) == PCI_CLASS_BRIDGE_ISA)
+#define IS_AZALIA(pdev) ((pdev)->vendor == 0x8086 && (pdev)->device == 0x3a3e)
 
 #define IOAPIC_RANGE_START     (0xfee00000)
 #define IOAPIC_RANGE_END       (0xfeefffff)
@@ -94,6 +95,7 @@ static inline unsigned long virt_to_dma_pfn(void *p)
 /* global iommu list, set NULL for ignored DMAR units */
 static struct intel_iommu **g_iommus;
 
+static void __init check_tylersburg_isoch(void);
 static int rwbf_quirk;
 
 /*
@@ -1934,6 +1936,9 @@ error:
 }
 
 static int iommu_identity_mapping;
+#define IDENTMAP_ALL           1
+#define IDENTMAP_GFX           2
+#define IDENTMAP_AZALIA                4
 
 static int iommu_domain_identity_map(struct dmar_domain *domain,
                                     unsigned long long start,
@@ -2151,8 +2156,14 @@ static int domain_add_dev_info(struct dmar_domain *domain,
 
 static int iommu_should_identity_map(struct pci_dev *pdev, int startup)
 {
-       if (iommu_identity_mapping == 2)
-               return IS_GFX_DEVICE(pdev);
+       if ((iommu_identity_mapping & IDENTMAP_AZALIA) && IS_AZALIA(pdev))
+               return 1;
+
+       if ((iommu_identity_mapping & IDENTMAP_GFX) && IS_GFX_DEVICE(pdev))
+               return 1;
+
+       if (!(iommu_identity_mapping & IDENTMAP_ALL))
+               return 0;
 
        /*
         * We want to start off with all devices in the 1:1 domain, and
@@ -2332,11 +2343,14 @@ int __init init_dmars(void)
        }
 
        if (iommu_pass_through)
-               iommu_identity_mapping = 1;
+               iommu_identity_mapping |= IDENTMAP_ALL;
+
 #ifdef CONFIG_DMAR_BROKEN_GFX_WA
-       else
-               iommu_identity_mapping = 2;
+       iommu_identity_mapping |= IDENTMAP_GFX;
 #endif
+
+       check_tylersburg_isoch();
+
        /*
         * If pass through is not set or not enabled, setup context entries for
         * identity mappings for rmrr, gfx, and isa and may fall back to static
@@ -3670,3 +3684,61 @@ static void __devinit quirk_iommu_rwbf(struct pci_dev *dev)
 }
 
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2a40, quirk_iommu_rwbf);
+
+/* On Tylersburg chipsets, some BIOSes have been known to enable the
+   ISOCH DMAR unit for the Azalia sound device, but not give it any
+   TLB entries, which causes it to deadlock. Check for that.  We do
+   this in a function called from init_dmars(), instead of in a PCI
+   quirk, because we don't want to print the obnoxious "BIOS broken"
+   message if VT-d is actually disabled.
+*/
+static void __init check_tylersburg_isoch(void)
+{
+       struct pci_dev *pdev;
+       uint32_t vtisochctrl;
+
+       /* If there's no Azalia in the system anyway, forget it. */
+       pdev = pci_get_device(PCI_VENDOR_ID_INTEL, 0x3a3e, NULL);
+       if (!pdev)
+               return;
+       pci_dev_put(pdev);
+
+       /* System Management Registers. Might be hidden, in which case
+          we can't do the sanity check. But that's OK, because the
+          known-broken BIOSes _don't_ actually hide it, so far. */
+       pdev = pci_get_device(PCI_VENDOR_ID_INTEL, 0x342e, NULL);
+       if (!pdev)
+               return;
+
+       if (pci_read_config_dword(pdev, 0x188, &vtisochctrl)) {
+               pci_dev_put(pdev);
+               return;
+       }
+
+       pci_dev_put(pdev);
+
+       /* If Azalia DMA is routed to the non-isoch DMAR unit, fine. */
+       if (vtisochctrl & 1)
+               return;
+
+       /* Drop all bits other than the number of TLB entries */
+       vtisochctrl &= 0x1c;
+
+       /* If we have the recommended number of TLB entries (16), fine. */
+       if (vtisochctrl == 0x10)
+               return;
+
+       /* Zero TLB entries? You get to ride the short bus to school. */
+       if (!vtisochctrl) {
+               WARN(1, "Your BIOS is broken; DMA routed to ISOCH DMAR unit but no TLB space.\n"
+                    "BIOS vendor: %s; Ver: %s; Product Version: %s\n",
+                    dmi_get_system_info(DMI_BIOS_VENDOR),
+                    dmi_get_system_info(DMI_BIOS_VERSION),
+                    dmi_get_system_info(DMI_PRODUCT_VERSION));
+               iommu_identity_mapping |= IDENTMAP_AZALIA;
+               return;
+       }
+       
+       printk(KERN_WARNING "DMAR: Recommended TLB entries for ISOCH unit is 16; your BIOS set %d\n",
+              vtisochctrl);
+}
index 6edecff..4e4c295 100644 (file)
@@ -513,7 +513,11 @@ static int pci_raw_set_power_state(struct pci_dev *dev, pci_power_t state)
        else if (state == PCI_D2 || dev->current_state == PCI_D2)
                udelay(PCI_PM_D2_DELAY);
 
-       dev->current_state = state;
+       pci_read_config_word(dev, dev->pm_cap + PCI_PM_CTRL, &pmcsr);
+       dev->current_state = (pmcsr & PCI_PM_CTRL_STATE_MASK);
+       if (dev->current_state != state && printk_ratelimit())
+               dev_info(&dev->dev, "Refused to change power state, "
+                       "currently in D%d\n", dev->current_state);
 
        /* According to section 5.4.1 of the "PCI BUS POWER MANAGEMENT
         * INTERFACE SPECIFICATION, REV. 1.2", a device transitioning
@@ -2542,10 +2546,10 @@ int pci_resource_bar(struct pci_dev *dev, int resno, enum pci_bar_type *type)
 
 /**
  * pci_set_vga_state - set VGA decode state on device and parents if requested
- * @dev the PCI device
- * @decode - true = enable decoding, false = disable decoding
- * @command_bits PCI_COMMAND_IO and/or PCI_COMMAND_MEMORY
- * @change_bridge - traverse ancestors and change bridges
+ * @dev: the PCI device
+ * @decode: true = enable decoding, false = disable decoding
+ * @command_bits: PCI_COMMAND_IO and/or PCI_COMMAND_MEMORY
+ * @change_bridge: traverse ancestors and change bridges
  */
 int pci_set_vga_state(struct pci_dev *dev, bool decode,
                      unsigned int command_bits, bool change_bridge)
@@ -2719,17 +2723,6 @@ int __attribute__ ((weak)) pci_ext_cfg_avail(struct pci_dev *dev)
        return 1;
 }
 
-static int __devinit pci_init(void)
-{
-       struct pci_dev *dev = NULL;
-
-       while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) {
-               pci_fixup_device(pci_fixup_final, dev);
-       }
-
-       return 0;
-}
-
 static int __init pci_setup(char *str)
 {
        while (str) {
@@ -2767,8 +2760,6 @@ static int __init pci_setup(char *str)
 }
 early_param("pci", pci_setup);
 
-device_initcall(pci_init);
-
 EXPORT_SYMBOL(pci_reenable_device);
 EXPORT_SYMBOL(pci_enable_device_io);
 EXPORT_SYMBOL(pci_enable_device_mem);
index 2ce8f9c..40c3cc5 100644 (file)
@@ -17,6 +17,7 @@
 
 #include <linux/module.h>
 #include <linux/pci.h>
+#include <linux/sched.h>
 #include <linux/kernel.h>
 #include <linux/errno.h>
 #include <linux/pm.h>
@@ -52,7 +53,7 @@ static struct pci_error_handlers aer_error_handlers = {
 
 static struct pcie_port_service_driver aerdriver = {
        .name           = "aer",
-       .port_type      = PCIE_ANY_PORT,
+       .port_type      = PCIE_RC_PORT,
        .service        = PCIE_PORT_SERVICE_AER,
 
        .probe          = aer_probe,
index 6df5c98..f635e47 100644 (file)
@@ -30,7 +30,6 @@ MODULE_DESCRIPTION(DRIVER_DESC);
 MODULE_LICENSE("GPL");
 
 /* global data */
-static const char device_name[] = "pcieport-driver";
 
 static int pcie_portdrv_restore_config(struct pci_dev *dev)
 {
@@ -262,7 +261,7 @@ static struct pci_error_handlers pcie_portdrv_err_handler = {
 };
 
 static struct pci_driver pcie_portdriver = {
-       .name           = (char *)device_name,
+       .name           = "pcieport",
        .id_table       = &port_pci_ids[0],
 
        .probe          = pcie_portdrv_probe,
index 6099fac..245d2cd 100644 (file)
@@ -670,6 +670,25 @@ static void __devinit quirk_vt8235_acpi(struct pci_dev *dev)
 }
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA,    PCI_DEVICE_ID_VIA_8235, quirk_vt8235_acpi);
 
+/*
+ * TI XIO2000a PCIe-PCI Bridge erroneously reports it supports fast back-to-back:
+ *     Disable fast back-to-back on the secondary bus segment
+ */
+static void __devinit quirk_xio2000a(struct pci_dev *dev)
+{
+       struct pci_dev *pdev;
+       u16 command;
+
+       dev_warn(&dev->dev, "TI XIO2000a quirk detected; "
+               "secondary bus fast back-to-back transfers disabled\n");
+       list_for_each_entry(pdev, &dev->subordinate->devices, bus_list) {
+               pci_read_config_word(pdev, PCI_COMMAND, &command);
+               if (command & PCI_COMMAND_FAST_BACK)
+                       pci_write_config_word(pdev, PCI_COMMAND, command & ~PCI_COMMAND_FAST_BACK);
+       }
+}
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_XIO2000A,
+                       quirk_xio2000a);
 
 #ifdef CONFIG_X86_IO_APIC 
 
@@ -990,7 +1009,7 @@ DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_INTEL,        PCI_DEVICE_ID_INTEL_82454NX,
 
 static void __devinit quirk_amd_ide_mode(struct pci_dev *pdev)
 {
-       /* set SBX00 SATA in IDE mode to AHCI mode */
+       /* set SBX00/Hudson-2 SATA in IDE mode to AHCI mode */
        u8 tmp;
 
        pci_read_config_byte(pdev, PCI_CLASS_DEVICE, &tmp);
@@ -1009,8 +1028,8 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_IXP600_SATA, quirk
 DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_IXP600_SATA, quirk_amd_ide_mode);
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_IXP700_SATA, quirk_amd_ide_mode);
 DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_IXP700_SATA, quirk_amd_ide_mode);
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_SB900_SATA_IDE, quirk_amd_ide_mode);
-DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_SB900_SATA_IDE, quirk_amd_ide_mode);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_HUDSON2_SATA_IDE, quirk_amd_ide_mode);
+DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_HUDSON2_SATA_IDE, quirk_amd_ide_mode);
 
 /*
  *     Serverworks CSB5 IDE does not fully support native mode
@@ -2572,6 +2591,19 @@ void pci_fixup_device(enum pci_fixup_pass pass, struct pci_dev *dev)
        }
        pci_do_fixups(dev, start, end);
 }
+
+static int __init pci_apply_final_quirks(void)
+{
+       struct pci_dev *dev = NULL;
+
+       while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) {
+               pci_fixup_device(pci_fixup_final, dev);
+       }
+
+       return 0;
+}
+
+fs_initcall_sync(pci_apply_final_quirks);
 #else
 void pci_fixup_device(enum pci_fixup_pass pass, struct pci_dev *dev) {}
 #endif
index 706f82d..c54526b 100644 (file)
@@ -205,43 +205,6 @@ int pci_assign_resource(struct pci_dev *dev, int resno)
        return ret;
 }
 
-#if 0
-int pci_assign_resource_fixed(struct pci_dev *dev, int resno)
-{
-       struct pci_bus *bus = dev->bus;
-       struct resource *res = dev->resource + resno;
-       unsigned int type_mask;
-       int i, ret = -EBUSY;
-
-       type_mask = IORESOURCE_IO | IORESOURCE_MEM | IORESOURCE_PREFETCH;
-
-       for (i = 0; i < PCI_BUS_NUM_RESOURCES; i++) {
-               struct resource *r = bus->resource[i];
-               if (!r)
-                       continue;
-
-               /* type_mask must match */
-               if ((res->flags ^ r->flags) & type_mask)
-                       continue;
-
-               ret = request_resource(r, res);
-
-               if (ret == 0)
-                       break;
-       }
-
-       if (ret) {
-               dev_err(&dev->dev, "BAR %d: can't allocate %s resource %pR\n",
-                       resno, res->flags & IORESOURCE_IO ? "I/O" : "mem", res);
-       } else if (resno < PCI_BRIDGE_RESOURCES) {
-               pci_update_resource(dev, resno);
-       }
-
-       return ret;
-}
-EXPORT_SYMBOL_GPL(pci_assign_resource_fixed);
-#endif
-
 /* Sort resources by alignment */
 void pdev_sort_resources(struct pci_dev *dev, struct resource_list *head)
 {
index 4a110b7..6c4a4fc 100644 (file)
@@ -1463,7 +1463,9 @@ int pccard_read_tuple(struct pcmcia_socket *s, unsigned int function, cisdata_t
            return -ENOMEM;
     }
     tuple.DesiredTuple = code;
-    tuple.Attributes = TUPLE_RETURN_COMMON;
+    tuple.Attributes = 0;
+    if (function == BIND_FN_ALL)
+           tuple.Attributes = TUPLE_RETURN_COMMON;
     ret = pccard_get_first_tuple(s, function, &tuple);
     if (ret != 0)
            goto done;
@@ -1490,7 +1492,7 @@ EXPORT_SYMBOL(pccard_read_tuple);
     
 ======================================================================*/
 
-int pccard_validate_cis(struct pcmcia_socket *s, unsigned int function, unsigned int *info)
+int pccard_validate_cis(struct pcmcia_socket *s, unsigned int *info)
 {
     tuple_t *tuple;
     cisparse_t *p;
@@ -1515,30 +1517,30 @@ int pccard_validate_cis(struct pcmcia_socket *s, unsigned int function, unsigned
     count = reserved = 0;
     tuple->DesiredTuple = RETURN_FIRST_TUPLE;
     tuple->Attributes = TUPLE_RETURN_COMMON;
-    ret = pccard_get_first_tuple(s, function, tuple);
+    ret = pccard_get_first_tuple(s, BIND_FN_ALL, tuple);
     if (ret != 0)
        goto done;
 
     /* First tuple should be DEVICE; we should really have either that
        or a CFTABLE_ENTRY of some sort */
     if ((tuple->TupleCode == CISTPL_DEVICE) ||
-       (pccard_read_tuple(s, function, CISTPL_CFTABLE_ENTRY, p) == 0) ||
-       (pccard_read_tuple(s, function, CISTPL_CFTABLE_ENTRY_CB, p) == 0))
+       (pccard_read_tuple(s, BIND_FN_ALL, CISTPL_CFTABLE_ENTRY, p) == 0) ||
+       (pccard_read_tuple(s, BIND_FN_ALL, CISTPL_CFTABLE_ENTRY_CB, p) == 0))
        dev_ok++;
 
     /* All cards should have a MANFID tuple, and/or a VERS_1 or VERS_2
        tuple, for card identification.  Certain old D-Link and Linksys
        cards have only a broken VERS_2 tuple; hence the bogus test. */
-    if ((pccard_read_tuple(s, function, CISTPL_MANFID, p) == 0) ||
-       (pccard_read_tuple(s, function, CISTPL_VERS_1, p) == 0) ||
-       (pccard_read_tuple(s, function, CISTPL_VERS_2, p) != -ENOSPC))
+    if ((pccard_read_tuple(s, BIND_FN_ALL, CISTPL_MANFID, p) == 0) ||
+       (pccard_read_tuple(s, BIND_FN_ALL, CISTPL_VERS_1, p) == 0) ||
+       (pccard_read_tuple(s, BIND_FN_ALL, CISTPL_VERS_2, p) != -ENOSPC))
        ident_ok++;
 
     if (!dev_ok && !ident_ok)
        goto done;
 
     for (count = 1; count < MAX_TUPLES; count++) {
-       ret = pccard_get_next_tuple(s, function, tuple);
+       ret = pccard_get_next_tuple(s, BIND_FN_ALL, tuple);
        if (ret != 0)
                break;
        if (((tuple->TupleCode > 0x23) && (tuple->TupleCode < 0x40)) ||
index 934d4be..698d75c 100644 (file)
@@ -98,10 +98,13 @@ EXPORT_SYMBOL(pcmcia_socket_list_rwsem);
  * These functions check for the appropriate struct pcmcia_soket arrays,
  * and pass them to the low-level functions pcmcia_{suspend,resume}_socket
  */
+static int socket_early_resume(struct pcmcia_socket *skt);
+static int socket_late_resume(struct pcmcia_socket *skt);
 static int socket_resume(struct pcmcia_socket *skt);
 static int socket_suspend(struct pcmcia_socket *skt);
 
-int pcmcia_socket_dev_suspend(struct device *dev)
+static void pcmcia_socket_dev_run(struct device *dev,
+                                 int (*cb)(struct pcmcia_socket *))
 {
        struct pcmcia_socket *socket;
 
@@ -110,29 +113,34 @@ int pcmcia_socket_dev_suspend(struct device *dev)
                if (socket->dev.parent != dev)
                        continue;
                mutex_lock(&socket->skt_mutex);
-               socket_suspend(socket);
+               cb(socket);
                mutex_unlock(&socket->skt_mutex);
        }
        up_read(&pcmcia_socket_list_rwsem);
+}
 
+int pcmcia_socket_dev_suspend(struct device *dev)
+{
+       pcmcia_socket_dev_run(dev, socket_suspend);
        return 0;
 }
 EXPORT_SYMBOL(pcmcia_socket_dev_suspend);
 
-int pcmcia_socket_dev_resume(struct device *dev)
+void pcmcia_socket_dev_early_resume(struct device *dev)
 {
-       struct pcmcia_socket *socket;
+       pcmcia_socket_dev_run(dev, socket_early_resume);
+}
+EXPORT_SYMBOL(pcmcia_socket_dev_early_resume);
 
-       down_read(&pcmcia_socket_list_rwsem);
-       list_for_each_entry(socket, &pcmcia_socket_list, socket_list) {
-               if (socket->dev.parent != dev)
-                       continue;
-               mutex_lock(&socket->skt_mutex);
-               socket_resume(socket);
-               mutex_unlock(&socket->skt_mutex);
-       }
-       up_read(&pcmcia_socket_list_rwsem);
+void pcmcia_socket_dev_late_resume(struct device *dev)
+{
+       pcmcia_socket_dev_run(dev, socket_late_resume);
+}
+EXPORT_SYMBOL(pcmcia_socket_dev_late_resume);
 
+int pcmcia_socket_dev_resume(struct device *dev)
+{
+       pcmcia_socket_dev_run(dev, socket_resume);
        return 0;
 }
 EXPORT_SYMBOL(pcmcia_socket_dev_resume);
@@ -546,29 +554,24 @@ static int socket_suspend(struct pcmcia_socket *skt)
        return 0;
 }
 
-/*
- * Resume a socket.  If a card is present, verify its CIS against
- * our cached copy.  If they are different, the card has been
- * replaced, and we need to tell the drivers.
- */
-static int socket_resume(struct pcmcia_socket *skt)
+static int socket_early_resume(struct pcmcia_socket *skt)
 {
-       int ret;
-
-       if (!(skt->state & SOCKET_SUSPEND))
-               return -EBUSY;
-
        skt->socket = dead_socket;
        skt->ops->init(skt);
        skt->ops->set_socket(skt, &skt->socket);
+       if (skt->state & SOCKET_PRESENT)
+               skt->resume_status = socket_setup(skt, resume_delay);
+       return 0;
+}
 
+static int socket_late_resume(struct pcmcia_socket *skt)
+{
        if (!(skt->state & SOCKET_PRESENT)) {
                skt->state &= ~SOCKET_SUSPEND;
                return socket_insert(skt);
        }
 
-       ret = socket_setup(skt, resume_delay);
-       if (ret == 0) {
+       if (skt->resume_status == 0) {
                /*
                 * FIXME: need a better check here for cardbus cards.
                 */
@@ -596,6 +599,20 @@ static int socket_resume(struct pcmcia_socket *skt)
        return 0;
 }
 
+/*
+ * Resume a socket.  If a card is present, verify its CIS against
+ * our cached copy.  If they are different, the card has been
+ * replaced, and we need to tell the drivers.
+ */
+static int socket_resume(struct pcmcia_socket *skt)
+{
+       if (!(skt->state & SOCKET_SUSPEND))
+               return -EBUSY;
+
+       socket_early_resume(skt);
+       return socket_late_resume(skt);
+}
+
 static void socket_remove(struct pcmcia_socket *skt)
 {
        dev_printk(KERN_NOTICE, &skt->dev,
index 79615e6..1f4098f 100644 (file)
@@ -197,8 +197,7 @@ int pccard_read_tuple(struct pcmcia_socket *s, unsigned int function,
                      cisdata_t code, void *parse);
 int pcmcia_replace_cis(struct pcmcia_socket *s,
                       const u8 *data, const size_t len);
-int pccard_validate_cis(struct pcmcia_socket *s, unsigned int function,
-                       unsigned int *count);
+int pccard_validate_cis(struct pcmcia_socket *s, unsigned int *count);
 
 /* rsrc_mgr.c */
 int pcmcia_validate_mem(struct pcmcia_socket *s);
index 9f300d3..f5b7079 100644 (file)
@@ -547,7 +547,7 @@ static int pcmcia_device_query(struct pcmcia_device *p_dev)
        if (!vers1)
                return -ENOMEM;
 
-       if (!pccard_read_tuple(p_dev->socket, p_dev->func,
+       if (!pccard_read_tuple(p_dev->socket, BIND_FN_ALL,
                               CISTPL_MANFID, &manf_id)) {
                p_dev->manf_id = manf_id.manf;
                p_dev->card_id = manf_id.card;
@@ -581,9 +581,9 @@ static int pcmcia_device_query(struct pcmcia_device *p_dev)
                kfree(devgeo);
        }
 
-       if (!pccard_read_tuple(p_dev->socket, p_dev->func, CISTPL_VERS_1,
+       if (!pccard_read_tuple(p_dev->socket, BIND_FN_ALL, CISTPL_VERS_1,
                               vers1)) {
-               for (i=0; i < vers1->ns; i++) {
+               for (i = 0; i < min_t(unsigned int, 4, vers1->ns); i++) {
                        char *tmp;
                        unsigned int length;
 
@@ -733,7 +733,7 @@ static int pcmcia_card_add(struct pcmcia_socket *s)
                return -EAGAIN; /* try again, but later... */
        }
 
-       ret = pccard_validate_cis(s, BIND_FN_ALL, &no_chains);
+       ret = pccard_validate_cis(s, &no_chains);
        if (ret || !no_chains) {
                ds_dev_dbg(0, &s->dev, "invalid CIS or invalid resources\n");
                return -ENODEV;
index b906abe..a4aacb8 100644 (file)
@@ -1053,8 +1053,8 @@ static int i365_set_io_map(u_short sock, struct pccard_io_map *io)
     u_char map, ioctl;
     
     debug(1, "SetIOMap(%d, %d, %#2.2x, %d ns, "
-         "%#x-%#x)\n", sock, io->map, io->flags,
-         io->speed, io->start, io->stop);
+         "%#llx-%#llx)\n", sock, io->map, io->flags, io->speed,
+         (unsigned long long)io->start, (unsigned long long)io->stop);
     map = io->map;
     if ((map > 1) || (io->start > 0xffff) || (io->stop > 0xffff) ||
        (io->stop < io->start)) return -EINVAL;
index d1d89c4..7dfbee1 100644 (file)
@@ -537,8 +537,9 @@ static int _pcc_set_io_map(u_short sock, struct pccard_io_map *io)
        u_char map;
 
        debug(3, "m32r_cfc: SetIOMap(%d, %d, %#2.2x, %d ns, "
-                 "%#lx-%#lx)\n", sock, io->map, io->flags,
-                 io->speed, io->start, io->stop);
+                 "%#llx-%#llx)\n", sock, io->map, io->flags,
+                 io->speed, (unsigned long long)io->start,
+                 (unsigned long long)io->stop);
        map = io->map;
 
        return 0;
@@ -554,8 +555,9 @@ static int _pcc_set_mem_map(u_short sock, struct pccard_mem_map *mem)
        pcc_socket_t *t = &socket[sock];
 
        debug(3, "m32r_cfc: SetMemMap(%d, %d, %#2.2x, %d ns, "
-                "%#lx, %#x)\n", sock, map, mem->flags,
-                mem->speed, mem->static_start, mem->card_start);
+                "%#llx, %#x)\n", sock, map, mem->flags,
+                mem->speed, (unsigned long long)mem->static_start,
+                mem->card_start);
 
        /*
         * sanity check
index a065583..c6524f9 100644 (file)
@@ -492,8 +492,9 @@ static int _pcc_set_io_map(u_short sock, struct pccard_io_map *io)
        u_char map;
 
        debug(3, "m32r-pcc: SetIOMap(%d, %d, %#2.2x, %d ns, "
-                 "%#x-%#x)\n", sock, io->map, io->flags,
-                 io->speed, io->start, io->stop);
+                 "%#llx-%#llx)\n", sock, io->map, io->flags,
+                 io->speed, (unsigned long long)io->start,
+                 (unsigned long long)io->stop);
        map = io->map;
 
        return 0;
@@ -515,8 +516,9 @@ static int _pcc_set_mem_map(u_short sock, struct pccard_mem_map *mem)
 #endif
 
        debug(3, "m32r-pcc: SetMemMap(%d, %d, %#2.2x, %d ns, "
-                "%#lx,  %#x)\n", sock, map, mem->flags,
-                mem->speed, mem->static_start, mem->card_start);
+                "%#llx,  %#x)\n", sock, map, mem->flags,
+                mem->speed, (unsigned long long)mem->static_start,
+                mem->card_start);
 
        /*
         * sanity check
index c69f2c4..403559b 100644 (file)
@@ -975,8 +975,9 @@ static int m8xx_set_io_map(struct pcmcia_socket *sock, struct pccard_io_map *io)
 #define M8XX_BASE (PCMCIA_IO_WIN_BASE + io->start)
 
        dprintk("SetIOMap(%d, %d, %#2.2x, %d ns, "
-               "%#4.4x-%#4.4x)\n", lsock, io->map, io->flags,
-               io->speed, io->start, io->stop);
+               "%#4.4llx-%#4.4llx)\n", lsock, io->map, io->flags,
+               io->speed, (unsigned long long)io->start,
+               (unsigned long long)io->stop);
 
        if ((io->map >= PCMCIA_IO_WIN_NO) || (io->start > 0xffff)
            || (io->stop > 0xffff) || (io->stop < io->start))
@@ -1055,8 +1056,9 @@ static int m8xx_set_mem_map(struct pcmcia_socket *sock,
        pcmconf8xx_t *pcmcia = s->pcmcia;
 
        dprintk("SetMemMap(%d, %d, %#2.2x, %d ns, "
-               "%#5.5lx, %#5.5x)\n", lsock, mem->map, mem->flags,
-               mem->speed, mem->static_start, mem->card_start);
+               "%#5.5llx, %#5.5x)\n", lsock, mem->map, mem->flags,
+               mem->speed, (unsigned long long)mem->static_start,
+               mem->card_start);
 
        if ((mem->map >= PCMCIA_MEM_WIN_NO)
 //          || ((mem->s) >= PCMCIA_MEM_WIN_SIZE)
@@ -1107,8 +1109,9 @@ static int m8xx_set_mem_map(struct pcmcia_socket *sock,
        }
 
        dprintk("SetMemMap(%d, %d, %#2.2x, %d ns, "
-               "%#5.5lx, %#5.5x)\n", lsock, mem->map, mem->flags,
-               mem->speed, mem->static_start, mem->card_start);
+               "%#5.5llx, %#5.5x)\n", lsock, mem->map, mem->flags,
+               mem->speed, (unsigned long long)mem->static_start,
+               mem->card_start);
 
        /* copy the struct and modify the copy */
 
index 32c4404..30cf71d 100644 (file)
@@ -881,7 +881,7 @@ static int ds_ioctl(struct inode * inode, struct file * file,
        mutex_lock(&s->skt_mutex);
        pcmcia_validate_mem(s);
        mutex_unlock(&s->skt_mutex);
-       ret = pccard_validate_cis(s, BIND_FN_ALL, &buf->cisinfo.Chains);
+       ret = pccard_validate_cis(s, &buf->cisinfo.Chains);
        break;
     case DS_SUSPEND_CARD:
        ret = pcmcia_suspend_card(s);
index 1c39d34..70a3346 100644 (file)
@@ -641,6 +641,12 @@ static int __devinit pd6729_pci_probe(struct pci_dev *dev,
        if ((ret = pci_enable_device(dev)))
                goto err_out_free_mem;
 
+       if (!pci_resource_start(dev, 0)) {
+               printk(KERN_INFO "pd6729: refusing to load the driver "
+                                "as the io_base is 0.\n");
+               goto err_out_free_mem;
+       }
+
        printk(KERN_INFO "pd6729: Cirrus PD6729 PCI to PCMCIA Bridge "
                "at 0x%llx on irq %d\n",
                (unsigned long long)pci_resource_start(dev, 0), dev->irq);
index 9ca22c7..7039f3c 100644 (file)
@@ -206,6 +206,7 @@ static void do_io_probe(struct pcmcia_socket *s, unsigned int base,
     /* First, what does a floating port look like? */
     b = kzalloc(256, GFP_KERNEL);
     if (!b) {
+           printk("\n");
            dev_printk(KERN_ERR, &s->dev,
                   "do_io_probe: unable to kmalloc 256 bytes");
             return;
@@ -275,7 +276,7 @@ static int readable(struct pcmcia_socket *s, struct resource *res,
        s->cis_mem.res = res;
        s->cis_virt = ioremap(res->start, s->map_size);
        if (s->cis_virt) {
-               ret = pccard_validate_cis(s, BIND_FN_ALL, count);
+               ret = pccard_validate_cis(s, count);
                /* invalidate mapping and CIS cache */
                iounmap(s->cis_virt);
                s->cis_virt = NULL;
index 163cf98..ef7e9e5 100644 (file)
@@ -336,8 +336,9 @@ soc_common_pcmcia_set_io_map(struct pcmcia_socket *sock, struct pccard_io_map *m
        struct soc_pcmcia_socket *skt = to_soc_pcmcia_socket(sock);
        unsigned short speed = map->speed;
 
-       debug(skt, 2, "map %u  speed %u start 0x%08x stop 0x%08x\n",
-               map->map, map->speed, map->start, map->stop);
+       debug(skt, 2, "map %u  speed %u start 0x%08llx stop 0x%08llx\n",
+               map->map, map->speed, (unsigned long long)map->start,
+               (unsigned long long)map->stop);
        debug(skt, 2, "flags: %s%s%s%s%s%s%s%s\n",
                (map->flags==0)?"<NONE>":"",
                (map->flags&MAP_ACTIVE)?"ACTIVE ":"",
index ff9a3bb..78d5aab 100644 (file)
@@ -300,7 +300,7 @@ static ssize_t pccard_show_cis(struct kobject *kobj,
 
                if (!(s->state & SOCKET_PRESENT))
                        return -ENODEV;
-               if (pccard_validate_cis(s, BIND_FN_ALL, &chains))
+               if (pccard_validate_cis(s, &chains))
                        return -EIO;
                if (!chains)
                        return -ENODATA;
index 582413f..6918849 100644 (file)
@@ -732,8 +732,8 @@ static int tcic_set_io_map(struct pcmcia_socket *sock, struct pccard_io_map *io)
     u_short base, len, ioctl;
     
     debug(1, "SetIOMap(%d, %d, %#2.2x, %d ns, "
-         "%#x-%#x)\n", psock, io->map, io->flags,
-         io->speed, io->start, io->stop);
+         "%#llx-%#llx)\n", psock, io->map, io->flags, io->speed,
+         (unsigned long long)io->start, (unsigned long long)io->stop);
     if ((io->map > 1) || (io->start > 0xffff) || (io->stop > 0xffff) ||
        (io->stop < io->start)) return -EINVAL;
     tcic_setw(TCIC_ADDR+2, TCIC_ADR2_INDREG | (psock << TCIC_SS_SHFT));
index abe0e44..8be4cc4 100644 (file)
@@ -1275,16 +1275,26 @@ static int yenta_dev_resume_noirq(struct device *dev)
        if (socket->type && socket->type->restore_state)
                socket->type->restore_state(socket);
 
-       return pcmcia_socket_dev_resume(dev);
+       pcmcia_socket_dev_early_resume(dev);
+       return 0;
+}
+
+static int yenta_dev_resume(struct device *dev)
+{
+       pcmcia_socket_dev_late_resume(dev);
+       return 0;
 }
 
 static struct dev_pm_ops yenta_pm_ops = {
        .suspend_noirq = yenta_dev_suspend_noirq,
        .resume_noirq = yenta_dev_resume_noirq,
+       .resume = yenta_dev_resume,
        .freeze_noirq = yenta_dev_suspend_noirq,
        .thaw_noirq = yenta_dev_resume_noirq,
+       .thaw = yenta_dev_resume,
        .poweroff_noirq = yenta_dev_suspend_noirq,
        .restore_noirq = yenta_dev_resume_noirq,
+       .restore = yenta_dev_resume,
 };
 
 #define YENTA_PM_OPS   (&yenta_pm_ops)
index 749e210..d379e74 100644 (file)
@@ -150,6 +150,8 @@ struct eeepc_hotk {
 /* The actual device the driver binds to */
 static struct eeepc_hotk *ehotk;
 
+static void eeepc_rfkill_hotplug(bool real);
+
 /* Platform device/driver */
 static int eeepc_hotk_thaw(struct device *device);
 static int eeepc_hotk_restore(struct device *device);
@@ -343,14 +345,23 @@ static bool eeepc_wlan_rfkill_blocked(void)
 static int eeepc_rfkill_set(void *data, bool blocked)
 {
        unsigned long asl = (unsigned long)data;
-       return set_acpi(asl, !blocked);
+       int ret;
+
+       if (asl != CM_ASL_WLAN)
+               return set_acpi(asl, !blocked);
+
+       /* hack to avoid panic with rt2860sta */
+       if (blocked)
+               eeepc_rfkill_hotplug(false);
+       ret = set_acpi(asl, !blocked);
+       return ret;
 }
 
 static const struct rfkill_ops eeepc_rfkill_ops = {
        .set_block = eeepc_rfkill_set,
 };
 
-static void __init eeepc_enable_camera(void)
+static void __devinit eeepc_enable_camera(void)
 {
        /*
         * If the following call to set_acpi() fails, it's because there's no
@@ -643,13 +654,13 @@ static int eeepc_get_adapter_status(struct hotplug_slot *hotplug_slot,
        return 0;
 }
 
-static void eeepc_rfkill_hotplug(void)
+static void eeepc_rfkill_hotplug(bool real)
 {
        struct pci_dev *dev;
        struct pci_bus *bus;
-       bool blocked = eeepc_wlan_rfkill_blocked();
+       bool blocked = real ? eeepc_wlan_rfkill_blocked() : true;
 
-       if (ehotk->wlan_rfkill)
+       if (real && ehotk->wlan_rfkill)
                rfkill_set_sw_state(ehotk->wlan_rfkill, blocked);
 
        mutex_lock(&ehotk->hotplug_lock);
@@ -692,7 +703,7 @@ static void eeepc_rfkill_notify(acpi_handle handle, u32 event, void *data)
        if (event != ACPI_NOTIFY_BUS_CHECK)
                return;
 
-       eeepc_rfkill_hotplug();
+       eeepc_rfkill_hotplug(true);
 }
 
 static void eeepc_hotk_notify(struct acpi_device *device, u32 event)
@@ -850,7 +861,7 @@ static int eeepc_hotk_restore(struct device *device)
 {
        /* Refresh both wlan rfkill state and pci hotplug */
        if (ehotk->wlan_rfkill)
-               eeepc_rfkill_hotplug();
+               eeepc_rfkill_hotplug(true);
 
        if (ehotk->bluetooth_rfkill)
                rfkill_set_sw_state(ehotk->bluetooth_rfkill,
@@ -993,7 +1004,7 @@ static void eeepc_rfkill_exit(void)
         * Refresh pci hotplug in case the rfkill state was changed after
         * eeepc_unregister_rfkill_notifier()
         */
-       eeepc_rfkill_hotplug();
+       eeepc_rfkill_hotplug(true);
        if (ehotk->hotplug_slot)
                pci_hp_deregister(ehotk->hotplug_slot);
 
@@ -1109,7 +1120,7 @@ static int eeepc_rfkill_init(struct device *dev)
         * Refresh pci hotplug in case the rfkill state was changed during
         * setup.
         */
-       eeepc_rfkill_hotplug();
+       eeepc_rfkill_hotplug(true);
 
 exit:
        if (result && result != -ENODEV)
@@ -1189,7 +1200,7 @@ static int eeepc_input_init(struct device *dev)
        return 0;
 }
 
-static int eeepc_hotk_add(struct acpi_device *device)
+static int __devinit eeepc_hotk_add(struct acpi_device *device)
 {
        struct device *dev;
        int result;
index f35aee5..bcd4ba8 100644 (file)
@@ -944,7 +944,7 @@ static int acpi_fujitsu_hotkey_remove(struct acpi_device *device, int type)
        struct fujitsu_hotkey_t *fujitsu_hotkey = acpi_driver_data(device);
        struct input_dev *input = fujitsu_hotkey->input;
 
-#ifdef CONFIG_LEDS_CLASS
+#if defined(CONFIG_LEDS_CLASS) || defined(CONFIG_LEDS_CLASS_MODULE)
        if (fujitsu_hotkey->logolamp_registered)
                led_classdev_unregister(&logolamp_led);
 
index 4cdb31a..a0c8162 100644 (file)
@@ -12,6 +12,7 @@
 */
 
 #include <linux/rtc.h>
+#include <linux/sched.h>
 #include <linux/log2.h>
 
 int rtc_read_time(struct rtc_device *rtc, struct rtc_time *tm)
index 8a11de9..62227cd 100644 (file)
@@ -13,6 +13,7 @@
 
 #include <linux/module.h>
 #include <linux/rtc.h>
+#include <linux/sched.h>
 #include "rtc-core.h"
 
 static dev_t rtc_devt;
index dad0449..aaccc8e 100644 (file)
@@ -2508,8 +2508,6 @@ int dasd_generic_restore_device(struct ccw_device *cdev)
        device->stopped &= ~DASD_UNRESUMED_PM;
 
        dasd_schedule_device_bh(device);
-       if (device->block)
-               dasd_schedule_block_bh(device->block);
 
        if (device->discipline->restore)
                rc = device->discipline->restore(device);
@@ -2520,6 +2518,9 @@ int dasd_generic_restore_device(struct ccw_device *cdev)
                 */
                device->stopped |= DASD_UNRESUMED_PM;
 
+       if (device->block)
+               dasd_schedule_block_bh(device->block);
+
        dasd_put_device(device);
        return 0;
 }
@@ -2532,6 +2533,7 @@ static struct dasd_ccw_req *dasd_generic_build_rdc(struct dasd_device *device,
 {
        struct dasd_ccw_req *cqr;
        struct ccw1 *ccw;
+       unsigned long *idaw;
 
        cqr = dasd_smalloc_request(magic, 1 /* RDC */, rdc_buffer_size, device);
 
@@ -2545,9 +2547,17 @@ static struct dasd_ccw_req *dasd_generic_build_rdc(struct dasd_device *device,
 
        ccw = cqr->cpaddr;
        ccw->cmd_code = CCW_CMD_RDC;
-       ccw->cda = (__u32)(addr_t)rdc_buffer;
-       ccw->count = rdc_buffer_size;
+       if (idal_is_needed(rdc_buffer, rdc_buffer_size)) {
+               idaw = (unsigned long *) (cqr->data);
+               ccw->cda = (__u32)(addr_t) idaw;
+               ccw->flags = CCW_FLAG_IDA;
+               idaw = idal_create_words(idaw, rdc_buffer, rdc_buffer_size);
+       } else {
+               ccw->cda = (__u32)(addr_t) rdc_buffer;
+               ccw->flags = 0;
+       }
 
+       ccw->count = rdc_buffer_size;
        cqr->startdev = device;
        cqr->memdev = device;
        cqr->expires = 10*HZ;
index ab35217..417b97c 100644 (file)
@@ -2338,6 +2338,8 @@ static struct dasd_ccw_req *dasd_eckd_build_cp(struct dasd_device *startdev,
        /* Calculate number of blocks/records per track. */
        blksize = block->bp_block;
        blk_per_trk = recs_per_track(&private->rdc_data, 0, blksize);
+       if (blk_per_trk == 0)
+               return ERR_PTR(-EINVAL);
        /* Calculate record id of first and last block. */
        first_rec = first_trk = blk_rq_pos(req) >> block->s2b_shift;
        first_offs = sector_div(first_trk, blk_per_trk);
@@ -3211,8 +3213,10 @@ int dasd_eckd_pm_freeze(struct dasd_device *device)
 int dasd_eckd_restore_device(struct dasd_device *device)
 {
        struct dasd_eckd_private *private;
+       struct dasd_eckd_characteristics temp_rdc_data;
        int is_known, rc;
        struct dasd_uid temp_uid;
+       unsigned long flags;
 
        private = (struct dasd_eckd_private *) device->private;
 
@@ -3225,7 +3229,8 @@ int dasd_eckd_restore_device(struct dasd_device *device)
        rc = dasd_eckd_generate_uid(device, &private->uid);
        dasd_get_uid(device->cdev, &temp_uid);
        if (memcmp(&private->uid, &temp_uid, sizeof(struct dasd_uid)) != 0)
-               dev_err(&device->cdev->dev, "The UID of the DASD has changed\n");
+               dev_err(&device->cdev->dev, "The UID of the DASD has "
+                       "changed\n");
        if (rc)
                goto out_err;
        dasd_set_uid(device->cdev, &private->uid);
@@ -3245,15 +3250,17 @@ int dasd_eckd_restore_device(struct dasd_device *device)
        dasd_eckd_read_features(device);
 
        /* Read Device Characteristics */
-       memset(&private->rdc_data, 0, sizeof(private->rdc_data));
        rc = dasd_generic_read_dev_chars(device, DASD_ECKD_MAGIC,
-                                        &private->rdc_data, 64);
+                                        &temp_rdc_data, 64);
        if (rc) {
                DBF_EVENT(DBF_WARNING,
                          "Read device characteristics failed, rc=%d for "
                          "device: %s", rc, dev_name(&device->cdev->dev));
                goto out_err;
        }
+       spin_lock_irqsave(get_ccwdev_lock(device->cdev), flags);
+       memcpy(&private->rdc_data, &temp_rdc_data, sizeof(temp_rdc_data));
+       spin_unlock_irqrestore(get_ccwdev_lock(device->cdev), flags);
 
        /* add device to alias management */
        dasd_alias_add_device(device);
index d6a022f..62ddf52 100644 (file)
@@ -1361,11 +1361,13 @@ static int raw3270_pm_start(struct ccw_device *cdev)
 
 void raw3270_pm_unfreeze(struct raw3270_view *view)
 {
+#ifdef CONFIG_TN3270_CONSOLE
        struct raw3270 *rp;
 
        rp = view->dev;
        if (rp && test_bit(RAW3270_FLAGS_FROZEN, &rp->flags))
                ccw_device_force_console();
+#endif
 }
 
 static struct ccw_device_id raw3270_id[] = {
index daaec18..b44462a 100644 (file)
@@ -26,7 +26,6 @@ static struct sclp_async_sccb *sccb;
 static int sclp_async_send_wait(char *message);
 static struct ctl_table_header *callhome_sysctl_header;
 static DEFINE_SPINLOCK(sclp_async_lock);
-static char nodename[64];
 #define SCLP_NORMAL_WRITE      0x00
 
 struct async_evbuf {
@@ -52,9 +51,10 @@ static struct sclp_register sclp_async_register = {
 static int call_home_on_panic(struct notifier_block *self,
                              unsigned long event, void *data)
 {
-               strncat(data, nodename, strlen(nodename));
-               sclp_async_send_wait(data);
-               return NOTIFY_DONE;
+       strncat(data, init_utsname()->nodename,
+               sizeof(init_utsname()->nodename));
+       sclp_async_send_wait(data);
+       return NOTIFY_DONE;
 }
 
 static struct notifier_block call_home_panic_nb = {
@@ -62,21 +62,20 @@ static struct notifier_block call_home_panic_nb = {
        .priority = INT_MAX,
 };
 
-static int proc_handler_callhome(ctl_table *ctl, int write, struct file *filp,
+static int proc_handler_callhome(struct ctl_table *ctl, int write,
                                 void __user *buffer, size_t *count,
                                 loff_t *ppos)
 {
        unsigned long val;
        int len, rc;
-       char buf[2];
+       char buf[3];
 
-       if (!*count | (*ppos && !write)) {
+       if (!*count || (*ppos && !write)) {
                *count = 0;
                return 0;
        }
        if (!write) {
-               len =  sprintf(buf, "%d\n", callhome_enabled);
-               buf[len] = '\0';
+               len = snprintf(buf, sizeof(buf), "%d\n", callhome_enabled);
                rc = copy_to_user(buffer, buf, sizeof(buf));
                if (rc != 0)
                        return -EFAULT;
@@ -100,7 +99,7 @@ static struct ctl_table callhome_table[] = {
        {
                .procname       = "callhome",
                .mode           = 0644,
-               .proc_handler   = &proc_handler_callhome,
+               .proc_handler   = proc_handler_callhome,
        },
        { .ctl_name = 0 }
 };
@@ -171,39 +170,29 @@ static int __init sclp_async_init(void)
        rc = sclp_register(&sclp_async_register);
        if (rc)
                return rc;
-       callhome_sysctl_header = register_sysctl_table(kern_dir_table);
-       if (!callhome_sysctl_header) {
-               rc = -ENOMEM;
-               goto out_sclp;
-       }
-       if (!(sclp_async_register.sclp_receive_mask & EVTYP_ASYNC_MASK)) {
-               rc = -EOPNOTSUPP;
+       rc = -EOPNOTSUPP;
+       if (!(sclp_async_register.sclp_receive_mask & EVTYP_ASYNC_MASK))
                goto out_sclp;
-       }
        rc = -ENOMEM;
+       callhome_sysctl_header = register_sysctl_table(kern_dir_table);
+       if (!callhome_sysctl_header)
+               goto out_sclp;
        request = kzalloc(sizeof(struct sclp_req), GFP_KERNEL);
-       if (!request)
-               goto out_sys;
        sccb = (struct sclp_async_sccb *) get_zeroed_page(GFP_KERNEL | GFP_DMA);
-       if (!sccb)
+       if (!request || !sccb)
                goto out_mem;
-       rc =  atomic_notifier_chain_register(&panic_notifier_list,
-                                            &call_home_panic_nb);
-       if (rc)
-               goto out_mem;
-
-       strncpy(nodename, init_utsname()->nodename, 64);
-       return 0;
-
+       rc = atomic_notifier_chain_register(&panic_notifier_list,
+                                           &call_home_panic_nb);
+       if (!rc)
+               goto out;
 out_mem:
        kfree(request);
        free_page((unsigned long) sccb);
-out_sys:
        unregister_sysctl_table(callhome_sysctl_header);
 out_sclp:
        sclp_unregister(&sclp_async_register);
+out:
        return rc;
-
 }
 module_init(sclp_async_init);
 
index 178724f..b9d2a00 100644 (file)
@@ -705,21 +705,6 @@ out_driver:
 }
 __initcall(sclp_vt220_tty_init);
 
-#ifdef CONFIG_SCLP_VT220_CONSOLE
-
-static void
-sclp_vt220_con_write(struct console *con, const char *buf, unsigned int count)
-{
-       __sclp_vt220_write((const unsigned char *) buf, count, 1, 1, 0);
-}
-
-static struct tty_driver *
-sclp_vt220_con_device(struct console *c, int *index)
-{
-       *index = 0;
-       return sclp_vt220_driver;
-}
-
 static void __sclp_vt220_flush_buffer(void)
 {
        unsigned long flags;
@@ -776,6 +761,21 @@ static void sclp_vt220_pm_event_fn(struct sclp_register *reg,
        }
 }
 
+#ifdef CONFIG_SCLP_VT220_CONSOLE
+
+static void
+sclp_vt220_con_write(struct console *con, const char *buf, unsigned int count)
+{
+       __sclp_vt220_write((const unsigned char *) buf, count, 1, 1, 0);
+}
+
+static struct tty_driver *
+sclp_vt220_con_device(struct console *c, int *index)
+{
+       *index = 0;
+       return sclp_vt220_driver;
+}
+
 static int
 sclp_vt220_notify(struct notifier_block *self,
                          unsigned long event, void *data)
index 64f57ef..0c0705b 100644 (file)
@@ -162,9 +162,10 @@ tapeblock_requeue(struct work_struct *work) {
        spin_lock_irq(&device->blk_data.request_queue_lock);
        while (
                !blk_queue_plugged(queue) &&
-               (req = blk_fetch_request(queue)) &&
+               blk_peek_request(queue) &&
                nr_queued < TAPEBLOCK_MIN_REQUEUE
        ) {
+               req = blk_fetch_request(queue);
                if (rq_data_dir(req) == WRITE) {
                        DBF_EVENT(1, "TBLOCK: Rejecting write request\n");
                        spin_unlock_irq(&device->blk_data.request_queue_lock);
index 6565f02..7eab9ab 100644 (file)
@@ -265,13 +265,11 @@ struct ccwdev_iter {
 static void *
 cio_ignore_proc_seq_start(struct seq_file *s, loff_t *offset)
 {
-       struct ccwdev_iter *iter;
+       struct ccwdev_iter *iter = s->private;
 
        if (*offset >= (__MAX_SUBCHANNEL + 1) * (__MAX_SSID + 1))
                return NULL;
-       iter = kzalloc(sizeof(struct ccwdev_iter), GFP_KERNEL);
-       if (!iter)
-               return ERR_PTR(-ENOMEM);
+       memset(iter, 0, sizeof(*iter));
        iter->ssid = *offset / (__MAX_SUBCHANNEL + 1);
        iter->devno = *offset % (__MAX_SUBCHANNEL + 1);
        return iter;
@@ -280,8 +278,6 @@ cio_ignore_proc_seq_start(struct seq_file *s, loff_t *offset)
 static void
 cio_ignore_proc_seq_stop(struct seq_file *s, void *it)
 {
-       if (!IS_ERR(it))
-               kfree(it);
 }
 
 static void *
@@ -378,14 +374,15 @@ static const struct seq_operations cio_ignore_proc_seq_ops = {
 static int
 cio_ignore_proc_open(struct inode *inode, struct file *file)
 {
-       return seq_open(file, &cio_ignore_proc_seq_ops);
+       return seq_open_private(file, &cio_ignore_proc_seq_ops,
+                               sizeof(struct ccwdev_iter));
 }
 
 static const struct file_operations cio_ignore_proc_fops = {
        .open    = cio_ignore_proc_open,
        .read    = seq_read,
        .llseek  = seq_lseek,
-       .release = seq_release,
+       .release = seq_release_private,
        .write   = cio_ignore_write,
 };
 
index 4000283..8ab5160 100644 (file)
@@ -393,7 +393,6 @@ int chp_new(struct chp_id chpid)
        chp->state = 1;
        chp->dev.parent = &channel_subsystems[chpid.cssid]->device;
        chp->dev.release = chp_release;
-       dev_set_name(&chp->dev, "chp%x.%02x", chpid.cssid, chpid.id);
 
        /* Obtain channel path description and fill it in. */
        ret = chsc_determine_base_channel_path_desc(chpid, &chp->desc);
@@ -411,6 +410,7 @@ int chp_new(struct chp_id chpid)
        } else {
                chp->cmg = -1;
        }
+       dev_set_name(&chp->dev, "chp%x.%02x", chpid.cssid, chpid.id);
 
        /* make it known to the system */
        ret = device_register(&chp->dev);
index f780bdd..2490b74 100644 (file)
@@ -1250,8 +1250,7 @@ static int io_subchannel_probe(struct subchannel *sch)
        unsigned long flags;
        struct ccw_dev_id dev_id;
 
-       cdev = sch_get_cdev(sch);
-       if (cdev) {
+       if (cio_is_console(sch->schid)) {
                rc = sysfs_create_group(&sch->dev.kobj,
                                        &io_subchannel_attr_group);
                if (rc)
@@ -1260,13 +1259,13 @@ static int io_subchannel_probe(struct subchannel *sch)
                                      "0.%x.%04x (rc=%d)\n",
                                      sch->schid.ssid, sch->schid.sch_no, rc);
                /*
-                * This subchannel already has an associated ccw_device.
+                * The console subchannel already has an associated ccw_device.
                 * Throw the delayed uevent for the subchannel, register
-                * the ccw_device and exit. This happens for all early
-                * devices, e.g. the console.
+                * the ccw_device and exit.
                 */
                dev_set_uevent_suppress(&sch->dev, 0);
                kobject_uevent(&sch->dev.kobj, KOBJ_ADD);
+               cdev = sch_get_cdev(sch);
                cdev->dev.groups = ccwdev_attr_groups;
                device_initialize(&cdev->dev);
                ccw_device_register(cdev);
@@ -1609,7 +1608,7 @@ int ccw_purge_blacklisted(void)
        return 0;
 }
 
-static void device_set_disconnected(struct ccw_device *cdev)
+void ccw_device_set_disconnected(struct ccw_device *cdev)
 {
        if (!cdev)
                return;
@@ -1705,7 +1704,7 @@ static int io_subchannel_sch_event(struct subchannel *sch, int slow)
                ccw_device_trigger_reprobe(cdev);
                break;
        case DISC:
-               device_set_disconnected(cdev);
+               ccw_device_set_disconnected(cdev);
                break;
        default:
                break;
index ed39a2c..246c648 100644 (file)
@@ -125,6 +125,7 @@ int ccw_device_stlck(struct ccw_device *);
 void ccw_device_trigger_reprobe(struct ccw_device *);
 void ccw_device_kill_io(struct ccw_device *);
 int ccw_device_notify(struct ccw_device *, int);
+void ccw_device_set_disconnected(struct ccw_device *cdev);
 void ccw_device_set_notoper(struct ccw_device *cdev);
 
 /* qdio needs this. */
index e728ce4..b9613d7 100644 (file)
@@ -387,19 +387,35 @@ ccw_device_done(struct ccw_device *cdev, int state)
 
        cdev->private->state = state;
 
-       if (state == DEV_STATE_BOXED) {
+       switch (state) {
+       case DEV_STATE_BOXED:
                CIO_MSG_EVENT(0, "Boxed device %04x on subchannel %04x\n",
                              cdev->private->dev_id.devno, sch->schid.sch_no);
                if (cdev->online && !ccw_device_notify(cdev, CIO_BOXED))
                        ccw_device_schedule_sch_unregister(cdev);
                cdev->private->flags.donotify = 0;
-       }
-       if (state == DEV_STATE_NOT_OPER) {
+               break;
+       case DEV_STATE_NOT_OPER:
                CIO_MSG_EVENT(0, "Device %04x gone on subchannel %04x\n",
                              cdev->private->dev_id.devno, sch->schid.sch_no);
                if (!ccw_device_notify(cdev, CIO_GONE))
                        ccw_device_schedule_sch_unregister(cdev);
+               else
+                       ccw_device_set_disconnected(cdev);
                cdev->private->flags.donotify = 0;
+               break;
+       case DEV_STATE_DISCONNECTED:
+               CIO_MSG_EVENT(0, "Disconnected device %04x on subchannel "
+                             "%04x\n", cdev->private->dev_id.devno,
+                             sch->schid.sch_no);
+               if (!ccw_device_notify(cdev, CIO_NO_PATH))
+                       ccw_device_schedule_sch_unregister(cdev);
+               else
+                       ccw_device_set_disconnected(cdev);
+               cdev->private->flags.donotify = 0;
+               break;
+       default:
+               break;
        }
 
        if (cdev->private->flags.donotify) {
@@ -671,6 +687,10 @@ ccw_device_offline(struct ccw_device *cdev)
                ccw_device_done(cdev, DEV_STATE_NOT_OPER);
                return 0;
        }
+       if (cdev->private->state == DEV_STATE_BOXED) {
+               ccw_device_done(cdev, DEV_STATE_BOXED);
+               return 0;
+       }
        if (ccw_device_is_orphan(cdev)) {
                ccw_device_done(cdev, DEV_STATE_OFFLINE);
                return 0;
@@ -730,11 +750,10 @@ ccw_device_recog_notoper(struct ccw_device *cdev, enum dev_event dev_event)
 static void ccw_device_generic_notoper(struct ccw_device *cdev,
                                       enum dev_event dev_event)
 {
-       struct subchannel *sch;
-
-       ccw_device_set_notoper(cdev);
-       sch = to_subchannel(cdev->dev.parent);
-       css_schedule_eval(sch->schid);
+       if (!ccw_device_notify(cdev, CIO_GONE))
+               ccw_device_schedule_sch_unregister(cdev);
+       else
+               ccw_device_set_disconnected(cdev);
 }
 
 /*
index c20d479..5677b40 100644 (file)
@@ -361,7 +361,7 @@ static void rng_type6CPRB_msgX(struct ap_device *ap_dev,
                .ToCardLen1     = sizeof *msg - sizeof(msg->hdr),
                .FromCardLen1   = sizeof *msg - sizeof(msg->hdr),
        };
-       static struct CPRBX static_cprbx = {
+       static struct CPRBX local_cprbx = {
                .cprb_len       = 0x00dc,
                .cprb_ver_id    = 0x02,
                .func_id        = {0x54, 0x32},
@@ -372,7 +372,7 @@ static void rng_type6CPRB_msgX(struct ap_device *ap_dev,
 
        msg->hdr = static_type6_hdrX;
        msg->hdr.FromCardLen2 = random_number_length,
-       msg->cprbx = static_cprbx;
+       msg->cprbx = local_cprbx;
        msg->cprbx.rpl_datal = random_number_length,
        msg->cprbx.domain = AP_QID_QUEUE(ap_dev->qid);
        memcpy(msg->function_code, msg->hdr.function_code, 0x02);
@@ -561,7 +561,8 @@ static int convert_response_ica(struct zcrypt_device *zdev,
                if (msg->cprbx.cprb_ver_id == 0x02)
                        return convert_type86_ica(zdev, reply,
                                                  outputdata, outputdatalength);
-               /* no break, incorrect cprb version is an unknown response */
+               /* Fall through, no break, incorrect cprb version is an unknown
+                * response */
        default: /* Unknown response type, this should NEVER EVER happen */
                zdev->online = 0;
                return -EAGAIN; /* repeat the request on a different device. */
@@ -587,7 +588,8 @@ static int convert_response_xcrb(struct zcrypt_device *zdev,
                }
                if (msg->cprbx.cprb_ver_id == 0x02)
                        return convert_type86_xcrb(zdev, reply, xcRB);
-               /* no break, incorrect cprb version is an unknown response */
+               /* Fall through, no break, incorrect cprb version is an unknown
+                * response */
        default: /* Unknown response type, this should NEVER EVER happen */
                xcRB->status = 0x0008044DL; /* HDD_InvalidParm */
                zdev->online = 0;
@@ -610,7 +612,8 @@ static int convert_response_rng(struct zcrypt_device *zdev,
                        return -EINVAL;
                if (msg->cprbx.cprb_ver_id == 0x02)
                        return convert_type86_rng(zdev, reply, data);
-               /* no break, incorrect cprb version is an unknown response */
+               /* Fall through, no break, incorrect cprb version is an unknown
+                * response */
        default: /* Unknown response type, this should NEVER EVER happen */
                zdev->online = 0;
                return -EAGAIN; /* repeat the request on a different device. */
index 102000d..3012355 100644 (file)
@@ -158,7 +158,12 @@ static int smsg_pm_restore_thaw(struct device *dev)
                smsg_path->flags = 0;
                rc = iucv_path_connect(smsg_path, &smsg_handler, "*MSG    ",
                                       NULL, NULL, NULL);
-               printk(KERN_ERR "iucv_path_connect returned with rc %i\n", rc);
+#ifdef CONFIG_PM_DEBUG
+               if (rc)
+                       printk(KERN_ERR
+                              "iucv_path_connect returned with rc %i\n", rc);
+#endif
+               cpcmd("SET SMSG IUCV", NULL, 0, NULL);
        }
        return 0;
 }
index 1be6bf7..2889e5f 100644 (file)
@@ -80,28 +80,35 @@ int zfcp_reqlist_isempty(struct zfcp_adapter *adapter)
 
 static void __init zfcp_init_device_configure(char *busid, u64 wwpn, u64 lun)
 {
+       struct ccw_device *ccwdev;
        struct zfcp_adapter *adapter;
        struct zfcp_port *port;
        struct zfcp_unit *unit;
 
-       mutex_lock(&zfcp_data.config_mutex);
-       read_lock_irq(&zfcp_data.config_lock);
-       adapter = zfcp_get_adapter_by_busid(busid);
-       if (adapter)
-               zfcp_adapter_get(adapter);
-       read_unlock_irq(&zfcp_data.config_lock);
+       ccwdev = get_ccwdev_by_busid(&zfcp_ccw_driver, busid);
+       if (!ccwdev)
+               return;
+
+       if (ccw_device_set_online(ccwdev))
+               goto out_ccwdev;
 
+       mutex_lock(&zfcp_data.config_mutex);
+       adapter = dev_get_drvdata(&ccwdev->dev);
        if (!adapter)
-               goto out_adapter;
-       port = zfcp_port_enqueue(adapter, wwpn, 0, 0);
-       if (IS_ERR(port))
+               goto out_unlock;
+       zfcp_adapter_get(adapter);
+
+       port = zfcp_get_port_by_wwpn(adapter, wwpn);
+       if (!port)
                goto out_port;
+
+       zfcp_port_get(port);
        unit = zfcp_unit_enqueue(port, lun);
        if (IS_ERR(unit))
                goto out_unit;
        mutex_unlock(&zfcp_data.config_mutex);
-       ccw_device_set_online(adapter->ccw_device);
 
+       zfcp_erp_unit_reopen(unit, 0, "auidc_1", NULL);
        zfcp_erp_wait(adapter);
        flush_work(&unit->scsi_work);
 
@@ -111,20 +118,23 @@ out_unit:
        zfcp_port_put(port);
 out_port:
        zfcp_adapter_put(adapter);
-out_adapter:
+out_unlock:
        mutex_unlock(&zfcp_data.config_mutex);
+out_ccwdev:
+       put_device(&ccwdev->dev);
        return;
 }
 
 static void __init zfcp_init_device_setup(char *devstr)
 {
        char *token;
-       char *str;
+       char *str, *str_saved;
        char busid[ZFCP_BUS_ID_SIZE];
        u64 wwpn, lun;
 
        /* duplicate devstr and keep the original for sysfs presentation*/
-       str = kmalloc(strlen(devstr) + 1, GFP_KERNEL);
+       str_saved = kmalloc(strlen(devstr) + 1, GFP_KERNEL);
+       str = str_saved;
        if (!str)
                return;
 
@@ -143,12 +153,12 @@ static void __init zfcp_init_device_setup(char *devstr)
        if (!token || strict_strtoull(token, 0, (unsigned long long *) &lun))
                goto err_out;
 
-       kfree(str);
+       kfree(str_saved);
        zfcp_init_device_configure(busid, wwpn, lun);
        return;
 
- err_out:
-       kfree(str);
+err_out:
+       kfree(str_saved);
        pr_err("%s is not a valid SCSI device\n", devstr);
 }
 
@@ -593,10 +603,8 @@ void zfcp_adapter_dequeue(struct zfcp_adapter *adapter)
        int retval = 0;
        unsigned long flags;
 
-       cancel_work_sync(&adapter->scan_work);
        cancel_work_sync(&adapter->stat_work);
        zfcp_fc_wka_ports_force_offline(adapter->gs);
-       zfcp_adapter_scsi_unregister(adapter);
        sysfs_remove_group(&adapter->ccw_device->dev.kobj,
                           &zfcp_sysfs_adapter_attrs);
        dev_set_drvdata(&adapter->ccw_device->dev, NULL);
index 0c90f8e..e083394 100644 (file)
@@ -102,6 +102,14 @@ static void zfcp_ccw_remove(struct ccw_device *ccw_device)
        adapter = dev_get_drvdata(&ccw_device->dev);
        if (!adapter)
                goto out;
+       mutex_unlock(&zfcp_data.config_mutex);
+
+       cancel_work_sync(&adapter->scan_work);
+
+       mutex_lock(&zfcp_data.config_mutex);
+
+       /* this also removes the scsi devices, so call it first */
+       zfcp_adapter_scsi_unregister(adapter);
 
        write_lock_irq(&zfcp_data.config_lock);
        list_for_each_entry_safe(port, p, &adapter->port_list_head, list) {
@@ -117,11 +125,8 @@ static void zfcp_ccw_remove(struct ccw_device *ccw_device)
        write_unlock_irq(&zfcp_data.config_lock);
 
        list_for_each_entry_safe(port, p, &port_remove_lh, list) {
-               list_for_each_entry_safe(unit, u, &unit_remove_lh, list) {
-                       if (unit->device)
-                               scsi_remove_device(unit->device);
+               list_for_each_entry_safe(unit, u, &unit_remove_lh, list)
                        zfcp_unit_dequeue(unit);
-               }
                zfcp_port_dequeue(port);
        }
        wait_event(adapter->remove_wq, atomic_read(&adapter->refcount) == 0);
@@ -192,13 +197,9 @@ static int zfcp_ccw_set_offline(struct ccw_device *ccw_device)
 
        mutex_lock(&zfcp_data.config_mutex);
        adapter = dev_get_drvdata(&ccw_device->dev);
-       if (!adapter)
-               goto out;
-
        zfcp_erp_adapter_shutdown(adapter, 0, "ccsoff1", NULL);
        zfcp_erp_wait(adapter);
        mutex_unlock(&zfcp_data.config_mutex);
-out:
        return 0;
 }
 
@@ -253,13 +254,17 @@ static void zfcp_ccw_shutdown(struct ccw_device *cdev)
 
        mutex_lock(&zfcp_data.config_mutex);
        adapter = dev_get_drvdata(&cdev->dev);
+       if (!adapter)
+               goto out;
+
        zfcp_erp_adapter_shutdown(adapter, 0, "ccshut1", NULL);
        zfcp_erp_wait(adapter);
        zfcp_erp_thread_kill(adapter);
+out:
        mutex_unlock(&zfcp_data.config_mutex);
 }
 
-static struct ccw_driver zfcp_ccw_driver = {
+struct ccw_driver zfcp_ccw_driver = {
        .owner       = THIS_MODULE,
        .name        = "zfcp",
        .ids         = zfcp_ccw_device_id,
@@ -284,20 +289,3 @@ int __init zfcp_ccw_register(void)
 {
        return ccw_driver_register(&zfcp_ccw_driver);
 }
-
-/**
- * zfcp_get_adapter_by_busid - find zfcp_adapter struct
- * @busid: bus id string of zfcp adapter to find
- */
-struct zfcp_adapter *zfcp_get_adapter_by_busid(char *busid)
-{
-       struct ccw_device *ccw_device;
-       struct zfcp_adapter *adapter = NULL;
-
-       ccw_device = get_ccwdev_by_busid(&zfcp_ccw_driver, busid);
-       if (ccw_device) {
-               adapter = dev_get_drvdata(&ccw_device->dev);
-               put_device(&ccw_device->dev);
-       }
-       return adapter;
-}
index 8305c87..ef681df 100644 (file)
@@ -86,8 +86,23 @@ static int zfcp_cfdc_copy_to_user(void __user  *user_buffer,
 static struct zfcp_adapter *zfcp_cfdc_get_adapter(u32 devno)
 {
        char busid[9];
+       struct ccw_device *ccwdev;
+       struct zfcp_adapter *adapter = NULL;
+
        snprintf(busid, sizeof(busid), "0.0.%04x", devno);
-       return zfcp_get_adapter_by_busid(busid);
+       ccwdev = get_ccwdev_by_busid(&zfcp_ccw_driver, busid);
+       if (!ccwdev)
+               goto out;
+
+       adapter = dev_get_drvdata(&ccwdev->dev);
+       if (!adapter)
+               goto out_put;
+
+       zfcp_adapter_get(adapter);
+out_put:
+       put_device(&ccwdev->dev);
+out:
+       return adapter;
 }
 
 static int zfcp_cfdc_set_fsf(struct zfcp_fsf_cfdc *fsf_cfdc, int command)
index 73d366b..f73e218 100644 (file)
@@ -858,10 +858,7 @@ static int zfcp_erp_port_strategy_open_common(struct zfcp_erp_action *act)
                if (fc_host_port_type(adapter->scsi_host) == FC_PORTTYPE_PTP)
                        return zfcp_erp_open_ptp_port(act);
                if (!port->d_id) {
-                       zfcp_port_get(port);
-                       if (!queue_work(adapter->work_queue,
-                                       &port->gid_pn_work))
-                               zfcp_port_put(port);
+                       zfcp_fc_trigger_did_lookup(port);
                        return ZFCP_ERP_EXIT;
                }
                return zfcp_erp_port_strategy_open_port(act);
@@ -869,12 +866,11 @@ static int zfcp_erp_port_strategy_open_common(struct zfcp_erp_action *act)
        case ZFCP_ERP_STEP_PORT_OPENING:
                /* D_ID might have changed during open */
                if (p_status & ZFCP_STATUS_COMMON_OPEN) {
-                       if (port->d_id)
-                               return ZFCP_ERP_SUCCEEDED;
-                       else {
-                               act->step = ZFCP_ERP_STEP_PORT_CLOSING;
-                               return ZFCP_ERP_CONTINUES;
+                       if (!port->d_id) {
+                               zfcp_fc_trigger_did_lookup(port);
+                               return ZFCP_ERP_EXIT;
                        }
+                       return ZFCP_ERP_SUCCEEDED;
                }
                if (port->d_id && !(p_status & ZFCP_STATUS_COMMON_NOESC)) {
                        port->d_id = 0;
@@ -889,19 +885,21 @@ static int zfcp_erp_port_strategy_open_common(struct zfcp_erp_action *act)
 static int zfcp_erp_port_strategy(struct zfcp_erp_action *erp_action)
 {
        struct zfcp_port *port = erp_action->port;
+       int p_status = atomic_read(&port->status);
 
-       if (atomic_read(&port->status) & ZFCP_STATUS_COMMON_NOESC)
+       if ((p_status & ZFCP_STATUS_COMMON_NOESC) &&
+           !(p_status & ZFCP_STATUS_COMMON_OPEN))
                goto close_init_done;
 
        switch (erp_action->step) {
        case ZFCP_ERP_STEP_UNINITIALIZED:
                zfcp_erp_port_strategy_clearstati(port);
-               if (atomic_read(&port->status) & ZFCP_STATUS_COMMON_OPEN)
+               if (p_status & ZFCP_STATUS_COMMON_OPEN)
                        return zfcp_erp_port_strategy_close(erp_action);
                break;
 
        case ZFCP_ERP_STEP_PORT_CLOSING:
-               if (atomic_read(&port->status) & ZFCP_STATUS_COMMON_OPEN)
+               if (p_status & ZFCP_STATUS_COMMON_OPEN)
                        return ZFCP_ERP_FAILED;
                break;
        }
index 36935bc..b3f28de 100644 (file)
@@ -28,7 +28,7 @@ extern int zfcp_sg_setup_table(struct scatterlist *, int);
 /* zfcp_ccw.c */
 extern int zfcp_ccw_register(void);
 extern int zfcp_ccw_priv_sch(struct zfcp_adapter *);
-extern struct zfcp_adapter *zfcp_get_adapter_by_busid(char *);
+extern struct ccw_driver zfcp_ccw_driver;
 
 /* zfcp_cfdc.c */
 extern struct miscdevice zfcp_cfdc_misc;
@@ -96,6 +96,7 @@ extern int zfcp_fc_scan_ports(struct zfcp_adapter *);
 extern void _zfcp_fc_scan_ports_later(struct work_struct *);
 extern void zfcp_fc_incoming_els(struct zfcp_fsf_req *);
 extern void zfcp_fc_port_did_lookup(struct work_struct *);
+extern void zfcp_fc_trigger_did_lookup(struct zfcp_port *);
 extern void zfcp_fc_plogi_evaluate(struct zfcp_port *, struct fsf_plogi *);
 extern void zfcp_fc_test_link(struct zfcp_port *);
 extern void zfcp_fc_link_test_work(struct work_struct *);
index 722f22d..df23bce 100644 (file)
@@ -361,6 +361,17 @@ out:
 }
 
 /**
+ * zfcp_fc_trigger_did_lookup - trigger the d_id lookup using a GID_PN request
+ * @port: The zfcp_port to lookup the d_id for.
+ */
+void zfcp_fc_trigger_did_lookup(struct zfcp_port *port)
+{
+       zfcp_port_get(port);
+       if (!queue_work(port->adapter->work_queue, &port->gid_pn_work))
+               zfcp_port_put(port);
+}
+
+/**
  * zfcp_fc_plogi_evaluate - evaluate PLOGI playload
  * @port: zfcp_port structure
  * @plogi: plogi payload
index f09c863..4e41baa 100644 (file)
@@ -1058,14 +1058,28 @@ static int zfcp_fsf_setup_ct_els_sbals(struct zfcp_fsf_req *req,
        bytes = zfcp_qdio_sbals_from_sg(adapter->qdio, &req->queue_req,
                                        SBAL_FLAGS0_TYPE_WRITE_READ,
                                        sg_resp, max_sbals);
+       req->qtcb->bottom.support.resp_buf_length = bytes;
        if (bytes <= 0)
                return -EIO;
 
+       return 0;
+}
+
+static int zfcp_fsf_setup_ct_els(struct zfcp_fsf_req *req,
+                                struct scatterlist *sg_req,
+                                struct scatterlist *sg_resp,
+                                int max_sbals)
+{
+       int ret;
+
+       ret = zfcp_fsf_setup_ct_els_sbals(req, sg_req, sg_resp, max_sbals);
+       if (ret)
+               return ret;
+
        /* common settings for ct/gs and els requests */
-       req->qtcb->bottom.support.resp_buf_length = bytes;
        req->qtcb->bottom.support.service_class = FSF_CLASS_3;
        req->qtcb->bottom.support.timeout = 2 * R_A_TOV;
-       zfcp_fsf_start_timer(req, 2 * R_A_TOV + 10);
+       zfcp_fsf_start_timer(req, (2 * R_A_TOV + 10) * HZ);
 
        return 0;
 }
@@ -1094,8 +1108,8 @@ int zfcp_fsf_send_ct(struct zfcp_send_ct *ct, mempool_t *pool)
        }
 
        req->status |= ZFCP_STATUS_FSFREQ_CLEANUP;
-       ret = zfcp_fsf_setup_ct_els_sbals(req, ct->req, ct->resp,
-                                         FSF_MAX_SBALS_PER_REQ);
+       ret = zfcp_fsf_setup_ct_els(req, ct->req, ct->resp,
+                                   FSF_MAX_SBALS_PER_REQ);
        if (ret)
                goto failed_send;
 
@@ -1192,7 +1206,7 @@ int zfcp_fsf_send_els(struct zfcp_send_els *els)
        }
 
        req->status |= ZFCP_STATUS_FSFREQ_CLEANUP;
-       ret = zfcp_fsf_setup_ct_els_sbals(req, els->req, els->resp, 2);
+       ret = zfcp_fsf_setup_ct_els(req, els->req, els->resp, 2);
 
        if (ret)
                goto failed_send;
@@ -1461,9 +1475,16 @@ static void zfcp_fsf_open_port_handler(struct zfcp_fsf_req *req)
                plogi = (struct fsf_plogi *) req->qtcb->bottom.support.els;
                if (req->qtcb->bottom.support.els1_length >=
                    FSF_PLOGI_MIN_LEN) {
-                       if (plogi->serv_param.wwpn != port->wwpn)
+                       if (plogi->serv_param.wwpn != port->wwpn) {
                                port->d_id = 0;
-                       else {
+                               dev_warn(&port->adapter->ccw_device->dev,
+                                        "A port opened with WWPN 0x%016Lx "
+                                        "returned data that identifies it as "
+                                        "WWPN 0x%016Lx\n",
+                                        (unsigned long long) port->wwpn,
+                                        (unsigned long long)
+                                         plogi->serv_param.wwpn);
+                       } else {
                                port->wwnn = plogi->serv_param.wwnn;
                                zfcp_fc_plogi_evaluate(port, plogi);
                        }
index 079a8cf..d310008 100644 (file)
@@ -224,6 +224,7 @@ static ssize_t zfcp_sysfs_unit_add_store(struct device *dev,
 
        zfcp_erp_unit_reopen(unit, 0, "syuas_1", NULL);
        zfcp_erp_wait(unit->port->adapter);
+       flush_work(&unit->scsi_work);
        zfcp_unit_put(unit);
 out:
        mutex_unlock(&zfcp_data.config_mutex);
index 82bb3b2..e11cca4 100644 (file)
@@ -366,6 +366,7 @@ config ISCSI_TCP
 
 source "drivers/scsi/cxgb3i/Kconfig"
 source "drivers/scsi/bnx2i/Kconfig"
+source "drivers/scsi/be2iscsi/Kconfig"
 
 config SGIWD93_SCSI
        tristate "SGI WD93C93 SCSI Driver"
@@ -1827,6 +1828,16 @@ config SCSI_SRP
          To compile this driver as a module, choose M here: the
          module will be called libsrp.
 
+config SCSI_BFA_FC
+       tristate "Brocade BFA Fibre Channel Support"
+       depends on PCI && SCSI
+       select SCSI_FC_ATTRS
+       help
+         This bfa driver supports all Brocade PCIe FC/FCOE host adapters.
+
+         To compile this driver as a module, choose M here. The module will
+         be called bfa.
+
 endif # SCSI_LOWLEVEL
 
 source "drivers/scsi/pcmcia/Kconfig"
index 61a94af..3ad61db 100644 (file)
@@ -86,6 +86,7 @@ obj-$(CONFIG_SCSI_QLOGIC_1280)        += qla1280.o
 obj-$(CONFIG_SCSI_QLA_FC)      += qla2xxx/
 obj-$(CONFIG_SCSI_QLA_ISCSI)   += qla4xxx/
 obj-$(CONFIG_SCSI_LPFC)                += lpfc/
+obj-$(CONFIG_SCSI_BFA_FC)      += bfa/
 obj-$(CONFIG_SCSI_PAS16)       += pas16.o
 obj-$(CONFIG_SCSI_T128)                += t128.o
 obj-$(CONFIG_SCSI_DMX3191D)    += dmx3191d.o
@@ -130,6 +131,7 @@ obj-$(CONFIG_SCSI_MVSAS)    += mvsas/
 obj-$(CONFIG_PS3_ROM)          += ps3rom.o
 obj-$(CONFIG_SCSI_CXGB3_ISCSI) += libiscsi.o libiscsi_tcp.o cxgb3i/
 obj-$(CONFIG_SCSI_BNX2_ISCSI)  += libiscsi.o bnx2i/
+obj-$(CONFIG_BE2ISCSI)         += libiscsi.o be2iscsi/
 obj-$(CONFIG_SCSI_PMCRAID)     += pmcraid.o
 
 obj-$(CONFIG_ARM)              += arm/
diff --git a/drivers/scsi/be2iscsi/Kconfig b/drivers/scsi/be2iscsi/Kconfig
new file mode 100644 (file)
index 0000000..2952fcd
--- /dev/null
@@ -0,0 +1,8 @@
+config BE2ISCSI
+       tristate "ServerEngines' 10Gbps iSCSI - BladeEngine 2"
+       depends on PCI && SCSI
+       select SCSI_ISCSI_ATTRS
+
+       help
+       This driver implements the iSCSI functionality for ServerEngines'
+       10Gbps Storage adapter - BladeEngine 2.
diff --git a/drivers/scsi/be2iscsi/Makefile b/drivers/scsi/be2iscsi/Makefile
new file mode 100644 (file)
index 0000000..c11f443
--- /dev/null
@@ -0,0 +1,8 @@
+#
+# Makefile to build the iSCSI driver for ServerEngine's BladeEngine.
+#
+#
+
+obj-$(CONFIG_BE2ISCSI) += be2iscsi.o
+
+be2iscsi-y := be_iscsi.o be_main.o be_mgmt.o be_cmds.o
diff --git a/drivers/scsi/be2iscsi/be.h b/drivers/scsi/be2iscsi/be.h
new file mode 100644 (file)
index 0000000..b36020d
--- /dev/null
@@ -0,0 +1,183 @@
+/**
+ * Copyright (C) 2005 - 2009 ServerEngines
+ * 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 version 2
+ * as published by the Free Software Foundation.  The full GNU General
+ * Public License is included in this distribution in the file called COPYING.
+ *
+ * Contact Information:
+ * linux-drivers@serverengines.com
+ *
+ * ServerEngines
+ * 209 N. Fair Oaks Ave
+ * Sunnyvale, CA 94085
+ */
+
+#ifndef BEISCSI_H
+#define BEISCSI_H
+
+#include <linux/pci.h>
+#include <linux/if_vlan.h>
+
+#define FW_VER_LEN 32
+
+struct be_dma_mem {
+       void *va;
+       dma_addr_t dma;
+       u32 size;
+};
+
+struct be_queue_info {
+       struct be_dma_mem dma_mem;
+       u16 len;
+       u16 entry_size;         /* Size of an element in the queue */
+       u16 id;
+       u16 tail, head;
+       bool created;
+       atomic_t used;          /* Number of valid elements in the queue */
+};
+
+static inline u32 MODULO(u16 val, u16 limit)
+{
+       WARN_ON(limit & (limit - 1));
+       return val & (limit - 1);
+}
+
+static inline void index_inc(u16 *index, u16 limit)
+{
+       *index = MODULO((*index + 1), limit);
+}
+
+static inline void *queue_head_node(struct be_queue_info *q)
+{
+       return q->dma_mem.va + q->head * q->entry_size;
+}
+
+static inline void *queue_tail_node(struct be_queue_info *q)
+{
+       return q->dma_mem.va + q->tail * q->entry_size;
+}
+
+static inline void queue_head_inc(struct be_queue_info *q)
+{
+       index_inc(&q->head, q->len);
+}
+
+static inline void queue_tail_inc(struct be_queue_info *q)
+{
+       index_inc(&q->tail, q->len);
+}
+
+/*ISCSI */
+
+struct be_eq_obj {
+       struct be_queue_info q;
+       char desc[32];
+
+       /* Adaptive interrupt coalescing (AIC) info */
+       bool enable_aic;
+       u16 min_eqd;            /* in usecs */
+       u16 max_eqd;            /* in usecs */
+       u16 cur_eqd;            /* in usecs */
+};
+
+struct be_mcc_obj {
+       struct be_queue_info *q;
+       struct be_queue_info *cq;
+};
+
+struct be_ctrl_info {
+       u8 __iomem *csr;
+       u8 __iomem *db;         /* Door Bell */
+       u8 __iomem *pcicfg;     /* PCI config space */
+       struct pci_dev *pdev;
+
+       /* Mbox used for cmd request/response */
+       spinlock_t mbox_lock;   /* For serializing mbox cmds to BE card */
+       struct be_dma_mem mbox_mem;
+       /* Mbox mem is adjusted to align to 16 bytes. The allocated addr
+        * is stored for freeing purpose */
+       struct be_dma_mem mbox_mem_alloced;
+
+       /* MCC Rings */
+       struct be_mcc_obj mcc_obj;
+       spinlock_t mcc_lock;    /* For serializing mcc cmds to BE card */
+       spinlock_t mcc_cq_lock;
+
+       /* MCC Async callback */
+       void (*async_cb) (void *adapter, bool link_up);
+       void *adapter_ctxt;
+};
+
+#include "be_cmds.h"
+
+#define PAGE_SHIFT_4K 12
+#define PAGE_SIZE_4K (1 << PAGE_SHIFT_4K)
+
+/* Returns number of pages spanned by the data starting at the given addr */
+#define PAGES_4K_SPANNED(_address, size)                               \
+               ((u32)((((size_t)(_address) & (PAGE_SIZE_4K - 1)) +     \
+                       (size) + (PAGE_SIZE_4K - 1)) >> PAGE_SHIFT_4K))
+
+/* Byte offset into the page corresponding to given address */
+#define OFFSET_IN_PAGE(addr)                                           \
+               ((size_t)(addr) & (PAGE_SIZE_4K-1))
+
+/* Returns bit offset within a DWORD of a bitfield */
+#define AMAP_BIT_OFFSET(_struct, field)                                \
+               (((size_t)&(((_struct *)0)->field))%32)
+
+/* Returns the bit mask of the field that is NOT shifted into location. */
+static inline u32 amap_mask(u32 bitsize)
+{
+       return (bitsize == 32 ? 0xFFFFFFFF : (1 << bitsize) - 1);
+}
+
+static inline void amap_set(void *ptr, u32 dw_offset, u32 mask,
+                                       u32 offset, u32 value)
+{
+       u32 *dw = (u32 *) ptr + dw_offset;
+       *dw &= ~(mask << offset);
+       *dw |= (mask & value) << offset;
+}
+
+#define AMAP_SET_BITS(_struct, field, ptr, val)                                \
+               amap_set(ptr,                                           \
+                       offsetof(_struct, field)/32,                    \
+                       amap_mask(sizeof(((_struct *)0)->field)),       \
+                       AMAP_BIT_OFFSET(_struct, field),                \
+                       val)
+
+static inline u32 amap_get(void *ptr, u32 dw_offset, u32 mask, u32 offset)
+{
+       u32 *dw = ptr;
+       return mask & (*(dw + dw_offset) >> offset);
+}
+
+#define AMAP_GET_BITS(_struct, field, ptr)                             \
+               amap_get(ptr,                                           \
+                       offsetof(_struct, field)/32,                    \
+                       amap_mask(sizeof(((_struct *)0)->field)),       \
+                       AMAP_BIT_OFFSET(_struct, field))
+
+#define be_dws_cpu_to_le(wrb, len) swap_dws(wrb, len)
+#define be_dws_le_to_cpu(wrb, len) swap_dws(wrb, len)
+static inline void swap_dws(void *wrb, int len)
+{
+#ifdef __BIG_ENDIAN
+       u32 *dw = wrb;
+       WARN_ON(len % 4);
+       do {
+               *dw = cpu_to_le32(*dw);
+               dw++;
+               len -= 4;
+       } while (len);
+#endif /* __BIG_ENDIAN */
+}
+
+extern void beiscsi_cq_notify(struct be_ctrl_info *ctrl, u16 qid, bool arm,
+                             u16 num_popped);
+
+#endif /* BEISCSI_H */
diff --git a/drivers/scsi/be2iscsi/be_cmds.c b/drivers/scsi/be2iscsi/be_cmds.c
new file mode 100644 (file)
index 0000000..08007b6
--- /dev/null
@@ -0,0 +1,523 @@
+/**
+ * Copyright (C) 2005 - 2009 ServerEngines
+ * 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 version 2
+ * as published by the Free Software Foundation.  The full GNU General
+ * Public License is included in this distribution in the file called COPYING.
+ *
+ * Contact Information:
+ * linux-drivers@serverengines.com
+ *
+ * ServerEngines
+ * 209 N. Fair Oaks Ave
+ * Sunnyvale, CA 94085
+ */
+
+#include "be.h"
+#include "be_mgmt.h"
+#include "be_main.h"
+
+static inline bool be_mcc_compl_is_new(struct be_mcc_compl *compl)
+{
+       if (compl->flags != 0) {
+               compl->flags = le32_to_cpu(compl->flags);
+               WARN_ON((compl->flags & CQE_FLAGS_VALID_MASK) == 0);
+               return true;
+       } else
+               return false;
+}
+
+static inline void be_mcc_compl_use(struct be_mcc_compl *compl)
+{
+       compl->flags = 0;
+}
+
+static int be_mcc_compl_process(struct be_ctrl_info *ctrl,
+                               struct be_mcc_compl *compl)
+{
+       u16 compl_status, extd_status;
+
+       be_dws_le_to_cpu(compl, 4);
+
+       compl_status = (compl->status >> CQE_STATUS_COMPL_SHIFT) &
+                                       CQE_STATUS_COMPL_MASK;
+       if (compl_status != MCC_STATUS_SUCCESS) {
+               extd_status = (compl->status >> CQE_STATUS_EXTD_SHIFT) &
+                                               CQE_STATUS_EXTD_MASK;
+               dev_err(&ctrl->pdev->dev,
+                       "error in cmd completion: status(compl/extd)=%d/%d\n",
+                       compl_status, extd_status);
+               return -1;
+       }
+       return 0;
+}
+
+static inline bool is_link_state_evt(u32 trailer)
+{
+       return (((trailer >> ASYNC_TRAILER_EVENT_CODE_SHIFT) &
+               ASYNC_TRAILER_EVENT_CODE_MASK) == ASYNC_EVENT_CODE_LINK_STATE);
+}
+
+void beiscsi_cq_notify(struct be_ctrl_info *ctrl, u16 qid, bool arm,
+                      u16 num_popped)
+{
+       u32 val = 0;
+       val |= qid & DB_CQ_RING_ID_MASK;
+       if (arm)
+               val |= 1 << DB_CQ_REARM_SHIFT;
+       val |= num_popped << DB_CQ_NUM_POPPED_SHIFT;
+       iowrite32(val, ctrl->db + DB_CQ_OFFSET);
+}
+
+static int be_mbox_db_ready_wait(struct be_ctrl_info *ctrl)
+{
+#define long_delay 2000
+       void __iomem *db = ctrl->db + MPU_MAILBOX_DB_OFFSET;
+       int cnt = 0, wait = 5;  /* in usecs */
+       u32 ready;
+
+       do {
+               ready = ioread32(db) & MPU_MAILBOX_DB_RDY_MASK;
+               if (ready)
+                       break;
+
+               if (cnt > 6000000) {
+                       dev_err(&ctrl->pdev->dev, "mbox_db poll timed out\n");
+                       return -1;
+               }
+
+               if (cnt > 50) {
+                       wait = long_delay;
+                       mdelay(long_delay / 1000);
+               } else
+                       udelay(wait);
+               cnt += wait;
+       } while (true);
+       return 0;
+}
+
+int be_mbox_notify(struct be_ctrl_info *ctrl)
+{
+       int status;
+       u32 val = 0;
+       void __iomem *db = ctrl->db + MPU_MAILBOX_DB_OFFSET;
+       struct be_dma_mem *mbox_mem = &ctrl->mbox_mem;
+       struct be_mcc_mailbox *mbox = mbox_mem->va;
+       struct be_mcc_compl *compl = &mbox->compl;
+
+       val &= ~MPU_MAILBOX_DB_RDY_MASK;
+       val |= MPU_MAILBOX_DB_HI_MASK;
+       val |= (upper_32_bits(mbox_mem->dma) >> 2) << 2;
+       iowrite32(val, db);
+
+       status = be_mbox_db_ready_wait(ctrl);
+       if (status != 0) {
+               SE_DEBUG(DBG_LVL_1, " be_mbox_db_ready_wait failed 1\n");
+               return status;
+       }
+       val = 0;
+       val &= ~MPU_MAILBOX_DB_RDY_MASK;
+       val &= ~MPU_MAILBOX_DB_HI_MASK;
+       val |= (u32) (mbox_mem->dma >> 4) << 2;
+       iowrite32(val, db);
+
+       status = be_mbox_db_ready_wait(ctrl);
+       if (status != 0) {
+               SE_DEBUG(DBG_LVL_1, " be_mbox_db_ready_wait failed 2\n");
+               return status;
+       }
+       if (be_mcc_compl_is_new(compl)) {
+               status = be_mcc_compl_process(ctrl, &mbox->compl);
+               be_mcc_compl_use(compl);
+               if (status) {
+                       SE_DEBUG(DBG_LVL_1, "After be_mcc_compl_process \n");
+                       return status;
+               }
+       } else {
+               dev_err(&ctrl->pdev->dev, "invalid mailbox completion\n");
+               return -1;
+       }
+       return 0;
+}
+
+void be_wrb_hdr_prepare(struct be_mcc_wrb *wrb, int payload_len,
+                               bool embedded, u8 sge_cnt)
+{
+       if (embedded)
+               wrb->embedded |= MCC_WRB_EMBEDDED_MASK;
+       else
+               wrb->embedded |= (sge_cnt & MCC_WRB_SGE_CNT_MASK) <<
+                                               MCC_WRB_SGE_CNT_SHIFT;
+       wrb->payload_length = payload_len;
+       be_dws_cpu_to_le(wrb, 8);
+}
+
+void be_cmd_hdr_prepare(struct be_cmd_req_hdr *req_hdr,
+                       u8 subsystem, u8 opcode, int cmd_len)
+{
+       req_hdr->opcode = opcode;
+       req_hdr->subsystem = subsystem;
+       req_hdr->request_length = cpu_to_le32(cmd_len - sizeof(*req_hdr));
+}
+
+static void be_cmd_page_addrs_prepare(struct phys_addr *pages, u32 max_pages,
+                                                       struct be_dma_mem *mem)
+{
+       int i, buf_pages;
+       u64 dma = (u64) mem->dma;
+
+       buf_pages = min(PAGES_4K_SPANNED(mem->va, mem->size), max_pages);
+       for (i = 0; i < buf_pages; i++) {
+               pages[i].lo = cpu_to_le32(dma & 0xFFFFFFFF);
+               pages[i].hi = cpu_to_le32(upper_32_bits(dma));
+               dma += PAGE_SIZE_4K;
+       }
+}
+
+static u32 eq_delay_to_mult(u32 usec_delay)
+{
+#define MAX_INTR_RATE 651042
+       const u32 round = 10;
+       u32 multiplier;
+
+       if (usec_delay == 0)
+               multiplier = 0;
+       else {
+               u32 interrupt_rate = 1000000 / usec_delay;
+               if (interrupt_rate == 0)
+                       multiplier = 1023;
+               else {
+                       multiplier = (MAX_INTR_RATE - interrupt_rate) * round;
+                       multiplier /= interrupt_rate;
+                       multiplier = (multiplier + round / 2) / round;
+                       multiplier = min(multiplier, (u32) 1023);
+               }
+       }
+       return multiplier;
+}
+
+struct be_mcc_wrb *wrb_from_mbox(struct be_dma_mem *mbox_mem)
+{
+       return &((struct be_mcc_mailbox *)(mbox_mem->va))->wrb;
+}
+
+int beiscsi_cmd_eq_create(struct be_ctrl_info *ctrl,
+                         struct be_queue_info *eq, int eq_delay)
+{
+       struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem);
+       struct be_cmd_req_eq_create *req = embedded_payload(wrb);
+       struct be_cmd_resp_eq_create *resp = embedded_payload(wrb);
+       struct be_dma_mem *q_mem = &eq->dma_mem;
+       int status;
+
+       spin_lock(&ctrl->mbox_lock);
+       memset(wrb, 0, sizeof(*wrb));
+
+       be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0);
+
+       be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
+                       OPCODE_COMMON_EQ_CREATE, sizeof(*req));
+
+       req->num_pages = cpu_to_le16(PAGES_4K_SPANNED(q_mem->va, q_mem->size));
+
+       AMAP_SET_BITS(struct amap_eq_context, func, req->context,
+                                               PCI_FUNC(ctrl->pdev->devfn));
+       AMAP_SET_BITS(struct amap_eq_context, valid, req->context, 1);
+       AMAP_SET_BITS(struct amap_eq_context, size, req->context, 0);
+       AMAP_SET_BITS(struct amap_eq_context, count, req->context,
+                                       __ilog2_u32(eq->len / 256));
+       AMAP_SET_BITS(struct amap_eq_context, delaymult, req->context,
+                                       eq_delay_to_mult(eq_delay));
+       be_dws_cpu_to_le(req->context, sizeof(req->context));
+
+       be_cmd_page_addrs_prepare(req->pages, ARRAY_SIZE(req->pages), q_mem);
+
+       status = be_mbox_notify(ctrl);
+       if (!status) {
+               eq->id = le16_to_cpu(resp->eq_id);
+               eq->created = true;
+       }
+       spin_unlock(&ctrl->mbox_lock);
+       return status;
+}
+
+int be_cmd_fw_initialize(struct be_ctrl_info *ctrl)
+{
+       struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem);
+       int status;
+       u8 *endian_check;
+
+       spin_lock(&ctrl->mbox_lock);
+       memset(wrb, 0, sizeof(*wrb));
+
+       endian_check = (u8 *) wrb;
+       *endian_check++ = 0xFF;
+       *endian_check++ = 0x12;
+       *endian_check++ = 0x34;
+       *endian_check++ = 0xFF;
+       *endian_check++ = 0xFF;
+       *endian_check++ = 0x56;
+       *endian_check++ = 0x78;
+       *endian_check++ = 0xFF;
+       be_dws_cpu_to_le(wrb, sizeof(*wrb));
+
+       status = be_mbox_notify(ctrl);
+       if (status)
+               SE_DEBUG(DBG_LVL_1, "be_cmd_fw_initialize Failed \n");
+
+       spin_unlock(&ctrl->mbox_lock);
+       return status;
+}
+
+int beiscsi_cmd_cq_create(struct be_ctrl_info *ctrl,
+                         struct be_queue_info *cq, struct be_queue_info *eq,
+                         bool sol_evts, bool no_delay, int coalesce_wm)
+{
+       struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem);
+       struct be_cmd_req_cq_create *req = embedded_payload(wrb);
+       struct be_cmd_resp_cq_create *resp = embedded_payload(wrb);
+       struct be_dma_mem *q_mem = &cq->dma_mem;
+       void *ctxt = &req->context;
+       int status;
+
+       spin_lock(&ctrl->mbox_lock);
+       memset(wrb, 0, sizeof(*wrb));
+
+       be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0);
+
+       be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
+                       OPCODE_COMMON_CQ_CREATE, sizeof(*req));
+
+       if (!q_mem->va)
+               SE_DEBUG(DBG_LVL_1, "uninitialized q_mem->va\n");
+
+       req->num_pages = cpu_to_le16(PAGES_4K_SPANNED(q_mem->va, q_mem->size));
+
+       AMAP_SET_BITS(struct amap_cq_context, coalescwm, ctxt, coalesce_wm);
+       AMAP_SET_BITS(struct amap_cq_context, nodelay, ctxt, no_delay);
+       AMAP_SET_BITS(struct amap_cq_context, count, ctxt,
+                     __ilog2_u32(cq->len / 256));
+       AMAP_SET_BITS(struct amap_cq_context, valid, ctxt, 1);
+       AMAP_SET_BITS(struct amap_cq_context, solevent, ctxt, sol_evts);
+       AMAP_SET_BITS(struct amap_cq_context, eventable, ctxt, 1);
+       AMAP_SET_BITS(struct amap_cq_context, eqid, ctxt, eq->id);
+       AMAP_SET_BITS(struct amap_cq_context, armed, ctxt, 1);
+       AMAP_SET_BITS(struct amap_cq_context, func, ctxt,
+                     PCI_FUNC(ctrl->pdev->devfn));
+       be_dws_cpu_to_le(ctxt, sizeof(req->context));
+
+       be_cmd_page_addrs_prepare(req->pages, ARRAY_SIZE(req->pages), q_mem);
+
+       status = be_mbox_notify(ctrl);
+       if (!status) {
+               cq->id = le16_to_cpu(resp->cq_id);
+               cq->created = true;
+       } else
+               SE_DEBUG(DBG_LVL_1, "In be_cmd_cq_create, status=ox%08x \n",
+                       status);
+       spin_unlock(&ctrl->mbox_lock);
+
+       return status;
+}
+
+static u32 be_encoded_q_len(int q_len)
+{
+       u32 len_encoded = fls(q_len);   /* log2(len) + 1 */
+       if (len_encoded == 16)
+               len_encoded = 0;
+       return len_encoded;
+}
+int beiscsi_cmd_q_destroy(struct be_ctrl_info *ctrl, struct be_queue_info *q,
+                         int queue_type)
+{
+       struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem);
+       struct be_cmd_req_q_destroy *req = embedded_payload(wrb);
+       u8 subsys = 0, opcode = 0;
+       int status;
+
+       spin_lock(&ctrl->mbox_lock);
+       memset(wrb, 0, sizeof(*wrb));
+       be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0);
+
+       switch (queue_type) {
+       case QTYPE_EQ:
+               subsys = CMD_SUBSYSTEM_COMMON;
+               opcode = OPCODE_COMMON_EQ_DESTROY;
+               break;
+       case QTYPE_CQ:
+               subsys = CMD_SUBSYSTEM_COMMON;
+               opcode = OPCODE_COMMON_CQ_DESTROY;
+               break;
+       case QTYPE_WRBQ:
+               subsys = CMD_SUBSYSTEM_ISCSI;
+               opcode = OPCODE_COMMON_ISCSI_WRBQ_DESTROY;
+               break;
+       case QTYPE_DPDUQ:
+               subsys = CMD_SUBSYSTEM_ISCSI;
+               opcode = OPCODE_COMMON_ISCSI_DEFQ_DESTROY;
+               break;
+       case QTYPE_SGL:
+               subsys = CMD_SUBSYSTEM_ISCSI;
+               opcode = OPCODE_COMMON_ISCSI_CFG_REMOVE_SGL_PAGES;
+               break;
+       default:
+               spin_unlock(&ctrl->mbox_lock);
+               BUG();
+               return -1;
+       }
+       be_cmd_hdr_prepare(&req->hdr, subsys, opcode, sizeof(*req));
+       if (queue_type != QTYPE_SGL)
+               req->id = cpu_to_le16(q->id);
+
+       status = be_mbox_notify(ctrl);
+
+       spin_unlock(&ctrl->mbox_lock);
+       return status;
+}
+
+int be_cmd_get_mac_addr(struct be_ctrl_info *ctrl, u8 *mac_addr)
+{
+       struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem);
+       struct be_cmd_req_get_mac_addr *req = embedded_payload(wrb);
+       int status;
+
+       spin_lock(&ctrl->mbox_lock);
+       memset(wrb, 0, sizeof(*wrb));
+       be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0);
+       be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ISCSI,
+                          OPCODE_COMMON_ISCSI_NTWK_GET_NIC_CONFIG,
+                          sizeof(*req));
+
+       status = be_mbox_notify(ctrl);
+       if (!status) {
+               struct be_cmd_resp_get_mac_addr *resp = embedded_payload(wrb);
+
+               memcpy(mac_addr, resp->mac_address, ETH_ALEN);
+       }
+
+       spin_unlock(&ctrl->mbox_lock);
+       return status;
+}
+
+int be_cmd_create_default_pdu_queue(struct be_ctrl_info *ctrl,
+                                   struct be_queue_info *cq,
+                                   struct be_queue_info *dq, int length,
+                                   int entry_size)
+{
+       struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem);
+       struct be_defq_create_req *req = embedded_payload(wrb);
+       struct be_dma_mem *q_mem = &dq->dma_mem;
+       void *ctxt = &req->context;
+       int status;
+
+       spin_lock(&ctrl->mbox_lock);
+       memset(wrb, 0, sizeof(*wrb));
+
+       be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0);
+
+       be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ISCSI,
+                          OPCODE_COMMON_ISCSI_DEFQ_CREATE, sizeof(*req));
+
+       req->num_pages = PAGES_4K_SPANNED(q_mem->va, q_mem->size);
+       AMAP_SET_BITS(struct amap_be_default_pdu_context, rx_pdid, ctxt, 0);
+       AMAP_SET_BITS(struct amap_be_default_pdu_context, rx_pdid_valid, ctxt,
+                     1);
+       AMAP_SET_BITS(struct amap_be_default_pdu_context, pci_func_id, ctxt,
+                     PCI_FUNC(ctrl->pdev->devfn));
+       AMAP_SET_BITS(struct amap_be_default_pdu_context, ring_size, ctxt,
+                     be_encoded_q_len(length / sizeof(struct phys_addr)));
+       AMAP_SET_BITS(struct amap_be_default_pdu_context, default_buffer_size,
+                     ctxt, entry_size);
+       AMAP_SET_BITS(struct amap_be_default_pdu_context, cq_id_recv, ctxt,
+                     cq->id);
+
+       be_dws_cpu_to_le(ctxt, sizeof(req->context));
+
+       be_cmd_page_addrs_prepare(req->pages, ARRAY_SIZE(req->pages), q_mem);
+
+       status = be_mbox_notify(ctrl);
+       if (!status) {
+               struct be_defq_create_resp *resp = embedded_payload(wrb);
+
+               dq->id = le16_to_cpu(resp->id);
+               dq->created = true;
+       }
+       spin_unlock(&ctrl->mbox_lock);
+
+       return status;
+}
+
+int be_cmd_wrbq_create(struct be_ctrl_info *ctrl, struct be_dma_mem *q_mem,
+                      struct be_queue_info *wrbq)
+{
+       struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem);
+       struct be_wrbq_create_req *req = embedded_payload(wrb);
+       struct be_wrbq_create_resp *resp = embedded_payload(wrb);
+       int status;
+
+       spin_lock(&ctrl->mbox_lock);
+       memset(wrb, 0, sizeof(*wrb));
+
+       be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0);
+
+       be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ISCSI,
+               OPCODE_COMMON_ISCSI_WRBQ_CREATE, sizeof(*req));
+       req->num_pages = PAGES_4K_SPANNED(q_mem->va, q_mem->size);
+       be_cmd_page_addrs_prepare(req->pages, ARRAY_SIZE(req->pages), q_mem);
+
+       status = be_mbox_notify(ctrl);
+       if (!status)
+               wrbq->id = le16_to_cpu(resp->cid);
+       spin_unlock(&ctrl->mbox_lock);
+       return status;
+}
+
+int be_cmd_iscsi_post_sgl_pages(struct be_ctrl_info *ctrl,
+                               struct be_dma_mem *q_mem,
+                               u32 page_offset, u32 num_pages)
+{
+       struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem);
+       struct be_post_sgl_pages_req *req = embedded_payload(wrb);
+       int status;
+       unsigned int curr_pages;
+       u32 internal_page_offset = 0;
+       u32 temp_num_pages = num_pages;
+
+       if (num_pages == 0xff)
+               num_pages = 1;
+
+       spin_lock(&ctrl->mbox_lock);
+       do {
+               memset(wrb, 0, sizeof(*wrb));
+               be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0);
+               be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ISCSI,
+                                  OPCODE_COMMON_ISCSI_CFG_POST_SGL_PAGES,
+                                  sizeof(*req));
+               curr_pages = BE_NUMBER_OF_FIELD(struct be_post_sgl_pages_req,
+                                               pages);
+               req->num_pages = min(num_pages, curr_pages);
+               req->page_offset = page_offset;
+               be_cmd_page_addrs_prepare(req->pages, req->num_pages, q_mem);
+               q_mem->dma = q_mem->dma + (req->num_pages * PAGE_SIZE);
+               internal_page_offset += req->num_pages;
+               page_offset += req->num_pages;
+               num_pages -= req->num_pages;
+
+               if (temp_num_pages == 0xff)
+                       req->num_pages = temp_num_pages;
+
+               status = be_mbox_notify(ctrl);
+               if (status) {
+                       SE_DEBUG(DBG_LVL_1,
+                                "FW CMD to map iscsi frags failed.\n");
+                       goto error;
+               }
+       } while (num_pages > 0);
+error:
+       spin_unlock(&ctrl->mbox_lock);
+       if (status != 0)
+               beiscsi_cmd_q_destroy(ctrl, NULL, QTYPE_SGL);
+       return status;
+}
diff --git a/drivers/scsi/be2iscsi/be_cmds.h b/drivers/scsi/be2iscsi/be_cmds.h
new file mode 100644 (file)
index 0000000..c20d686
--- /dev/null
@@ -0,0 +1,877 @@
+/**
+ * Copyright (C) 2005 - 2009 ServerEngines
+ * 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 version 2
+ * as published by the Free Software Foundation.  The full GNU General
+ * Public License is included in this distribution in the file called COPYING.
+ *
+ * Contact Information:
+ * linux-drivers@serverengines.com
+ *
+ * ServerEngines
+ * 209 N. Fair Oaks Ave
+ * Sunnyvale, CA 94085
+ */
+
+#ifndef BEISCSI_CMDS_H
+#define BEISCSI_CMDS_H
+
+/**
+ * The driver sends configuration and managements command requests to the
+ * firmware in the BE. These requests are communicated to the processor
+ * using Work Request Blocks (WRBs) submitted to the MCC-WRB ring or via one
+ * WRB inside a MAILBOX.
+ * The commands are serviced by the ARM processor in the BladeEngine's MPU.
+ */
+struct be_sge {
+       u32 pa_lo;
+       u32 pa_hi;
+       u32 len;
+};
+
+#define MCC_WRB_SGE_CNT_SHIFT 3        /* bits 3 - 7 of dword 0 */
+#define MCC_WRB_SGE_CNT_MASK 0x1F      /* bits 3 - 7 of dword 0 */
+struct be_mcc_wrb {
+       u32 embedded;           /* dword 0 */
+       u32 payload_length;     /* dword 1 */
+       u32 tag0;               /* dword 2 */
+       u32 tag1;               /* dword 3 */
+       u32 rsvd;               /* dword 4 */
+       union {
+               u8 embedded_payload[236];       /* used by embedded cmds */
+               struct be_sge sgl[19];  /* used by non-embedded cmds */
+       } payload;
+};
+
+#define CQE_FLAGS_VALID_MASK (1 << 31)
+#define CQE_FLAGS_ASYNC_MASK (1 << 30)
+
+/* Completion Status */
+#define MCC_STATUS_SUCCESS 0x0
+
+#define CQE_STATUS_COMPL_MASK 0xFFFF
+#define CQE_STATUS_COMPL_SHIFT 0       /* bits 0 - 15 */
+#define CQE_STATUS_EXTD_MASK 0xFFFF
+#define CQE_STATUS_EXTD_SHIFT 0                /* bits 0 - 15 */
+
+struct be_mcc_compl {
+       u32 status;             /* dword 0 */
+       u32 tag0;               /* dword 1 */
+       u32 tag1;               /* dword 2 */
+       u32 flags;              /* dword 3 */
+};
+
+/********* Mailbox door bell *************/
+/**
+ * Used for driver communication with the FW.
+ * The software must write this register twice to post any command. First,
+ * it writes the register with hi=1 and the upper bits of the physical address
+ * for the MAILBOX structure. Software must poll the ready bit until this
+ * is acknowledged. Then, sotware writes the register with hi=0 with the lower
+ * bits in the address. It must poll the ready bit until the command is
+ * complete. Upon completion, the MAILBOX will contain a valid completion
+ * queue entry.
+ */
+#define MPU_MAILBOX_DB_OFFSET  0x160
+#define MPU_MAILBOX_DB_RDY_MASK        0x1     /* bit 0 */
+#define MPU_MAILBOX_DB_HI_MASK 0x2     /* bit 1 */
+
+/********** MPU semphore ******************/
+#define MPU_EP_SEMAPHORE_OFFSET 0xac
+#define EP_SEMAPHORE_POST_STAGE_MASK 0x0000FFFF
+#define EP_SEMAPHORE_POST_ERR_MASK 0x1
+#define EP_SEMAPHORE_POST_ERR_SHIFT 31
+
+/********** MCC door bell ************/
+#define DB_MCCQ_OFFSET 0x140
+#define DB_MCCQ_RING_ID_MASK 0x7FF             /* bits 0 - 10 */
+/* Number of entries posted */
+#define DB_MCCQ_NUM_POSTED_SHIFT 16            /* bits 16 - 29 */
+
+/* MPU semphore POST stage values */
+#define POST_STAGE_ARMFW_RDY           0xc000  /* FW is done with POST */
+
+/**
+ * When the async bit of mcc_compl is set, the last 4 bytes of
+ * mcc_compl is interpreted as follows:
+ */
+#define ASYNC_TRAILER_EVENT_CODE_SHIFT 8       /* bits 8 - 15 */
+#define ASYNC_TRAILER_EVENT_CODE_MASK  0xFF
+#define ASYNC_EVENT_CODE_LINK_STATE    0x1
+struct be_async_event_trailer {
+       u32 code;
+};
+
+enum {
+       ASYNC_EVENT_LINK_DOWN = 0x0,
+       ASYNC_EVENT_LINK_UP = 0x1
+};
+
+/**
+ * When the event code of an async trailer is link-state, the mcc_compl
+ * must be interpreted as follows
+ */
+struct be_async_event_link_state {
+       u8 physical_port;
+       u8 port_link_status;
+       u8 port_duplex;
+       u8 port_speed;
+       u8 port_fault;
+       u8 rsvd0[7];
+       struct be_async_event_trailer trailer;
+} __packed;
+
+struct be_mcc_mailbox {
+       struct be_mcc_wrb wrb;
+       struct be_mcc_compl compl;
+};
+
+/* Type of subsystems supported by FW */
+#define CMD_SUBSYSTEM_COMMON    0x1
+#define CMD_SUBSYSTEM_ISCSI     0x2
+#define CMD_SUBSYSTEM_ETH       0x3
+#define CMD_SUBSYSTEM_ISCSI_INI 0x6
+#define CMD_COMMON_TCP_UPLOAD   0x1
+
+/**
+ * List of common opcodes subsystem  CMD_SUBSYSTEM_COMMON
+ * These opcodes are unique for each subsystem defined above
+ */
+#define OPCODE_COMMON_CQ_CREATE                                12
+#define OPCODE_COMMON_EQ_CREATE                                13
+#define OPCODE_COMMON_MCC_CREATE                       21
+#define OPCODE_COMMON_GET_CNTL_ATTRIBUTES               32
+#define OPCODE_COMMON_GET_FW_VERSION                   35
+#define OPCODE_COMMON_MODIFY_EQ_DELAY                  41
+#define OPCODE_COMMON_FIRMWARE_CONFIG                  42
+#define OPCODE_COMMON_MCC_DESTROY                      53
+#define OPCODE_COMMON_CQ_DESTROY                       54
+#define OPCODE_COMMON_EQ_DESTROY                       55
+#define OPCODE_COMMON_QUERY_FIRMWARE_CONFIG            58
+#define OPCODE_COMMON_FUNCTION_RESET                   61
+
+/**
+ * LIST of opcodes that are common between Initiator and Target
+ * used by CMD_SUBSYSTEM_ISCSI
+ * These opcodes are unique for each subsystem defined above
+ */
+#define OPCODE_COMMON_ISCSI_CFG_POST_SGL_PAGES         2
+#define OPCODE_COMMON_ISCSI_CFG_REMOVE_SGL_PAGES        3
+#define OPCODE_COMMON_ISCSI_NTWK_GET_NIC_CONFIG                7
+#define OPCODE_COMMON_ISCSI_SET_FRAGNUM_BITS_FOR_SGL_CRA 61
+#define OPCODE_COMMON_ISCSI_DEFQ_CREATE                 64
+#define OPCODE_COMMON_ISCSI_DEFQ_DESTROY               65
+#define OPCODE_COMMON_ISCSI_WRBQ_CREATE                        66
+#define OPCODE_COMMON_ISCSI_WRBQ_DESTROY               67
+
+struct be_cmd_req_hdr {
+       u8 opcode;              /* dword 0 */
+       u8 subsystem;           /* dword 0 */
+       u8 port_number;         /* dword 0 */
+       u8 domain;              /* dword 0 */
+       u32 timeout;            /* dword 1 */
+       u32 request_length;     /* dword 2 */
+       u32 rsvd;               /* dword 3 */
+};
+
+struct be_cmd_resp_hdr {
+       u32 info;               /* dword 0 */
+       u32 status;             /* dword 1 */
+       u32 response_length;    /* dword 2 */
+       u32 actual_resp_len;    /* dword 3 */
+};
+
+struct phys_addr {
+       u32 lo;
+       u32 hi;
+};
+
+/**************************
+ * BE Command definitions *
+ **************************/
+
+/**
+ * Pseudo amap definition in which each bit of the actual structure is defined
+ * as a byte - used to calculate offset/shift/mask of each field
+ */
+struct amap_eq_context {
+       u8 cidx[13];            /* dword 0 */
+       u8 rsvd0[3];            /* dword 0 */
+       u8 epidx[13];           /* dword 0 */
+       u8 valid;               /* dword 0 */
+       u8 rsvd1;               /* dword 0 */
+       u8 size;                /* dword 0 */
+       u8 pidx[13];            /* dword 1 */
+       u8 rsvd2[3];            /* dword 1 */
+       u8 pd[10];              /* dword 1 */
+       u8 count[3];            /* dword 1 */
+       u8 solevent;            /* dword 1 */
+       u8 stalled;             /* dword 1 */
+       u8 armed;               /* dword 1 */
+       u8 rsvd3[4];            /* dword 2 */
+       u8 func[8];             /* dword 2 */
+       u8 rsvd4;               /* dword 2 */
+       u8 delaymult[10];       /* dword 2 */
+       u8 rsvd5[2];            /* dword 2 */
+       u8 phase[2];            /* dword 2 */
+       u8 nodelay;             /* dword 2 */
+       u8 rsvd6[4];            /* dword 2 */
+       u8 rsvd7[32];           /* dword 3 */
+} __packed;
+
+struct be_cmd_req_eq_create {
+       struct be_cmd_req_hdr hdr;      /* dw[4] */
+       u16 num_pages;          /* sword */
+       u16 rsvd0;              /* sword */
+       u8 context[sizeof(struct amap_eq_context) / 8]; /* dw[4] */
+       struct phys_addr pages[8];
+} __packed;
+
+struct be_cmd_resp_eq_create {
+       struct be_cmd_resp_hdr resp_hdr;
+       u16 eq_id;              /* sword */
+       u16 rsvd0;              /* sword */
+} __packed;
+
+struct mac_addr {
+       u16 size_of_struct;
+       u8 addr[ETH_ALEN];
+} __packed;
+
+struct be_cmd_req_mac_query {
+       struct be_cmd_req_hdr hdr;
+       u8 type;
+       u8 permanent;
+       u16 if_id;
+} __packed;
+
+struct be_cmd_resp_mac_query {
+       struct be_cmd_resp_hdr hdr;
+       struct mac_addr mac;
+};
+
+/******************** Create CQ ***************************/
+/**
+ * Pseudo amap definition in which each bit of the actual structure is defined
+ * as a byte - used to calculate offset/shift/mask of each field
+ */
+struct amap_cq_context {
+       u8 cidx[11];            /* dword 0 */
+       u8 rsvd0;               /* dword 0 */
+       u8 coalescwm[2];        /* dword 0 */
+       u8 nodelay;             /* dword 0 */
+       u8 epidx[11];           /* dword 0 */
+       u8 rsvd1;               /* dword 0 */
+       u8 count[2];            /* dword 0 */
+       u8 valid;               /* dword 0 */
+       u8 solevent;            /* dword 0 */
+       u8 eventable;           /* dword 0 */
+       u8 pidx[11];            /* dword 1 */
+       u8 rsvd2;               /* dword 1 */
+       u8 pd[10];              /* dword 1 */
+       u8 eqid[8];             /* dword 1 */
+       u8 stalled;             /* dword 1 */
+       u8 armed;               /* dword 1 */
+       u8 rsvd3[4];            /* dword 2 */
+       u8 func[8];             /* dword 2 */
+       u8 rsvd4[20];           /* dword 2 */
+       u8 rsvd5[32];           /* dword 3 */
+} __packed;
+
+struct be_cmd_req_cq_create {
+       struct be_cmd_req_hdr hdr;
+       u16 num_pages;
+       u16 rsvd0;
+       u8 context[sizeof(struct amap_cq_context) / 8];
+       struct phys_addr pages[4];
+} __packed;
+
+struct be_cmd_resp_cq_create {
+       struct be_cmd_resp_hdr hdr;
+       u16 cq_id;
+       u16 rsvd0;
+} __packed;
+
+/******************** Create MCCQ ***************************/
+/**
+ * Pseudo amap definition in which each bit of the actual structure is defined
+ * as a byte - used to calculate offset/shift/mask of each field
+ */
+struct amap_mcc_context {
+       u8 con_index[14];
+       u8 rsvd0[2];
+       u8 ring_size[4];
+       u8 fetch_wrb;
+       u8 fetch_r2t;
+       u8 cq_id[10];
+       u8 prod_index[14];
+       u8 fid[8];
+       u8 pdid[9];
+       u8 valid;
+       u8 rsvd1[32];
+       u8 rsvd2[32];
+} __packed;
+
+struct be_cmd_req_mcc_create {
+       struct be_cmd_req_hdr hdr;
+       u16 num_pages;
+       u16 rsvd0;
+       u8 context[sizeof(struct amap_mcc_context) / 8];
+       struct phys_addr pages[8];
+} __packed;
+
+struct be_cmd_resp_mcc_create {
+       struct be_cmd_resp_hdr hdr;
+       u16 id;
+       u16 rsvd0;
+} __packed;
+
+/******************** Q Destroy  ***************************/
+/* Type of Queue to be destroyed */
+enum {
+       QTYPE_EQ = 1,
+       QTYPE_CQ,
+       QTYPE_MCCQ,
+       QTYPE_WRBQ,
+       QTYPE_DPDUQ,
+       QTYPE_SGL
+};
+
+struct be_cmd_req_q_destroy {
+       struct be_cmd_req_hdr hdr;
+       u16 id;
+       u16 bypass_flush;       /* valid only for rx q destroy */
+} __packed;
+
+struct macaddr {
+       u8 byte[ETH_ALEN];
+};
+
+struct be_cmd_req_mcast_mac_config {
+       struct be_cmd_req_hdr hdr;
+       u16 num_mac;
+       u8 promiscuous;
+       u8 interface_id;
+       struct macaddr mac[32];
+} __packed;
+
+static inline void *embedded_payload(struct be_mcc_wrb *wrb)
+{
+       return wrb->payload.embedded_payload;
+}
+
+static inline struct be_sge *nonembedded_sgl(struct be_mcc_wrb *wrb)
+{
+       return &wrb->payload.sgl[0];
+}
+
+/******************** Modify EQ Delay *******************/
+struct be_cmd_req_modify_eq_delay {
+       struct be_cmd_req_hdr hdr;
+       u32 num_eq;
+       struct {
+               u32 eq_id;
+               u32 phase;
+               u32 delay_multiplier;
+       } delay[8];
+} __packed;
+
+/******************** Get MAC ADDR *******************/
+
+#define ETH_ALEN       6
+
+
+struct be_cmd_req_get_mac_addr {
+       struct be_cmd_req_hdr hdr;
+       u32 nic_port_count;
+       u32 speed;
+       u32 max_speed;
+       u32 link_state;
+       u32 max_frame_size;
+       u16 size_of_structure;
+       u8 mac_address[ETH_ALEN];
+       u32 rsvd[23];
+};
+
+struct be_cmd_resp_get_mac_addr {
+       struct be_cmd_resp_hdr hdr;
+       u32 nic_port_count;
+       u32 speed;
+       u32 max_speed;
+       u32 link_state;
+       u32 max_frame_size;
+       u16 size_of_structure;
+       u8 mac_address[6];
+       u32 rsvd[23];
+};
+
+int beiscsi_cmd_eq_create(struct be_ctrl_info *ctrl,
+                         struct be_queue_info *eq, int eq_delay);
+
+int beiscsi_cmd_cq_create(struct be_ctrl_info *ctrl,
+                         struct be_queue_info *cq, struct be_queue_info *eq,
+                         bool sol_evts, bool no_delay,
+                         int num_cqe_dma_coalesce);
+
+int beiscsi_cmd_q_destroy(struct be_ctrl_info *ctrl, struct be_queue_info *q,
+                         int type);
+int be_poll_mcc(struct be_ctrl_info *ctrl);
+unsigned char mgmt_check_supported_fw(struct be_ctrl_info *ctrl);
+int be_cmd_get_mac_addr(struct be_ctrl_info *ctrl, u8 *mac_addr);
+
+/*ISCSI Functuions */
+int be_cmd_fw_initialize(struct be_ctrl_info *ctrl);
+
+struct be_mcc_wrb *wrb_from_mbox(struct be_dma_mem *mbox_mem);
+
+int be_mbox_notify(struct be_ctrl_info *ctrl);
+
+int be_cmd_create_default_pdu_queue(struct be_ctrl_info *ctrl,
+                                   struct be_queue_info *cq,
+                                   struct be_queue_info *dq, int length,
+                                   int entry_size);
+
+int be_cmd_iscsi_post_sgl_pages(struct be_ctrl_info *ctrl,
+                               struct be_dma_mem *q_mem, u32 page_offset,
+                               u32 num_pages);
+
+int be_cmd_wrbq_create(struct be_ctrl_info *ctrl, struct be_dma_mem *q_mem,
+                      struct be_queue_info *wrbq);
+
+struct be_default_pdu_context {
+       u32 dw[4];
+} __packed;
+
+struct amap_be_default_pdu_context {
+       u8 dbuf_cindex[13];     /* dword 0 */
+       u8 rsvd0[3];            /* dword 0 */
+       u8 ring_size[4];        /* dword 0 */
+       u8 ring_state[4];       /* dword 0 */
+       u8 rsvd1[8];            /* dword 0 */
+       u8 dbuf_pindex[13];     /* dword 1 */
+       u8 rsvd2;               /* dword 1 */
+       u8 pci_func_id[8];      /* dword 1 */
+       u8 rx_pdid[9];          /* dword 1 */
+       u8 rx_pdid_valid;       /* dword 1 */
+       u8 default_buffer_size[16];     /* dword 2 */
+       u8 cq_id_recv[10];      /* dword 2 */
+       u8 rx_pdid_not_valid;   /* dword 2 */
+       u8 rsvd3[5];            /* dword 2 */
+       u8 rsvd4[32];           /* dword 3 */
+} __packed;
+
+struct be_defq_create_req {
+       struct be_cmd_req_hdr hdr;
+       u16 num_pages;
+       u8 ulp_num;
+       u8 rsvd0;
+       struct be_default_pdu_context context;
+       struct phys_addr pages[8];
+} __packed;
+
+struct be_defq_create_resp {
+       struct be_cmd_req_hdr hdr;
+       u16 id;
+       u16 rsvd0;
+} __packed;
+
+struct be_post_sgl_pages_req {
+       struct be_cmd_req_hdr hdr;
+       u16 num_pages;
+       u16 page_offset;
+       u32 rsvd0;
+       struct phys_addr pages[26];
+       u32 rsvd1;
+} __packed;
+
+struct be_wrbq_create_req {
+       struct be_cmd_req_hdr hdr;
+       u16 num_pages;
+       u8 ulp_num;
+       u8 rsvd0;
+       struct phys_addr pages[8];
+} __packed;
+
+struct be_wrbq_create_resp {
+       struct be_cmd_resp_hdr resp_hdr;
+       u16 cid;
+       u16 rsvd0;
+} __packed;
+
+#define SOL_CID_MASK           0x0000FFC0
+#define SOL_CODE_MASK          0x0000003F
+#define SOL_WRB_INDEX_MASK     0x00FF0000
+#define SOL_CMD_WND_MASK       0xFF000000
+#define SOL_RES_CNT_MASK       0x7FFFFFFF
+#define SOL_EXP_CMD_SN_MASK    0xFFFFFFFF
+#define SOL_HW_STS_MASK                0x000000FF
+#define SOL_STS_MASK           0x0000FF00
+#define SOL_RESP_MASK          0x00FF0000
+#define SOL_FLAGS_MASK         0x7F000000
+#define SOL_S_MASK             0x80000000
+
+struct sol_cqe {
+       u32 dw[4];
+};
+
+struct amap_sol_cqe {
+       u8 hw_sts[8];           /* dword 0 */
+       u8 i_sts[8];            /* dword 0 */
+       u8 i_resp[8];           /* dword 0 */
+       u8 i_flags[7];          /* dword 0 */
+       u8 s;                   /* dword 0 */
+       u8 i_exp_cmd_sn[32];    /* dword 1 */
+       u8 code[6];             /* dword 2 */
+       u8 cid[10];             /* dword 2 */
+       u8 wrb_index[8];        /* dword 2 */
+       u8 i_cmd_wnd[8];        /* dword 2 */
+       u8 i_res_cnt[31];       /* dword 3 */
+       u8 valid;               /* dword 3 */
+} __packed;
+
+
+/**
+ * Post WRB Queue Doorbell Register used by the host Storage
+ * stack to notify the
+ * controller of a posted Work Request Block
+ */
+#define DB_WRB_POST_CID_MASK           0x3FF   /* bits 0 - 9 */
+#define DB_DEF_PDU_WRB_INDEX_MASK      0xFF    /* bits 0 - 9 */
+
+#define DB_DEF_PDU_WRB_INDEX_SHIFT     16
+#define DB_DEF_PDU_NUM_POSTED_SHIFT    24
+
+struct fragnum_bits_for_sgl_cra_in {
+       struct be_cmd_req_hdr hdr;
+       u32 num_bits;
+} __packed;
+
+struct iscsi_cleanup_req {
+       struct be_cmd_req_hdr hdr;
+       u16 chute;
+       u8 hdr_ring_id;
+       u8 data_ring_id;
+
+} __packed;
+
+struct eq_delay {
+       u32 eq_id;
+       u32 phase;
+       u32 delay_multiplier;
+} __packed;
+
+struct be_eq_delay_params_in {
+       struct be_cmd_req_hdr hdr;
+       u32 num_eq;
+       struct eq_delay delay[8];
+} __packed;
+
+struct ip_address_format {
+       u16 size_of_structure;
+       u8 reserved;
+       u8 ip_type;
+       u8 ip_address[16];
+       u32 rsvd0;
+} __packed;
+
+struct tcp_connect_and_offload_in {
+       struct be_cmd_req_hdr hdr;
+       struct ip_address_format ip_address;
+       u16 tcp_port;
+       u16 cid;
+       u16 cq_id;
+       u16 defq_id;
+       struct phys_addr dataout_template_pa;
+       u16 hdr_ring_id;
+       u16 data_ring_id;
+       u8 do_offload;
+       u8 rsvd0[3];
+} __packed;
+
+struct tcp_connect_and_offload_out {
+       struct be_cmd_resp_hdr hdr;
+       u32 connection_handle;
+       u16 cid;
+       u16 rsvd0;
+
+} __packed;
+
+struct be_mcc_wrb_context {
+       struct MCC_WRB *wrb;
+       int *users_final_status;
+} __packed;
+
+#define DB_DEF_PDU_RING_ID_MASK                0x3FF   /* bits 0 - 9 */
+#define DB_DEF_PDU_CQPROC_MASK         0x3FFF  /* bits 0 - 9 */
+#define DB_DEF_PDU_REARM_SHIFT         14
+#define DB_DEF_PDU_EVENT_SHIFT         15
+#define DB_DEF_PDU_CQPROC_SHIFT                16
+
+struct dmsg_cqe {
+       u32 dw[4];
+} __packed;
+
+struct tcp_upload_params_in {
+       struct be_cmd_req_hdr hdr;
+       u16 id;
+       u16 upload_type;
+       u32 reset_seq;
+} __packed;
+
+struct tcp_upload_params_out {
+       u32 dw[32];
+} __packed;
+
+union tcp_upload_params {
+       struct tcp_upload_params_in request;
+       struct tcp_upload_params_out response;
+} __packed;
+
+struct be_ulp_fw_cfg {
+       u32 ulp_mode;
+       u32 etx_base;
+       u32 etx_count;
+       u32 sq_base;
+       u32 sq_count;
+       u32 rq_base;
+       u32 rq_count;
+       u32 dq_base;
+       u32 dq_count;
+       u32 lro_base;
+       u32 lro_count;
+       u32 icd_base;
+       u32 icd_count;
+};
+
+struct be_fw_cfg {
+       struct be_cmd_req_hdr hdr;
+       u32 be_config_number;
+       u32 asic_revision;
+       u32 phys_port;
+       u32 function_mode;
+       struct be_ulp_fw_cfg ulp[2];
+       u32 function_caps;
+} __packed;
+
+#define CMD_ISCSI_COMMAND_INVALIDATE  1
+#define ISCSI_OPCODE_SCSI_DATA_OUT      5
+#define OPCODE_COMMON_ISCSI_TCP_CONNECT_AND_OFFLOAD 70
+#define OPCODE_ISCSI_INI_DRIVER_OFFLOAD_SESSION 41
+#define OPCODE_COMMON_MODIFY_EQ_DELAY  41
+#define OPCODE_COMMON_ISCSI_CLEANUP    59
+#define        OPCODE_COMMON_TCP_UPLOAD        56
+#define OPCODE_COMMON_ISCSI_ERROR_RECOVERY_INVALIDATE_COMMANDS 1
+/* --- CMD_ISCSI_INVALIDATE_CONNECTION_TYPE --- */
+#define CMD_ISCSI_CONNECTION_INVALIDATE 1
+#define CMD_ISCSI_CONNECTION_ISSUE_TCP_RST 2
+#define OPCODE_ISCSI_INI_DRIVER_INVALIDATE_CONNECTION 42
+
+#define INI_WR_CMD                     1       /* Initiator write command */
+#define INI_TMF_CMD                    2       /* Initiator TMF command */
+#define INI_NOPOUT_CMD                 3       /* Initiator; Send a NOP-OUT */
+#define INI_RD_CMD                     5       /* Initiator requesting to send
+                                                * a read command
+                                                */
+#define TGT_CTX_UPDT_CMD               7       /* Target context update */
+#define TGT_STS_CMD                    8       /* Target R2T and other BHS
+                                                * where only the status number
+                                                * need to be updated
+                                                */
+#define TGT_DATAIN_CMD                 9       /* Target Data-Ins in response
+                                                * to read command
+                                                */
+#define TGT_SOS_PDU                    10      /* Target:standalone status
+                                                * response
+                                                */
+#define TGT_DM_CMD                     11      /* Indicates that the bhs
+                                                *  preparedby
+                                                * driver should not be touched
+                                                */
+/* --- CMD_CHUTE_TYPE --- */
+#define CMD_CONNECTION_CHUTE_0         1
+#define CMD_CONNECTION_CHUTE_1         2
+#define CMD_CONNECTION_CHUTE_2         3
+
+#define EQ_MAJOR_CODE_COMPLETION       0
+
+#define CMD_ISCSI_SESSION_DEL_CFG_FROM_FLASH 0
+#define CMD_ISCSI_SESSION_SAVE_CFG_ON_FLASH 1
+
+/* --- CONNECTION_UPLOAD_PARAMS --- */
+/* These parameters are used to define the type of upload desired.  */
+#define CONNECTION_UPLOAD_GRACEFUL      1      /* Graceful upload  */
+#define CONNECTION_UPLOAD_ABORT_RESET   2      /* Abortive upload with
+                                                * reset
+                                                */
+#define CONNECTION_UPLOAD_ABORT                3       /* Abortive upload without
+                                                * reset
+                                                */
+#define CONNECTION_UPLOAD_ABORT_WITH_SEQ 4     /* Abortive upload with reset,
+                                                * sequence number by driver  */
+
+/* Returns byte size of given field with a structure. */
+
+/* Returns the number of items in the field array. */
+#define BE_NUMBER_OF_FIELD(_type_, _field_)    \
+       (FIELD_SIZEOF(_type_, _field_)/sizeof((((_type_ *)0)->_field_[0])))\
+
+/**
+ * Different types of iSCSI completions to host driver for both initiator
+ * and taget mode
+ * of operation.
+ */
+#define SOL_CMD_COMPLETE               1       /* Solicited command completed
+                                                * normally
+                                                */
+#define SOL_CMD_KILLED_DATA_DIGEST_ERR  2      /* Solicited command got
+                                                * invalidated internally due
+                                                * to Data Digest error
+                                                */
+#define CXN_KILLED_PDU_SIZE_EXCEEDS_DSL 3      /* Connection got invalidated
+                                                * internally
+                                                * due to a recieved PDU
+                                                * size > DSL
+                                                */
+#define CXN_KILLED_BURST_LEN_MISMATCH   4      /* Connection got invalidated
+                                                * internally due ti received
+                                                * PDU sequence size >
+                                                * FBL/MBL.
+                                                */
+#define CXN_KILLED_AHS_RCVD            5       /* Connection got invalidated
+                                                * internally due to a recieved
+                                                * PDU Hdr that has
+                                                * AHS */
+#define CXN_KILLED_HDR_DIGEST_ERR      6       /* Connection got invalidated
+                                                * internally due to Hdr Digest
+                                                * error
+                                                */
+#define CXN_KILLED_UNKNOWN_HDR         7       /* Connection got invalidated
+                                                *  internally
+                                                * due to a bad opcode in the
+                                                * pdu hdr
+                                                */
+#define CXN_KILLED_STALE_ITT_TTT_RCVD  8       /* Connection got invalidated
+                                                * internally due to a recieved
+                                                * ITT/TTT that does not belong
+                                                * to this Connection
+                                                */
+#define CXN_KILLED_INVALID_ITT_TTT_RCVD 9      /* Connection got invalidated
+                                                * internally due to recieved
+                                                * ITT/TTT value > Max
+                                                * Supported ITTs/TTTs
+                                                */
+#define CXN_KILLED_RST_RCVD            10      /* Connection got invalidated
+                                                * internally due to an
+                                                * incoming TCP RST
+                                                */
+#define CXN_KILLED_TIMED_OUT           11      /* Connection got invalidated
+                                                * internally due to timeout on
+                                                * tcp segment 12 retransmit
+                                                * attempts failed
+                                                */
+#define CXN_KILLED_RST_SENT            12      /* Connection got invalidated
+                                                * internally due to TCP RST
+                                                * sent by the Tx side
+                                                */
+#define CXN_KILLED_FIN_RCVD            13      /* Connection got invalidated
+                                                * internally due to an
+                                                * incoming TCP FIN.
+                                                */
+#define CXN_KILLED_BAD_UNSOL_PDU_RCVD  14      /* Connection got invalidated
+                                                * internally due to bad
+                                                * unsolicited PDU Unsolicited
+                                                * PDUs are PDUs with
+                                                * ITT=0xffffffff
+                                                */
+#define CXN_KILLED_BAD_WRB_INDEX_ERROR 15      /* Connection got invalidated
+                                                * internally due to bad WRB
+                                                * index.
+                                                */
+#define CXN_KILLED_OVER_RUN_RESIDUAL   16      /* Command got invalidated
+                                                * internally due to recived
+                                                * command has residual
+                                                * over run bytes.
+                                                */
+#define CXN_KILLED_UNDER_RUN_RESIDUAL  17      /* Command got invalidated
+                                                * internally due to recived
+                                                * command has residual under
+                                                * run bytes.
+                                                */
+#define CMD_KILLED_INVALID_STATSN_RCVD 18      /* Command got invalidated
+                                                * internally due to a recieved
+                                                * PDU has an invalid StatusSN
+                                                */
+#define CMD_KILLED_INVALID_R2T_RCVD    19      /* Command got invalidated
+                                                * internally due to a recieved
+                                                * an R2T with some invalid
+                                                * fields in it
+                                                */
+#define CMD_CXN_KILLED_LUN_INVALID     20      /* Command got invalidated
+                                                * internally due to received
+                                                * PDU has an invalid LUN.
+                                                */
+#define CMD_CXN_KILLED_ICD_INVALID     21      /* Command got invalidated
+                                                * internally due to the
+                                                * corresponding ICD not in a
+                                                * valid state
+                                                */
+#define CMD_CXN_KILLED_ITT_INVALID     22      /* Command got invalidated due
+                                                *  to received PDU has an
+                                                *  invalid ITT.
+                                                */
+#define CMD_CXN_KILLED_SEQ_OUTOFORDER  23      /* Command got invalidated due
+                                                * to received sequence buffer
+                                                * offset is out of order.
+                                                */
+#define CMD_CXN_KILLED_INVALID_DATASN_RCVD 24  /* Command got invalidated
+                                                * internally due to a
+                                                * recieved PDU has an invalid
+                                                * DataSN
+                                                */
+#define CXN_INVALIDATE_NOTIFY          25      /* Connection invalidation
+                                                * completion notify.
+                                                */
+#define CXN_INVALIDATE_INDEX_NOTIFY    26      /* Connection invalidation
+                                                * completion
+                                                * with data PDU index.
+                                                */
+#define CMD_INVALIDATED_NOTIFY         27      /* Command invalidation
+                                                * completionnotifify.
+                                                */
+#define UNSOL_HDR_NOTIFY               28      /* Unsolicited header notify.*/
+#define UNSOL_DATA_NOTIFY              29      /* Unsolicited data notify.*/
+#define UNSOL_DATA_DIGEST_ERROR_NOTIFY         30      /* Unsolicited data digest
+                                                * error notify.
+                                                */
+#define DRIVERMSG_NOTIFY               31      /* TCP acknowledge based
+                                                * notification.
+                                                */
+#define CXN_KILLED_CMND_DATA_NOT_ON_SAME_CONN 32 /* Connection got invalidated
+                                                 * internally due to command
+                                                 * and data are not on same
+                                                 * connection.
+                                                 */
+#define SOL_CMD_KILLED_DIF_ERR         33      /* Solicited command got
+                                                *  invalidated internally due
+                                                *  to DIF error
+                                                */
+#define CXN_KILLED_SYN_RCVD            34      /* Connection got invalidated
+                                                * internally due to incoming
+                                                * TCP SYN
+                                                */
+#define CXN_KILLED_IMM_DATA_RCVD       35      /* Connection got invalidated
+                                                * internally due to an
+                                                * incoming Unsolicited PDU
+                                                * that has immediate data on
+                                                * the cxn
+                                                */
+
+void be_wrb_hdr_prepare(struct be_mcc_wrb *wrb, int payload_len,
+                       bool embedded, u8 sge_cnt);
+
+void be_cmd_hdr_prepare(struct be_cmd_req_hdr *req_hdr,
+                       u8 subsystem, u8 opcode, int cmd_len);
+
+#endif /* !BEISCSI_CMDS_H */
diff --git a/drivers/scsi/be2iscsi/be_iscsi.c b/drivers/scsi/be2iscsi/be_iscsi.c
new file mode 100644 (file)
index 0000000..2fd2544
--- /dev/null
@@ -0,0 +1,638 @@
+/**
+ * Copyright (C) 2005 - 2009 ServerEngines
+ * 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 version 2
+ * as published by the Free Software Foundation.  The full GNU General
+ * Public License is included in this distribution in the file called COPYING.
+ *
+ * Written by: Jayamohan Kallickal (jayamohank@serverengines.com)
+ *
+ * Contact Information:
+ * linux-drivers@serverengines.com
+ *
+ * ServerEngines
+ * 209 N. Fair Oaks Ave
+ * Sunnyvale, CA 94085
+ *
+ */
+
+#include <scsi/libiscsi.h>
+#include <scsi/scsi_transport_iscsi.h>
+#include <scsi/scsi_transport.h>
+#include <scsi/scsi_cmnd.h>
+#include <scsi/scsi_device.h>
+#include <scsi/scsi_host.h>
+#include <scsi/scsi.h>
+
+#include "be_iscsi.h"
+
+extern struct iscsi_transport beiscsi_iscsi_transport;
+
+/**
+ * beiscsi_session_create - creates a new iscsi session
+ * @cmds_max: max commands supported
+ * @qdepth: max queue depth supported
+ * @initial_cmdsn: initial iscsi CMDSN
+ */
+struct iscsi_cls_session *beiscsi_session_create(struct iscsi_endpoint *ep,
+                                                u16 cmds_max,
+                                                u16 qdepth,
+                                                u32 initial_cmdsn)
+{
+       struct Scsi_Host *shost;
+       struct beiscsi_endpoint *beiscsi_ep;
+       struct iscsi_cls_session *cls_session;
+       struct beiscsi_hba *phba;
+       struct iscsi_session *sess;
+       struct beiscsi_session *beiscsi_sess;
+       struct beiscsi_io_task *io_task;
+
+       SE_DEBUG(DBG_LVL_8, "In beiscsi_session_create\n");
+
+       if (!ep) {
+               SE_DEBUG(DBG_LVL_1, "beiscsi_session_create: invalid ep \n");
+               return NULL;
+       }
+       beiscsi_ep = ep->dd_data;
+       phba = beiscsi_ep->phba;
+       shost = phba->shost;
+       if (cmds_max > beiscsi_ep->phba->params.wrbs_per_cxn) {
+               shost_printk(KERN_ERR, shost, "Cannot handle %d cmds."
+                            "Max cmds per session supported is %d. Using %d. "
+                            "\n", cmds_max,
+                             beiscsi_ep->phba->params.wrbs_per_cxn,
+                             beiscsi_ep->phba->params.wrbs_per_cxn);
+               cmds_max = beiscsi_ep->phba->params.wrbs_per_cxn;
+       }
+
+        cls_session = iscsi_session_setup(&beiscsi_iscsi_transport,
+                                          shost, cmds_max,
+                                          sizeof(*beiscsi_sess),
+                                          sizeof(*io_task),
+                                          initial_cmdsn, ISCSI_MAX_TARGET);
+       if (!cls_session)
+               return NULL;
+       sess = cls_session->dd_data;
+       beiscsi_sess = sess->dd_data;
+       beiscsi_sess->bhs_pool =  pci_pool_create("beiscsi_bhs_pool",
+                                                  phba->pcidev,
+                                                  sizeof(struct be_cmd_bhs),
+                                                  64, 0);
+       if (!beiscsi_sess->bhs_pool)
+               goto destroy_sess;
+
+       return cls_session;
+destroy_sess:
+       iscsi_session_teardown(cls_session);
+       return NULL;
+}
+
+/**
+ * beiscsi_session_destroy - destroys iscsi session
+ * @cls_session:       pointer to iscsi cls session
+ *
+ * Destroys iSCSI session instance and releases
+ * resources allocated for it.
+ */
+void beiscsi_session_destroy(struct iscsi_cls_session *cls_session)
+{
+       struct iscsi_session *sess = cls_session->dd_data;
+       struct beiscsi_session *beiscsi_sess = sess->dd_data;
+
+       pci_pool_destroy(beiscsi_sess->bhs_pool);
+       iscsi_session_teardown(cls_session);
+}
+
+/**
+ * beiscsi_conn_create - create an instance of iscsi connection
+ * @cls_session: ptr to iscsi_cls_session
+ * @cid: iscsi cid
+ */
+struct iscsi_cls_conn *
+beiscsi_conn_create(struct iscsi_cls_session *cls_session, u32 cid)
+{
+       struct beiscsi_hba *phba;
+       struct Scsi_Host *shost;
+       struct iscsi_cls_conn *cls_conn;
+       struct beiscsi_conn *beiscsi_conn;
+       struct iscsi_conn *conn;
+       struct iscsi_session *sess;
+       struct beiscsi_session *beiscsi_sess;
+
+       SE_DEBUG(DBG_LVL_8, "In beiscsi_conn_create ,cid"
+                "from iscsi layer=%d\n", cid);
+       shost = iscsi_session_to_shost(cls_session);
+       phba = iscsi_host_priv(shost);
+
+       cls_conn = iscsi_conn_setup(cls_session, sizeof(*beiscsi_conn), cid);
+       if (!cls_conn)
+               return NULL;
+
+       conn = cls_conn->dd_data;
+       beiscsi_conn = conn->dd_data;
+       beiscsi_conn->ep = NULL;
+       beiscsi_conn->phba = phba;
+       beiscsi_conn->conn = conn;
+       sess = cls_session->dd_data;
+       beiscsi_sess = sess->dd_data;
+       beiscsi_conn->beiscsi_sess = beiscsi_sess;
+       return cls_conn;
+}
+
+/**
+ * beiscsi_bindconn_cid - Bind the beiscsi_conn with phba connection table
+ * @beiscsi_conn: The pointer to  beiscsi_conn structure
+ * @phba: The phba instance
+ * @cid: The cid to free
+ */
+static int beiscsi_bindconn_cid(struct beiscsi_hba *phba,
+                               struct beiscsi_conn *beiscsi_conn,
+                               unsigned int cid)
+{
+       if (phba->conn_table[cid]) {
+               SE_DEBUG(DBG_LVL_1,
+                        "Connection table already occupied. Detected clash\n");
+               return -EINVAL;
+       } else {
+               SE_DEBUG(DBG_LVL_8, "phba->conn_table[%d]=%p(beiscsi_conn) \n",
+                        cid, beiscsi_conn);
+               phba->conn_table[cid] = beiscsi_conn;
+       }
+       return 0;
+}
+
+/**
+ * beiscsi_conn_bind - Binds iscsi session/connection with TCP connection
+ * @cls_session: pointer to iscsi cls session
+ * @cls_conn: pointer to iscsi cls conn
+ * @transport_fd: EP handle(64 bit)
+ *
+ * This function binds the TCP Conn with iSCSI Connection and Session.
+ */
+int beiscsi_conn_bind(struct iscsi_cls_session *cls_session,
+                     struct iscsi_cls_conn *cls_conn,
+                     u64 transport_fd, int is_leading)
+{
+       struct iscsi_conn *conn = cls_conn->dd_data;
+       struct beiscsi_conn *beiscsi_conn = conn->dd_data;
+       struct Scsi_Host *shost =
+               (struct Scsi_Host *)iscsi_session_to_shost(cls_session);
+       struct beiscsi_hba *phba = (struct beiscsi_hba *)iscsi_host_priv(shost);
+       struct beiscsi_endpoint *beiscsi_ep;
+       struct iscsi_endpoint *ep;
+
+       SE_DEBUG(DBG_LVL_8, "In beiscsi_conn_bind\n");
+       ep = iscsi_lookup_endpoint(transport_fd);
+       if (!ep)
+               return -EINVAL;
+
+       beiscsi_ep = ep->dd_data;
+
+       if (iscsi_conn_bind(cls_session, cls_conn, is_leading))
+               return -EINVAL;
+
+       if (beiscsi_ep->phba != phba) {
+               SE_DEBUG(DBG_LVL_8,
+                        "beiscsi_ep->hba=%p not equal to phba=%p \n",
+                        beiscsi_ep->phba, phba);
+               return -EEXIST;
+       }
+
+       beiscsi_conn->beiscsi_conn_cid = beiscsi_ep->ep_cid;
+       beiscsi_conn->ep = beiscsi_ep;
+       beiscsi_ep->conn = beiscsi_conn;
+       SE_DEBUG(DBG_LVL_8, "beiscsi_conn=%p conn=%p ep_cid=%d \n",
+                beiscsi_conn, conn, beiscsi_ep->ep_cid);
+       return beiscsi_bindconn_cid(phba, beiscsi_conn, beiscsi_ep->ep_cid);
+}
+
+/**
+ * beiscsi_conn_get_param - get the iscsi parameter
+ * @cls_conn: pointer to iscsi cls conn
+ * @param: parameter type identifier
+ * @buf: buffer pointer
+ *
+ * returns iscsi parameter
+ */
+int beiscsi_conn_get_param(struct iscsi_cls_conn *cls_conn,
+                          enum iscsi_param param, char *buf)
+{
+       struct beiscsi_endpoint *beiscsi_ep;
+       struct iscsi_conn *conn = cls_conn->dd_data;
+       struct beiscsi_conn *beiscsi_conn = conn->dd_data;
+       int len = 0;
+
+       beiscsi_ep = beiscsi_conn->ep;
+       if (!beiscsi_ep) {
+               SE_DEBUG(DBG_LVL_1,
+                        "In beiscsi_conn_get_param , no beiscsi_ep\n");
+               return -1;
+       }
+
+       switch (param) {
+       case ISCSI_PARAM_CONN_PORT:
+               len = sprintf(buf, "%hu\n", beiscsi_ep->dst_tcpport);
+               break;
+       case ISCSI_PARAM_CONN_ADDRESS:
+               if (beiscsi_ep->ip_type == BE2_IPV4)
+                       len = sprintf(buf, "%pI4\n", &beiscsi_ep->dst_addr);
+               else
+                       len = sprintf(buf, "%pI6\n", &beiscsi_ep->dst6_addr);
+               break;
+       default:
+               return iscsi_conn_get_param(cls_conn, param, buf);
+       }
+       return len;
+}
+
+int beiscsi_set_param(struct iscsi_cls_conn *cls_conn,
+                     enum iscsi_param param, char *buf, int buflen)
+{
+       struct iscsi_conn *conn = cls_conn->dd_data;
+       struct iscsi_session *session = conn->session;
+       int ret;
+
+       ret = iscsi_set_param(cls_conn, param, buf, buflen);
+       if (ret)
+               return ret;
+       /*
+        * If userspace tried to set the value to higher than we can
+        * support override here.
+        */
+       switch (param) {
+       case ISCSI_PARAM_FIRST_BURST:
+               if (session->first_burst > 8192)
+                       session->first_burst = 8192;
+               break;
+       case ISCSI_PARAM_MAX_RECV_DLENGTH:
+               if (conn->max_recv_dlength > 65536)
+                       conn->max_recv_dlength = 65536;
+               break;
+       case ISCSI_PARAM_MAX_BURST:
+               if (session->first_burst > 262144)
+                       session->first_burst = 262144;
+               break;
+       default:
+               return 0;
+       }
+
+       return 0;
+}
+
+/**
+ * beiscsi_get_host_param - get the iscsi parameter
+ * @shost: pointer to scsi_host structure
+ * @param: parameter type identifier
+ * @buf: buffer pointer
+ *
+ * returns host parameter
+ */
+int beiscsi_get_host_param(struct Scsi_Host *shost,
+                          enum iscsi_host_param param, char *buf)
+{
+       struct beiscsi_hba *phba = (struct beiscsi_hba *)iscsi_host_priv(shost);
+       int len = 0;
+
+       switch (param) {
+       case ISCSI_HOST_PARAM_HWADDRESS:
+               be_cmd_get_mac_addr(&phba->ctrl, phba->mac_address);
+               len = sysfs_format_mac(buf, phba->mac_address, ETH_ALEN);
+               break;
+       default:
+               return iscsi_host_get_param(shost, param, buf);
+       }
+       return len;
+}
+
+/**
+ * beiscsi_conn_get_stats - get the iscsi stats
+ * @cls_conn: pointer to iscsi cls conn
+ * @stats: pointer to iscsi_stats structure
+ *
+ * returns iscsi stats
+ */
+void beiscsi_conn_get_stats(struct iscsi_cls_conn *cls_conn,
+                           struct iscsi_stats *stats)
+{
+       struct iscsi_conn *conn = cls_conn->dd_data;
+
+       SE_DEBUG(DBG_LVL_8, "In beiscsi_conn_get_stats\n");
+       stats->txdata_octets = conn->txdata_octets;
+       stats->rxdata_octets = conn->rxdata_octets;
+       stats->dataout_pdus = conn->dataout_pdus_cnt;
+       stats->scsirsp_pdus = conn->scsirsp_pdus_cnt;
+       stats->scsicmd_pdus = conn->scsicmd_pdus_cnt;
+       stats->datain_pdus = conn->datain_pdus_cnt;
+       stats->tmfrsp_pdus = conn->tmfrsp_pdus_cnt;
+       stats->tmfcmd_pdus = conn->tmfcmd_pdus_cnt;
+       stats->r2t_pdus = conn->r2t_pdus_cnt;
+       stats->digest_err = 0;
+       stats->timeout_err = 0;
+       stats->custom_length = 0;
+       strcpy(stats->custom[0].desc, "eh_abort_cnt");
+       stats->custom[0].value = conn->eh_abort_cnt;
+}
+
+/**
+ * beiscsi_set_params_for_offld - get the parameters for offload
+ * @beiscsi_conn: pointer to beiscsi_conn
+ * @params: pointer to offload_params structure
+ */
+static void  beiscsi_set_params_for_offld(struct beiscsi_conn *beiscsi_conn,
+                                         struct beiscsi_offload_params *params)
+{
+       struct iscsi_conn *conn = beiscsi_conn->conn;
+       struct iscsi_session *session = conn->session;
+
+       AMAP_SET_BITS(struct amap_beiscsi_offload_params, max_burst_length,
+                     params, session->max_burst);
+       AMAP_SET_BITS(struct amap_beiscsi_offload_params,
+                     max_send_data_segment_length, params,
+                     conn->max_xmit_dlength);
+       AMAP_SET_BITS(struct amap_beiscsi_offload_params, first_burst_length,
+                     params, session->first_burst);
+       AMAP_SET_BITS(struct amap_beiscsi_offload_params, erl, params,
+                     session->erl);
+       AMAP_SET_BITS(struct amap_beiscsi_offload_params, dde, params,
+                     conn->datadgst_en);
+       AMAP_SET_BITS(struct amap_beiscsi_offload_params, hde, params,
+                     conn->hdrdgst_en);
+       AMAP_SET_BITS(struct amap_beiscsi_offload_params, ir2t, params,
+                     session->initial_r2t_en);
+       AMAP_SET_BITS(struct amap_beiscsi_offload_params, imd, params,
+                     session->imm_data_en);
+       AMAP_SET_BITS(struct amap_beiscsi_offload_params, exp_statsn, params,
+                     (conn->exp_statsn - 1));
+}
+
+/**
+ * beiscsi_conn_start - offload of session to chip
+ * @cls_conn: pointer to beiscsi_conn
+ */
+int beiscsi_conn_start(struct iscsi_cls_conn *cls_conn)
+{
+       struct iscsi_conn *conn = cls_conn->dd_data;
+       struct beiscsi_conn *beiscsi_conn = conn->dd_data;
+       struct beiscsi_endpoint *beiscsi_ep;
+       struct beiscsi_offload_params params;
+       struct iscsi_session *session = conn->session;
+       struct Scsi_Host *shost = iscsi_session_to_shost(session->cls_session);
+       struct beiscsi_hba *phba = iscsi_host_priv(shost);
+
+       memset(&params, 0, sizeof(struct beiscsi_offload_params));
+       beiscsi_ep = beiscsi_conn->ep;
+       if (!beiscsi_ep)
+               SE_DEBUG(DBG_LVL_1, "In beiscsi_conn_start , no beiscsi_ep\n");
+
+       free_mgmt_sgl_handle(phba, beiscsi_conn->plogin_sgl_handle);
+       beiscsi_conn->login_in_progress = 0;
+       beiscsi_set_params_for_offld(beiscsi_conn, &params);
+       beiscsi_offload_connection(beiscsi_conn, &params);
+       iscsi_conn_start(cls_conn);
+       return 0;
+}
+
+/**
+ * beiscsi_get_cid - Allocate a cid
+ * @phba: The phba instance
+ */
+static int beiscsi_get_cid(struct beiscsi_hba *phba)
+{
+       unsigned short cid = 0xFFFF;
+
+       if (!phba->avlbl_cids)
+               return cid;
+
+       cid = phba->cid_array[phba->cid_alloc++];
+       if (phba->cid_alloc == phba->params.cxns_per_ctrl)
+               phba->cid_alloc = 0;
+       phba->avlbl_cids--;
+       return cid;
+}
+
+/**
+ * beiscsi_open_conn - Ask FW to open a TCP connection
+ * @ep:        endpoint to be used
+ * @src_addr: The source IP address
+ * @dst_addr: The Destination  IP address
+ *
+ * Asks the FW to open a TCP connection
+ */
+static int beiscsi_open_conn(struct iscsi_endpoint *ep,
+                            struct sockaddr *src_addr,
+                            struct sockaddr *dst_addr, int non_blocking)
+{
+       struct beiscsi_endpoint *beiscsi_ep = ep->dd_data;
+       struct beiscsi_hba *phba = beiscsi_ep->phba;
+       int ret = -1;
+
+       beiscsi_ep->ep_cid = beiscsi_get_cid(phba);
+       if (beiscsi_ep->ep_cid == 0xFFFF) {
+               SE_DEBUG(DBG_LVL_1, "No free cid available\n");
+               return ret;
+       }
+       SE_DEBUG(DBG_LVL_8, "In beiscsi_open_conn, ep_cid=%d ",
+                beiscsi_ep->ep_cid);
+       phba->ep_array[beiscsi_ep->ep_cid] = ep;
+       if (beiscsi_ep->ep_cid >
+           (phba->fw_config.iscsi_cid_start + phba->params.cxns_per_ctrl)) {
+               SE_DEBUG(DBG_LVL_1, "Failed in allocate iscsi cid\n");
+               return ret;
+       }
+
+       beiscsi_ep->cid_vld = 0;
+       return mgmt_open_connection(phba, dst_addr, beiscsi_ep);
+}
+
+/**
+ * beiscsi_put_cid - Free the cid
+ * @phba: The phba for which the cid is being freed
+ * @cid: The cid to free
+ */
+static void beiscsi_put_cid(struct beiscsi_hba *phba, unsigned short cid)
+{
+       phba->avlbl_cids++;
+       phba->cid_array[phba->cid_free++] = cid;
+       if (phba->cid_free == phba->params.cxns_per_ctrl)
+               phba->cid_free = 0;
+}
+
+/**
+ * beiscsi_free_ep - free endpoint
+ * @ep:        pointer to iscsi endpoint structure
+ */
+static void beiscsi_free_ep(struct iscsi_endpoint *ep)
+{
+       struct beiscsi_endpoint *beiscsi_ep = ep->dd_data;
+       struct beiscsi_hba *phba = beiscsi_ep->phba;
+
+       beiscsi_put_cid(phba, beiscsi_ep->ep_cid);
+       beiscsi_ep->phba = NULL;
+       iscsi_destroy_endpoint(ep);
+}
+
+/**
+ * beiscsi_ep_connect - Ask chip to create TCP Conn
+ * @scsi_host: Pointer to scsi_host structure
+ * @dst_addr: The IP address of Target
+ * @non_blocking: blocking or non-blocking call
+ *
+ * This routines first asks chip to create a connection and then allocates an EP
+ */
+struct iscsi_endpoint *
+beiscsi_ep_connect(struct Scsi_Host *shost, struct sockaddr *dst_addr,
+                  int non_blocking)
+{
+       struct beiscsi_hba *phba;
+       struct beiscsi_endpoint *beiscsi_ep;
+       struct iscsi_endpoint *ep;
+       int ret;
+
+       SE_DEBUG(DBG_LVL_8, "In beiscsi_ep_connect \n");
+       if (shost)
+               phba = iscsi_host_priv(shost);
+       else {
+               ret = -ENXIO;
+               SE_DEBUG(DBG_LVL_1, "shost is NULL \n");
+               return ERR_PTR(ret);
+       }
+       ep = iscsi_create_endpoint(sizeof(struct beiscsi_endpoint));
+       if (!ep) {
+               ret = -ENOMEM;
+               return ERR_PTR(ret);
+       }
+
+       beiscsi_ep = ep->dd_data;
+       beiscsi_ep->phba = phba;
+
+       if (beiscsi_open_conn(ep, NULL, dst_addr, non_blocking)) {
+               SE_DEBUG(DBG_LVL_1, "Failed in allocate iscsi cid\n");
+               ret = -ENOMEM;
+               goto free_ep;
+       }
+
+       return ep;
+
+free_ep:
+       beiscsi_free_ep(ep);
+       return ERR_PTR(ret);
+}
+
+/**
+ * beiscsi_ep_poll - Poll to see if connection is established
+ * @ep:        endpoint to be used
+ * @timeout_ms: timeout specified in millisecs
+ *
+ * Poll to see if TCP connection established
+ */
+int beiscsi_ep_poll(struct iscsi_endpoint *ep, int timeout_ms)
+{
+       struct beiscsi_endpoint *beiscsi_ep = ep->dd_data;
+
+       SE_DEBUG(DBG_LVL_8, "In  beiscsi_ep_poll\n");
+       if (beiscsi_ep->cid_vld == 1)
+               return 1;
+       else
+               return 0;
+}
+
+/**
+ * beiscsi_close_conn - Upload the  connection
+ * @ep: The iscsi endpoint
+ * @flag: The type of connection closure
+ */
+static int beiscsi_close_conn(struct iscsi_endpoint *ep, int flag)
+{
+       int ret = 0;
+       struct beiscsi_endpoint *beiscsi_ep = ep->dd_data;
+       struct beiscsi_hba *phba = beiscsi_ep->phba;
+
+       if (MGMT_STATUS_SUCCESS !=
+           mgmt_upload_connection(phba, beiscsi_ep->ep_cid,
+               CONNECTION_UPLOAD_GRACEFUL)) {
+               SE_DEBUG(DBG_LVL_8, "upload failed for cid 0x%x",
+                        beiscsi_ep->ep_cid);
+               ret = -1;
+       }
+
+       return ret;
+}
+
+/**
+ * beiscsi_ep_disconnect - Tears down the TCP connection
+ * @ep:        endpoint to be used
+ *
+ * Tears down the TCP connection
+ */
+void beiscsi_ep_disconnect(struct iscsi_endpoint *ep)
+{
+       struct beiscsi_conn *beiscsi_conn;
+       struct beiscsi_endpoint *beiscsi_ep;
+       struct beiscsi_hba *phba;
+       int flag = 0;
+
+       beiscsi_ep = ep->dd_data;
+       phba = beiscsi_ep->phba;
+       SE_DEBUG(DBG_LVL_8, "In beiscsi_ep_disconnect\n");
+
+       if (beiscsi_ep->conn) {
+               beiscsi_conn = beiscsi_ep->conn;
+               iscsi_suspend_queue(beiscsi_conn->conn);
+               beiscsi_close_conn(ep, flag);
+       }
+
+       beiscsi_free_ep(ep);
+}
+
+/**
+ * beiscsi_unbind_conn_to_cid - Unbind the beiscsi_conn from phba conn table
+ * @phba: The phba instance
+ * @cid: The cid to free
+ */
+static int beiscsi_unbind_conn_to_cid(struct beiscsi_hba *phba,
+                                     unsigned int cid)
+{
+       if (phba->conn_table[cid])
+               phba->conn_table[cid] = NULL;
+       else {
+               SE_DEBUG(DBG_LVL_8, "Connection table Not occupied. \n");
+               return -EINVAL;
+       }
+       return 0;
+}
+
+/**
+ * beiscsi_conn_stop - Invalidate and stop the connection
+ * @cls_conn: pointer to get iscsi_conn
+ * @flag: The type of connection closure
+ */
+void beiscsi_conn_stop(struct iscsi_cls_conn *cls_conn, int flag)
+{
+       struct iscsi_conn *conn = cls_conn->dd_data;
+       struct beiscsi_conn *beiscsi_conn = conn->dd_data;
+       struct beiscsi_endpoint *beiscsi_ep;
+       struct iscsi_session *session = conn->session;
+       struct Scsi_Host *shost = iscsi_session_to_shost(session->cls_session);
+       struct beiscsi_hba *phba = iscsi_host_priv(shost);
+       unsigned int status;
+       unsigned short savecfg_flag = CMD_ISCSI_SESSION_SAVE_CFG_ON_FLASH;
+
+       SE_DEBUG(DBG_LVL_8, "In beiscsi_conn_stop\n");
+       beiscsi_ep = beiscsi_conn->ep;
+       if (!beiscsi_ep) {
+               SE_DEBUG(DBG_LVL_8, "In beiscsi_conn_stop , no beiscsi_ep\n");
+               return;
+       }
+       status = mgmt_invalidate_connection(phba, beiscsi_ep,
+                                           beiscsi_ep->ep_cid, 1,
+                                           savecfg_flag);
+       if (status != MGMT_STATUS_SUCCESS) {
+               SE_DEBUG(DBG_LVL_1,
+                        "mgmt_invalidate_connection Failed for cid=%d \n",
+                        beiscsi_ep->ep_cid);
+       }
+       beiscsi_unbind_conn_to_cid(phba, beiscsi_ep->ep_cid);
+       iscsi_conn_stop(cls_conn, flag);
+}
diff --git a/drivers/scsi/be2iscsi/be_iscsi.h b/drivers/scsi/be2iscsi/be_iscsi.h
new file mode 100644 (file)
index 0000000..f92ffc5
--- /dev/null
@@ -0,0 +1,75 @@
+/**
+ * Copyright (C) 2005 - 2009 ServerEngines
+ * 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 version 2
+ * as published by the Free Software Foundation.  The full GNU General
+ * Public License is included in this distribution in the file called COPYING.
+ *
+ * Written by: Jayamohan Kallickal (jayamohank@serverengines.com)
+ *
+ * Contact Information:
+ * linux-drivers@serverengines.com
+ *
+ * ServerEngines
+ * 209 N. Fair Oaks Ave
+ * Sunnyvale, CA 94085
+ *
+ */
+
+#ifndef _BE_ISCSI_
+#define _BE_ISCSI_
+
+#include "be_main.h"
+#include "be_mgmt.h"
+
+#define BE2_IPV4  0x1
+#define BE2_IPV6  0x10
+
+void beiscsi_offload_connection(struct beiscsi_conn *beiscsi_conn,
+                               struct beiscsi_offload_params *params);
+
+void beiscsi_offload_iscsi(struct beiscsi_hba *phba, struct iscsi_conn *conn,
+                          struct beiscsi_conn *beiscsi_conn,
+                          unsigned int fw_handle);
+
+struct iscsi_cls_session *beiscsi_session_create(struct iscsi_endpoint *ep,
+                                                uint16_t cmds_max,
+                                                uint16_t qdepth,
+                                                uint32_t initial_cmdsn);
+
+void beiscsi_session_destroy(struct iscsi_cls_session *cls_session);
+
+struct iscsi_cls_conn *beiscsi_conn_create(struct iscsi_cls_session
+                                          *cls_session, uint32_t cid);
+
+int beiscsi_conn_bind(struct iscsi_cls_session *cls_session,
+                     struct iscsi_cls_conn *cls_conn,
+                     uint64_t transport_fd, int is_leading);
+
+int beiscsi_conn_get_param(struct iscsi_cls_conn *cls_conn,
+                          enum iscsi_param param, char *buf);
+
+int beiscsi_get_host_param(struct Scsi_Host *shost,
+                          enum iscsi_host_param param, char *buf);
+
+int beiscsi_set_param(struct iscsi_cls_conn *cls_conn,
+                     enum iscsi_param param, char *buf, int buflen);
+
+int beiscsi_conn_start(struct iscsi_cls_conn *cls_conn);
+
+void beiscsi_conn_stop(struct iscsi_cls_conn *cls_conn, int flag);
+
+struct iscsi_endpoint *beiscsi_ep_connect(struct Scsi_Host *shost,
+                                         struct sockaddr *dst_addr,
+                                         int non_blocking);
+
+int beiscsi_ep_poll(struct iscsi_endpoint *ep, int timeout_ms);
+
+void beiscsi_ep_disconnect(struct iscsi_endpoint *ep);
+
+void beiscsi_conn_get_stats(struct iscsi_cls_conn *cls_conn,
+                           struct iscsi_stats *stats);
+
+#endif
diff --git a/drivers/scsi/be2iscsi/be_main.c b/drivers/scsi/be2iscsi/be_main.c
new file mode 100644 (file)
index 0000000..4f1aca3
--- /dev/null
@@ -0,0 +1,3390 @@
+/**
+ * Copyright (C) 2005 - 2009 ServerEngines
+ * 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 version 2
+ * as published by the Free Software Foundation.  The full GNU General
+ * Public License is included in this distribution in the file called COPYING.
+ *
+ * Written by: Jayamohan Kallickal (jayamohank@serverengines.com)
+ *
+ * Contact Information:
+ * linux-drivers@serverengines.com
+ *
+ *  ServerEngines
+ * 209 N. Fair Oaks Ave
+ * Sunnyvale, CA 94085
+ *
+ */
+#include <linux/reboot.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/blkdev.h>
+#include <linux/pci.h>
+#include <linux/string.h>
+#include <linux/kernel.h>
+#include <linux/semaphore.h>
+
+#include <scsi/libiscsi.h>
+#include <scsi/scsi_transport_iscsi.h>
+#include <scsi/scsi_transport.h>
+#include <scsi/scsi_cmnd.h>
+#include <scsi/scsi_device.h>
+#include <scsi/scsi_host.h>
+#include <scsi/scsi.h>
+#include "be_main.h"
+#include "be_iscsi.h"
+#include "be_mgmt.h"
+
+static unsigned int be_iopoll_budget = 10;
+static unsigned int be_max_phys_size = 64;
+static unsigned int enable_msix;
+
+MODULE_DEVICE_TABLE(pci, beiscsi_pci_id_table);
+MODULE_DESCRIPTION(DRV_DESC " " BUILD_STR);
+MODULE_AUTHOR("ServerEngines Corporation");
+MODULE_LICENSE("GPL");
+module_param(be_iopoll_budget, int, 0);
+module_param(enable_msix, int, 0);
+module_param(be_max_phys_size, uint, S_IRUGO);
+MODULE_PARM_DESC(be_max_phys_size, "Maximum Size (In Kilobytes) of physically"
+                                  "contiguous memory that can be allocated."
+                                  "Range is 16 - 128");
+
+static int beiscsi_slave_configure(struct scsi_device *sdev)
+{
+       blk_queue_max_segment_size(sdev->request_queue, 65536);
+       return 0;
+}
+
+static struct scsi_host_template beiscsi_sht = {
+       .module = THIS_MODULE,
+       .name = "ServerEngines 10Gbe open-iscsi Initiator Driver",
+       .proc_name = DRV_NAME,
+       .queuecommand = iscsi_queuecommand,
+       .eh_abort_handler = iscsi_eh_abort,
+       .change_queue_depth = iscsi_change_queue_depth,
+       .slave_configure = beiscsi_slave_configure,
+       .target_alloc = iscsi_target_alloc,
+       .eh_device_reset_handler = iscsi_eh_device_reset,
+       .eh_target_reset_handler = iscsi_eh_target_reset,
+       .sg_tablesize = BEISCSI_SGLIST_ELEMENTS,
+       .can_queue = BE2_IO_DEPTH,
+       .this_id = -1,
+       .max_sectors = BEISCSI_MAX_SECTORS,
+       .cmd_per_lun = BEISCSI_CMD_PER_LUN,
+       .use_clustering = ENABLE_CLUSTERING,
+};
+static struct scsi_transport_template *beiscsi_scsi_transport;
+
+/*------------------- PCI Driver operations and data ----------------- */
+static DEFINE_PCI_DEVICE_TABLE(beiscsi_pci_id_table) = {
+       { PCI_DEVICE(BE_VENDOR_ID, BE_DEVICE_ID1) },
+       { PCI_DEVICE(BE_VENDOR_ID, OC_DEVICE_ID1) },
+       { PCI_DEVICE(BE_VENDOR_ID, OC_DEVICE_ID2) },
+       { 0 }
+};
+MODULE_DEVICE_TABLE(pci, beiscsi_pci_id_table);
+
+static struct beiscsi_hba *beiscsi_hba_alloc(struct pci_dev *pcidev)
+{
+       struct beiscsi_hba *phba;
+       struct Scsi_Host *shost;
+
+       shost = iscsi_host_alloc(&beiscsi_sht, sizeof(*phba), 0);
+       if (!shost) {
+               dev_err(&pcidev->dev, "beiscsi_hba_alloc -"
+                       "iscsi_host_alloc failed \n");
+               return NULL;
+       }
+       shost->dma_boundary = pcidev->dma_mask;
+       shost->max_id = BE2_MAX_SESSIONS;
+       shost->max_channel = 0;
+       shost->max_cmd_len = BEISCSI_MAX_CMD_LEN;
+       shost->max_lun = BEISCSI_NUM_MAX_LUN;
+       shost->transportt = beiscsi_scsi_transport;
+
+       phba = iscsi_host_priv(shost);
+       memset(phba, 0, sizeof(*phba));
+       phba->shost = shost;
+       phba->pcidev = pci_dev_get(pcidev);
+
+       if (iscsi_host_add(shost, &phba->pcidev->dev))
+               goto free_devices;
+       return phba;
+
+free_devices:
+       pci_dev_put(phba->pcidev);
+       iscsi_host_free(phba->shost);
+       return NULL;
+}
+
+static void beiscsi_unmap_pci_function(struct beiscsi_hba *phba)
+{
+       if (phba->csr_va) {
+               iounmap(phba->csr_va);
+               phba->csr_va = NULL;
+       }
+       if (phba->db_va) {
+               iounmap(phba->db_va);
+               phba->db_va = NULL;
+       }
+       if (phba->pci_va) {
+               iounmap(phba->pci_va);
+               phba->pci_va = NULL;
+       }
+}
+
+static int beiscsi_map_pci_bars(struct beiscsi_hba *phba,
+                               struct pci_dev *pcidev)
+{
+       u8 __iomem *addr;
+
+       addr = ioremap_nocache(pci_resource_start(pcidev, 2),
+                              pci_resource_len(pcidev, 2));
+       if (addr == NULL)
+               return -ENOMEM;
+       phba->ctrl.csr = addr;
+       phba->csr_va = addr;
+       phba->csr_pa.u.a64.address = pci_resource_start(pcidev, 2);
+
+       addr = ioremap_nocache(pci_resource_start(pcidev, 4), 128 * 1024);
+       if (addr == NULL)
+               goto pci_map_err;
+       phba->ctrl.db = addr;
+       phba->db_va = addr;
+       phba->db_pa.u.a64.address =  pci_resource_start(pcidev, 4);
+
+       addr = ioremap_nocache(pci_resource_start(pcidev, 1),
+                              pci_resource_len(pcidev, 1));
+       if (addr == NULL)
+               goto pci_map_err;
+       phba->ctrl.pcicfg = addr;
+       phba->pci_va = addr;
+       phba->pci_pa.u.a64.address = pci_resource_start(pcidev, 1);
+       return 0;
+
+pci_map_err:
+       beiscsi_unmap_pci_function(phba);
+       return -ENOMEM;
+}
+
+static int beiscsi_enable_pci(struct pci_dev *pcidev)
+{
+       int ret;
+
+       ret = pci_enable_device(pcidev);
+       if (ret) {
+               dev_err(&pcidev->dev, "beiscsi_enable_pci - enable device "
+                       "failed. Returning -ENODEV\n");
+               return ret;
+       }
+
+       if (pci_set_consistent_dma_mask(pcidev, DMA_BIT_MASK(64))) {
+               ret = pci_set_consistent_dma_mask(pcidev, DMA_BIT_MASK(32));
+               if (ret) {
+                       dev_err(&pcidev->dev, "Could not set PCI DMA Mask\n");
+                       pci_disable_device(pcidev);
+                       return ret;
+               }
+       }
+       return 0;
+}
+
+static int be_ctrl_init(struct beiscsi_hba *phba, struct pci_dev *pdev)
+{
+       struct be_ctrl_info *ctrl = &phba->ctrl;
+       struct be_dma_mem *mbox_mem_alloc = &ctrl->mbox_mem_alloced;
+       struct be_dma_mem *mbox_mem_align = &ctrl->mbox_mem;
+       int status = 0;
+
+       ctrl->pdev = pdev;
+       status = beiscsi_map_pci_bars(phba, pdev);
+       if (status)
+               return status;
+
+       mbox_mem_alloc->size = sizeof(struct be_mcc_mailbox) + 16;
+       mbox_mem_alloc->va = pci_alloc_consistent(pdev,
+                                                 mbox_mem_alloc->size,
+                                                 &mbox_mem_alloc->dma);
+       if (!mbox_mem_alloc->va) {
+               beiscsi_unmap_pci_function(phba);
+               status = -ENOMEM;
+               return status;
+       }
+
+       mbox_mem_align->size = sizeof(struct be_mcc_mailbox);
+       mbox_mem_align->va = PTR_ALIGN(mbox_mem_alloc->va, 16);
+       mbox_mem_align->dma = PTR_ALIGN(mbox_mem_alloc->dma, 16);
+       memset(mbox_mem_align->va, 0, sizeof(struct be_mcc_mailbox));
+       spin_lock_init(&ctrl->mbox_lock);
+       return status;
+}
+
+static void beiscsi_get_params(struct beiscsi_hba *phba)
+{
+       phba->params.ios_per_ctrl = BE2_IO_DEPTH;
+       phba->params.cxns_per_ctrl = BE2_MAX_SESSIONS;
+       phba->params.asyncpdus_per_ctrl = BE2_ASYNCPDUS;
+       phba->params.icds_per_ctrl = BE2_MAX_ICDS / 2;
+       phba->params.num_sge_per_io = BE2_SGE;
+       phba->params.defpdu_hdr_sz = BE2_DEFPDU_HDR_SZ;
+       phba->params.defpdu_data_sz = BE2_DEFPDU_DATA_SZ;
+       phba->params.eq_timer = 64;
+       phba->params.num_eq_entries =
+           (((BE2_CMDS_PER_CXN * 2 + BE2_LOGOUTS + BE2_TMFS + BE2_ASYNCPDUS) /
+                                                               512) + 1) * 512;
+       phba->params.num_eq_entries = (phba->params.num_eq_entries < 1024)
+                               ? 1024 : phba->params.num_eq_entries;
+       SE_DEBUG(DBG_LVL_8, "phba->params.num_eq_entries=%d \n",
+                phba->params.num_eq_entries);
+       phba->params.num_cq_entries =
+           (((BE2_CMDS_PER_CXN * 2 + BE2_LOGOUTS + BE2_TMFS + BE2_ASYNCPDUS) /
+                                                               512) + 1) * 512;
+       SE_DEBUG(DBG_LVL_8,
+               "phba->params.num_cq_entries=%d BE2_CMDS_PER_CXN=%d"
+               "BE2_LOGOUTS=%d BE2_TMFS=%d BE2_ASYNCPDUS=%d \n",
+               phba->params.num_cq_entries, BE2_CMDS_PER_CXN,
+               BE2_LOGOUTS, BE2_TMFS, BE2_ASYNCPDUS);
+       phba->params.wrbs_per_cxn = 256;
+}
+
+static void hwi_ring_eq_db(struct beiscsi_hba *phba,
+                          unsigned int id, unsigned int clr_interrupt,
+                          unsigned int num_processed,
+                          unsigned char rearm, unsigned char event)
+{
+       u32 val = 0;
+       val |= id & DB_EQ_RING_ID_MASK;
+       if (rearm)
+               val |= 1 << DB_EQ_REARM_SHIFT;
+       if (clr_interrupt)
+               val |= 1 << DB_EQ_CLR_SHIFT;
+       if (event)
+               val |= 1 << DB_EQ_EVNT_SHIFT;
+       val |= num_processed << DB_EQ_NUM_POPPED_SHIFT;
+       iowrite32(val, phba->db_va + DB_EQ_OFFSET);
+}
+
+/**
+ * be_isr - The isr routine of the driver.
+ * @irq: Not used
+ * @dev_id: Pointer to host adapter structure
+ */
+static irqreturn_t be_isr(int irq, void *dev_id)
+{
+       struct beiscsi_hba *phba;
+       struct hwi_controller *phwi_ctrlr;
+       struct hwi_context_memory *phwi_context;
+       struct be_eq_entry *eqe = NULL;
+       struct be_queue_info *eq;
+       struct be_queue_info *cq;
+       unsigned long flags, index;
+       unsigned int num_eq_processed;
+       struct be_ctrl_info *ctrl;
+       int isr;
+
+       phba = dev_id;
+       if (!enable_msix) {
+               ctrl = &phba->ctrl;;
+               isr = ioread32(ctrl->csr + CEV_ISR0_OFFSET +
+                              (PCI_FUNC(ctrl->pdev->devfn) * CEV_ISR_SIZE));
+               if (!isr)
+                       return IRQ_NONE;
+       }
+
+       phwi_ctrlr = phba->phwi_ctrlr;
+       phwi_context = phwi_ctrlr->phwi_ctxt;
+       eq = &phwi_context->be_eq.q;
+       cq = &phwi_context->be_cq;
+       index = 0;
+       eqe = queue_tail_node(eq);
+       if (!eqe)
+               SE_DEBUG(DBG_LVL_1, "eqe is NULL\n");
+
+       num_eq_processed = 0;
+       if (blk_iopoll_enabled) {
+               while (eqe->dw[offsetof(struct amap_eq_entry, valid) / 32]
+                                       & EQE_VALID_MASK) {
+                       if (!blk_iopoll_sched_prep(&phba->iopoll))
+                               blk_iopoll_sched(&phba->iopoll);
+
+                       AMAP_SET_BITS(struct amap_eq_entry, valid, eqe, 0);
+                       queue_tail_inc(eq);
+                       eqe = queue_tail_node(eq);
+                       num_eq_processed++;
+                       SE_DEBUG(DBG_LVL_8, "Valid EQE\n");
+               }
+               if (num_eq_processed) {
+                       hwi_ring_eq_db(phba, eq->id, 0, num_eq_processed, 0, 1);
+                       return IRQ_HANDLED;
+               } else
+                       return IRQ_NONE;
+       } else {
+               while (eqe->dw[offsetof(struct amap_eq_entry, valid) / 32]
+                                               & EQE_VALID_MASK) {
+
+                       if (((eqe->dw[offsetof(struct amap_eq_entry,
+                            resource_id) / 32] &
+                            EQE_RESID_MASK) >> 16) != cq->id) {
+                               spin_lock_irqsave(&phba->isr_lock, flags);
+                               phba->todo_mcc_cq = 1;
+                               spin_unlock_irqrestore(&phba->isr_lock, flags);
+                       } else {
+                               spin_lock_irqsave(&phba->isr_lock, flags);
+                               phba->todo_cq = 1;
+                               spin_unlock_irqrestore(&phba->isr_lock, flags);
+                       }
+                       AMAP_SET_BITS(struct amap_eq_entry, valid, eqe, 0);
+                       queue_tail_inc(eq);
+                       eqe = queue_tail_node(eq);
+                       num_eq_processed++;
+               }
+               if (phba->todo_cq || phba->todo_mcc_cq)
+                       queue_work(phba->wq, &phba->work_cqs);
+
+               if (num_eq_processed) {
+                       hwi_ring_eq_db(phba, eq->id, 0, num_eq_processed, 1, 1);
+                       return IRQ_HANDLED;
+               } else
+                       return IRQ_NONE;
+       }
+}
+
+static int beiscsi_init_irqs(struct beiscsi_hba *phba)
+{
+       struct pci_dev *pcidev = phba->pcidev;
+       int ret;
+
+       ret = request_irq(pcidev->irq, be_isr, IRQF_SHARED, "beiscsi", phba);
+       if (ret) {
+               shost_printk(KERN_ERR, phba->shost, "beiscsi_init_irqs-"
+                            "Failed to register irq\\n");
+               return ret;
+       }
+       return 0;
+}
+
+static void hwi_ring_cq_db(struct beiscsi_hba *phba,
+                          unsigned int id, unsigned int num_processed,
+                          unsigned char rearm, unsigned char event)
+{
+       u32 val = 0;
+       val |= id & DB_CQ_RING_ID_MASK;
+       if (rearm)
+               val |= 1 << DB_CQ_REARM_SHIFT;
+       val |= num_processed << DB_CQ_NUM_POPPED_SHIFT;
+       iowrite32(val, phba->db_va + DB_CQ_OFFSET);
+}
+
+/*
+ * async pdus include
+ * a. unsolicited NOP-In (target initiated NOP-In)
+ * b. Async Messages
+ * c. Reject PDU
+ * d. Login response
+ * These headers arrive unprocessed by the EP firmware and iSCSI layer
+ * process them
+ */
+static unsigned int
+beiscsi_process_async_pdu(struct beiscsi_conn *beiscsi_conn,
+                         struct beiscsi_hba *phba,
+                         unsigned short cid,
+                         struct pdu_base *ppdu,
+                         unsigned long pdu_len,
+                         void *pbuffer, unsigned long buf_len)
+{
+       struct iscsi_conn *conn = beiscsi_conn->conn;
+       struct iscsi_session *session = conn->session;
+
+       switch (ppdu->dw[offsetof(struct amap_pdu_base, opcode) / 32] &
+                                               PDUBASE_OPCODE_MASK) {
+       case ISCSI_OP_NOOP_IN:
+               pbuffer = NULL;
+               buf_len = 0;
+               break;
+       case ISCSI_OP_ASYNC_EVENT:
+               break;
+       case ISCSI_OP_REJECT:
+               WARN_ON(!pbuffer);
+               WARN_ON(!(buf_len == 48));
+               SE_DEBUG(DBG_LVL_1, "In ISCSI_OP_REJECT\n");
+               break;
+       case ISCSI_OP_LOGIN_RSP:
+               break;
+       default:
+               shost_printk(KERN_WARNING, phba->shost,
+                            "Unrecognized opcode 0x%x in async msg \n",
+                            (ppdu->
+                            dw[offsetof(struct amap_pdu_base, opcode) / 32]
+                                               & PDUBASE_OPCODE_MASK));
+               return 1;
+       }
+
+       spin_lock_bh(&session->lock);
+       __iscsi_complete_pdu(conn, (struct iscsi_hdr *)ppdu, pbuffer, buf_len);
+       spin_unlock_bh(&session->lock);
+       return 0;
+}
+
+static struct sgl_handle *alloc_io_sgl_handle(struct beiscsi_hba *phba)
+{
+       struct sgl_handle *psgl_handle;
+
+       if (phba->io_sgl_hndl_avbl) {
+               SE_DEBUG(DBG_LVL_8,
+                        "In alloc_io_sgl_handle,io_sgl_alloc_index=%d \n",
+                        phba->io_sgl_alloc_index);
+               psgl_handle = phba->io_sgl_hndl_base[phba->
+                                               io_sgl_alloc_index];
+               phba->io_sgl_hndl_base[phba->io_sgl_alloc_index] = NULL;
+               phba->io_sgl_hndl_avbl--;
+               if (phba->io_sgl_alloc_index == (phba->params.ios_per_ctrl - 1))
+                       phba->io_sgl_alloc_index = 0;
+               else
+                       phba->io_sgl_alloc_index++;
+       } else
+               psgl_handle = NULL;
+       return psgl_handle;
+}
+
+static void
+free_io_sgl_handle(struct beiscsi_hba *phba, struct sgl_handle *psgl_handle)
+{
+       SE_DEBUG(DBG_LVL_8, "In free_,io_sgl_free_index=%d \n",
+                phba->io_sgl_free_index);
+       if (phba->io_sgl_hndl_base[phba->io_sgl_free_index]) {
+               /*
+                * this can happen if clean_task is called on a task that
+                * failed in xmit_task or alloc_pdu.
+                */
+                SE_DEBUG(DBG_LVL_8,
+                        "Double Free in IO SGL io_sgl_free_index=%d,"
+                        "value there=%p \n", phba->io_sgl_free_index,
+                        phba->io_sgl_hndl_base[phba->io_sgl_free_index]);
+               return;
+       }
+       phba->io_sgl_hndl_base[phba->io_sgl_free_index] = psgl_handle;
+       phba->io_sgl_hndl_avbl++;
+       if (phba->io_sgl_free_index == (phba->params.ios_per_ctrl - 1))
+               phba->io_sgl_free_index = 0;
+       else
+               phba->io_sgl_free_index++;
+}
+
+/**
+ * alloc_wrb_handle - To allocate a wrb handle
+ * @phba: The hba pointer
+ * @cid: The cid to use for allocation
+ * @index: index allocation and wrb index
+ *
+ * This happens under session_lock until submission to chip
+ */
+struct wrb_handle *alloc_wrb_handle(struct beiscsi_hba *phba, unsigned int cid,
+                                   int index)
+{
+       struct hwi_wrb_context *pwrb_context;
+       struct hwi_controller *phwi_ctrlr;
+       struct wrb_handle *pwrb_handle;
+
+       phwi_ctrlr = phba->phwi_ctrlr;
+       pwrb_context = &phwi_ctrlr->wrb_context[cid];
+       pwrb_handle = pwrb_context->pwrb_handle_base[index];
+       pwrb_handle->wrb_index = index;
+       pwrb_handle->nxt_wrb_index = index;
+       return pwrb_handle;
+}
+
+/**
+ * free_wrb_handle - To free the wrb handle back to pool
+ * @phba: The hba pointer
+ * @pwrb_context: The context to free from
+ * @pwrb_handle: The wrb_handle to free
+ *
+ * This happens under session_lock until submission to chip
+ */
+static void
+free_wrb_handle(struct beiscsi_hba *phba, struct hwi_wrb_context *pwrb_context,
+               struct wrb_handle *pwrb_handle)
+{
+       SE_DEBUG(DBG_LVL_8,
+                "FREE WRB: pwrb_handle=%p free_index=%d=0x%x"
+                "wrb_handles_available=%d \n",
+                pwrb_handle, pwrb_context->free_index,
+                pwrb_context->free_index, pwrb_context->wrb_handles_available);
+}
+
+static struct sgl_handle *alloc_mgmt_sgl_handle(struct beiscsi_hba *phba)
+{
+       struct sgl_handle *psgl_handle;
+
+       if (phba->eh_sgl_hndl_avbl) {
+               psgl_handle = phba->eh_sgl_hndl_base[phba->eh_sgl_alloc_index];
+               phba->eh_sgl_hndl_base[phba->eh_sgl_alloc_index] = NULL;
+               SE_DEBUG(DBG_LVL_8, "mgmt_sgl_alloc_index=%d=0x%x \n",
+                        phba->eh_sgl_alloc_index, phba->eh_sgl_alloc_index);
+               phba->eh_sgl_hndl_avbl--;
+               if (phba->eh_sgl_alloc_index ==
+                   (phba->params.icds_per_ctrl - phba->params.ios_per_ctrl -
+                    1))
+                       phba->eh_sgl_alloc_index = 0;
+               else
+                       phba->eh_sgl_alloc_index++;
+       } else
+               psgl_handle = NULL;
+       return psgl_handle;
+}
+
+void
+free_mgmt_sgl_handle(struct beiscsi_hba *phba, struct sgl_handle *psgl_handle)
+{
+
+       if (phba->eh_sgl_hndl_base[phba->eh_sgl_free_index]) {
+               /*
+                * this can happen if clean_task is called on a task that
+                * failed in xmit_task or alloc_pdu.
+                */
+               SE_DEBUG(DBG_LVL_8,
+                        "Double Free in eh SGL ,eh_sgl_free_index=%d \n",
+                        phba->eh_sgl_free_index);
+               return;
+       }
+       phba->eh_sgl_hndl_base[phba->eh_sgl_free_index] = psgl_handle;
+       phba->eh_sgl_hndl_avbl++;
+       if (phba->eh_sgl_free_index ==
+           (phba->params.icds_per_ctrl - phba->params.ios_per_ctrl - 1))
+               phba->eh_sgl_free_index = 0;
+       else
+               phba->eh_sgl_free_index++;
+}
+
+static void
+be_complete_io(struct beiscsi_conn *beiscsi_conn,
+              struct iscsi_task *task, struct sol_cqe *psol)
+{
+       struct beiscsi_io_task *io_task = task->dd_data;
+       struct be_status_bhs *sts_bhs =
+                               (struct be_status_bhs *)io_task->cmd_bhs;
+       struct iscsi_conn *conn = beiscsi_conn->conn;
+       unsigned int sense_len;
+       unsigned char *sense;
+       u32 resid = 0, exp_cmdsn, max_cmdsn;
+       u8 rsp, status, flags;
+
+       exp_cmdsn = be32_to_cpu(psol->
+                       dw[offsetof(struct amap_sol_cqe, i_exp_cmd_sn) / 32]
+                       & SOL_EXP_CMD_SN_MASK);
+       max_cmdsn = be32_to_cpu((psol->
+                       dw[offsetof(struct amap_sol_cqe, i_exp_cmd_sn) / 32]
+                       & SOL_EXP_CMD_SN_MASK) +
+                       ((psol->dw[offsetof(struct amap_sol_cqe, i_cmd_wnd)
+                               / 32] & SOL_CMD_WND_MASK) >> 24) - 1);
+       rsp = ((psol->dw[offsetof(struct amap_sol_cqe, i_resp) / 32]
+                                               & SOL_RESP_MASK) >> 16);
+       status = ((psol->dw[offsetof(struct amap_sol_cqe, i_sts) / 32]
+                                               & SOL_STS_MASK) >> 8);
+       flags = ((psol->dw[offsetof(struct amap_sol_cqe, i_flags) / 32]
+                                       & SOL_FLAGS_MASK) >> 24) | 0x80;
+
+       task->sc->result = (DID_OK << 16) | status;
+       if (rsp != ISCSI_STATUS_CMD_COMPLETED) {
+               task->sc->result = DID_ERROR << 16;
+               goto unmap;
+       }
+
+       /* bidi not initially supported */
+       if (flags & (ISCSI_FLAG_CMD_UNDERFLOW | ISCSI_FLAG_CMD_OVERFLOW)) {
+               resid = (psol->dw[offsetof(struct amap_sol_cqe, i_res_cnt) /
+                               32] & SOL_RES_CNT_MASK);
+
+               if (!status && (flags & ISCSI_FLAG_CMD_OVERFLOW))
+                       task->sc->result = DID_ERROR << 16;
+
+               if (flags & ISCSI_FLAG_CMD_UNDERFLOW) {
+                       scsi_set_resid(task->sc, resid);
+                       if (!status && (scsi_bufflen(task->sc) - resid <
+                           task->sc->underflow))
+                               task->sc->result = DID_ERROR << 16;
+               }
+       }
+
+       if (status == SAM_STAT_CHECK_CONDITION) {
+               sense = sts_bhs->sense_info + sizeof(unsigned short);
+               sense_len =
+                   cpu_to_be16((unsigned short)(sts_bhs->sense_info[0]));
+               memcpy(task->sc->sense_buffer, sense,
+                      min_t(u16, sense_len, SCSI_SENSE_BUFFERSIZE));
+       }
+       if (io_task->cmd_bhs->iscsi_hdr.flags & ISCSI_FLAG_CMD_READ) {
+               if (psol->dw[offsetof(struct amap_sol_cqe, i_res_cnt) / 32]
+                                                       & SOL_RES_CNT_MASK)
+                        conn->rxdata_octets += (psol->
+                             dw[offsetof(struct amap_sol_cqe, i_res_cnt) / 32]
+                                                       & SOL_RES_CNT_MASK);
+       }
+unmap:
+       scsi_dma_unmap(io_task->scsi_cmnd);
+       iscsi_complete_scsi_task(task, exp_cmdsn, max_cmdsn);
+}
+
+static void
+be_complete_logout(struct beiscsi_conn *beiscsi_conn,
+                  struct iscsi_task *task, struct sol_cqe *psol)
+{
+       struct iscsi_logout_rsp *hdr;
+       struct iscsi_conn *conn = beiscsi_conn->conn;
+
+       hdr = (struct iscsi_logout_rsp *)task->hdr;
+       hdr->t2wait = 5;
+       hdr->t2retain = 0;
+       hdr->flags = ((psol->dw[offsetof(struct amap_sol_cqe, i_flags) / 32]
+                                       & SOL_FLAGS_MASK) >> 24) | 0x80;
+       hdr->response = (psol->dw[offsetof(struct amap_sol_cqe, i_resp) /
+                                       32] & SOL_RESP_MASK);
+       hdr->exp_cmdsn = cpu_to_be32(psol->
+                       dw[offsetof(struct amap_sol_cqe, i_exp_cmd_sn) / 32]
+                                       & SOL_EXP_CMD_SN_MASK);
+       hdr->max_cmdsn = be32_to_cpu((psol->
+                        dw[offsetof(struct amap_sol_cqe, i_exp_cmd_sn) / 32]
+                                       & SOL_EXP_CMD_SN_MASK) +
+                       ((psol->dw[offsetof(struct amap_sol_cqe, i_cmd_wnd)
+                                       / 32] & SOL_CMD_WND_MASK) >> 24) - 1);
+       hdr->hlength = 0;
+
+       __iscsi_complete_pdu(conn, (struct iscsi_hdr *)hdr, NULL, 0);
+}
+
+static void
+be_complete_tmf(struct beiscsi_conn *beiscsi_conn,
+               struct iscsi_task *task, struct sol_cqe *psol)
+{
+       struct iscsi_tm_rsp *hdr;
+       struct iscsi_conn *conn = beiscsi_conn->conn;
+
+       hdr = (struct iscsi_tm_rsp *)task->hdr;
+       hdr->flags = ((psol->dw[offsetof(struct amap_sol_cqe, i_flags) / 32]
+                                       & SOL_FLAGS_MASK) >> 24) | 0x80;
+       hdr->response = (psol->dw[offsetof(struct amap_sol_cqe, i_resp) /
+                                       32] & SOL_RESP_MASK);
+       hdr->exp_cmdsn = cpu_to_be32(psol->dw[offsetof(struct amap_sol_cqe,
+                                    i_exp_cmd_sn) / 32] & SOL_EXP_CMD_SN_MASK);
+       hdr->max_cmdsn = be32_to_cpu((psol->dw[offsetof(struct amap_sol_cqe,
+                       i_exp_cmd_sn) / 32] & SOL_EXP_CMD_SN_MASK) +
+                       ((psol->dw[offsetof(struct amap_sol_cqe, i_cmd_wnd)
+                       / 32] & SOL_CMD_WND_MASK) >> 24) - 1);
+       __iscsi_complete_pdu(conn, (struct iscsi_hdr *)hdr, NULL, 0);
+}
+
+static void
+hwi_complete_drvr_msgs(struct beiscsi_conn *beiscsi_conn,
+                      struct beiscsi_hba *phba, struct sol_cqe *psol)
+{
+       struct hwi_wrb_context *pwrb_context;
+       struct wrb_handle *pwrb_handle;
+       struct hwi_controller *phwi_ctrlr;
+       struct iscsi_conn *conn = beiscsi_conn->conn;
+       struct iscsi_session *session = conn->session;
+
+       phwi_ctrlr = phba->phwi_ctrlr;
+       pwrb_context = &phwi_ctrlr->wrb_context[((psol->
+                               dw[offsetof(struct amap_sol_cqe, cid) / 32] &
+                               SOL_CID_MASK) >> 6)];
+       pwrb_handle = pwrb_context->pwrb_handle_basestd[((psol->
+                               dw[offsetof(struct amap_sol_cqe, wrb_index) /
+                               32] & SOL_WRB_INDEX_MASK) >> 16)];
+       spin_lock_bh(&session->lock);
+       free_wrb_handle(phba, pwrb_context, pwrb_handle);
+       spin_unlock_bh(&session->lock);
+}
+
+static void
+be_complete_nopin_resp(struct beiscsi_conn *beiscsi_conn,
+                      struct iscsi_task *task, struct sol_cqe *psol)
+{
+       struct iscsi_nopin *hdr;
+       struct iscsi_conn *conn = beiscsi_conn->conn;
+
+       hdr = (struct iscsi_nopin *)task->hdr;
+       hdr->flags = ((psol->dw[offsetof(struct amap_sol_cqe, i_flags) / 32]
+                       & SOL_FLAGS_MASK) >> 24) | 0x80;
+       hdr->exp_cmdsn = cpu_to_be32(psol->dw[offsetof(struct amap_sol_cqe,
+                                    i_exp_cmd_sn) / 32] & SOL_EXP_CMD_SN_MASK);
+       hdr->max_cmdsn = be32_to_cpu((psol->dw[offsetof(struct amap_sol_cqe,
+                       i_exp_cmd_sn) / 32] & SOL_EXP_CMD_SN_MASK) +
+                       ((psol->dw[offsetof(struct amap_sol_cqe, i_cmd_wnd)
+                       / 32] & SOL_CMD_WND_MASK) >> 24) - 1);
+       hdr->opcode = ISCSI_OP_NOOP_IN;
+       __iscsi_complete_pdu(conn, (struct iscsi_hdr *)hdr, NULL, 0);
+}
+
+static void hwi_complete_cmd(struct beiscsi_conn *beiscsi_conn,
+                            struct beiscsi_hba *phba, struct sol_cqe *psol)
+{
+       struct hwi_wrb_context *pwrb_context;
+       struct wrb_handle *pwrb_handle;
+       struct iscsi_wrb *pwrb = NULL;
+       struct hwi_controller *phwi_ctrlr;
+       struct iscsi_task *task;
+       struct beiscsi_io_task *io_task;
+       struct iscsi_conn *conn = beiscsi_conn->conn;
+       struct iscsi_session *session = conn->session;
+
+       phwi_ctrlr = phba->phwi_ctrlr;
+
+       pwrb_context = &phwi_ctrlr->
+               wrb_context[((psol->dw[offsetof(struct amap_sol_cqe, cid) / 32]
+               & SOL_CID_MASK) >> 6)];
+       pwrb_handle = pwrb_context->pwrb_handle_basestd[((psol->
+                               dw[offsetof(struct amap_sol_cqe, wrb_index) /
+                               32] & SOL_WRB_INDEX_MASK) >> 16)];
+
+       task = pwrb_handle->pio_handle;
+       io_task = task->dd_data;
+       spin_lock_bh(&session->lock);
+       pwrb = pwrb_handle->pwrb;
+       switch ((pwrb->dw[offsetof(struct amap_iscsi_wrb, type) / 32] &
+                WRB_TYPE_MASK) >> 28) {
+       case HWH_TYPE_IO:
+       case HWH_TYPE_IO_RD:
+               if ((task->hdr->opcode & ISCSI_OPCODE_MASK) ==
+                   ISCSI_OP_NOOP_OUT) {
+                       be_complete_nopin_resp(beiscsi_conn, task, psol);
+               } else
+                       be_complete_io(beiscsi_conn, task, psol);
+               break;
+
+       case HWH_TYPE_LOGOUT:
+               be_complete_logout(beiscsi_conn, task, psol);
+               break;
+
+       case HWH_TYPE_LOGIN:
+               SE_DEBUG(DBG_LVL_1,
+                        "\t\t No HWH_TYPE_LOGIN Expected in hwi_complete_cmd"
+                        "- Solicited path \n");
+               break;
+
+       case HWH_TYPE_TMF:
+               be_complete_tmf(beiscsi_conn, task, psol);
+               break;
+
+       case HWH_TYPE_NOP:
+               be_complete_nopin_resp(beiscsi_conn, task, psol);
+               break;
+
+       default:
+               shost_printk(KERN_WARNING, phba->shost,
+                           "wrb_index 0x%x CID 0x%x\n",
+                           ((psol->dw[offsetof(struct amap_iscsi_wrb, type) /
+                                       32] & SOL_WRB_INDEX_MASK) >> 16),
+                           ((psol->dw[offsetof(struct amap_sol_cqe, cid) / 32]
+                                       & SOL_CID_MASK) >> 6));
+               break;
+       }
+
+       spin_unlock_bh(&session->lock);
+}
+
+static struct list_head *hwi_get_async_busy_list(struct hwi_async_pdu_context
+                                         *pasync_ctx, unsigned int is_header,
+                                         unsigned int host_write_ptr)
+{
+       if (is_header)
+               return &pasync_ctx->async_entry[host_write_ptr].
+                   header_busy_list;
+       else
+               return &pasync_ctx->async_entry[host_write_ptr].data_busy_list;
+}
+
+static struct async_pdu_handle *
+hwi_get_async_handle(struct beiscsi_hba *phba,
+                    struct beiscsi_conn *beiscsi_conn,
+                    struct hwi_async_pdu_context *pasync_ctx,
+                    struct i_t_dpdu_cqe *pdpdu_cqe, unsigned int *pcq_index)
+{
+       struct be_bus_address phys_addr;
+       struct list_head *pbusy_list;
+       struct async_pdu_handle *pasync_handle = NULL;
+       int buffer_len = 0;
+       unsigned char buffer_index = -1;
+       unsigned char is_header = 0;
+
+       phys_addr.u.a32.address_lo =
+           pdpdu_cqe->dw[offsetof(struct amap_i_t_dpdu_cqe, db_addr_lo) / 32] -
+           ((pdpdu_cqe->dw[offsetof(struct amap_i_t_dpdu_cqe, dpl) / 32]
+                                               & PDUCQE_DPL_MASK) >> 16);
+       phys_addr.u.a32.address_hi =
+           pdpdu_cqe->dw[offsetof(struct amap_i_t_dpdu_cqe, db_addr_hi) / 32];
+
+       phys_addr.u.a64.address =
+                       *((unsigned long long *)(&phys_addr.u.a64.address));
+
+       switch (pdpdu_cqe->dw[offsetof(struct amap_i_t_dpdu_cqe, code) / 32]
+                       & PDUCQE_CODE_MASK) {
+       case UNSOL_HDR_NOTIFY:
+               is_header = 1;
+
+               pbusy_list = hwi_get_async_busy_list(pasync_ctx, 1,
+                       (pdpdu_cqe->dw[offsetof(struct amap_i_t_dpdu_cqe,
+                       index) / 32] & PDUCQE_INDEX_MASK));
+
+               buffer_len = (unsigned int)(phys_addr.u.a64.address -
+                               pasync_ctx->async_header.pa_base.u.a64.address);
+
+               buffer_index = buffer_len /
+                               pasync_ctx->async_header.buffer_size;
+
+               break;
+       case UNSOL_DATA_NOTIFY:
+               pbusy_list = hwi_get_async_busy_list(pasync_ctx, 0, (pdpdu_cqe->
+                                       dw[offsetof(struct amap_i_t_dpdu_cqe,
+                                       index) / 32] & PDUCQE_INDEX_MASK));
+               buffer_len = (unsigned long)(phys_addr.u.a64.address -
+                                       pasync_ctx->async_data.pa_base.u.
+                                       a64.address);
+               buffer_index = buffer_len / pasync_ctx->async_data.buffer_size;
+               break;
+       default:
+               pbusy_list = NULL;
+               shost_printk(KERN_WARNING, phba->shost,
+                       "Unexpected code=%d \n",
+                        pdpdu_cqe->dw[offsetof(struct amap_i_t_dpdu_cqe,
+                                       code) / 32] & PDUCQE_CODE_MASK);
+               return NULL;
+       }
+
+       WARN_ON(!(buffer_index <= pasync_ctx->async_data.num_entries));
+       WARN_ON(list_empty(pbusy_list));
+       list_for_each_entry(pasync_handle, pbusy_list, link) {
+               WARN_ON(pasync_handle->consumed);
+               if (pasync_handle->index == buffer_index)
+                       break;
+       }
+
+       WARN_ON(!pasync_handle);
+
+       pasync_handle->cri = (unsigned short)beiscsi_conn->beiscsi_conn_cid;
+       pasync_handle->is_header = is_header;
+       pasync_handle->buffer_len = ((pdpdu_cqe->
+                       dw[offsetof(struct amap_i_t_dpdu_cqe, dpl) / 32]
+                       & PDUCQE_DPL_MASK) >> 16);
+
+       *pcq_index = (pdpdu_cqe->dw[offsetof(struct amap_i_t_dpdu_cqe,
+                       index) / 32] & PDUCQE_INDEX_MASK);
+       return pasync_handle;
+}
+
+static unsigned int
+hwi_update_async_writables(struct hwi_async_pdu_context *pasync_ctx,
+                          unsigned int is_header, unsigned int cq_index)
+{
+       struct list_head *pbusy_list;
+       struct async_pdu_handle *pasync_handle;
+       unsigned int num_entries, writables = 0;
+       unsigned int *pep_read_ptr, *pwritables;
+
+
+       if (is_header) {
+               pep_read_ptr = &pasync_ctx->async_header.ep_read_ptr;
+               pwritables = &pasync_ctx->async_header.writables;
+               num_entries = pasync_ctx->async_header.num_entries;
+       } else {
+               pep_read_ptr = &pasync_ctx->async_data.ep_read_ptr;
+               pwritables = &pasync_ctx->async_data.writables;
+               num_entries = pasync_ctx->async_data.num_entries;
+       }
+
+       while ((*pep_read_ptr) != cq_index) {
+               (*pep_read_ptr)++;
+               *pep_read_ptr = (*pep_read_ptr) % num_entries;
+
+               pbusy_list = hwi_get_async_busy_list(pasync_ctx, is_header,
+                                                    *pep_read_ptr);
+               if (writables == 0)
+                       WARN_ON(list_empty(pbusy_list));
+
+               if (!list_empty(pbusy_list)) {
+                       pasync_handle = list_entry(pbusy_list->next,
+                                                  struct async_pdu_handle,
+                                                  link);
+                       WARN_ON(!pasync_handle);
+                       pasync_handle->consumed = 1;
+               }
+
+               writables++;
+       }
+
+       if (!writables) {
+               SE_DEBUG(DBG_LVL_1,
+                        "Duplicate notification received - index 0x%x!!\n",
+                        cq_index);
+               WARN_ON(1);
+       }
+
+       *pwritables = *pwritables + writables;
+       return 0;
+}
+
+static unsigned int hwi_free_async_msg(struct beiscsi_hba *phba,
+                                      unsigned int cri)
+{
+       struct hwi_controller *phwi_ctrlr;
+       struct hwi_async_pdu_context *pasync_ctx;
+       struct async_pdu_handle *pasync_handle, *tmp_handle;
+       struct list_head *plist;
+       unsigned int i = 0;
+
+       phwi_ctrlr = phba->phwi_ctrlr;
+       pasync_ctx = HWI_GET_ASYNC_PDU_CTX(phwi_ctrlr);
+
+       plist  = &pasync_ctx->async_entry[cri].wait_queue.list;
+
+       list_for_each_entry_safe(pasync_handle, tmp_handle, plist, link) {
+               list_del(&pasync_handle->link);
+
+               if (i == 0) {
+                       list_add_tail(&pasync_handle->link,
+                                     &pasync_ctx->async_header.free_list);
+                       pasync_ctx->async_header.free_entries++;
+                       i++;
+               } else {
+                       list_add_tail(&pasync_handle->link,
+                                     &pasync_ctx->async_data.free_list);
+                       pasync_ctx->async_data.free_entries++;
+                       i++;
+               }
+       }
+
+       INIT_LIST_HEAD(&pasync_ctx->async_entry[cri].wait_queue.list);
+       pasync_ctx->async_entry[cri].wait_queue.hdr_received = 0;
+       pasync_ctx->async_entry[cri].wait_queue.bytes_received = 0;
+       return 0;
+}
+
+static struct phys_addr *
+hwi_get_ring_address(struct hwi_async_pdu_context *pasync_ctx,
+                    unsigned int is_header, unsigned int host_write_ptr)
+{
+       struct phys_addr *pasync_sge = NULL;
+
+       if (is_header)
+               pasync_sge = pasync_ctx->async_header.ring_base;
+       else
+               pasync_sge = pasync_ctx->async_data.ring_base;
+
+       return pasync_sge + host_write_ptr;
+}
+
+static void hwi_post_async_buffers(struct beiscsi_hba *phba,
+                                  unsigned int is_header)
+{
+       struct hwi_controller *phwi_ctrlr;
+       struct hwi_async_pdu_context *pasync_ctx;
+       struct async_pdu_handle *pasync_handle;
+       struct list_head *pfree_link, *pbusy_list;
+       struct phys_addr *pasync_sge;
+       unsigned int ring_id, num_entries;
+       unsigned int host_write_num;
+       unsigned int writables;
+       unsigned int i = 0;
+       u32 doorbell = 0;
+
+       phwi_ctrlr = phba->phwi_ctrlr;
+       pasync_ctx = HWI_GET_ASYNC_PDU_CTX(phwi_ctrlr);
+
+       if (is_header) {
+               num_entries = pasync_ctx->async_header.num_entries;
+               writables = min(pasync_ctx->async_header.writables,
+                               pasync_ctx->async_header.free_entries);
+               pfree_link = pasync_ctx->async_header.free_list.next;
+               host_write_num = pasync_ctx->async_header.host_write_ptr;
+               ring_id = phwi_ctrlr->default_pdu_hdr.id;
+       } else {
+               num_entries = pasync_ctx->async_data.num_entries;
+               writables = min(pasync_ctx->async_data.writables,
+                               pasync_ctx->async_data.free_entries);
+               pfree_link = pasync_ctx->async_data.free_list.next;
+               host_write_num = pasync_ctx->async_data.host_write_ptr;
+               ring_id = phwi_ctrlr->default_pdu_data.id;
+       }
+
+       writables = (writables / 8) * 8;
+       if (writables) {
+               for (i = 0; i < writables; i++) {
+                       pbusy_list =
+                           hwi_get_async_busy_list(pasync_ctx, is_header,
+                                                   host_write_num);
+                       pasync_handle =
+                           list_entry(pfree_link, struct async_pdu_handle,
+                                                               link);
+                       WARN_ON(!pasync_handle);
+                       pasync_handle->consumed = 0;
+
+                       pfree_link = pfree_link->next;
+
+                       pasync_sge = hwi_get_ring_address(pasync_ctx,
+                                               is_header, host_write_num);
+
+                       pasync_sge->hi = pasync_handle->pa.u.a32.address_lo;
+                       pasync_sge->lo = pasync_handle->pa.u.a32.address_hi;
+
+                       list_move(&pasync_handle->link, pbusy_list);
+
+                       host_write_num++;
+                       host_write_num = host_write_num % num_entries;
+               }
+
+               if (is_header) {
+                       pasync_ctx->async_header.host_write_ptr =
+                                                       host_write_num;
+                       pasync_ctx->async_header.free_entries -= writables;
+                       pasync_ctx->async_header.writables -= writables;
+                       pasync_ctx->async_header.busy_entries += writables;
+               } else {
+                       pasync_ctx->async_data.host_write_ptr = host_write_num;
+                       pasync_ctx->async_data.free_entries -= writables;
+                       pasync_ctx->async_data.writables -= writables;
+                       pasync_ctx->async_data.busy_entries += writables;
+               }
+
+               doorbell |= ring_id & DB_DEF_PDU_RING_ID_MASK;
+               doorbell |= 1 << DB_DEF_PDU_REARM_SHIFT;
+               doorbell |= 0 << DB_DEF_PDU_EVENT_SHIFT;
+               doorbell |= (writables & DB_DEF_PDU_CQPROC_MASK)
+                                       << DB_DEF_PDU_CQPROC_SHIFT;
+
+               iowrite32(doorbell, phba->db_va + DB_RXULP0_OFFSET);
+       }
+}
+
+static void hwi_flush_default_pdu_buffer(struct beiscsi_hba *phba,
+                                        struct beiscsi_conn *beiscsi_conn,
+                                        struct i_t_dpdu_cqe *pdpdu_cqe)
+{
+       struct hwi_controller *phwi_ctrlr;
+       struct hwi_async_pdu_context *pasync_ctx;
+       struct async_pdu_handle *pasync_handle = NULL;
+       unsigned int cq_index = -1;
+
+       phwi_ctrlr = phba->phwi_ctrlr;
+       pasync_ctx = HWI_GET_ASYNC_PDU_CTX(phwi_ctrlr);
+
+       pasync_handle = hwi_get_async_handle(phba, beiscsi_conn, pasync_ctx,
+                                            pdpdu_cqe, &cq_index);
+       BUG_ON(pasync_handle->is_header != 0);
+       if (pasync_handle->consumed == 0)
+               hwi_update_async_writables(pasync_ctx, pasync_handle->is_header,
+                                          cq_index);
+
+       hwi_free_async_msg(phba, pasync_handle->cri);
+       hwi_post_async_buffers(phba, pasync_handle->is_header);
+}
+
+static unsigned int
+hwi_fwd_async_msg(struct beiscsi_conn *beiscsi_conn,
+                 struct beiscsi_hba *phba,
+                 struct hwi_async_pdu_context *pasync_ctx, unsigned short cri)
+{
+       struct list_head *plist;
+       struct async_pdu_handle *pasync_handle;
+       void *phdr = NULL;
+       unsigned int hdr_len = 0, buf_len = 0;
+       unsigned int status, index = 0, offset = 0;
+       void *pfirst_buffer = NULL;
+       unsigned int num_buf = 0;
+
+       plist = &pasync_ctx->async_entry[cri].wait_queue.list;
+
+       list_for_each_entry(pasync_handle, plist, link) {
+               if (index == 0) {
+                       phdr = pasync_handle->pbuffer;
+                       hdr_len = pasync_handle->buffer_len;
+               } else {
+                       buf_len = pasync_handle->buffer_len;
+                       if (!num_buf) {
+                               pfirst_buffer = pasync_handle->pbuffer;
+                               num_buf++;
+                       }
+                       memcpy(pfirst_buffer + offset,
+                              pasync_handle->pbuffer, buf_len);
+                       offset = buf_len;
+               }
+               index++;
+       }
+
+       status = beiscsi_process_async_pdu(beiscsi_conn, phba,
+                                          beiscsi_conn->beiscsi_conn_cid,
+                                          phdr, hdr_len, pfirst_buffer,
+                                          buf_len);
+
+       if (status == 0)
+               hwi_free_async_msg(phba, cri);
+       return 0;
+}
+
+static unsigned int
+hwi_gather_async_pdu(struct beiscsi_conn *beiscsi_conn,
+                    struct beiscsi_hba *phba,
+                    struct async_pdu_handle *pasync_handle)
+{
+       struct hwi_async_pdu_context *pasync_ctx;
+       struct hwi_controller *phwi_ctrlr;
+       unsigned int bytes_needed = 0, status = 0;
+       unsigned short cri = pasync_handle->cri;
+       struct pdu_base *ppdu;
+
+       phwi_ctrlr = phba->phwi_ctrlr;
+       pasync_ctx = HWI_GET_ASYNC_PDU_CTX(phwi_ctrlr);
+
+       list_del(&pasync_handle->link);
+       if (pasync_handle->is_header) {
+               pasync_ctx->async_header.busy_entries--;
+               if (pasync_ctx->async_entry[cri].wait_queue.hdr_received) {
+                       hwi_free_async_msg(phba, cri);
+                       BUG();
+               }
+
+               pasync_ctx->async_entry[cri].wait_queue.bytes_received = 0;
+               pasync_ctx->async_entry[cri].wait_queue.hdr_received = 1;
+               pasync_ctx->async_entry[cri].wait_queue.hdr_len =
+                               (unsigned short)pasync_handle->buffer_len;
+               list_add_tail(&pasync_handle->link,
+                             &pasync_ctx->async_entry[cri].wait_queue.list);
+
+               ppdu = pasync_handle->pbuffer;
+               bytes_needed = ((((ppdu->dw[offsetof(struct amap_pdu_base,
+                       data_len_hi) / 32] & PDUBASE_DATALENHI_MASK) << 8) &
+                       0xFFFF0000) | ((be16_to_cpu((ppdu->
+                       dw[offsetof(struct amap_pdu_base, data_len_lo) / 32]
+                       & PDUBASE_DATALENLO_MASK) >> 16)) & 0x0000FFFF));
+
+               if (status == 0) {
+                       pasync_ctx->async_entry[cri].wait_queue.bytes_needed =
+                           bytes_needed;
+
+                       if (bytes_needed == 0)
+                               status = hwi_fwd_async_msg(beiscsi_conn, phba,
+                                                          pasync_ctx, cri);
+               }
+       } else {
+               pasync_ctx->async_data.busy_entries--;
+               if (pasync_ctx->async_entry[cri].wait_queue.hdr_received) {
+                       list_add_tail(&pasync_handle->link,
+                                     &pasync_ctx->async_entry[cri].wait_queue.
+                                     list);
+                       pasync_ctx->async_entry[cri].wait_queue.
+                               bytes_received +=
+                               (unsigned short)pasync_handle->buffer_len;
+
+                       if (pasync_ctx->async_entry[cri].wait_queue.
+                           bytes_received >=
+                           pasync_ctx->async_entry[cri].wait_queue.
+                           bytes_needed)
+                               status = hwi_fwd_async_msg(beiscsi_conn, phba,
+                                                          pasync_ctx, cri);
+               }
+       }
+       return status;
+}
+
+static void hwi_process_default_pdu_ring(struct beiscsi_conn *beiscsi_conn,
+                                        struct beiscsi_hba *phba,
+                                        struct i_t_dpdu_cqe *pdpdu_cqe)
+{
+       struct hwi_controller *phwi_ctrlr;
+       struct hwi_async_pdu_context *pasync_ctx;
+       struct async_pdu_handle *pasync_handle = NULL;
+       unsigned int cq_index = -1;
+
+       phwi_ctrlr = phba->phwi_ctrlr;
+       pasync_ctx = HWI_GET_ASYNC_PDU_CTX(phwi_ctrlr);
+       pasync_handle = hwi_get_async_handle(phba, beiscsi_conn, pasync_ctx,
+                                            pdpdu_cqe, &cq_index);
+
+       if (pasync_handle->consumed == 0)
+               hwi_update_async_writables(pasync_ctx, pasync_handle->is_header,
+                                          cq_index);
+       hwi_gather_async_pdu(beiscsi_conn, phba, pasync_handle);
+       hwi_post_async_buffers(phba, pasync_handle->is_header);
+}
+
+static unsigned int beiscsi_process_cq(struct beiscsi_hba *phba)
+{
+       struct hwi_controller *phwi_ctrlr;
+       struct hwi_context_memory *phwi_context;
+       struct be_queue_info *cq;
+       struct sol_cqe *sol;
+       struct dmsg_cqe *dmsg;
+       unsigned int num_processed = 0;
+       unsigned int tot_nump = 0;
+       struct beiscsi_conn *beiscsi_conn;
+
+       phwi_ctrlr = phba->phwi_ctrlr;
+       phwi_context = phwi_ctrlr->phwi_ctxt;
+       cq = &phwi_context->be_cq;
+       sol = queue_tail_node(cq);
+
+       while (sol->dw[offsetof(struct amap_sol_cqe, valid) / 32] &
+              CQE_VALID_MASK) {
+               be_dws_le_to_cpu(sol, sizeof(struct sol_cqe));
+
+               beiscsi_conn = phba->conn_table[(u32) (sol->
+                                dw[offsetof(struct amap_sol_cqe, cid) / 32] &
+                                SOL_CID_MASK) >> 6];
+
+               if (!beiscsi_conn || !beiscsi_conn->ep) {
+                       shost_printk(KERN_WARNING, phba->shost,
+                                    "Connection table empty for cid = %d\n",
+                                    (u32)(sol->dw[offsetof(struct amap_sol_cqe,
+                                    cid) / 32] & SOL_CID_MASK) >> 6);
+                       return 0;
+               }
+
+               if (num_processed >= 32) {
+                       hwi_ring_cq_db(phba, phwi_context->be_cq.id,
+                                       num_processed, 0, 0);
+                       tot_nump += num_processed;
+                       num_processed = 0;
+               }
+
+               switch ((u32) sol->dw[offsetof(struct amap_sol_cqe, code) /
+                       32] & CQE_CODE_MASK) {
+               case SOL_CMD_COMPLETE:
+                       hwi_complete_cmd(beiscsi_conn, phba, sol);
+                       break;
+               case DRIVERMSG_NOTIFY:
+                       SE_DEBUG(DBG_LVL_8, "Received DRIVERMSG_NOTIFY \n");
+                       dmsg = (struct dmsg_cqe *)sol;
+                       hwi_complete_drvr_msgs(beiscsi_conn, phba, sol);
+                       break;
+               case UNSOL_HDR_NOTIFY:
+               case UNSOL_DATA_NOTIFY:
+                       SE_DEBUG(DBG_LVL_8, "Received UNSOL_HDR/DATA_NOTIFY\n");
+                       hwi_process_default_pdu_ring(beiscsi_conn, phba,
+                                            (struct i_t_dpdu_cqe *)sol);
+                       break;
+               case CXN_INVALIDATE_INDEX_NOTIFY:
+               case CMD_INVALIDATED_NOTIFY:
+               case CXN_INVALIDATE_NOTIFY:
+                       SE_DEBUG(DBG_LVL_1,
+                                "Ignoring CQ Error notification for cmd/cxn"
+                                "invalidate\n");
+                       break;
+               case SOL_CMD_KILLED_DATA_DIGEST_ERR:
+               case CMD_KILLED_INVALID_STATSN_RCVD:
+               case CMD_KILLED_INVALID_R2T_RCVD:
+               case CMD_CXN_KILLED_LUN_INVALID:
+               case CMD_CXN_KILLED_ICD_INVALID:
+               case CMD_CXN_KILLED_ITT_INVALID:
+               case CMD_CXN_KILLED_SEQ_OUTOFORDER:
+               case CMD_CXN_KILLED_INVALID_DATASN_RCVD:
+                       SE_DEBUG(DBG_LVL_1,
+                                "CQ Error notification for cmd.. "
+                                "code %d cid 0x%x\n",
+                                sol->dw[offsetof(struct amap_sol_cqe, code) /
+                                32] & CQE_CODE_MASK,
+                                (sol->dw[offsetof(struct amap_sol_cqe, cid) /
+                                32] & SOL_CID_MASK));
+                       break;
+               case UNSOL_DATA_DIGEST_ERROR_NOTIFY:
+                       SE_DEBUG(DBG_LVL_1,
+                                "Digest error on def pdu ring, dropping..\n");
+                       hwi_flush_default_pdu_buffer(phba, beiscsi_conn,
+                                            (struct i_t_dpdu_cqe *) sol);
+                       break;
+               case CXN_KILLED_PDU_SIZE_EXCEEDS_DSL:
+               case CXN_KILLED_BURST_LEN_MISMATCH:
+               case CXN_KILLED_AHS_RCVD:
+               case CXN_KILLED_HDR_DIGEST_ERR:
+               case CXN_KILLED_UNKNOWN_HDR:
+               case CXN_KILLED_STALE_ITT_TTT_RCVD:
+               case CXN_KILLED_INVALID_ITT_TTT_RCVD:
+               case CXN_KILLED_TIMED_OUT:
+               case CXN_KILLED_FIN_RCVD:
+               case CXN_KILLED_BAD_UNSOL_PDU_RCVD:
+               case CXN_KILLED_BAD_WRB_INDEX_ERROR:
+               case CXN_KILLED_OVER_RUN_RESIDUAL:
+               case CXN_KILLED_UNDER_RUN_RESIDUAL:
+               case CXN_KILLED_CMND_DATA_NOT_ON_SAME_CONN:
+                       SE_DEBUG(DBG_LVL_1, "CQ Error %d, resetting CID "
+                                "0x%x...\n",
+                                sol->dw[offsetof(struct amap_sol_cqe, code) /
+                                32] & CQE_CODE_MASK,
+                                sol->dw[offsetof(struct amap_sol_cqe, cid) /
+                                32] & CQE_CID_MASK);
+                       iscsi_conn_failure(beiscsi_conn->conn,
+                                          ISCSI_ERR_CONN_FAILED);
+                       break;
+               case CXN_KILLED_RST_SENT:
+               case CXN_KILLED_RST_RCVD:
+                       SE_DEBUG(DBG_LVL_1, "CQ Error %d, reset received/sent "
+                                "on CID 0x%x...\n",
+                                sol->dw[offsetof(struct amap_sol_cqe, code) /
+                                32] & CQE_CODE_MASK,
+                                sol->dw[offsetof(struct amap_sol_cqe, cid) /
+                                32] & CQE_CID_MASK);
+                       iscsi_conn_failure(beiscsi_conn->conn,
+                                          ISCSI_ERR_CONN_FAILED);
+                       break;
+               default:
+                       SE_DEBUG(DBG_LVL_1, "CQ Error Invalid code= %d "
+                                "received on CID 0x%x...\n",
+                                sol->dw[offsetof(struct amap_sol_cqe, code) /
+                                32] & CQE_CODE_MASK,
+                                sol->dw[offsetof(struct amap_sol_cqe, cid) /
+                                32] & CQE_CID_MASK);
+                       break;
+               }
+
+               AMAP_SET_BITS(struct amap_sol_cqe, valid, sol, 0);
+               queue_tail_inc(cq);
+               sol = queue_tail_node(cq);
+               num_processed++;
+       }
+
+       if (num_processed > 0) {
+               tot_nump += num_processed;
+               hwi_ring_cq_db(phba, phwi_context->be_cq.id, num_processed,
+                              1, 0);
+       }
+       return tot_nump;
+}
+
+static void beiscsi_process_all_cqs(struct work_struct *work)
+{
+       unsigned long flags;
+       struct beiscsi_hba *phba =
+           container_of(work, struct beiscsi_hba, work_cqs);
+
+       if (phba->todo_mcc_cq) {
+               spin_lock_irqsave(&phba->isr_lock, flags);
+               phba->todo_mcc_cq = 0;
+               spin_unlock_irqrestore(&phba->isr_lock, flags);
+               SE_DEBUG(DBG_LVL_1, "MCC Interrupt Not expected \n");
+       }
+
+       if (phba->todo_cq) {
+               spin_lock_irqsave(&phba->isr_lock, flags);
+               phba->todo_cq = 0;
+               spin_unlock_irqrestore(&phba->isr_lock, flags);
+               beiscsi_process_cq(phba);
+       }
+}
+
+static int be_iopoll(struct blk_iopoll *iop, int budget)
+{
+       static unsigned int ret;
+       struct beiscsi_hba *phba;
+
+       phba = container_of(iop, struct beiscsi_hba, iopoll);
+
+       ret = beiscsi_process_cq(phba);
+       if (ret < budget) {
+               struct hwi_controller *phwi_ctrlr;
+               struct hwi_context_memory *phwi_context;
+
+               phwi_ctrlr = phba->phwi_ctrlr;
+               phwi_context = phwi_ctrlr->phwi_ctxt;
+               blk_iopoll_complete(iop);
+               hwi_ring_eq_db(phba, phwi_context->be_eq.q.id, 0,
+                                                       0, 1, 1);
+       }
+       return ret;
+}
+
+static void
+hwi_write_sgl(struct iscsi_wrb *pwrb, struct scatterlist *sg,
+             unsigned int num_sg, struct beiscsi_io_task *io_task)
+{
+       struct iscsi_sge *psgl;
+       unsigned short sg_len, index;
+       unsigned int sge_len = 0;
+       unsigned long long addr;
+       struct scatterlist *l_sg;
+       unsigned int offset;
+
+       AMAP_SET_BITS(struct amap_iscsi_wrb, iscsi_bhs_addr_lo, pwrb,
+                                     io_task->bhs_pa.u.a32.address_lo);
+       AMAP_SET_BITS(struct amap_iscsi_wrb, iscsi_bhs_addr_hi, pwrb,
+                                     io_task->bhs_pa.u.a32.address_hi);
+
+       l_sg = sg;
+       for (index = 0; (index < num_sg) && (index < 2); index++, sg_next(sg)) {
+               if (index == 0) {
+                       sg_len = sg_dma_len(sg);
+                       addr = (u64) sg_dma_address(sg);
+                       AMAP_SET_BITS(struct amap_iscsi_wrb, sge0_addr_lo, pwrb,
+                                                       (addr & 0xFFFFFFFF));
+                       AMAP_SET_BITS(struct amap_iscsi_wrb, sge0_addr_hi, pwrb,
+                                                       (addr >> 32));
+                       AMAP_SET_BITS(struct amap_iscsi_wrb, sge0_len, pwrb,
+                                                       sg_len);
+                       sge_len = sg_len;
+                       AMAP_SET_BITS(struct amap_iscsi_wrb, sge0_last, pwrb,
+                                                       1);
+               } else {
+                       AMAP_SET_BITS(struct amap_iscsi_wrb, sge0_last, pwrb,
+                                                       0);
+                       AMAP_SET_BITS(struct amap_iscsi_wrb, sge1_r2t_offset,
+                                                       pwrb, sge_len);
+                       sg_len = sg_dma_len(sg);
+                       addr = (u64) sg_dma_address(sg);
+                       AMAP_SET_BITS(struct amap_iscsi_wrb, sge1_addr_lo, pwrb,
+                                                       (addr & 0xFFFFFFFF));
+                       AMAP_SET_BITS(struct amap_iscsi_wrb, sge1_addr_hi, pwrb,
+                                                       (addr >> 32));
+                       AMAP_SET_BITS(struct amap_iscsi_wrb, sge1_len, pwrb,
+                                                       sg_len);
+               }
+       }
+       psgl = (struct iscsi_sge *)io_task->psgl_handle->pfrag;
+       memset(psgl, 0, sizeof(*psgl) * BE2_SGE);
+
+       AMAP_SET_BITS(struct amap_iscsi_sge, len, psgl, io_task->bhs_len - 2);
+
+       AMAP_SET_BITS(struct amap_iscsi_sge, addr_hi, psgl,
+                       io_task->bhs_pa.u.a32.address_hi);
+       AMAP_SET_BITS(struct amap_iscsi_sge, addr_lo, psgl,
+                       io_task->bhs_pa.u.a32.address_lo);
+
+       if (num_sg == 2)
+               AMAP_SET_BITS(struct amap_iscsi_wrb, sge1_last, pwrb, 1);
+       sg = l_sg;
+       psgl++;
+       psgl++;
+       offset = 0;
+       for (index = 0; index < num_sg; index++, sg_next(sg), psgl++) {
+               sg_len = sg_dma_len(sg);
+               addr = (u64) sg_dma_address(sg);
+               AMAP_SET_BITS(struct amap_iscsi_sge, addr_lo, psgl,
+                                               (addr & 0xFFFFFFFF));
+               AMAP_SET_BITS(struct amap_iscsi_sge, addr_hi, psgl,
+                                               (addr >> 32));
+               AMAP_SET_BITS(struct amap_iscsi_sge, len, psgl, sg_len);
+               AMAP_SET_BITS(struct amap_iscsi_sge, sge_offset, psgl, offset);
+               AMAP_SET_BITS(struct amap_iscsi_sge, last_sge, psgl, 0);
+               offset += sg_len;
+       }
+       psgl--;
+       AMAP_SET_BITS(struct amap_iscsi_sge, last_sge, psgl, 1);
+}
+
+static void hwi_write_buffer(struct iscsi_wrb *pwrb, struct iscsi_task *task)
+{
+       struct iscsi_sge *psgl;
+       unsigned long long addr;
+       struct beiscsi_io_task *io_task = task->dd_data;
+       struct beiscsi_conn *beiscsi_conn = io_task->conn;
+       struct beiscsi_hba *phba = beiscsi_conn->phba;
+
+       io_task->bhs_len = sizeof(struct be_nonio_bhs) - 2;
+       AMAP_SET_BITS(struct amap_iscsi_wrb, iscsi_bhs_addr_lo, pwrb,
+                               io_task->bhs_pa.u.a32.address_lo);
+       AMAP_SET_BITS(struct amap_iscsi_wrb, iscsi_bhs_addr_hi, pwrb,
+                               io_task->bhs_pa.u.a32.address_hi);
+
+       if (task->data) {
+               if (task->data_count) {
+                       AMAP_SET_BITS(struct amap_iscsi_wrb, dsp, pwrb, 1);
+                       addr = (u64) pci_map_single(phba->pcidev,
+                                                   task->data,
+                                                   task->data_count, 1);
+               } else {
+                       AMAP_SET_BITS(struct amap_iscsi_wrb, dsp, pwrb, 0);
+                       addr = 0;
+               }
+               AMAP_SET_BITS(struct amap_iscsi_wrb, sge0_addr_lo, pwrb,
+                                               (addr & 0xFFFFFFFF));
+               AMAP_SET_BITS(struct amap_iscsi_wrb, sge0_addr_hi, pwrb,
+                                               (addr >> 32));
+               AMAP_SET_BITS(struct amap_iscsi_wrb, sge0_len, pwrb,
+                                               task->data_count);
+
+               AMAP_SET_BITS(struct amap_iscsi_wrb, sge0_last, pwrb, 1);
+       } else {
+               AMAP_SET_BITS(struct amap_iscsi_wrb, dsp, pwrb, 0);
+               addr = 0;
+       }
+
+       psgl = (struct iscsi_sge *)io_task->psgl_handle->pfrag;
+
+       AMAP_SET_BITS(struct amap_iscsi_sge, len, psgl, io_task->bhs_len);
+
+       AMAP_SET_BITS(struct amap_iscsi_sge, addr_hi, psgl,
+                     io_task->bhs_pa.u.a32.address_hi);
+       AMAP_SET_BITS(struct amap_iscsi_sge, addr_lo, psgl,
+                     io_task->bhs_pa.u.a32.address_lo);
+       if (task->data) {
+               psgl++;
+               AMAP_SET_BITS(struct amap_iscsi_sge, addr_hi, psgl, 0);
+               AMAP_SET_BITS(struct amap_iscsi_sge, addr_lo, psgl, 0);
+               AMAP_SET_BITS(struct amap_iscsi_sge, len, psgl, 0);
+               AMAP_SET_BITS(struct amap_iscsi_sge, sge_offset, psgl, 0);
+               AMAP_SET_BITS(struct amap_iscsi_sge, rsvd0, psgl, 0);
+               AMAP_SET_BITS(struct amap_iscsi_sge, last_sge, psgl, 0);
+
+               psgl++;
+               if (task->data) {
+                       AMAP_SET_BITS(struct amap_iscsi_sge, addr_lo, psgl,
+                                               (addr & 0xFFFFFFFF));
+                       AMAP_SET_BITS(struct amap_iscsi_sge, addr_hi, psgl,
+                                               (addr >> 32));
+               }
+               AMAP_SET_BITS(struct amap_iscsi_sge, len, psgl, 0x106);
+       }
+       AMAP_SET_BITS(struct amap_iscsi_sge, last_sge, psgl, 1);
+}
+
+static void beiscsi_find_mem_req(struct beiscsi_hba *phba)
+{
+       unsigned int num_cq_pages, num_eq_pages, num_async_pdu_buf_pages;
+       unsigned int num_async_pdu_data_pages, wrb_sz_per_cxn;
+       unsigned int num_async_pdu_buf_sgl_pages, num_async_pdu_data_sgl_pages;
+
+       num_cq_pages = PAGES_REQUIRED(phba->params.num_cq_entries * \
+                                     sizeof(struct sol_cqe));
+       num_eq_pages = PAGES_REQUIRED(phba->params.num_eq_entries * \
+                                     sizeof(struct be_eq_entry));
+       num_async_pdu_buf_pages =
+                       PAGES_REQUIRED(phba->params.asyncpdus_per_ctrl * \
+                                      phba->params.defpdu_hdr_sz);
+       num_async_pdu_buf_sgl_pages =
+                       PAGES_REQUIRED(phba->params.asyncpdus_per_ctrl * \
+                                      sizeof(struct phys_addr));
+       num_async_pdu_data_pages =
+                       PAGES_REQUIRED(phba->params.asyncpdus_per_ctrl * \
+                                      phba->params.defpdu_data_sz);
+       num_async_pdu_data_sgl_pages =
+                       PAGES_REQUIRED(phba->params.asyncpdus_per_ctrl * \
+                                      sizeof(struct phys_addr));
+
+       phba->params.hwi_ws_sz = sizeof(struct hwi_controller);
+
+       phba->mem_req[ISCSI_MEM_GLOBAL_HEADER] = 2 *
+                                                BE_ISCSI_PDU_HEADER_SIZE;
+       phba->mem_req[HWI_MEM_ADDN_CONTEXT] =
+                                           sizeof(struct hwi_context_memory);
+
+       phba->mem_req[HWI_MEM_CQ] = num_cq_pages * PAGE_SIZE;
+       phba->mem_req[HWI_MEM_EQ] = num_eq_pages * PAGE_SIZE;
+
+       phba->mem_req[HWI_MEM_WRB] = sizeof(struct iscsi_wrb)
+           * (phba->params.wrbs_per_cxn)
+           * phba->params.cxns_per_ctrl;
+       wrb_sz_per_cxn =  sizeof(struct wrb_handle) *
+                                (phba->params.wrbs_per_cxn);
+       phba->mem_req[HWI_MEM_WRBH] = roundup_pow_of_two((wrb_sz_per_cxn) *
+                               phba->params.cxns_per_ctrl);
+
+       phba->mem_req[HWI_MEM_SGLH] = sizeof(struct sgl_handle) *
+               phba->params.icds_per_ctrl;
+       phba->mem_req[HWI_MEM_SGE] = sizeof(struct iscsi_sge) *
+               phba->params.num_sge_per_io * phba->params.icds_per_ctrl;
+
+       phba->mem_req[HWI_MEM_ASYNC_HEADER_BUF] =
+               num_async_pdu_buf_pages * PAGE_SIZE;
+       phba->mem_req[HWI_MEM_ASYNC_DATA_BUF] =
+               num_async_pdu_data_pages * PAGE_SIZE;
+       phba->mem_req[HWI_MEM_ASYNC_HEADER_RING] =
+               num_async_pdu_buf_sgl_pages * PAGE_SIZE;
+       phba->mem_req[HWI_MEM_ASYNC_DATA_RING] =
+               num_async_pdu_data_sgl_pages * PAGE_SIZE;
+       phba->mem_req[HWI_MEM_ASYNC_HEADER_HANDLE] =
+               phba->params.asyncpdus_per_ctrl *
+               sizeof(struct async_pdu_handle);
+       phba->mem_req[HWI_MEM_ASYNC_DATA_HANDLE] =
+               phba->params.asyncpdus_per_ctrl *
+               sizeof(struct async_pdu_handle);
+       phba->mem_req[HWI_MEM_ASYNC_PDU_CONTEXT] =
+               sizeof(struct hwi_async_pdu_context) +
+               (phba->params.cxns_per_ctrl * sizeof(struct hwi_async_entry));
+}
+
+static int beiscsi_alloc_mem(struct beiscsi_hba *phba)
+{
+       struct be_mem_descriptor *mem_descr;
+       dma_addr_t bus_add;
+       struct mem_array *mem_arr, *mem_arr_orig;
+       unsigned int i, j, alloc_size, curr_alloc_size;
+
+       phba->phwi_ctrlr = kmalloc(phba->params.hwi_ws_sz, GFP_KERNEL);
+       if (!phba->phwi_ctrlr)
+               return -ENOMEM;
+
+       phba->init_mem = kcalloc(SE_MEM_MAX, sizeof(*mem_descr),
+                                GFP_KERNEL);
+       if (!phba->init_mem) {
+               kfree(phba->phwi_ctrlr);
+               return -ENOMEM;
+       }
+
+       mem_arr_orig = kmalloc(sizeof(*mem_arr_orig) * BEISCSI_MAX_FRAGS_INIT,
+                              GFP_KERNEL);
+       if (!mem_arr_orig) {
+               kfree(phba->init_mem);
+               kfree(phba->phwi_ctrlr);
+               return -ENOMEM;
+       }
+
+       mem_descr = phba->init_mem;
+       for (i = 0; i < SE_MEM_MAX; i++) {
+               j = 0;
+               mem_arr = mem_arr_orig;
+               alloc_size = phba->mem_req[i];
+               memset(mem_arr, 0, sizeof(struct mem_array) *
+                      BEISCSI_MAX_FRAGS_INIT);
+               curr_alloc_size = min(be_max_phys_size * 1024, alloc_size);
+               do {
+                       mem_arr->virtual_address = pci_alloc_consistent(
+                                                       phba->pcidev,
+                                                       curr_alloc_size,
+                                                       &bus_add);
+                       if (!mem_arr->virtual_address) {
+                               if (curr_alloc_size <= BE_MIN_MEM_SIZE)
+                                       goto free_mem;
+                               if (curr_alloc_size -
+                                       rounddown_pow_of_two(curr_alloc_size))
+                                       curr_alloc_size = rounddown_pow_of_two
+                                                            (curr_alloc_size);
+                               else
+                                       curr_alloc_size = curr_alloc_size / 2;
+                       } else {
+                               mem_arr->bus_address.u.
+                                   a64.address = (__u64) bus_add;
+                               mem_arr->size = curr_alloc_size;
+                               alloc_size -= curr_alloc_size;
+                               curr_alloc_size = min(be_max_phys_size *
+                                                     1024, alloc_size);
+                               j++;
+                               mem_arr++;
+                       }
+               } while (alloc_size);
+               mem_descr->num_elements = j;
+               mem_descr->size_in_bytes = phba->mem_req[i];
+               mem_descr->mem_array = kmalloc(sizeof(*mem_arr) * j,
+                                              GFP_KERNEL);
+               if (!mem_descr->mem_array)
+                       goto free_mem;
+
+               memcpy(mem_descr->mem_array, mem_arr_orig,
+                      sizeof(struct mem_array) * j);
+               mem_descr++;
+       }
+       kfree(mem_arr_orig);
+       return 0;
+free_mem:
+       mem_descr->num_elements = j;
+       while ((i) || (j)) {
+               for (j = mem_descr->num_elements; j > 0; j--) {
+                       pci_free_consistent(phba->pcidev,
+                                           mem_descr->mem_array[j - 1].size,
+                                           mem_descr->mem_array[j - 1].
+                                           virtual_address,
+                                           mem_descr->mem_array[j - 1].
+                                           bus_address.u.a64.address);
+               }
+               if (i) {
+                       i--;
+                       kfree(mem_descr->mem_array);
+                       mem_descr--;
+               }
+       }
+       kfree(mem_arr_orig);
+       kfree(phba->init_mem);
+       kfree(phba->phwi_ctrlr);
+       return -ENOMEM;
+}
+
+static int beiscsi_get_memory(struct beiscsi_hba *phba)
+{
+       beiscsi_find_mem_req(phba);
+       return beiscsi_alloc_mem(phba);
+}
+
+static void iscsi_init_global_templates(struct beiscsi_hba *phba)
+{
+       struct pdu_data_out *pdata_out;
+       struct pdu_nop_out *pnop_out;
+       struct be_mem_descriptor *mem_descr;
+
+       mem_descr = phba->init_mem;
+       mem_descr += ISCSI_MEM_GLOBAL_HEADER;
+       pdata_out =
+           (struct pdu_data_out *)mem_descr->mem_array[0].virtual_address;
+       memset(pdata_out, 0, BE_ISCSI_PDU_HEADER_SIZE);
+
+       AMAP_SET_BITS(struct amap_pdu_data_out, opcode, pdata_out,
+                     IIOC_SCSI_DATA);
+
+       pnop_out =
+           (struct pdu_nop_out *)((unsigned char *)mem_descr->mem_array[0].
+                                  virtual_address + BE_ISCSI_PDU_HEADER_SIZE);
+
+       memset(pnop_out, 0, BE_ISCSI_PDU_HEADER_SIZE);
+       AMAP_SET_BITS(struct amap_pdu_nop_out, ttt, pnop_out, 0xFFFFFFFF);
+       AMAP_SET_BITS(struct amap_pdu_nop_out, f_bit, pnop_out, 1);
+       AMAP_SET_BITS(struct amap_pdu_nop_out, i_bit, pnop_out, 0);
+}
+
+static void beiscsi_init_wrb_handle(struct beiscsi_hba *phba)
+{
+       struct be_mem_descriptor *mem_descr_wrbh, *mem_descr_wrb;
+       struct wrb_handle *pwrb_handle;
+       struct hwi_controller *phwi_ctrlr;
+       struct hwi_wrb_context *pwrb_context;
+       struct iscsi_wrb *pwrb;
+       unsigned int num_cxn_wrbh;
+       unsigned int num_cxn_wrb, j, idx, index;
+
+       mem_descr_wrbh = phba->init_mem;
+       mem_descr_wrbh += HWI_MEM_WRBH;
+
+       mem_descr_wrb = phba->init_mem;
+       mem_descr_wrb += HWI_MEM_WRB;
+
+       idx = 0;
+       pwrb_handle = mem_descr_wrbh->mem_array[idx].virtual_address;
+       num_cxn_wrbh = ((mem_descr_wrbh->mem_array[idx].size) /
+                       ((sizeof(struct wrb_handle)) *
+                        phba->params.wrbs_per_cxn));
+       phwi_ctrlr = phba->phwi_ctrlr;
+
+       for (index = 0; index < phba->params.cxns_per_ctrl * 2; index += 2) {
+               pwrb_context = &phwi_ctrlr->wrb_context[index];
+               SE_DEBUG(DBG_LVL_8, "cid=%d pwrb_context=%p \n", index,
+                                               pwrb_context);
+               pwrb_context->pwrb_handle_base =
+                               kzalloc(sizeof(struct wrb_handle *) *
+                                       phba->params.wrbs_per_cxn, GFP_KERNEL);
+               pwrb_context->pwrb_handle_basestd =
+                               kzalloc(sizeof(struct wrb_handle *) *
+                                       phba->params.wrbs_per_cxn, GFP_KERNEL);
+               if (num_cxn_wrbh) {
+                       pwrb_context->alloc_index = 0;
+                       pwrb_context->wrb_handles_available = 0;
+                       for (j = 0; j < phba->params.wrbs_per_cxn; j++) {
+                               pwrb_context->pwrb_handle_base[j] = pwrb_handle;
+                               pwrb_context->pwrb_handle_basestd[j] =
+                                                               pwrb_handle;
+                               pwrb_context->wrb_handles_available++;
+                               pwrb_handle++;
+                       }
+                       pwrb_context->free_index = 0;
+                       num_cxn_wrbh--;
+               } else {
+                       idx++;
+                       pwrb_handle =
+                           mem_descr_wrbh->mem_array[idx].virtual_address;
+                       num_cxn_wrbh =
+                           ((mem_descr_wrbh->mem_array[idx].size) /
+                            ((sizeof(struct wrb_handle)) *
+                             phba->params.wrbs_per_cxn));
+                       pwrb_context->alloc_index = 0;
+                       for (j = 0; j < phba->params.wrbs_per_cxn; j++) {
+                               pwrb_context->pwrb_handle_base[j] = pwrb_handle;
+                               pwrb_context->pwrb_handle_basestd[j] =
+                                   pwrb_handle;
+                               pwrb_context->wrb_handles_available++;
+                               pwrb_handle++;
+                       }
+                       pwrb_context->free_index = 0;
+                       num_cxn_wrbh--;
+               }
+       }
+       idx = 0;
+       pwrb = mem_descr_wrb->mem_array[idx].virtual_address;
+       num_cxn_wrb =
+           ((mem_descr_wrb->mem_array[idx].size) / (sizeof(struct iscsi_wrb)) *
+            phba->params.wrbs_per_cxn);
+
+       for (index = 0; index < phba->params.cxns_per_ctrl; index += 2) {
+               pwrb_context = &phwi_ctrlr->wrb_context[index];
+               if (num_cxn_wrb) {
+                       for (j = 0; j < phba->params.wrbs_per_cxn; j++) {
+                               pwrb_handle = pwrb_context->pwrb_handle_base[j];
+                               pwrb_handle->pwrb = pwrb;
+                               pwrb++;
+                       }
+                       num_cxn_wrb--;
+               } else {
+                       idx++;
+                       pwrb = mem_descr_wrb->mem_array[idx].virtual_address;
+                       num_cxn_wrb = ((mem_descr_wrb->mem_array[idx].size) /
+                                       (sizeof(struct iscsi_wrb)) *
+                                       phba->params.wrbs_per_cxn);
+                       for (j = 0; j < phba->params.wrbs_per_cxn; j++) {
+                               pwrb_handle = pwrb_context->pwrb_handle_base[j];
+                               pwrb_handle->pwrb = pwrb;
+                               pwrb++;
+                       }
+                       num_cxn_wrb--;
+               }
+       }
+}
+
+static void hwi_init_async_pdu_ctx(struct beiscsi_hba *phba)
+{
+       struct hwi_controller *phwi_ctrlr;
+       struct hba_parameters *p = &phba->params;
+       struct hwi_async_pdu_context *pasync_ctx;
+       struct async_pdu_handle *pasync_header_h, *pasync_data_h;
+       unsigned int index;
+       struct be_mem_descriptor *mem_descr;
+
+       mem_descr = (struct be_mem_descriptor *)phba->init_mem;
+       mem_descr += HWI_MEM_ASYNC_PDU_CONTEXT;
+
+       phwi_ctrlr = phba->phwi_ctrlr;
+       phwi_ctrlr->phwi_ctxt->pasync_ctx = (struct hwi_async_pdu_context *)
+                               mem_descr->mem_array[0].virtual_address;
+       pasync_ctx = phwi_ctrlr->phwi_ctxt->pasync_ctx;
+       memset(pasync_ctx, 0, sizeof(*pasync_ctx));
+
+       pasync_ctx->async_header.num_entries = p->asyncpdus_per_ctrl;
+       pasync_ctx->async_header.buffer_size = p->defpdu_hdr_sz;
+       pasync_ctx->async_data.buffer_size = p->defpdu_data_sz;
+       pasync_ctx->async_data.num_entries = p->asyncpdus_per_ctrl;
+
+       mem_descr = (struct be_mem_descriptor *)phba->init_mem;
+       mem_descr += HWI_MEM_ASYNC_HEADER_BUF;
+       if (mem_descr->mem_array[0].virtual_address) {
+               SE_DEBUG(DBG_LVL_8,
+                        "hwi_init_async_pdu_ctx HWI_MEM_ASYNC_HEADER_BUF"
+                        "va=%p \n", mem_descr->mem_array[0].virtual_address);
+       } else
+               shost_printk(KERN_WARNING, phba->shost,
+                            "No Virtual address \n");
+
+       pasync_ctx->async_header.va_base =
+                       mem_descr->mem_array[0].virtual_address;
+
+       pasync_ctx->async_header.pa_base.u.a64.address =
+                       mem_descr->mem_array[0].bus_address.u.a64.address;
+
+       mem_descr = (struct be_mem_descriptor *)phba->init_mem;
+       mem_descr += HWI_MEM_ASYNC_HEADER_RING;
+       if (mem_descr->mem_array[0].virtual_address) {
+               SE_DEBUG(DBG_LVL_8,
+                        "hwi_init_async_pdu_ctx HWI_MEM_ASYNC_HEADER_RING"
+                        "va=%p \n", mem_descr->mem_array[0].virtual_address);
+       } else
+               shost_printk(KERN_WARNING, phba->shost,
+                           "No Virtual address \n");
+       pasync_ctx->async_header.ring_base =
+                       mem_descr->mem_array[0].virtual_address;
+
+       mem_descr = (struct be_mem_descriptor *)phba->init_mem;
+       mem_descr += HWI_MEM_ASYNC_HEADER_HANDLE;
+       if (mem_descr->mem_array[0].virtual_address) {
+               SE_DEBUG(DBG_LVL_8,
+                        "hwi_init_async_pdu_ctx HWI_MEM_ASYNC_HEADER_HANDLE"
+                        "va=%p \n", mem_descr->mem_array[0].virtual_address);
+       } else
+               shost_printk(KERN_WARNING, phba->shost,
+                           "No Virtual address \n");
+
+       pasync_ctx->async_header.handle_base =
+                       mem_descr->mem_array[0].virtual_address;
+       pasync_ctx->async_header.writables = 0;
+       INIT_LIST_HEAD(&pasync_ctx->async_header.free_list);
+
+       mem_descr = (struct be_mem_descriptor *)phba->init_mem;
+       mem_descr += HWI_MEM_ASYNC_DATA_BUF;
+       if (mem_descr->mem_array[0].virtual_address) {
+               SE_DEBUG(DBG_LVL_8,
+                        "hwi_init_async_pdu_ctx HWI_MEM_ASYNC_DATA_BUF"
+                        "va=%p \n", mem_descr->mem_array[0].virtual_address);
+       } else
+               shost_printk(KERN_WARNING, phba->shost,
+                           "No Virtual address \n");
+       pasync_ctx->async_data.va_base =
+                       mem_descr->mem_array[0].virtual_address;
+       pasync_ctx->async_data.pa_base.u.a64.address =
+                       mem_descr->mem_array[0].bus_address.u.a64.address;
+
+       mem_descr = (struct be_mem_descriptor *)phba->init_mem;
+       mem_descr += HWI_MEM_ASYNC_DATA_RING;
+       if (mem_descr->mem_array[0].virtual_address) {
+               SE_DEBUG(DBG_LVL_8,
+                        "hwi_init_async_pdu_ctx HWI_MEM_ASYNC_DATA_RING"
+                        "va=%p \n", mem_descr->mem_array[0].virtual_address);
+       } else
+               shost_printk(KERN_WARNING, phba->shost,
+                            "No Virtual address \n");
+
+       pasync_ctx->async_data.ring_base =
+                       mem_descr->mem_array[0].virtual_address;
+
+       mem_descr = (struct be_mem_descriptor *)phba->init_mem;
+       mem_descr += HWI_MEM_ASYNC_DATA_HANDLE;
+       if (!mem_descr->mem_array[0].virtual_address)
+               shost_printk(KERN_WARNING, phba->shost,
+                           "No Virtual address \n");
+
+       pasync_ctx->async_data.handle_base =
+                       mem_descr->mem_array[0].virtual_address;
+       pasync_ctx->async_data.writables = 0;
+       INIT_LIST_HEAD(&pasync_ctx->async_data.free_list);
+
+       pasync_header_h =
+               (struct async_pdu_handle *)pasync_ctx->async_header.handle_base;
+       pasync_data_h =
+               (struct async_pdu_handle *)pasync_ctx->async_data.handle_base;
+
+       for (index = 0; index < p->asyncpdus_per_ctrl; index++) {
+               pasync_header_h->cri = -1;
+               pasync_header_h->index = (char)index;
+               INIT_LIST_HEAD(&pasync_header_h->link);
+               pasync_header_h->pbuffer =
+                       (void *)((unsigned long)
+                       (pasync_ctx->async_header.va_base) +
+                       (p->defpdu_hdr_sz * index));
+
+               pasync_header_h->pa.u.a64.address =
+                       pasync_ctx->async_header.pa_base.u.a64.address +
+                       (p->defpdu_hdr_sz * index);
+
+               list_add_tail(&pasync_header_h->link,
+                               &pasync_ctx->async_header.free_list);
+               pasync_header_h++;
+               pasync_ctx->async_header.free_entries++;
+               pasync_ctx->async_header.writables++;
+
+               INIT_LIST_HEAD(&pasync_ctx->async_entry[index].wait_queue.list);
+               INIT_LIST_HEAD(&pasync_ctx->async_entry[index].
+                              header_busy_list);
+               pasync_data_h->cri = -1;
+               pasync_data_h->index = (char)index;
+               INIT_LIST_HEAD(&pasync_data_h->link);
+               pasync_data_h->pbuffer =
+                       (void *)((unsigned long)
+                       (pasync_ctx->async_data.va_base) +
+                       (p->defpdu_data_sz * index));
+
+               pasync_data_h->pa.u.a64.address =
+                   pasync_ctx->async_data.pa_base.u.a64.address +
+                   (p->defpdu_data_sz * index);
+
+               list_add_tail(&pasync_data_h->link,
+                             &pasync_ctx->async_data.free_list);
+               pasync_data_h++;
+               pasync_ctx->async_data.free_entries++;
+               pasync_ctx->async_data.writables++;
+
+               INIT_LIST_HEAD(&pasync_ctx->async_entry[index].data_busy_list);
+       }
+
+       pasync_ctx->async_header.host_write_ptr = 0;
+       pasync_ctx->async_header.ep_read_ptr = -1;
+       pasync_ctx->async_data.host_write_ptr = 0;
+       pasync_ctx->async_data.ep_read_ptr = -1;
+}
+
+static int
+be_sgl_create_contiguous(void *virtual_address,
+                        u64 physical_address, u32 length,
+                        struct be_dma_mem *sgl)
+{
+       WARN_ON(!virtual_address);
+       WARN_ON(!physical_address);
+       WARN_ON(!length > 0);
+       WARN_ON(!sgl);
+
+       sgl->va = virtual_address;
+       sgl->dma = physical_address;
+       sgl->size = length;
+
+       return 0;
+}
+
+static void be_sgl_destroy_contiguous(struct be_dma_mem *sgl)
+{
+       memset(sgl, 0, sizeof(*sgl));
+}
+
+static void
+hwi_build_be_sgl_arr(struct beiscsi_hba *phba,
+                    struct mem_array *pmem, struct be_dma_mem *sgl)
+{
+       if (sgl->va)
+               be_sgl_destroy_contiguous(sgl);
+
+       be_sgl_create_contiguous(pmem->virtual_address,
+                                pmem->bus_address.u.a64.address,
+                                pmem->size, sgl);
+}
+
+static void
+hwi_build_be_sgl_by_offset(struct beiscsi_hba *phba,
+                          struct mem_array *pmem, struct be_dma_mem *sgl)
+{
+       if (sgl->va)
+               be_sgl_destroy_contiguous(sgl);
+
+       be_sgl_create_contiguous((unsigned char *)pmem->virtual_address,
+                                pmem->bus_address.u.a64.address,
+                                pmem->size, sgl);
+}
+
+static int be_fill_queue(struct be_queue_info *q,
+               u16 len, u16 entry_size, void *vaddress)
+{
+       struct be_dma_mem *mem = &q->dma_mem;
+
+       memset(q, 0, sizeof(*q));
+       q->len = len;
+       q->entry_size = entry_size;
+       mem->size = len * entry_size;
+       mem->va = vaddress;
+       if (!mem->va)
+               return -ENOMEM;
+       memset(mem->va, 0, mem->size);
+       return 0;
+}
+
+static int beiscsi_create_eq(struct beiscsi_hba *phba,
+                            struct hwi_context_memory *phwi_context)
+{
+       unsigned int idx;
+       int ret;
+       struct be_queue_info *eq;
+       struct be_dma_mem *mem;
+       struct be_mem_descriptor *mem_descr;
+       void *eq_vaddress;
+
+       idx = 0;
+       eq = &phwi_context->be_eq.q;
+       mem = &eq->dma_mem;
+       mem_descr = phba->init_mem;
+       mem_descr += HWI_MEM_EQ;
+       eq_vaddress = mem_descr->mem_array[idx].virtual_address;
+
+       ret = be_fill_queue(eq, phba->params.num_eq_entries,
+                           sizeof(struct be_eq_entry), eq_vaddress);
+       if (ret) {
+               shost_printk(KERN_ERR, phba->shost,
+                            "be_fill_queue Failed for EQ \n");
+               return ret;
+       }
+
+       mem->dma = mem_descr->mem_array[idx].bus_address.u.a64.address;
+
+       ret = beiscsi_cmd_eq_create(&phba->ctrl, eq,
+                                   phwi_context->be_eq.cur_eqd);
+       if (ret) {
+               shost_printk(KERN_ERR, phba->shost, "beiscsi_cmd_eq_create"
+                            "Failedfor EQ \n");
+               return ret;
+       }
+       SE_DEBUG(DBG_LVL_8, "eq id is %d\n", phwi_context->be_eq.q.id);
+       return 0;
+}
+
+static int beiscsi_create_cq(struct beiscsi_hba *phba,
+                            struct hwi_context_memory *phwi_context)
+{
+       unsigned int idx;
+       int ret;
+       struct be_queue_info *cq, *eq;
+       struct be_dma_mem *mem;
+       struct be_mem_descriptor *mem_descr;
+       void *cq_vaddress;
+
+       idx = 0;
+       cq = &phwi_context->be_cq;
+       eq = &phwi_context->be_eq.q;
+       mem = &cq->dma_mem;
+       mem_descr = phba->init_mem;
+       mem_descr += HWI_MEM_CQ;
+       cq_vaddress = mem_descr->mem_array[idx].virtual_address;
+       ret = be_fill_queue(cq, phba->params.icds_per_ctrl / 2,
+                           sizeof(struct sol_cqe), cq_vaddress);
+       if (ret) {
+               shost_printk(KERN_ERR, phba->shost,
+                            "be_fill_queue Failed for ISCSI CQ \n");
+               return ret;
+       }
+
+       mem->dma = mem_descr->mem_array[idx].bus_address.u.a64.address;
+       ret = beiscsi_cmd_cq_create(&phba->ctrl, cq, eq, false, false, 0);
+       if (ret) {
+               shost_printk(KERN_ERR, phba->shost,
+                            "beiscsi_cmd_eq_create Failed for ISCSI CQ \n");
+               return ret;
+       }
+       SE_DEBUG(DBG_LVL_8, "iscsi cq id is %d\n", phwi_context->be_cq.id);
+       SE_DEBUG(DBG_LVL_8, "ISCSI CQ CREATED\n");
+       return 0;
+}
+
+static int
+beiscsi_create_def_hdr(struct beiscsi_hba *phba,
+                      struct hwi_context_memory *phwi_context,
+                      struct hwi_controller *phwi_ctrlr,
+                      unsigned int def_pdu_ring_sz)
+{
+       unsigned int idx;
+       int ret;
+       struct be_queue_info *dq, *cq;
+       struct be_dma_mem *mem;
+       struct be_mem_descriptor *mem_descr;
+       void *dq_vaddress;
+
+       idx = 0;
+       dq = &phwi_context->be_def_hdrq;
+       cq = &phwi_context->be_cq;
+       mem = &dq->dma_mem;
+       mem_descr = phba->init_mem;
+       mem_descr += HWI_MEM_ASYNC_HEADER_RING;
+       dq_vaddress = mem_descr->mem_array[idx].virtual_address;
+       ret = be_fill_queue(dq, mem_descr->mem_array[0].size /
+                           sizeof(struct phys_addr),
+                           sizeof(struct phys_addr), dq_vaddress);
+       if (ret) {
+               shost_printk(KERN_ERR, phba->shost,
+                            "be_fill_queue Failed for DEF PDU HDR\n");
+               return ret;
+       }
+       mem->dma = mem_descr->mem_array[idx].bus_address.u.a64.address;
+       ret = be_cmd_create_default_pdu_queue(&phba->ctrl, cq, dq,
+                                             def_pdu_ring_sz,
+                                             phba->params.defpdu_hdr_sz);
+       if (ret) {
+               shost_printk(KERN_ERR, phba->shost,
+                            "be_cmd_create_default_pdu_queue Failed DEFHDR\n");
+               return ret;
+       }
+       phwi_ctrlr->default_pdu_hdr.id = phwi_context->be_def_hdrq.id;
+       SE_DEBUG(DBG_LVL_8, "iscsi def pdu id is %d\n",
+                phwi_context->be_def_hdrq.id);
+       hwi_post_async_buffers(phba, 1);
+       return 0;
+}
+
+static int
+beiscsi_create_def_data(struct beiscsi_hba *phba,
+                       struct hwi_context_memory *phwi_context,
+                       struct hwi_controller *phwi_ctrlr,
+                       unsigned int def_pdu_ring_sz)
+{
+       unsigned int idx;
+       int ret;
+       struct be_queue_info *dataq, *cq;
+       struct be_dma_mem *mem;
+       struct be_mem_descriptor *mem_descr;
+       void *dq_vaddress;
+
+       idx = 0;
+       dataq = &phwi_context->be_def_dataq;
+       cq = &phwi_context->be_cq;
+       mem = &dataq->dma_mem;
+       mem_descr = phba->init_mem;
+       mem_descr += HWI_MEM_ASYNC_DATA_RING;
+       dq_vaddress = mem_descr->mem_array[idx].virtual_address;
+       ret = be_fill_queue(dataq, mem_descr->mem_array[0].size /
+                           sizeof(struct phys_addr),
+                           sizeof(struct phys_addr), dq_vaddress);
+       if (ret) {
+               shost_printk(KERN_ERR, phba->shost,
+                            "be_fill_queue Failed for DEF PDU DATA\n");
+               return ret;
+       }
+       mem->dma = mem_descr->mem_array[idx].bus_address.u.a64.address;
+       ret = be_cmd_create_default_pdu_queue(&phba->ctrl, cq, dataq,
+                                             def_pdu_ring_sz,
+                                             phba->params.defpdu_data_sz);
+       if (ret) {
+               shost_printk(KERN_ERR, phba->shost,
+                            "be_cmd_create_default_pdu_queue Failed"
+                            " for DEF PDU DATA\n");
+               return ret;
+       }
+       phwi_ctrlr->default_pdu_data.id = phwi_context->be_def_dataq.id;
+       SE_DEBUG(DBG_LVL_8, "iscsi def data id is %d\n",
+                phwi_context->be_def_dataq.id);
+       hwi_post_async_buffers(phba, 0);
+       SE_DEBUG(DBG_LVL_8, "DEFAULT PDU DATA RING CREATED \n");
+       return 0;
+}
+
+static int
+beiscsi_post_pages(struct beiscsi_hba *phba)
+{
+       struct be_mem_descriptor *mem_descr;
+       struct mem_array *pm_arr;
+       unsigned int page_offset, i;
+       struct be_dma_mem sgl;
+       int status;
+
+       mem_descr = phba->init_mem;
+       mem_descr += HWI_MEM_SGE;
+       pm_arr = mem_descr->mem_array;
+
+       page_offset = (sizeof(struct iscsi_sge) * phba->params.num_sge_per_io *
+                       phba->fw_config.iscsi_icd_start) / PAGE_SIZE;
+       for (i = 0; i < mem_descr->num_elements; i++) {
+               hwi_build_be_sgl_arr(phba, pm_arr, &sgl);
+               status = be_cmd_iscsi_post_sgl_pages(&phba->ctrl, &sgl,
+                                               page_offset,
+                                               (pm_arr->size / PAGE_SIZE));
+               page_offset += pm_arr->size / PAGE_SIZE;
+               if (status != 0) {
+                       shost_printk(KERN_ERR, phba->shost,
+                                    "post sgl failed.\n");
+                       return status;
+               }
+               pm_arr++;
+       }
+       SE_DEBUG(DBG_LVL_8, "POSTED PAGES \n");
+       return 0;
+}
+
+static int
+beiscsi_create_wrb_rings(struct beiscsi_hba *phba,
+                        struct hwi_context_memory *phwi_context,
+                        struct hwi_controller *phwi_ctrlr)
+{
+       unsigned int wrb_mem_index, offset, size, num_wrb_rings;
+       u64 pa_addr_lo;
+       unsigned int idx, num, i;
+       struct mem_array *pwrb_arr;
+       void *wrb_vaddr;
+       struct be_dma_mem sgl;
+       struct be_mem_descriptor *mem_descr;
+       int status;
+
+       idx = 0;
+       mem_descr = phba->init_mem;
+       mem_descr += HWI_MEM_WRB;
+       pwrb_arr = kmalloc(sizeof(*pwrb_arr) * phba->params.cxns_per_ctrl,
+                          GFP_KERNEL);
+       if (!pwrb_arr) {
+               shost_printk(KERN_ERR, phba->shost,
+                            "Memory alloc failed in create wrb ring.\n");
+               return -ENOMEM;
+       }
+       wrb_vaddr = mem_descr->mem_array[idx].virtual_address;
+       pa_addr_lo = mem_descr->mem_array[idx].bus_address.u.a64.address;
+       num_wrb_rings = mem_descr->mem_array[idx].size /
+               (phba->params.wrbs_per_cxn * sizeof(struct iscsi_wrb));
+
+       for (num = 0; num < phba->params.cxns_per_ctrl; num++) {
+               if (num_wrb_rings) {
+                       pwrb_arr[num].virtual_address = wrb_vaddr;
+                       pwrb_arr[num].bus_address.u.a64.address = pa_addr_lo;
+                       pwrb_arr[num].size = phba->params.wrbs_per_cxn *
+                                           sizeof(struct iscsi_wrb);
+                       wrb_vaddr += pwrb_arr[num].size;
+                       pa_addr_lo += pwrb_arr[num].size;
+                       num_wrb_rings--;
+               } else {
+                       idx++;
+                       wrb_vaddr = mem_descr->mem_array[idx].virtual_address;
+                       pa_addr_lo = mem_descr->mem_array[idx].\
+                                       bus_address.u.a64.address;
+                       num_wrb_rings = mem_descr->mem_array[idx].size /
+                                       (phba->params.wrbs_per_cxn *
+                                       sizeof(struct iscsi_wrb));
+                       pwrb_arr[num].virtual_address = wrb_vaddr;
+                       pwrb_arr[num].bus_address.u.a64.address\
+                                               = pa_addr_lo;
+                       pwrb_arr[num].size = phba->params.wrbs_per_cxn *
+                                                sizeof(struct iscsi_wrb);
+                       wrb_vaddr += pwrb_arr[num].size;
+                       pa_addr_lo   += pwrb_arr[num].size;
+                       num_wrb_rings--;
+               }
+       }
+       for (i = 0; i < phba->params.cxns_per_ctrl; i++) {
+               wrb_mem_index = 0;
+               offset = 0;
+               size = 0;
+
+               hwi_build_be_sgl_by_offset(phba, &pwrb_arr[i], &sgl);
+               status = be_cmd_wrbq_create(&phba->ctrl, &sgl,
+                                           &phwi_context->be_wrbq[i]);
+               if (status != 0) {
+                       shost_printk(KERN_ERR, phba->shost,
+                                    "wrbq create failed.");
+                       return status;
+               }
+               phwi_ctrlr->wrb_context[i].cid = phwi_context->be_wrbq[i].id;
+       }
+       kfree(pwrb_arr);
+       return 0;
+}
+
+static void free_wrb_handles(struct beiscsi_hba *phba)
+{
+       unsigned int index;
+       struct hwi_controller *phwi_ctrlr;
+       struct hwi_wrb_context *pwrb_context;
+
+       phwi_ctrlr = phba->phwi_ctrlr;
+       for (index = 0; index < phba->params.cxns_per_ctrl * 2; index += 2) {
+               pwrb_context = &phwi_ctrlr->wrb_context[index];
+               kfree(pwrb_context->pwrb_handle_base);
+               kfree(pwrb_context->pwrb_handle_basestd);
+       }
+}
+
+static void hwi_cleanup(struct beiscsi_hba *phba)
+{
+       struct be_queue_info *q;
+       struct be_ctrl_info *ctrl = &phba->ctrl;
+       struct hwi_controller *phwi_ctrlr;
+       struct hwi_context_memory *phwi_context;
+       int i;
+
+       phwi_ctrlr = phba->phwi_ctrlr;
+       phwi_context = phwi_ctrlr->phwi_ctxt;
+       for (i = 0; i < phba->params.cxns_per_ctrl; i++) {
+               q = &phwi_context->be_wrbq[i];
+               if (q->created)
+                       beiscsi_cmd_q_destroy(ctrl, q, QTYPE_WRBQ);
+       }
+
+       free_wrb_handles(phba);
+
+       q = &phwi_context->be_def_hdrq;
+       if (q->created)
+               beiscsi_cmd_q_destroy(ctrl, q, QTYPE_DPDUQ);
+
+       q = &phwi_context->be_def_dataq;
+       if (q->created)
+               beiscsi_cmd_q_destroy(ctrl, q, QTYPE_DPDUQ);
+
+       beiscsi_cmd_q_destroy(ctrl, NULL, QTYPE_SGL);
+
+       q = &phwi_context->be_cq;
+       if (q->created)
+               beiscsi_cmd_q_destroy(ctrl, q, QTYPE_CQ);
+
+       q = &phwi_context->be_eq.q;
+       if (q->created)
+               beiscsi_cmd_q_destroy(ctrl, q, QTYPE_EQ);
+}
+
+static int hwi_init_port(struct beiscsi_hba *phba)
+{
+       struct hwi_controller *phwi_ctrlr;
+       struct hwi_context_memory *phwi_context;
+       unsigned int def_pdu_ring_sz;
+       struct be_ctrl_info *ctrl = &phba->ctrl;
+       int status;
+
+       def_pdu_ring_sz =
+               phba->params.asyncpdus_per_ctrl * sizeof(struct phys_addr);
+       phwi_ctrlr = phba->phwi_ctrlr;
+
+       phwi_context = phwi_ctrlr->phwi_ctxt;
+       phwi_context->be_eq.max_eqd = 0;
+       phwi_context->be_eq.min_eqd = 0;
+       phwi_context->be_eq.cur_eqd = 64;
+       phwi_context->be_eq.enable_aic = false;
+       be_cmd_fw_initialize(&phba->ctrl);
+       status = beiscsi_create_eq(phba, phwi_context);
+       if (status != 0) {
+               shost_printk(KERN_ERR, phba->shost, "EQ not created \n");
+               goto error;
+       }
+
+       status = mgmt_check_supported_fw(ctrl);
+       if (status != 0) {
+               shost_printk(KERN_ERR, phba->shost,
+                            "Unsupported fw version \n");
+               goto error;
+       }
+
+       status = mgmt_get_fw_config(ctrl, phba);
+       if (status != 0) {
+               shost_printk(KERN_ERR, phba->shost,
+                            "Error getting fw config\n");
+               goto error;
+       }
+
+       status = beiscsi_create_cq(phba, phwi_context);
+       if (status != 0) {
+               shost_printk(KERN_ERR, phba->shost, "CQ not created\n");
+               goto error;
+       }
+
+       status = beiscsi_create_def_hdr(phba, phwi_context, phwi_ctrlr,
+                                       def_pdu_ring_sz);
+       if (status != 0) {
+               shost_printk(KERN_ERR, phba->shost,
+                            "Default Header not created\n");
+               goto error;
+       }
+
+       status = beiscsi_create_def_data(phba, phwi_context,
+                                        phwi_ctrlr, def_pdu_ring_sz);
+       if (status != 0) {
+               shost_printk(KERN_ERR, phba->shost,
+                            "Default Data not created\n");
+               goto error;
+       }
+
+       status = beiscsi_post_pages(phba);
+       if (status != 0) {
+               shost_printk(KERN_ERR, phba->shost, "Post SGL Pages Failed\n");
+               goto error;
+       }
+
+       status = beiscsi_create_wrb_rings(phba, phwi_context, phwi_ctrlr);
+       if (status != 0) {
+               shost_printk(KERN_ERR, phba->shost,
+                            "WRB Rings not created\n");
+               goto error;
+       }
+
+       SE_DEBUG(DBG_LVL_8, "hwi_init_port success\n");
+       return 0;
+
+error:
+       shost_printk(KERN_ERR, phba->shost, "hwi_init_port failed");
+       hwi_cleanup(phba);
+       return -ENOMEM;
+}
+
+
+static int hwi_init_controller(struct beiscsi_hba *phba)
+{
+       struct hwi_controller *phwi_ctrlr;
+
+       phwi_ctrlr = phba->phwi_ctrlr;
+       if (1 == phba->init_mem[HWI_MEM_ADDN_CONTEXT].num_elements) {
+               phwi_ctrlr->phwi_ctxt = (struct hwi_context_memory *)phba->
+                   init_mem[HWI_MEM_ADDN_CONTEXT].mem_array[0].virtual_address;
+               SE_DEBUG(DBG_LVL_8, " phwi_ctrlr->phwi_ctxt=%p \n",
+                        phwi_ctrlr->phwi_ctxt);
+       } else {
+               shost_printk(KERN_ERR, phba->shost,
+                            "HWI_MEM_ADDN_CONTEXT is more than one element."
+                            "Failing to load\n");
+               return -ENOMEM;
+       }
+
+       iscsi_init_global_templates(phba);
+       beiscsi_init_wrb_handle(phba);
+       hwi_init_async_pdu_ctx(phba);
+       if (hwi_init_port(phba) != 0) {
+               shost_printk(KERN_ERR, phba->shost,
+                            "hwi_init_controller failed\n");
+               return -ENOMEM;
+       }
+       return 0;
+}
+
+static void beiscsi_free_mem(struct beiscsi_hba *phba)
+{
+       struct be_mem_descriptor *mem_descr;
+       int i, j;
+
+       mem_descr = phba->init_mem;
+       i = 0;
+       j = 0;
+       for (i = 0; i < SE_MEM_MAX; i++) {
+               for (j = mem_descr->num_elements; j > 0; j--) {
+                       pci_free_consistent(phba->pcidev,
+                         mem_descr->mem_array[j - 1].size,
+                         mem_descr->mem_array[j - 1].virtual_address,
+                         mem_descr->mem_array[j - 1].bus_address.
+                               u.a64.address);
+               }
+               kfree(mem_descr->mem_array);
+               mem_descr++;
+       }
+       kfree(phba->init_mem);
+       kfree(phba->phwi_ctrlr);
+}
+
+static int beiscsi_init_controller(struct beiscsi_hba *phba)
+{
+       int ret = -ENOMEM;
+
+       ret = beiscsi_get_memory(phba);
+       if (ret < 0) {
+               shost_printk(KERN_ERR, phba->shost, "beiscsi_dev_probe -"
+                            "Failed in beiscsi_alloc_memory \n");
+               return ret;
+       }
+
+       ret = hwi_init_controller(phba);
+       if (ret)
+               goto free_init;
+       SE_DEBUG(DBG_LVL_8, "Return success from beiscsi_init_controller");
+       return 0;
+
+free_init:
+       beiscsi_free_mem(phba);
+       return -ENOMEM;
+}
+
+static int beiscsi_init_sgl_handle(struct beiscsi_hba *phba)
+{
+       struct be_mem_descriptor *mem_descr_sglh, *mem_descr_sg;
+       struct sgl_handle *psgl_handle;
+       struct iscsi_sge *pfrag;
+       unsigned int arr_index, i, idx;
+
+       phba->io_sgl_hndl_avbl = 0;
+       phba->eh_sgl_hndl_avbl = 0;
+       mem_descr_sglh = phba->init_mem;
+       mem_descr_sglh += HWI_MEM_SGLH;
+       if (1 == mem_descr_sglh->num_elements) {
+               phba->io_sgl_hndl_base = kzalloc(sizeof(struct sgl_handle *) *
+                                                phba->params.ios_per_ctrl,
+                                                GFP_KERNEL);
+               if (!phba->io_sgl_hndl_base) {
+                       shost_printk(KERN_ERR, phba->shost,
+                                    "Mem Alloc Failed. Failing to load\n");
+                       return -ENOMEM;
+               }
+               phba->eh_sgl_hndl_base = kzalloc(sizeof(struct sgl_handle *) *
+                                                (phba->params.icds_per_ctrl -
+                                                phba->params.ios_per_ctrl),
+                                                GFP_KERNEL);
+               if (!phba->eh_sgl_hndl_base) {
+                       kfree(phba->io_sgl_hndl_base);
+                       shost_printk(KERN_ERR, phba->shost,
+                                    "Mem Alloc Failed. Failing to load\n");
+                       return -ENOMEM;
+               }
+       } else {
+               shost_printk(KERN_ERR, phba->shost,
+                            "HWI_MEM_SGLH is more than one element."
+                            "Failing to load\n");
+               return -ENOMEM;
+       }
+
+       arr_index = 0;
+       idx = 0;
+       while (idx < mem_descr_sglh->num_elements) {
+               psgl_handle = mem_descr_sglh->mem_array[idx].virtual_address;
+
+               for (i = 0; i < (mem_descr_sglh->mem_array[idx].size /
+                     sizeof(struct sgl_handle)); i++) {
+                       if (arr_index < phba->params.ios_per_ctrl) {
+                               phba->io_sgl_hndl_base[arr_index] = psgl_handle;
+                               phba->io_sgl_hndl_avbl++;
+                               arr_index++;
+                       } else {
+                               phba->eh_sgl_hndl_base[arr_index -
+                                       phba->params.ios_per_ctrl] =
+                                                               psgl_handle;
+                               arr_index++;
+                               phba->eh_sgl_hndl_avbl++;
+                       }
+                       psgl_handle++;
+               }
+               idx++;
+       }
+       SE_DEBUG(DBG_LVL_8,
+                "phba->io_sgl_hndl_avbl=%d"
+                "phba->eh_sgl_hndl_avbl=%d \n",
+                phba->io_sgl_hndl_avbl,
+                phba->eh_sgl_hndl_avbl);
+       mem_descr_sg = phba->init_mem;
+       mem_descr_sg += HWI_MEM_SGE;
+       SE_DEBUG(DBG_LVL_8, "\n mem_descr_sg->num_elements=%d \n",
+                mem_descr_sg->num_elements);
+       arr_index = 0;
+       idx = 0;
+       while (idx < mem_descr_sg->num_elements) {
+               pfrag = mem_descr_sg->mem_array[idx].virtual_address;
+
+               for (i = 0;
+                    i < (mem_descr_sg->mem_array[idx].size) /
+                    (sizeof(struct iscsi_sge) * phba->params.num_sge_per_io);
+                    i++) {
+                       if (arr_index < phba->params.ios_per_ctrl)
+                               psgl_handle = phba->io_sgl_hndl_base[arr_index];
+                       else
+                               psgl_handle = phba->eh_sgl_hndl_base[arr_index -
+                                               phba->params.ios_per_ctrl];
+                       psgl_handle->pfrag = pfrag;
+                       AMAP_SET_BITS(struct amap_iscsi_sge, addr_hi, pfrag, 0);
+                       AMAP_SET_BITS(struct amap_iscsi_sge, addr_lo, pfrag, 0);
+                       pfrag += phba->params.num_sge_per_io;
+                       psgl_handle->sgl_index =
+                               phba->fw_config.iscsi_cid_start + arr_index++;
+               }
+               idx++;
+       }
+       phba->io_sgl_free_index = 0;
+       phba->io_sgl_alloc_index = 0;
+       phba->eh_sgl_free_index = 0;
+       phba->eh_sgl_alloc_index = 0;
+       return 0;
+}
+
+static int hba_setup_cid_tbls(struct beiscsi_hba *phba)
+{
+       int i, new_cid;
+
+       phba->cid_array = kmalloc(sizeof(void *) * phba->params.cxns_per_ctrl,
+                                 GFP_KERNEL);
+       if (!phba->cid_array) {
+               shost_printk(KERN_ERR, phba->shost,
+                            "Failed to allocate memory in "
+                            "hba_setup_cid_tbls\n");
+               return -ENOMEM;
+       }
+       phba->ep_array = kmalloc(sizeof(struct iscsi_endpoint *) *
+                                phba->params.cxns_per_ctrl * 2, GFP_KERNEL);
+       if (!phba->ep_array) {
+               shost_printk(KERN_ERR, phba->shost,
+                            "Failed to allocate memory in "
+                            "hba_setup_cid_tbls \n");
+               kfree(phba->cid_array);
+               return -ENOMEM;
+       }
+       new_cid = phba->fw_config.iscsi_icd_start;
+       for (i = 0; i < phba->params.cxns_per_ctrl; i++) {
+               phba->cid_array[i] = new_cid;
+               new_cid += 2;
+       }
+       phba->avlbl_cids = phba->params.cxns_per_ctrl;
+       return 0;
+}
+
+static unsigned char hwi_enable_intr(struct beiscsi_hba *phba)
+{
+       struct be_ctrl_info *ctrl = &phba->ctrl;
+       struct hwi_controller *phwi_ctrlr;
+       struct hwi_context_memory *phwi_context;
+       struct be_queue_info *eq;
+       u8 __iomem *addr;
+       u32 reg;
+       u32 enabled;
+
+       phwi_ctrlr = phba->phwi_ctrlr;
+       phwi_context = phwi_ctrlr->phwi_ctxt;
+
+       eq = &phwi_context->be_eq.q;
+       addr = (u8 __iomem *) ((u8 __iomem *) ctrl->pcicfg +
+                       PCICFG_MEMBAR_CTRL_INT_CTRL_OFFSET);
+       reg = ioread32(addr);
+       SE_DEBUG(DBG_LVL_8, "reg =x%08x \n", reg);
+
+       enabled = reg & MEMBAR_CTRL_INT_CTRL_HOSTINTR_MASK;
+       if (!enabled) {
+               reg |= MEMBAR_CTRL_INT_CTRL_HOSTINTR_MASK;
+               SE_DEBUG(DBG_LVL_8, "reg =x%08x addr=%p \n", reg, addr);
+               iowrite32(reg, addr);
+               SE_DEBUG(DBG_LVL_8, "eq->id=%d \n", eq->id);
+
+               hwi_ring_eq_db(phba, eq->id, 0, 0, 1, 1);
+       } else
+               shost_printk(KERN_WARNING, phba->shost,
+                            "In hwi_enable_intr, Not Enabled \n");
+       return true;
+}
+
+static void hwi_disable_intr(struct beiscsi_hba *phba)
+{
+       struct be_ctrl_info *ctrl = &phba->ctrl;
+
+       u8 __iomem *addr = ctrl->pcicfg + PCICFG_MEMBAR_CTRL_INT_CTRL_OFFSET;
+       u32 reg = ioread32(addr);
+
+       u32 enabled = reg & MEMBAR_CTRL_INT_CTRL_HOSTINTR_MASK;
+       if (enabled) {
+               reg &= ~MEMBAR_CTRL_INT_CTRL_HOSTINTR_MASK;
+               iowrite32(reg, addr);
+       } else
+               shost_printk(KERN_WARNING, phba->shost,
+                            "In hwi_disable_intr, Already Disabled \n");
+}
+
+static int beiscsi_init_port(struct beiscsi_hba *phba)
+{
+       int ret;
+
+       ret = beiscsi_init_controller(phba);
+       if (ret < 0) {
+               shost_printk(KERN_ERR, phba->shost,
+                            "beiscsi_dev_probe - Failed in"
+                            "beiscsi_init_controller \n");
+               return ret;
+       }
+       ret = beiscsi_init_sgl_handle(phba);
+       if (ret < 0) {
+               shost_printk(KERN_ERR, phba->shost,
+                            "beiscsi_dev_probe - Failed in"
+                            "beiscsi_init_sgl_handle \n");
+               goto do_cleanup_ctrlr;
+       }
+
+       if (hba_setup_cid_tbls(phba)) {
+               shost_printk(KERN_ERR, phba->shost,
+                            "Failed in hba_setup_cid_tbls\n");
+               kfree(phba->io_sgl_hndl_base);
+               kfree(phba->eh_sgl_hndl_base);
+               goto do_cleanup_ctrlr;
+       }
+
+       return ret;
+
+do_cleanup_ctrlr:
+       hwi_cleanup(phba);
+       return ret;
+}
+
+static void hwi_purge_eq(struct beiscsi_hba *phba)
+{
+       struct hwi_controller *phwi_ctrlr;
+       struct hwi_context_memory *phwi_context;
+       struct be_queue_info *eq;
+       struct be_eq_entry *eqe = NULL;
+
+       phwi_ctrlr = phba->phwi_ctrlr;
+       phwi_context = phwi_ctrlr->phwi_ctxt;
+       eq = &phwi_context->be_eq.q;
+       eqe = queue_tail_node(eq);
+
+       while (eqe->dw[offsetof(struct amap_eq_entry, valid) / 32]
+                                               & EQE_VALID_MASK) {
+               AMAP_SET_BITS(struct amap_eq_entry, valid, eqe, 0);
+               queue_tail_inc(eq);
+               eqe = queue_tail_node(eq);
+       }
+}
+
+static void beiscsi_clean_port(struct beiscsi_hba *phba)
+{
+       unsigned char mgmt_status;
+
+       mgmt_status = mgmt_epfw_cleanup(phba, CMD_CONNECTION_CHUTE_0);
+       if (mgmt_status)
+               shost_printk(KERN_WARNING, phba->shost,
+                            "mgmt_epfw_cleanup FAILED \n");
+       hwi_cleanup(phba);
+       hwi_purge_eq(phba);
+       kfree(phba->io_sgl_hndl_base);
+       kfree(phba->eh_sgl_hndl_base);
+       kfree(phba->cid_array);
+       kfree(phba->ep_array);
+}
+
+void
+beiscsi_offload_connection(struct beiscsi_conn *beiscsi_conn,
+                          struct beiscsi_offload_params *params)
+{
+       struct wrb_handle *pwrb_handle;
+       struct iscsi_target_context_update_wrb *pwrb = NULL;
+       struct be_mem_descriptor *mem_descr;
+       struct beiscsi_hba *phba = beiscsi_conn->phba;
+       u32 doorbell = 0;
+
+       /*
+        * We can always use 0 here because it is reserved by libiscsi for
+        * login/startup related tasks.
+        */
+       pwrb_handle = alloc_wrb_handle(phba, beiscsi_conn->beiscsi_conn_cid, 0);
+       pwrb = (struct iscsi_target_context_update_wrb *)pwrb_handle->pwrb;
+       memset(pwrb, 0, sizeof(*pwrb));
+       AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb,
+                     max_burst_length, pwrb, params->dw[offsetof
+                     (struct amap_beiscsi_offload_params,
+                     max_burst_length) / 32]);
+       AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb,
+                     max_send_data_segment_length, pwrb,
+                     params->dw[offsetof(struct amap_beiscsi_offload_params,
+                     max_send_data_segment_length) / 32]);
+       AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb,
+                     first_burst_length,
+                     pwrb,
+                     params->dw[offsetof(struct amap_beiscsi_offload_params,
+                     first_burst_length) / 32]);
+
+       AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, erl, pwrb,
+                     (params->dw[offsetof(struct amap_beiscsi_offload_params,
+                     erl) / 32] & OFFLD_PARAMS_ERL));
+       AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, dde, pwrb,
+                     (params->dw[offsetof(struct amap_beiscsi_offload_params,
+                     dde) / 32] & OFFLD_PARAMS_DDE) >> 2);
+       AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, hde, pwrb,
+                     (params->dw[offsetof(struct amap_beiscsi_offload_params,
+                     hde) / 32] & OFFLD_PARAMS_HDE) >> 3);
+       AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, ir2t, pwrb,
+                     (params->dw[offsetof(struct amap_beiscsi_offload_params,
+                     ir2t) / 32] & OFFLD_PARAMS_IR2T) >> 4);
+       AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, imd, pwrb,
+                     (params->dw[offsetof(struct amap_beiscsi_offload_params,
+                      imd) / 32] & OFFLD_PARAMS_IMD) >> 5);
+       AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, stat_sn,
+                     pwrb,
+                     (params->dw[offsetof(struct amap_beiscsi_offload_params,
+                     exp_statsn) / 32] + 1));
+       AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, type, pwrb,
+                     0x7);
+       AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, wrb_idx,
+                     pwrb, pwrb_handle->wrb_index);
+       AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, ptr2nextwrb,
+                     pwrb, pwrb_handle->nxt_wrb_index);
+       AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb,
+                       session_state, pwrb, 0);
+       AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, compltonack,
+                     pwrb, 1);
+       AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, notpredblq,
+                     pwrb, 0);
+       AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, mode, pwrb,
+                     0);
+
+       mem_descr = phba->init_mem;
+       mem_descr += ISCSI_MEM_GLOBAL_HEADER;
+
+       AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb,
+                       pad_buffer_addr_hi, pwrb,
+                     mem_descr->mem_array[0].bus_address.u.a32.address_hi);
+       AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb,
+                       pad_buffer_addr_lo, pwrb,
+                     mem_descr->mem_array[0].bus_address.u.a32.address_lo);
+
+       be_dws_le_to_cpu(pwrb, sizeof(struct iscsi_target_context_update_wrb));
+
+       doorbell |= beiscsi_conn->beiscsi_conn_cid & DB_WRB_POST_CID_MASK;
+       doorbell |= (pwrb_handle->wrb_index & DB_DEF_PDU_WRB_INDEX_MASK) <<
+                                       DB_DEF_PDU_WRB_INDEX_SHIFT;
+       doorbell |= 1 << DB_DEF_PDU_NUM_POSTED_SHIFT;
+
+       iowrite32(doorbell, phba->db_va + DB_TXULP0_OFFSET);
+}
+
+static void beiscsi_parse_pdu(struct iscsi_conn *conn, itt_t itt,
+                             int *index, int *age)
+{
+       *index = be32_to_cpu(itt) >> 16;
+       if (age)
+               *age = conn->session->age;
+}
+
+/**
+ * beiscsi_alloc_pdu - allocates pdu and related resources
+ * @task: libiscsi task
+ * @opcode: opcode of pdu for task
+ *
+ * This is called with the session lock held. It will allocate
+ * the wrb and sgl if needed for the command. And it will prep
+ * the pdu's itt. beiscsi_parse_pdu will later translate
+ * the pdu itt to the libiscsi task itt.
+ */
+static int beiscsi_alloc_pdu(struct iscsi_task *task, uint8_t opcode)
+{
+       struct beiscsi_io_task *io_task = task->dd_data;
+       struct iscsi_conn *conn = task->conn;
+       struct beiscsi_conn *beiscsi_conn = conn->dd_data;
+       struct beiscsi_hba *phba = beiscsi_conn->phba;
+       struct hwi_wrb_context *pwrb_context;
+       struct hwi_controller *phwi_ctrlr;
+       itt_t itt;
+       struct beiscsi_session *beiscsi_sess = beiscsi_conn->beiscsi_sess;
+       dma_addr_t paddr;
+
+       io_task->cmd_bhs = pci_pool_alloc(beiscsi_sess->bhs_pool,
+                                         GFP_KERNEL, &paddr);
+
+       if (!io_task->cmd_bhs)
+               return -ENOMEM;
+
+       io_task->bhs_pa.u.a64.address = paddr;
+       io_task->pwrb_handle = alloc_wrb_handle(phba,
+                                               beiscsi_conn->beiscsi_conn_cid,
+                                               task->itt);
+       io_task->pwrb_handle->pio_handle = task;
+       io_task->conn = beiscsi_conn;
+
+       task->hdr = (struct iscsi_hdr *)&io_task->cmd_bhs->iscsi_hdr;
+       task->hdr_max = sizeof(struct be_cmd_bhs);
+
+       if (task->sc) {
+               spin_lock(&phba->io_sgl_lock);
+               io_task->psgl_handle = alloc_io_sgl_handle(phba);
+               spin_unlock(&phba->io_sgl_lock);
+               if (!io_task->psgl_handle)
+                       goto free_hndls;
+
+       } else {
+               io_task->scsi_cmnd = NULL;
+               if ((task->hdr->opcode & ISCSI_OPCODE_MASK) == ISCSI_OP_LOGIN) {
+                       if (!beiscsi_conn->login_in_progress) {
+                               spin_lock(&phba->mgmt_sgl_lock);
+                               io_task->psgl_handle = (struct sgl_handle *)
+                                               alloc_mgmt_sgl_handle(phba);
+                               spin_unlock(&phba->mgmt_sgl_lock);
+                               if (!io_task->psgl_handle)
+                                       goto free_hndls;
+
+                               beiscsi_conn->login_in_progress = 1;
+                               beiscsi_conn->plogin_sgl_handle =
+                                                       io_task->psgl_handle;
+                       } else {
+                               io_task->psgl_handle =
+                                               beiscsi_conn->plogin_sgl_handle;
+                       }
+               } else {
+                       spin_lock(&phba->mgmt_sgl_lock);
+                       io_task->psgl_handle = alloc_mgmt_sgl_handle(phba);
+                       spin_unlock(&phba->mgmt_sgl_lock);
+                       if (!io_task->psgl_handle)
+                               goto free_hndls;
+               }
+       }
+       itt = (itt_t) cpu_to_be32(((unsigned int)task->itt << 16) |
+                       (unsigned int)(io_task->psgl_handle->sgl_index));
+       io_task->cmd_bhs->iscsi_hdr.itt = itt;
+       return 0;
+
+free_hndls:
+       phwi_ctrlr = phba->phwi_ctrlr;
+       pwrb_context = &phwi_ctrlr->wrb_context[beiscsi_conn->beiscsi_conn_cid];
+       free_wrb_handle(phba, pwrb_context, io_task->pwrb_handle);
+       io_task->pwrb_handle = NULL;
+       pci_pool_free(beiscsi_sess->bhs_pool, io_task->cmd_bhs,
+                     io_task->bhs_pa.u.a64.address);
+       SE_DEBUG(DBG_LVL_1, "Alloc of SGL_ICD Failed \n");
+       return -ENOMEM;
+}
+
+static void beiscsi_cleanup_task(struct iscsi_task *task)
+{
+       struct beiscsi_io_task *io_task = task->dd_data;
+       struct iscsi_conn *conn = task->conn;
+       struct beiscsi_conn *beiscsi_conn = conn->dd_data;
+       struct beiscsi_hba *phba = beiscsi_conn->phba;
+       struct beiscsi_session *beiscsi_sess = beiscsi_conn->beiscsi_sess;
+       struct hwi_wrb_context *pwrb_context;
+       struct hwi_controller *phwi_ctrlr;
+
+       phwi_ctrlr = phba->phwi_ctrlr;
+       pwrb_context = &phwi_ctrlr->wrb_context[beiscsi_conn->beiscsi_conn_cid];
+       if (io_task->pwrb_handle) {
+               free_wrb_handle(phba, pwrb_context, io_task->pwrb_handle);
+               io_task->pwrb_handle = NULL;
+       }
+
+       if (io_task->cmd_bhs) {
+               pci_pool_free(beiscsi_sess->bhs_pool, io_task->cmd_bhs,
+                             io_task->bhs_pa.u.a64.address);
+       }
+
+       if (task->sc) {
+               if (io_task->psgl_handle) {
+                       spin_lock(&phba->io_sgl_lock);
+                       free_io_sgl_handle(phba, io_task->psgl_handle);
+                       spin_unlock(&phba->io_sgl_lock);
+                       io_task->psgl_handle = NULL;
+               }
+       } else {
+               if ((task->hdr->opcode & ISCSI_OPCODE_MASK) == ISCSI_OP_LOGIN)
+                       return;
+               if (io_task->psgl_handle) {
+                       spin_lock(&phba->mgmt_sgl_lock);
+                       free_mgmt_sgl_handle(phba, io_task->psgl_handle);
+                       spin_unlock(&phba->mgmt_sgl_lock);
+                       io_task->psgl_handle = NULL;
+               }
+       }
+}
+
+static int beiscsi_iotask(struct iscsi_task *task, struct scatterlist *sg,
+                         unsigned int num_sg, unsigned int xferlen,
+                         unsigned int writedir)
+{
+
+       struct beiscsi_io_task *io_task = task->dd_data;
+       struct iscsi_conn *conn = task->conn;
+       struct beiscsi_conn *beiscsi_conn = conn->dd_data;
+       struct beiscsi_hba *phba = beiscsi_conn->phba;
+       struct iscsi_wrb *pwrb = NULL;
+       unsigned int doorbell = 0;
+
+       pwrb = io_task->pwrb_handle->pwrb;
+       io_task->cmd_bhs->iscsi_hdr.exp_statsn = 0;
+       io_task->bhs_len = sizeof(struct be_cmd_bhs);
+
+       if (writedir) {
+               SE_DEBUG(DBG_LVL_4, " WRITE Command \t");
+               memset(&io_task->cmd_bhs->iscsi_data_pdu, 0, 48);
+               AMAP_SET_BITS(struct amap_pdu_data_out, itt,
+                             &io_task->cmd_bhs->iscsi_data_pdu,
+                             (unsigned int)io_task->cmd_bhs->iscsi_hdr.itt);
+               AMAP_SET_BITS(struct amap_pdu_data_out, opcode,
+                             &io_task->cmd_bhs->iscsi_data_pdu,
+                             ISCSI_OPCODE_SCSI_DATA_OUT);
+               AMAP_SET_BITS(struct amap_pdu_data_out, final_bit,
+                             &io_task->cmd_bhs->iscsi_data_pdu, 1);
+               AMAP_SET_BITS(struct amap_iscsi_wrb, type, pwrb, INI_WR_CMD);
+               AMAP_SET_BITS(struct amap_iscsi_wrb, dsp, pwrb, 1);
+       } else {
+               SE_DEBUG(DBG_LVL_4, "READ Command \t");
+               AMAP_SET_BITS(struct amap_iscsi_wrb, type, pwrb, INI_RD_CMD);
+               AMAP_SET_BITS(struct amap_iscsi_wrb, dsp, pwrb, 0);
+       }
+       memcpy(&io_task->cmd_bhs->iscsi_data_pdu.
+              dw[offsetof(struct amap_pdu_data_out, lun) / 32],
+              io_task->cmd_bhs->iscsi_hdr.lun, sizeof(struct scsi_lun));
+
+       AMAP_SET_BITS(struct amap_iscsi_wrb, lun, pwrb,
+                     cpu_to_be16((unsigned short)io_task->cmd_bhs->iscsi_hdr.
+                                 lun[0]));
+       AMAP_SET_BITS(struct amap_iscsi_wrb, r2t_exp_dtl, pwrb, xferlen);
+       AMAP_SET_BITS(struct amap_iscsi_wrb, wrb_idx, pwrb,
+                     io_task->pwrb_handle->wrb_index);
+       AMAP_SET_BITS(struct amap_iscsi_wrb, cmdsn_itt, pwrb,
+                     be32_to_cpu(task->cmdsn));
+       AMAP_SET_BITS(struct amap_iscsi_wrb, sgl_icd_idx, pwrb,
+                     io_task->psgl_handle->sgl_index);
+
+       hwi_write_sgl(pwrb, sg, num_sg, io_task);
+
+       AMAP_SET_BITS(struct amap_iscsi_wrb, ptr2nextwrb, pwrb,
+                     io_task->pwrb_handle->nxt_wrb_index);
+       be_dws_le_to_cpu(pwrb, sizeof(struct iscsi_wrb));
+
+       doorbell |= beiscsi_conn->beiscsi_conn_cid & DB_WRB_POST_CID_MASK;
+       doorbell |= (io_task->pwrb_handle->wrb_index &
+                    DB_DEF_PDU_WRB_INDEX_MASK) << DB_DEF_PDU_WRB_INDEX_SHIFT;
+       doorbell |= 1 << DB_DEF_PDU_NUM_POSTED_SHIFT;
+
+       iowrite32(doorbell, phba->db_va + DB_TXULP0_OFFSET);
+       return 0;
+}
+
+static int beiscsi_mtask(struct iscsi_task *task)
+{
+       struct beiscsi_io_task *aborted_io_task, *io_task = task->dd_data;
+       struct iscsi_conn *conn = task->conn;
+       struct beiscsi_conn *beiscsi_conn = conn->dd_data;
+       struct beiscsi_hba *phba = beiscsi_conn->phba;
+       struct iscsi_wrb *pwrb = NULL;
+       unsigned int doorbell = 0;
+       struct iscsi_task *aborted_task;
+
+       pwrb = io_task->pwrb_handle->pwrb;
+       AMAP_SET_BITS(struct amap_iscsi_wrb, cmdsn_itt, pwrb,
+                     be32_to_cpu(task->cmdsn));
+       AMAP_SET_BITS(struct amap_iscsi_wrb, wrb_idx, pwrb,
+                     io_task->pwrb_handle->wrb_index);
+       AMAP_SET_BITS(struct amap_iscsi_wrb, sgl_icd_idx, pwrb,
+                     io_task->psgl_handle->sgl_index);
+
+       switch (task->hdr->opcode & ISCSI_OPCODE_MASK) {
+       case ISCSI_OP_LOGIN:
+               AMAP_SET_BITS(struct amap_iscsi_wrb, type, pwrb, TGT_DM_CMD);
+               AMAP_SET_BITS(struct amap_iscsi_wrb, dmsg, pwrb, 0);
+               AMAP_SET_BITS(struct amap_iscsi_wrb, cmdsn_itt, pwrb, 1);
+               hwi_write_buffer(pwrb, task);
+               break;
+       case ISCSI_OP_NOOP_OUT:
+               AMAP_SET_BITS(struct amap_iscsi_wrb, type, pwrb, INI_RD_CMD);
+               hwi_write_buffer(pwrb, task);
+               break;
+       case ISCSI_OP_TEXT:
+               AMAP_SET_BITS(struct amap_iscsi_wrb, type, pwrb, INI_WR_CMD);
+               AMAP_SET_BITS(struct amap_iscsi_wrb, dsp, pwrb, 1);
+               hwi_write_buffer(pwrb, task);
+               break;
+       case ISCSI_OP_SCSI_TMFUNC:
+               aborted_task = iscsi_itt_to_task(conn,
+                                       ((struct iscsi_tm *)task->hdr)->rtt);
+                if (!aborted_task)
+                       return 0;
+               aborted_io_task = aborted_task->dd_data;
+               if (!aborted_io_task->scsi_cmnd)
+                       return 0;
+
+               mgmt_invalidate_icds(phba,
+                                    aborted_io_task->psgl_handle->sgl_index,
+                                    beiscsi_conn->beiscsi_conn_cid);
+               AMAP_SET_BITS(struct amap_iscsi_wrb, type, pwrb, INI_TMF_CMD);
+               AMAP_SET_BITS(struct amap_iscsi_wrb, dmsg, pwrb, 0);
+               hwi_write_buffer(pwrb, task);
+               break;
+       case ISCSI_OP_LOGOUT:
+               AMAP_SET_BITS(struct amap_iscsi_wrb, dmsg, pwrb, 0);
+               AMAP_SET_BITS(struct amap_iscsi_wrb, type, pwrb,
+                               HWH_TYPE_LOGOUT);
+               hwi_write_buffer(pwrb, task);
+               break;
+
+       default:
+               SE_DEBUG(DBG_LVL_1, "opcode =%d Not supported \n",
+                        task->hdr->opcode & ISCSI_OPCODE_MASK);
+               return -EINVAL;
+       }
+
+       AMAP_SET_BITS(struct amap_iscsi_wrb, r2t_exp_dtl, pwrb,
+                     be32_to_cpu(task->data_count));
+       AMAP_SET_BITS(struct amap_iscsi_wrb, ptr2nextwrb, pwrb,
+                     io_task->pwrb_handle->nxt_wrb_index);
+       be_dws_le_to_cpu(pwrb, sizeof(struct iscsi_wrb));
+
+       doorbell |= beiscsi_conn->beiscsi_conn_cid & DB_WRB_POST_CID_MASK;
+       doorbell |= (io_task->pwrb_handle->wrb_index &
+                    DB_DEF_PDU_WRB_INDEX_MASK) << DB_DEF_PDU_WRB_INDEX_SHIFT;
+       doorbell |= 1 << DB_DEF_PDU_NUM_POSTED_SHIFT;
+       iowrite32(doorbell, phba->db_va + DB_TXULP0_OFFSET);
+       return 0;
+}
+
+static int beiscsi_task_xmit(struct iscsi_task *task)
+{
+       struct iscsi_conn *conn = task->conn;
+       struct beiscsi_io_task *io_task = task->dd_data;
+       struct scsi_cmnd *sc = task->sc;
+       struct beiscsi_conn *beiscsi_conn = conn->dd_data;
+       struct scatterlist *sg;
+       int num_sg;
+       unsigned int  writedir = 0, xferlen = 0;
+
+       SE_DEBUG(DBG_LVL_4, "\n cid=%d In beiscsi_task_xmit task=%p conn=%p \t"
+                "beiscsi_conn=%p \n", beiscsi_conn->beiscsi_conn_cid,
+                task, conn, beiscsi_conn);
+       if (!sc)
+               return beiscsi_mtask(task);
+
+       io_task->scsi_cmnd = sc;
+       num_sg = scsi_dma_map(sc);
+       if (num_sg < 0) {
+               SE_DEBUG(DBG_LVL_1, " scsi_dma_map Failed\n")
+               return num_sg;
+       }
+       SE_DEBUG(DBG_LVL_4, "xferlen=0x%08x scmd=%p num_sg=%d sernum=%lu\n",
+                 (scsi_bufflen(sc)), sc, num_sg, sc->serial_number);
+       xferlen = scsi_bufflen(sc);
+       sg = scsi_sglist(sc);
+       if (sc->sc_data_direction == DMA_TO_DEVICE) {
+               writedir = 1;
+               SE_DEBUG(DBG_LVL_4, "task->imm_count=0x%08x \n",
+                        task->imm_count);
+       } else
+               writedir = 0;
+       return beiscsi_iotask(task, sg, num_sg, xferlen, writedir);
+}
+
+static void beiscsi_remove(struct pci_dev *pcidev)
+{
+       struct beiscsi_hba *phba = NULL;
+
+       phba = (struct beiscsi_hba *)pci_get_drvdata(pcidev);
+       if (!phba) {
+               dev_err(&pcidev->dev, "beiscsi_remove called with no phba \n");
+               return;
+       }
+
+       hwi_disable_intr(phba);
+       if (phba->pcidev->irq)
+               free_irq(phba->pcidev->irq, phba);
+       destroy_workqueue(phba->wq);
+       if (blk_iopoll_enabled)
+               blk_iopoll_disable(&phba->iopoll);
+
+       beiscsi_clean_port(phba);
+       beiscsi_free_mem(phba);
+       beiscsi_unmap_pci_function(phba);
+       pci_free_consistent(phba->pcidev,
+                           phba->ctrl.mbox_mem_alloced.size,
+                           phba->ctrl.mbox_mem_alloced.va,
+                           phba->ctrl.mbox_mem_alloced.dma);
+       iscsi_host_remove(phba->shost);
+       pci_dev_put(phba->pcidev);
+       iscsi_host_free(phba->shost);
+}
+
+static int __devinit beiscsi_dev_probe(struct pci_dev *pcidev,
+                               const struct pci_device_id *id)
+{
+       struct beiscsi_hba *phba = NULL;
+       int ret;
+
+       ret = beiscsi_enable_pci(pcidev);
+       if (ret < 0) {
+               shost_printk(KERN_ERR, phba->shost, "beiscsi_dev_probe-"
+                            "Failed to enable pci device \n");
+               return ret;
+       }
+
+       phba = beiscsi_hba_alloc(pcidev);
+       if (!phba) {
+               dev_err(&pcidev->dev, "beiscsi_dev_probe-"
+                       " Failed in beiscsi_hba_alloc \n");
+               goto disable_pci;
+       }
+
+       pci_set_drvdata(pcidev, phba);
+       ret = be_ctrl_init(phba, pcidev);
+       if (ret) {
+               shost_printk(KERN_ERR, phba->shost, "beiscsi_dev_probe-"
+                               "Failed in be_ctrl_init\n");
+               goto hba_free;
+       }
+
+       spin_lock_init(&phba->io_sgl_lock);
+       spin_lock_init(&phba->mgmt_sgl_lock);
+       spin_lock_init(&phba->isr_lock);
+       beiscsi_get_params(phba);
+       ret = beiscsi_init_port(phba);
+       if (ret < 0) {
+               shost_printk(KERN_ERR, phba->shost, "beiscsi_dev_probe-"
+                            "Failed in beiscsi_init_port\n");
+               goto free_port;
+       }
+
+       snprintf(phba->wq_name, sizeof(phba->wq_name), "beiscsi_q_irq%u",
+                phba->shost->host_no);
+       phba->wq = create_singlethread_workqueue(phba->wq_name);
+       if (!phba->wq) {
+               shost_printk(KERN_ERR, phba->shost, "beiscsi_dev_probe-"
+                               "Failed to allocate work queue\n");
+               goto free_twq;
+       }
+
+       INIT_WORK(&phba->work_cqs, beiscsi_process_all_cqs);
+
+       if (blk_iopoll_enabled) {
+               blk_iopoll_init(&phba->iopoll, be_iopoll_budget, be_iopoll);
+               blk_iopoll_enable(&phba->iopoll);
+       }
+
+       ret = beiscsi_init_irqs(phba);
+       if (ret < 0) {
+               shost_printk(KERN_ERR, phba->shost, "beiscsi_dev_probe-"
+                            "Failed to beiscsi_init_irqs\n");
+               goto free_blkenbld;
+       }
+       ret = hwi_enable_intr(phba);
+       if (ret < 0) {
+               shost_printk(KERN_ERR, phba->shost, "beiscsi_dev_probe-"
+                            "Failed to hwi_enable_intr\n");
+               goto free_ctrlr;
+       }
+
+       SE_DEBUG(DBG_LVL_8, "\n\n\n SUCCESS - DRIVER LOADED \n\n\n");
+       return 0;
+
+free_ctrlr:
+       if (phba->pcidev->irq)
+               free_irq(phba->pcidev->irq, phba);
+free_blkenbld:
+       destroy_workqueue(phba->wq);
+       if (blk_iopoll_enabled)
+               blk_iopoll_disable(&phba->iopoll);
+free_twq:
+       beiscsi_clean_port(phba);
+       beiscsi_free_mem(phba);
+free_port:
+       pci_free_consistent(phba->pcidev,
+                           phba->ctrl.mbox_mem_alloced.size,
+                           phba->ctrl.mbox_mem_alloced.va,
+                          phba->ctrl.mbox_mem_alloced.dma);
+       beiscsi_unmap_pci_function(phba);
+hba_free:
+       iscsi_host_remove(phba->shost);
+       pci_dev_put(phba->pcidev);
+       iscsi_host_free(phba->shost);
+disable_pci:
+       pci_disable_device(pcidev);
+       return ret;
+}
+
+struct iscsi_transport beiscsi_iscsi_transport = {
+       .owner = THIS_MODULE,
+       .name = DRV_NAME,
+       .caps = CAP_RECOVERY_L0 | CAP_HDRDGST |
+               CAP_MULTI_R2T | CAP_DATADGST | CAP_DATA_PATH_OFFLOAD,
+       .param_mask = ISCSI_MAX_RECV_DLENGTH |
+               ISCSI_MAX_XMIT_DLENGTH |
+               ISCSI_HDRDGST_EN |
+               ISCSI_DATADGST_EN |
+               ISCSI_INITIAL_R2T_EN |
+               ISCSI_MAX_R2T |
+               ISCSI_IMM_DATA_EN |
+               ISCSI_FIRST_BURST |
+               ISCSI_MAX_BURST |
+               ISCSI_PDU_INORDER_EN |
+               ISCSI_DATASEQ_INORDER_EN |
+               ISCSI_ERL |
+               ISCSI_CONN_PORT |
+               ISCSI_CONN_ADDRESS |
+               ISCSI_EXP_STATSN |
+               ISCSI_PERSISTENT_PORT |
+               ISCSI_PERSISTENT_ADDRESS |
+               ISCSI_TARGET_NAME | ISCSI_TPGT |
+               ISCSI_USERNAME | ISCSI_PASSWORD |
+               ISCSI_USERNAME_IN | ISCSI_PASSWORD_IN |
+               ISCSI_FAST_ABORT | ISCSI_ABORT_TMO |
+               ISCSI_LU_RESET_TMO |
+               ISCSI_PING_TMO | ISCSI_RECV_TMO |
+               ISCSI_IFACE_NAME | ISCSI_INITIATOR_NAME,
+       .host_param_mask = ISCSI_HOST_HWADDRESS | ISCSI_HOST_IPADDRESS |
+                               ISCSI_HOST_INITIATOR_NAME,
+       .create_session = beiscsi_session_create,
+       .destroy_session = beiscsi_session_destroy,
+       .create_conn = beiscsi_conn_create,
+       .bind_conn = beiscsi_conn_bind,
+       .destroy_conn = iscsi_conn_teardown,
+       .set_param = beiscsi_set_param,
+       .get_conn_param = beiscsi_conn_get_param,
+       .get_session_param = iscsi_session_get_param,
+       .get_host_param = beiscsi_get_host_param,
+       .start_conn = beiscsi_conn_start,
+       .stop_conn = beiscsi_conn_stop,
+       .send_pdu = iscsi_conn_send_pdu,
+       .xmit_task = beiscsi_task_xmit,
+       .cleanup_task = beiscsi_cleanup_task,
+       .alloc_pdu = beiscsi_alloc_pdu,
+       .parse_pdu_itt = beiscsi_parse_pdu,
+       .get_stats = beiscsi_conn_get_stats,
+       .ep_connect = beiscsi_ep_connect,
+       .ep_poll = beiscsi_ep_poll,
+       .ep_disconnect = beiscsi_ep_disconnect,
+       .session_recovery_timedout = iscsi_session_recovery_timedout,
+};
+
+static struct pci_driver beiscsi_pci_driver = {
+       .name = DRV_NAME,
+       .probe = beiscsi_dev_probe,
+       .remove = beiscsi_remove,
+       .id_table = beiscsi_pci_id_table
+};
+
+static int __init beiscsi_module_init(void)
+{
+       int ret;
+
+       beiscsi_scsi_transport =
+                       iscsi_register_transport(&beiscsi_iscsi_transport);
+       if (!beiscsi_scsi_transport) {
+               SE_DEBUG(DBG_LVL_1,
+                        "beiscsi_module_init - Unable to  register beiscsi"
+                        "transport.\n");
+               ret = -ENOMEM;
+       }
+       SE_DEBUG(DBG_LVL_8, "In beiscsi_module_init, tt=%p \n",
+                &beiscsi_iscsi_transport);
+
+       ret = pci_register_driver(&beiscsi_pci_driver);
+       if (ret) {
+               SE_DEBUG(DBG_LVL_1,
+                        "beiscsi_module_init - Unable to  register"
+                        "beiscsi pci driver.\n");
+               goto unregister_iscsi_transport;
+       }
+       return 0;
+
+unregister_iscsi_transport:
+       iscsi_unregister_transport(&beiscsi_iscsi_transport);
+       return ret;
+}
+
+static void __exit beiscsi_module_exit(void)
+{
+       pci_unregister_driver(&beiscsi_pci_driver);
+       iscsi_unregister_transport(&beiscsi_iscsi_transport);
+}
+
+module_init(beiscsi_module_init);
+module_exit(beiscsi_module_exit);
diff --git a/drivers/scsi/be2iscsi/be_main.h b/drivers/scsi/be2iscsi/be_main.h
new file mode 100644 (file)
index 0000000..53c9b70
--- /dev/null
@@ -0,0 +1,837 @@
+/**
+ * Copyright (C) 2005 - 2009 ServerEngines
+ * 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 version 2
+ * as published by the Free Software Foundation.  The full GNU General
+ * Public License is included in this distribution in the file called COPYING.
+ *
+ * Written by: Jayamohan Kallickal (jayamohank@serverengines.com)
+ *
+ * Contact Information:
+ * linux-drivers@serverengines.com
+ *
+ * ServerEngines
+ * 209 N. Fair Oaks Ave
+ * Sunnyvale, CA 94085
+ *
+ */
+
+#ifndef _BEISCSI_MAIN_
+#define _BEISCSI_MAIN_
+
+
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/in.h>
+#include <linux/blk-iopoll.h>
+#include <scsi/scsi.h>
+#include <scsi/scsi_cmnd.h>
+#include <scsi/scsi_device.h>
+#include <scsi/scsi_host.h>
+#include <scsi/iscsi_proto.h>
+#include <scsi/libiscsi.h>
+#include <scsi/scsi_transport_iscsi.h>
+
+#include "be.h"
+
+
+
+#define DRV_NAME               "be2iscsi"
+#define BUILD_STR              "2.0.527.0"
+
+#define BE_NAME                        "ServerEngines BladeEngine2" \
+                               "Linux iSCSI Driver version" BUILD_STR
+#define DRV_DESC               BE_NAME " " "Driver"
+
+#define BE_VENDOR_ID           0x19A2
+#define BE_DEVICE_ID1          0x212
+#define OC_DEVICE_ID1          0x702
+#define OC_DEVICE_ID2          0x703
+
+#define BE2_MAX_SESSIONS       64
+#define BE2_CMDS_PER_CXN       128
+#define BE2_LOGOUTS            BE2_MAX_SESSIONS
+#define BE2_TMFS               16
+#define BE2_NOPOUT_REQ         16
+#define BE2_ASYNCPDUS          BE2_MAX_SESSIONS
+#define BE2_MAX_ICDS           2048
+#define BE2_SGE                        32
+#define BE2_DEFPDU_HDR_SZ      64
+#define BE2_DEFPDU_DATA_SZ     8192
+#define BE2_IO_DEPTH \
+       (BE2_MAX_ICDS / 2 - (BE2_LOGOUTS + BE2_TMFS + BE2_NOPOUT_REQ))
+
+#define BEISCSI_SGLIST_ELEMENTS        BE2_SGE
+
+#define BEISCSI_MAX_CMNDS      1024    /* Max IO's per Ctrlr sht->can_queue */
+#define BEISCSI_CMD_PER_LUN    128     /* scsi_host->cmd_per_lun */
+#define BEISCSI_MAX_SECTORS    2048    /* scsi_host->max_sectors */
+
+#define BEISCSI_MAX_CMD_LEN    16      /* scsi_host->max_cmd_len */
+#define BEISCSI_NUM_MAX_LUN    256     /* scsi_host->max_lun */
+#define BEISCSI_NUM_DEVICES_SUPPORTED  0x01
+#define BEISCSI_MAX_FRAGS_INIT 192
+#define BE_NUM_MSIX_ENTRIES    1
+#define MPU_EP_SEMAPHORE       0xac
+
+#define BE_SENSE_INFO_SIZE             258
+#define BE_ISCSI_PDU_HEADER_SIZE       64
+#define BE_MIN_MEM_SIZE                        16384
+
+#define IIOC_SCSI_DATA                  0x05   /* Write Operation */
+
+#define DBG_LVL                                0x00000001
+#define DBG_LVL_1                      0x00000001
+#define DBG_LVL_2                      0x00000002
+#define DBG_LVL_3                      0x00000004
+#define DBG_LVL_4                      0x00000008
+#define DBG_LVL_5                      0x00000010
+#define DBG_LVL_6                      0x00000020
+#define DBG_LVL_7                      0x00000040
+#define DBG_LVL_8                      0x00000080
+
+#define SE_DEBUG(debug_mask, fmt, args...)             \
+do {                                                   \
+       if (debug_mask & DBG_LVL) {                     \
+               printk(KERN_ERR "(%s():%d):", __func__, __LINE__);\
+               printk(fmt, ##args);                    \
+       }                                               \
+} while (0);
+
+/**
+ * hardware needs the async PDU buffers to be posted in multiples of 8
+ * So have atleast 8 of them by default
+ */
+
+#define HWI_GET_ASYNC_PDU_CTX(phwi)    (phwi->phwi_ctxt->pasync_ctx)
+
+/********* Memory BAR register ************/
+#define PCICFG_MEMBAR_CTRL_INT_CTRL_OFFSET     0xfc
+/**
+ * Host Interrupt Enable, if set interrupts are enabled although "PCI Interrupt
+ * Disable" may still globally block interrupts in addition to individual
+ * interrupt masks; a mechanism for the device driver to block all interrupts
+ * atomically without having to arbitrate for the PCI Interrupt Disable bit
+ * with the OS.
+ */
+#define MEMBAR_CTRL_INT_CTRL_HOSTINTR_MASK     (1 << 29)       /* bit 29 */
+
+/********* ISR0 Register offset **********/
+#define CEV_ISR0_OFFSET                        0xC18
+#define CEV_ISR_SIZE                           4
+
+/**
+ * Macros for reading/writing a protection domain or CSR registers
+ * in BladeEngine.
+ */
+
+#define DB_TXULP0_OFFSET 0x40
+#define DB_RXULP0_OFFSET 0xA0
+/********* Event Q door bell *************/
+#define DB_EQ_OFFSET                   DB_CQ_OFFSET
+#define DB_EQ_RING_ID_MASK             0x1FF   /* bits 0 - 8 */
+/* Clear the interrupt for this eq */
+#define DB_EQ_CLR_SHIFT                        (9)     /* bit 9 */
+/* Must be 1 */
+#define DB_EQ_EVNT_SHIFT               (10)    /* bit 10 */
+/* Number of event entries processed */
+#define DB_EQ_NUM_POPPED_SHIFT         (16)    /* bits 16 - 28 */
+/* Rearm bit */
+#define DB_EQ_REARM_SHIFT              (29)    /* bit 29 */
+
+/********* Compl Q door bell *************/
+#define DB_CQ_OFFSET                   0x120
+#define DB_CQ_RING_ID_MASK             0x3FF   /* bits 0 - 9 */
+/* Number of event entries processed */
+#define DB_CQ_NUM_POPPED_SHIFT         (16)    /* bits 16 - 28 */
+/* Rearm bit */
+#define DB_CQ_REARM_SHIFT              (29)    /* bit 29 */
+
+#define GET_HWI_CONTROLLER_WS(pc)      (pc->phwi_ctrlr)
+#define HWI_GET_DEF_BUFQ_ID(pc) (((struct hwi_controller *)\
+               (GET_HWI_CONTROLLER_WS(pc)))->default_pdu_data.id)
+#define HWI_GET_DEF_HDRQ_ID(pc) (((struct hwi_controller *)\
+               (GET_HWI_CONTROLLER_WS(pc)))->default_pdu_hdr.id)
+
+#define PAGES_REQUIRED(x) \
+       ((x < PAGE_SIZE) ? 1 :  ((x + PAGE_SIZE - 1) / PAGE_SIZE))
+
+enum be_mem_enum {
+       HWI_MEM_ADDN_CONTEXT,
+       HWI_MEM_CQ,
+       HWI_MEM_EQ,
+       HWI_MEM_WRB,
+       HWI_MEM_WRBH,
+       HWI_MEM_SGLH,   /* 5 */
+       HWI_MEM_SGE,
+       HWI_MEM_ASYNC_HEADER_BUF,
+       HWI_MEM_ASYNC_DATA_BUF,
+       HWI_MEM_ASYNC_HEADER_RING,
+       HWI_MEM_ASYNC_DATA_RING,        /* 10 */
+       HWI_MEM_ASYNC_HEADER_HANDLE,
+       HWI_MEM_ASYNC_DATA_HANDLE,
+       HWI_MEM_ASYNC_PDU_CONTEXT,
+       ISCSI_MEM_GLOBAL_HEADER,
+       SE_MEM_MAX      /* 15 */
+};
+
+struct be_bus_address32 {
+       unsigned int address_lo;
+       unsigned int address_hi;
+};
+
+struct be_bus_address64 {
+       unsigned long long address;
+};
+
+struct be_bus_address {
+       union {
+               struct be_bus_address32 a32;
+               struct be_bus_address64 a64;
+       } u;
+};
+
+struct mem_array {
+       struct be_bus_address bus_address;      /* Bus address of location */
+       void *virtual_address;          /* virtual address to the location */
+       unsigned int size;              /* Size required by memory block */
+};
+
+struct be_mem_descriptor {
+       unsigned int index;     /* Index of this memory parameter */
+       unsigned int category;  /* type indicates cached/non-cached */
+       unsigned int num_elements;      /* number of elements in this
+                                        * descriptor
+                                        */
+       unsigned int alignment_mask;    /* Alignment mask for this block */
+       unsigned int size_in_bytes;     /* Size required by memory block */
+       struct mem_array *mem_array;
+};
+
+struct sgl_handle {
+       unsigned int sgl_index;
+       struct iscsi_sge *pfrag;
+};
+
+struct hba_parameters {
+       unsigned int ios_per_ctrl;
+       unsigned int cxns_per_ctrl;
+       unsigned int asyncpdus_per_ctrl;
+       unsigned int icds_per_ctrl;
+       unsigned int num_sge_per_io;
+       unsigned int defpdu_hdr_sz;
+       unsigned int defpdu_data_sz;
+       unsigned int num_cq_entries;
+       unsigned int num_eq_entries;
+       unsigned int wrbs_per_cxn;
+       unsigned int crashmode;
+       unsigned int hba_num;
+
+       unsigned int mgmt_ws_sz;
+       unsigned int hwi_ws_sz;
+
+       unsigned int eto;
+       unsigned int ldto;
+
+       unsigned int dbg_flags;
+       unsigned int num_cxn;
+
+       unsigned int eq_timer;
+       /**
+        * These are calculated from other params. They're here
+        * for debug purposes
+        */
+       unsigned int num_mcc_pages;
+       unsigned int num_mcc_cq_pages;
+       unsigned int num_cq_pages;
+       unsigned int num_eq_pages;
+
+       unsigned int num_async_pdu_buf_pages;
+       unsigned int num_async_pdu_buf_sgl_pages;
+       unsigned int num_async_pdu_buf_cq_pages;
+
+       unsigned int num_async_pdu_hdr_pages;
+       unsigned int num_async_pdu_hdr_sgl_pages;
+       unsigned int num_async_pdu_hdr_cq_pages;
+
+       unsigned int num_sge;
+};
+
+struct beiscsi_hba {
+       struct hba_parameters params;
+       struct hwi_controller *phwi_ctrlr;
+       unsigned int mem_req[SE_MEM_MAX];
+       /* PCI BAR mapped addresses */
+       u8 __iomem *csr_va;     /* CSR */
+       u8 __iomem *db_va;      /* Door  Bell  */
+       u8 __iomem *pci_va;     /* PCI Config */
+       struct be_bus_address csr_pa;   /* CSR */
+       struct be_bus_address db_pa;    /* CSR */
+       struct be_bus_address pci_pa;   /* CSR */
+       /* PCI representation of our HBA */
+       struct pci_dev *pcidev;
+       unsigned int state;
+       unsigned short asic_revision;
+       struct blk_iopoll       iopoll;
+       struct be_mem_descriptor *init_mem;
+
+       unsigned short io_sgl_alloc_index;
+       unsigned short io_sgl_free_index;
+       unsigned short io_sgl_hndl_avbl;
+       struct sgl_handle **io_sgl_hndl_base;
+
+       unsigned short eh_sgl_alloc_index;
+       unsigned short eh_sgl_free_index;
+       unsigned short eh_sgl_hndl_avbl;
+       struct sgl_handle **eh_sgl_hndl_base;
+       spinlock_t io_sgl_lock;
+       spinlock_t mgmt_sgl_lock;
+       spinlock_t isr_lock;
+       unsigned int age;
+       unsigned short avlbl_cids;
+       unsigned short cid_alloc;
+       unsigned short cid_free;
+       struct beiscsi_conn *conn_table[BE2_MAX_SESSIONS * 2];
+       struct list_head hba_queue;
+       unsigned short *cid_array;
+       struct iscsi_endpoint **ep_array;
+       struct Scsi_Host *shost;
+       struct {
+               /**
+                * group together since they are used most frequently
+                * for cid to cri conversion
+                */
+               unsigned int iscsi_cid_start;
+               unsigned int phys_port;
+
+               unsigned int isr_offset;
+               unsigned int iscsi_icd_start;
+               unsigned int iscsi_cid_count;
+               unsigned int iscsi_icd_count;
+               unsigned int pci_function;
+
+               unsigned short cid_alloc;
+               unsigned short cid_free;
+               unsigned short avlbl_cids;
+               spinlock_t cid_lock;
+       } fw_config;
+
+       u8 mac_address[ETH_ALEN];
+       unsigned short todo_cq;
+       unsigned short todo_mcc_cq;
+       char wq_name[20];
+       struct workqueue_struct *wq;    /* The actuak work queue */
+       struct work_struct work_cqs;    /* The work being queued */
+       struct be_ctrl_info ctrl;
+};
+
+struct beiscsi_session {
+       struct pci_pool *bhs_pool;
+};
+
+/**
+ * struct beiscsi_conn - iscsi connection structure
+ */
+struct beiscsi_conn {
+       struct iscsi_conn *conn;
+       struct beiscsi_hba *phba;
+       u32 exp_statsn;
+       u32 beiscsi_conn_cid;
+       struct beiscsi_endpoint *ep;
+       unsigned short login_in_progress;
+       struct sgl_handle *plogin_sgl_handle;
+       struct beiscsi_session *beiscsi_sess;
+};
+
+/* This structure is used by the chip */
+struct pdu_data_out {
+       u32 dw[12];
+};
+/**
+ * Pseudo amap definition in which each bit of the actual structure is defined
+ * as a byte: used to calculate offset/shift/mask of each field
+ */
+struct amap_pdu_data_out {
+       u8 opcode[6];           /* opcode */
+       u8 rsvd0[2];            /* should be 0 */
+       u8 rsvd1[7];
+       u8 final_bit;           /* F bit */
+       u8 rsvd2[16];
+       u8 ahs_length[8];       /* no AHS */
+       u8 data_len_hi[8];
+       u8 data_len_lo[16];     /* DataSegmentLength */
+       u8 lun[64];
+       u8 itt[32];             /* ITT; initiator task tag */
+       u8 ttt[32];             /* TTT; valid for R2T or 0xffffffff */
+       u8 rsvd3[32];
+       u8 exp_stat_sn[32];
+       u8 rsvd4[32];
+       u8 data_sn[32];
+       u8 buffer_offset[32];
+       u8 rsvd5[32];
+};
+
+struct be_cmd_bhs {
+       struct iscsi_cmd iscsi_hdr;
+       unsigned char pad1[16];
+       struct pdu_data_out iscsi_data_pdu;
+       unsigned char pad2[BE_SENSE_INFO_SIZE -
+                       sizeof(struct pdu_data_out)];
+};
+
+struct beiscsi_io_task {
+       struct wrb_handle *pwrb_handle;
+       struct sgl_handle *psgl_handle;
+       struct beiscsi_conn *conn;
+       struct scsi_cmnd *scsi_cmnd;
+       unsigned int cmd_sn;
+       unsigned int flags;
+       unsigned short cid;
+       unsigned short header_len;
+
+       struct be_cmd_bhs *cmd_bhs;
+       struct be_bus_address bhs_pa;
+       unsigned short bhs_len;
+};
+
+struct be_nonio_bhs {
+       struct iscsi_hdr iscsi_hdr;
+       unsigned char pad1[16];
+       struct pdu_data_out iscsi_data_pdu;
+       unsigned char pad2[BE_SENSE_INFO_SIZE -
+                       sizeof(struct pdu_data_out)];
+};
+
+struct be_status_bhs {
+       struct iscsi_cmd iscsi_hdr;
+       unsigned char pad1[16];
+       /**
+        * The plus 2 below is to hold the sense info length that gets
+        * DMA'ed by RxULP
+        */
+       unsigned char sense_info[BE_SENSE_INFO_SIZE];
+};
+
+struct iscsi_sge {
+       u32 dw[4];
+};
+
+/**
+ * Pseudo amap definition in which each bit of the actual structure is defined
+ * as a byte: used to calculate offset/shift/mask of each field
+ */
+struct amap_iscsi_sge {
+       u8 addr_hi[32];
+       u8 addr_lo[32];
+       u8 sge_offset[22];      /* DWORD 2 */
+       u8 rsvd0[9];            /* DWORD 2 */
+       u8 last_sge;            /* DWORD 2 */
+       u8 len[17];             /* DWORD 3 */
+       u8 rsvd1[15];           /* DWORD 3 */
+};
+
+struct beiscsi_offload_params {
+       u32 dw[5];
+};
+
+#define OFFLD_PARAMS_ERL       0x00000003
+#define OFFLD_PARAMS_DDE       0x00000004
+#define OFFLD_PARAMS_HDE       0x00000008
+#define OFFLD_PARAMS_IR2T      0x00000010
+#define OFFLD_PARAMS_IMD       0x00000020
+
+/**
+ * Pseudo amap definition in which each bit of the actual structure is defined
+ * as a byte: used to calculate offset/shift/mask of each field
+ */
+struct amap_beiscsi_offload_params {
+       u8 max_burst_length[32];
+       u8 max_send_data_segment_length[32];
+       u8 first_burst_length[32];
+       u8 erl[2];
+       u8 dde[1];
+       u8 hde[1];
+       u8 ir2t[1];
+       u8 imd[1];
+       u8 pad[26];
+       u8 exp_statsn[32];
+};
+
+/* void hwi_complete_drvr_msgs(struct beiscsi_conn *beiscsi_conn,
+               struct beiscsi_hba *phba, struct sol_cqe *psol);*/
+
+struct async_pdu_handle {
+       struct list_head link;
+       struct be_bus_address pa;
+       void *pbuffer;
+       unsigned int consumed;
+       unsigned char index;
+       unsigned char is_header;
+       unsigned short cri;
+       unsigned long buffer_len;
+};
+
+struct hwi_async_entry {
+       struct {
+               unsigned char hdr_received;
+               unsigned char hdr_len;
+               unsigned short bytes_received;
+               unsigned int bytes_needed;
+               struct list_head list;
+       } wait_queue;
+
+       struct list_head header_busy_list;
+       struct list_head data_busy_list;
+};
+
+#define BE_MIN_ASYNC_ENTRIES 128
+
+struct hwi_async_pdu_context {
+       struct {
+               struct be_bus_address pa_base;
+               void *va_base;
+               void *ring_base;
+               struct async_pdu_handle *handle_base;
+
+               unsigned int host_write_ptr;
+               unsigned int ep_read_ptr;
+               unsigned int writables;
+
+               unsigned int free_entries;
+               unsigned int busy_entries;
+               unsigned int buffer_size;
+               unsigned int num_entries;
+
+               struct list_head free_list;
+       } async_header;
+
+       struct {
+               struct be_bus_address pa_base;
+               void *va_base;
+               void *ring_base;
+               struct async_pdu_handle *handle_base;
+
+               unsigned int host_write_ptr;
+               unsigned int ep_read_ptr;
+               unsigned int writables;
+
+               unsigned int free_entries;
+               unsigned int busy_entries;
+               unsigned int buffer_size;
+               struct list_head free_list;
+               unsigned int num_entries;
+       } async_data;
+
+       /**
+        * This is a varying size list! Do not add anything
+        * after this entry!!
+        */
+       struct hwi_async_entry async_entry[BE_MIN_ASYNC_ENTRIES];
+};
+
+#define PDUCQE_CODE_MASK       0x0000003F
+#define PDUCQE_DPL_MASK                0xFFFF0000
+#define PDUCQE_INDEX_MASK      0x0000FFFF
+
+struct i_t_dpdu_cqe {
+       u32 dw[4];
+} __packed;
+
+/**
+ * Pseudo amap definition in which each bit of the actual structure is defined
+ * as a byte: used to calculate offset/shift/mask of each field
+ */
+struct amap_i_t_dpdu_cqe {
+       u8 db_addr_hi[32];
+       u8 db_addr_lo[32];
+       u8 code[6];
+       u8 cid[10];
+       u8 dpl[16];
+       u8 index[16];
+       u8 num_cons[10];
+       u8 rsvd0[4];
+       u8 final;
+       u8 valid;
+} __packed;
+
+#define CQE_VALID_MASK 0x80000000
+#define CQE_CODE_MASK  0x0000003F
+#define CQE_CID_MASK   0x0000FFC0
+
+#define EQE_VALID_MASK         0x00000001
+#define EQE_MAJORCODE_MASK     0x0000000E
+#define EQE_RESID_MASK         0xFFFF0000
+
+struct be_eq_entry {
+       u32 dw[1];
+} __packed;
+
+/**
+ * Pseudo amap definition in which each bit of the actual structure is defined
+ * as a byte: used to calculate offset/shift/mask of each field
+ */
+struct amap_eq_entry {
+       u8 valid;               /* DWORD 0 */
+       u8 major_code[3];       /* DWORD 0 */
+       u8 minor_code[12];      /* DWORD 0 */
+       u8 resource_id[16];     /* DWORD 0 */
+
+} __packed;
+
+struct cq_db {
+       u32 dw[1];
+} __packed;
+
+/**
+ * Pseudo amap definition in which each bit of the actual structure is defined
+ * as a byte: used to calculate offset/shift/mask of each field
+ */
+struct amap_cq_db {
+       u8 qid[10];
+       u8 event[1];
+       u8 rsvd0[5];
+       u8 num_popped[13];
+       u8 rearm[1];
+       u8 rsvd1[2];
+} __packed;
+
+void beiscsi_process_eq(struct beiscsi_hba *phba);
+
+
+struct iscsi_wrb {
+       u32 dw[16];
+} __packed;
+
+#define WRB_TYPE_MASK 0xF0000000
+
+/**
+ * Pseudo amap definition in which each bit of the actual structure is defined
+ * as a byte: used to calculate offset/shift/mask of each field
+ */
+struct amap_iscsi_wrb {
+       u8 lun[14];             /* DWORD 0 */
+       u8 lt;                  /* DWORD 0 */
+       u8 invld;               /* DWORD 0 */
+       u8 wrb_idx[8];          /* DWORD 0 */
+       u8 dsp;                 /* DWORD 0 */
+       u8 dmsg;                /* DWORD 0 */
+       u8 undr_run;            /* DWORD 0 */
+       u8 over_run;            /* DWORD 0 */
+       u8 type[4];             /* DWORD 0 */
+       u8 ptr2nextwrb[8];      /* DWORD 1 */
+       u8 r2t_exp_dtl[24];     /* DWORD 1 */
+       u8 sgl_icd_idx[12];     /* DWORD 2 */
+       u8 rsvd0[20];           /* DWORD 2 */
+       u8 exp_data_sn[32];     /* DWORD 3 */
+       u8 iscsi_bhs_addr_hi[32];       /* DWORD 4 */
+       u8 iscsi_bhs_addr_lo[32];       /* DWORD 5 */
+       u8 cmdsn_itt[32];       /* DWORD 6 */
+       u8 dif_ref_tag[32];     /* DWORD 7 */
+       u8 sge0_addr_hi[32];    /* DWORD 8 */
+       u8 sge0_addr_lo[32];    /* DWORD 9  */
+       u8 sge0_offset[22];     /* DWORD 10 */
+       u8 pbs;                 /* DWORD 10 */
+       u8 dif_mode[2];         /* DWORD 10 */
+       u8 rsvd1[6];            /* DWORD 10 */
+       u8 sge0_last;           /* DWORD 10 */
+       u8 sge0_len[17];        /* DWORD 11 */
+       u8 dif_meta_tag[14];    /* DWORD 11 */
+       u8 sge0_in_ddr;         /* DWORD 11 */
+       u8 sge1_addr_hi[32];    /* DWORD 12 */
+       u8 sge1_addr_lo[32];    /* DWORD 13 */
+       u8 sge1_r2t_offset[22]; /* DWORD 14 */
+       u8 rsvd2[9];            /* DWORD 14 */
+       u8 sge1_last;           /* DWORD 14 */
+       u8 sge1_len[17];        /* DWORD 15 */
+       u8 ref_sgl_icd_idx[12]; /* DWORD 15 */
+       u8 rsvd3[2];            /* DWORD 15 */
+       u8 sge1_in_ddr;         /* DWORD 15 */
+
+} __packed;
+
+struct wrb_handle *alloc_wrb_handle(struct beiscsi_hba *phba, unsigned int cid,
+                                   int index);
+void
+free_mgmt_sgl_handle(struct beiscsi_hba *phba, struct sgl_handle *psgl_handle);
+
+struct pdu_nop_out {
+       u32 dw[12];
+};
+
+/**
+ * Pseudo amap definition in which each bit of the actual structure is defined
+ * as a byte: used to calculate offset/shift/mask of each field
+ */
+struct amap_pdu_nop_out {
+       u8 opcode[6];           /* opcode 0x00 */
+       u8 i_bit;               /* I Bit */
+       u8 x_bit;               /* reserved; should be 0 */
+       u8 fp_bit_filler1[7];
+       u8 f_bit;               /* always 1 */
+       u8 reserved1[16];
+       u8 ahs_length[8];       /* no AHS */
+       u8 data_len_hi[8];
+       u8 data_len_lo[16];     /* DataSegmentLength */
+       u8 lun[64];
+       u8 itt[32];             /* initiator id for ping or 0xffffffff */
+       u8 ttt[32];             /* target id for ping or 0xffffffff */
+       u8 cmd_sn[32];
+       u8 exp_stat_sn[32];
+       u8 reserved5[128];
+};
+
+#define PDUBASE_OPCODE_MASK    0x0000003F
+#define PDUBASE_DATALENHI_MASK 0x0000FF00
+#define PDUBASE_DATALENLO_MASK 0xFFFF0000
+
+struct pdu_base {
+       u32 dw[16];
+} __packed;
+
+/**
+ * Pseudo amap definition in which each bit of the actual structure is defined
+ * as a byte: used to calculate offset/shift/mask of each field
+ */
+struct amap_pdu_base {
+       u8 opcode[6];
+       u8 i_bit;               /* immediate bit */
+       u8 x_bit;               /* reserved, always 0 */
+       u8 reserved1[24];       /* opcode-specific fields */
+       u8 ahs_length[8];       /* length units is 4 byte words */
+       u8 data_len_hi[8];
+       u8 data_len_lo[16];     /* DatasegmentLength */
+       u8 lun[64];             /* lun or opcode-specific fields */
+       u8 itt[32];             /* initiator task tag */
+       u8 reserved4[224];
+};
+
+struct iscsi_target_context_update_wrb {
+       u32 dw[16];
+} __packed;
+
+/**
+ * Pseudo amap definition in which each bit of the actual structure is defined
+ * as a byte: used to calculate offset/shift/mask of each field
+ */
+struct amap_iscsi_target_context_update_wrb {
+       u8 lun[14];             /* DWORD 0 */
+       u8 lt;                  /* DWORD 0 */
+       u8 invld;               /* DWORD 0 */
+       u8 wrb_idx[8];          /* DWORD 0 */
+       u8 dsp;                 /* DWORD 0 */
+       u8 dmsg;                /* DWORD 0 */
+       u8 undr_run;            /* DWORD 0 */
+       u8 over_run;            /* DWORD 0 */
+       u8 type[4];             /* DWORD 0 */
+       u8 ptr2nextwrb[8];      /* DWORD 1 */
+       u8 max_burst_length[19];        /* DWORD 1 */
+       u8 rsvd0[5];            /* DWORD 1 */
+       u8 rsvd1[15];           /* DWORD 2 */
+       u8 max_send_data_segment_length[17];    /* DWORD 2 */
+       u8 first_burst_length[14];      /* DWORD 3 */
+       u8 rsvd2[2];            /* DWORD 3 */
+       u8 tx_wrbindex_drv_msg[8];      /* DWORD 3 */
+       u8 rsvd3[5];            /* DWORD 3 */
+       u8 session_state[3];    /* DWORD 3 */
+       u8 rsvd4[16];           /* DWORD 4 */
+       u8 tx_jumbo;            /* DWORD 4 */
+       u8 hde;                 /* DWORD 4 */
+       u8 dde;                 /* DWORD 4 */
+       u8 erl[2];              /* DWORD 4 */
+       u8 domain_id[5];                /* DWORD 4 */
+       u8 mode;                /* DWORD 4 */
+       u8 imd;                 /* DWORD 4 */
+       u8 ir2t;                /* DWORD 4 */
+       u8 notpredblq[2];       /* DWORD 4 */
+       u8 compltonack;         /* DWORD 4 */
+       u8 stat_sn[32];         /* DWORD 5 */
+       u8 pad_buffer_addr_hi[32];      /* DWORD 6 */
+       u8 pad_buffer_addr_lo[32];      /* DWORD 7 */
+       u8 pad_addr_hi[32];     /* DWORD 8 */
+       u8 pad_addr_lo[32];     /* DWORD 9 */
+       u8 rsvd5[32];           /* DWORD 10 */
+       u8 rsvd6[32];           /* DWORD 11 */
+       u8 rsvd7[32];           /* DWORD 12 */
+       u8 rsvd8[32];           /* DWORD 13 */
+       u8 rsvd9[32];           /* DWORD 14 */
+       u8 rsvd10[32];          /* DWORD 15 */
+
+} __packed;
+
+struct be_ring {
+       u32 pages;              /* queue size in pages */
+       u32 id;                 /* queue id assigned by beklib */
+       u32 num;                /* number of elements in queue */
+       u32 cidx;               /* consumer index */
+       u32 pidx;               /* producer index -- not used by most rings */
+       u32 item_size;          /* size in bytes of one object */
+
+       void *va;               /* The virtual address of the ring.  This
+                                * should be last to allow 32 & 64 bit debugger
+                                * extensions to work.
+                                */
+};
+
+struct hwi_wrb_context {
+       struct list_head wrb_handle_list;
+       struct list_head wrb_handle_drvr_list;
+       struct wrb_handle **pwrb_handle_base;
+       struct wrb_handle **pwrb_handle_basestd;
+       struct iscsi_wrb *plast_wrb;
+       unsigned short alloc_index;
+       unsigned short free_index;
+       unsigned short wrb_handles_available;
+       unsigned short cid;
+};
+
+struct hwi_controller {
+       struct list_head io_sgl_list;
+       struct list_head eh_sgl_list;
+       struct sgl_handle *psgl_handle_base;
+       unsigned int wrb_mem_index;
+
+       struct hwi_wrb_context wrb_context[BE2_MAX_SESSIONS * 2];
+       struct mcc_wrb *pmcc_wrb_base;
+       struct be_ring default_pdu_hdr;
+       struct be_ring default_pdu_data;
+       struct hwi_context_memory *phwi_ctxt;
+       unsigned short cq_errors[CXN_KILLED_CMND_DATA_NOT_ON_SAME_CONN];
+};
+
+enum hwh_type_enum {
+       HWH_TYPE_IO = 1,
+       HWH_TYPE_LOGOUT = 2,
+       HWH_TYPE_TMF = 3,
+       HWH_TYPE_NOP = 4,
+       HWH_TYPE_IO_RD = 5,
+       HWH_TYPE_LOGIN = 11,
+       HWH_TYPE_INVALID = 0xFFFFFFFF
+};
+
+struct wrb_handle {
+       enum hwh_type_enum type;
+       unsigned short wrb_index;
+       unsigned short nxt_wrb_index;
+
+       struct iscsi_task *pio_handle;
+       struct iscsi_wrb *pwrb;
+};
+
+struct hwi_context_memory {
+       struct be_eq_obj be_eq;
+       struct be_queue_info be_cq;
+       struct be_queue_info be_mcc_cq;
+       struct be_queue_info be_mcc;
+
+       struct be_queue_info be_def_hdrq;
+       struct be_queue_info be_def_dataq;
+
+       struct be_queue_info be_wrbq[BE2_MAX_SESSIONS];
+       struct be_mcc_wrb_context *pbe_mcc_context;
+
+       struct hwi_async_pdu_context *pasync_ctx;
+};
+
+#endif
diff --git a/drivers/scsi/be2iscsi/be_mgmt.c b/drivers/scsi/be2iscsi/be_mgmt.c
new file mode 100644 (file)
index 0000000..12e644f
--- /dev/null
@@ -0,0 +1,321 @@
+/**
+ * Copyright (C) 2005 - 2009 ServerEngines
+ * 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 version 2
+ * as published by the Free Software Foundation.  The full GNU General
+ * Public License is included in this distribution in the file called COPYING.
+ *
+ * Written by: Jayamohan Kallickal (jayamohank@serverengines.com)
+ *
+ * Contact Information:
+ * linux-drivers@serverengines.com
+ *
+ * ServerEngines
+ * 209 N. Fair Oaks Ave
+ * Sunnyvale, CA 94085
+ *
+ */
+
+#include "be_mgmt.h"
+#include "be_iscsi.h"
+
+unsigned char mgmt_get_fw_config(struct be_ctrl_info *ctrl,
+                               struct beiscsi_hba *phba)
+{
+       struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem);
+       struct be_fw_cfg *req = embedded_payload(wrb);
+       int status = 0;
+
+       spin_lock(&ctrl->mbox_lock);
+       memset(wrb, 0, sizeof(*wrb));
+
+       be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0);
+
+       be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
+                          OPCODE_COMMON_QUERY_FIRMWARE_CONFIG, sizeof(*req));
+
+       status = be_mbox_notify(ctrl);
+       if (!status) {
+               struct be_fw_cfg *pfw_cfg;
+               pfw_cfg = req;
+               phba->fw_config.phys_port = pfw_cfg->phys_port;
+               phba->fw_config.iscsi_icd_start =
+                                       pfw_cfg->ulp[0].icd_base;
+               phba->fw_config.iscsi_icd_count =
+                                       pfw_cfg->ulp[0].icd_count;
+               phba->fw_config.iscsi_cid_start =
+                                       pfw_cfg->ulp[0].sq_base;
+               phba->fw_config.iscsi_cid_count =
+                                       pfw_cfg->ulp[0].sq_count;
+       } else {
+               shost_printk(KERN_WARNING, phba->shost,
+                            "Failed in mgmt_get_fw_config \n");
+       }
+
+       spin_unlock(&ctrl->mbox_lock);
+       return status;
+}
+
+unsigned char mgmt_check_supported_fw(struct be_ctrl_info *ctrl)
+{
+       struct be_dma_mem nonemb_cmd;
+       struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem);
+       struct be_mgmt_controller_attributes *req;
+       struct be_sge *sge = nonembedded_sgl(wrb);
+       int status = 0;
+
+       nonemb_cmd.va = pci_alloc_consistent(ctrl->pdev,
+                               sizeof(struct be_mgmt_controller_attributes),
+                               &nonemb_cmd.dma);
+       if (nonemb_cmd.va == NULL) {
+               SE_DEBUG(DBG_LVL_1,
+                        "Failed to allocate memory for mgmt_check_supported_fw"
+                        "\n");
+               return -1;
+       }
+       nonemb_cmd.size = sizeof(struct be_mgmt_controller_attributes);
+       req = nonemb_cmd.va;
+       spin_lock(&ctrl->mbox_lock);
+       memset(wrb, 0, sizeof(*wrb));
+       be_wrb_hdr_prepare(wrb, sizeof(*req), false, 1);
+       be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
+                          OPCODE_COMMON_GET_CNTL_ATTRIBUTES, sizeof(*req));
+       sge->pa_hi = cpu_to_le32(upper_32_bits(nonemb_cmd.dma));
+       sge->pa_lo = cpu_to_le32(nonemb_cmd.dma & 0xFFFFFFFF);
+       sge->len = cpu_to_le32(nonemb_cmd.size);
+
+       status = be_mbox_notify(ctrl);
+       if (!status) {
+               struct be_mgmt_controller_attributes_resp *resp = nonemb_cmd.va;
+               SE_DEBUG(DBG_LVL_8, "Firmware version of CMD: %s\n",
+                       resp->params.hba_attribs.flashrom_version_string);
+               SE_DEBUG(DBG_LVL_8, "Firmware version is : %s\n",
+                       resp->params.hba_attribs.firmware_version_string);
+               SE_DEBUG(DBG_LVL_8,
+                       "Developer Build, not performing version check...\n");
+
+       } else
+               SE_DEBUG(DBG_LVL_1, " Failed in mgmt_check_supported_fw\n");
+       if (nonemb_cmd.va)
+               pci_free_consistent(ctrl->pdev, nonemb_cmd.size,
+                                   nonemb_cmd.va, nonemb_cmd.dma);
+
+       spin_unlock(&ctrl->mbox_lock);
+       return status;
+}
+
+unsigned char mgmt_epfw_cleanup(struct beiscsi_hba *phba, unsigned short chute)
+{
+       struct be_ctrl_info *ctrl = &phba->ctrl;
+       struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem);
+       struct iscsi_cleanup_req *req = embedded_payload(wrb);
+       int status = 0;
+
+       spin_lock(&ctrl->mbox_lock);
+       memset(wrb, 0, sizeof(*wrb));
+
+       be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0);
+       be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ISCSI,
+                          OPCODE_COMMON_ISCSI_CLEANUP, sizeof(*req));
+
+       req->chute = chute;
+       req->hdr_ring_id = 0;
+       req->data_ring_id = 0;
+
+       status = be_mbox_notify(ctrl);
+       if (status)
+               shost_printk(KERN_WARNING, phba->shost,
+                            " mgmt_epfw_cleanup , FAILED\n");
+       spin_unlock(&ctrl->mbox_lock);
+       return status;
+}
+
+unsigned char mgmt_invalidate_icds(struct beiscsi_hba *phba,
+                                  unsigned int icd, unsigned int cid)
+{
+       struct be_dma_mem nonemb_cmd;
+       struct be_ctrl_info *ctrl = &phba->ctrl;
+       struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem);
+       struct be_sge *sge = nonembedded_sgl(wrb);
+       struct invalidate_commands_params_in *req;
+       int status = 0;
+
+       nonemb_cmd.va = pci_alloc_consistent(ctrl->pdev,
+                               sizeof(struct invalidate_commands_params_in),
+                               &nonemb_cmd.dma);
+       if (nonemb_cmd.va == NULL) {
+               SE_DEBUG(DBG_LVL_1,
+                        "Failed to allocate memory for"
+                        "mgmt_invalidate_icds \n");
+               return -1;
+       }
+       nonemb_cmd.size = sizeof(struct invalidate_commands_params_in);
+       req = nonemb_cmd.va;
+       spin_lock(&ctrl->mbox_lock);
+       memset(wrb, 0, sizeof(*wrb));
+
+       be_wrb_hdr_prepare(wrb, sizeof(*req), false, 1);
+       be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ISCSI,
+                       OPCODE_COMMON_ISCSI_ERROR_RECOVERY_INVALIDATE_COMMANDS,
+                       sizeof(*req));
+       req->ref_handle = 0;
+       req->cleanup_type = CMD_ISCSI_COMMAND_INVALIDATE;
+       req->icd_count = 0;
+       req->table[req->icd_count].icd = icd;
+       req->table[req->icd_count].cid = cid;
+       sge->pa_hi = cpu_to_le32(upper_32_bits(nonemb_cmd.dma));
+       sge->pa_lo = cpu_to_le32(nonemb_cmd.dma & 0xFFFFFFFF);
+       sge->len = cpu_to_le32(nonemb_cmd.size);
+
+       status = be_mbox_notify(ctrl);
+       if (status)
+               SE_DEBUG(DBG_LVL_1, "ICDS Invalidation Failed\n");
+       spin_unlock(&ctrl->mbox_lock);
+       if (nonemb_cmd.va)
+               pci_free_consistent(ctrl->pdev, nonemb_cmd.size,
+                                   nonemb_cmd.va, nonemb_cmd.dma);
+       return status;
+}
+
+unsigned char mgmt_invalidate_connection(struct beiscsi_hba *phba,
+                                        struct beiscsi_endpoint *beiscsi_ep,
+                                        unsigned short cid,
+                                        unsigned short issue_reset,
+                                        unsigned short savecfg_flag)
+{
+       struct be_ctrl_info *ctrl = &phba->ctrl;
+       struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem);
+       struct iscsi_invalidate_connection_params_in *req =
+                                               embedded_payload(wrb);
+       int status = 0;
+
+       spin_lock(&ctrl->mbox_lock);
+       memset(wrb, 0, sizeof(*wrb));
+
+       be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0);
+       be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ISCSI_INI,
+                          OPCODE_ISCSI_INI_DRIVER_INVALIDATE_CONNECTION,
+                          sizeof(*req));
+       req->session_handle = beiscsi_ep->fw_handle;
+       req->cid = cid;
+       if (issue_reset)
+               req->cleanup_type = CMD_ISCSI_CONNECTION_ISSUE_TCP_RST;
+       else
+               req->cleanup_type = CMD_ISCSI_CONNECTION_INVALIDATE;
+       req->save_cfg = savecfg_flag;
+       status = be_mbox_notify(ctrl);
+       if (status)
+               SE_DEBUG(DBG_LVL_1, "Invalidation Failed\n");
+
+       spin_unlock(&ctrl->mbox_lock);
+       return status;
+}
+
+unsigned char mgmt_upload_connection(struct beiscsi_hba *phba,
+                               unsigned short cid, unsigned int upload_flag)
+{
+       struct be_ctrl_info *ctrl = &phba->ctrl;
+       struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem);
+       struct tcp_upload_params_in *req = embedded_payload(wrb);
+       int status = 0;
+
+       spin_lock(&ctrl->mbox_lock);
+       memset(wrb, 0, sizeof(*wrb));
+
+       be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0);
+       be_cmd_hdr_prepare(&req->hdr, CMD_COMMON_TCP_UPLOAD,
+                          OPCODE_COMMON_TCP_UPLOAD, sizeof(*req));
+       req->id = (unsigned short)cid;
+       req->upload_type = (unsigned char)upload_flag;
+       status = be_mbox_notify(ctrl);
+       if (status)
+               SE_DEBUG(DBG_LVL_1, "mgmt_upload_connection Failed\n");
+       spin_unlock(&ctrl->mbox_lock);
+       return status;
+}
+
+int mgmt_open_connection(struct beiscsi_hba *phba,
+                        struct sockaddr *dst_addr,
+                        struct beiscsi_endpoint *beiscsi_ep)
+{
+       struct hwi_controller *phwi_ctrlr;
+       struct hwi_context_memory *phwi_context;
+       struct sockaddr_in *daddr_in = (struct sockaddr_in *)dst_addr;
+       struct sockaddr_in6 *daddr_in6 = (struct sockaddr_in6 *)dst_addr;
+       struct be_ctrl_info *ctrl = &phba->ctrl;
+       struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem);
+       struct tcp_connect_and_offload_in *req = embedded_payload(wrb);
+       unsigned short def_hdr_id;
+       unsigned short def_data_id;
+       struct phys_addr template_address = { 0, 0 };
+       struct phys_addr *ptemplate_address;
+       int status = 0;
+       unsigned short cid = beiscsi_ep->ep_cid;
+
+       phwi_ctrlr = phba->phwi_ctrlr;
+       phwi_context = phwi_ctrlr->phwi_ctxt;
+       def_hdr_id = (unsigned short)HWI_GET_DEF_HDRQ_ID(phba);
+       def_data_id = (unsigned short)HWI_GET_DEF_BUFQ_ID(phba);
+
+       ptemplate_address = &template_address;
+       ISCSI_GET_PDU_TEMPLATE_ADDRESS(phba, ptemplate_address);
+       spin_lock(&ctrl->mbox_lock);
+       memset(wrb, 0, sizeof(*wrb));
+
+       be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0);
+       be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ISCSI,
+                          OPCODE_COMMON_ISCSI_TCP_CONNECT_AND_OFFLOAD,
+                          sizeof(*req));
+       if (dst_addr->sa_family == PF_INET) {
+               __be32 s_addr = daddr_in->sin_addr.s_addr;
+               req->ip_address.ip_type = BE2_IPV4;
+               req->ip_address.ip_address[0] = s_addr & 0x000000ff;
+               req->ip_address.ip_address[1] = (s_addr & 0x0000ff00) >> 8;
+               req->ip_address.ip_address[2] = (s_addr & 0x00ff0000) >> 16;
+               req->ip_address.ip_address[3] = (s_addr & 0xff000000) >> 24;
+               req->tcp_port = ntohs(daddr_in->sin_port);
+               beiscsi_ep->dst_addr = daddr_in->sin_addr.s_addr;
+               beiscsi_ep->dst_tcpport = ntohs(daddr_in->sin_port);
+               beiscsi_ep->ip_type = BE2_IPV4;
+       } else if (dst_addr->sa_family == PF_INET6) {
+               req->ip_address.ip_type = BE2_IPV6;
+               memcpy(&req->ip_address.ip_address,
+                      &daddr_in6->sin6_addr.in6_u.u6_addr8, 16);
+               req->tcp_port = ntohs(daddr_in6->sin6_port);
+               beiscsi_ep->dst_tcpport = ntohs(daddr_in6->sin6_port);
+               memcpy(&beiscsi_ep->dst6_addr,
+                      &daddr_in6->sin6_addr.in6_u.u6_addr8, 16);
+               beiscsi_ep->ip_type = BE2_IPV6;
+       } else{
+               shost_printk(KERN_ERR, phba->shost, "unknown addr family %d\n",
+                            dst_addr->sa_family);
+               spin_unlock(&ctrl->mbox_lock);
+               return -EINVAL;
+
+       }
+       req->cid = cid;
+       req->cq_id = phwi_context->be_cq.id;
+       req->defq_id = def_hdr_id;
+       req->hdr_ring_id = def_hdr_id;
+       req->data_ring_id = def_data_id;
+       req->do_offload = 1;
+       req->dataout_template_pa.lo = ptemplate_address->lo;
+       req->dataout_template_pa.hi = ptemplate_address->hi;
+       status = be_mbox_notify(ctrl);
+       if (!status) {
+               struct iscsi_endpoint *ep;
+               struct tcp_connect_and_offload_out *ptcpcnct_out =
+                                                       embedded_payload(wrb);
+
+               ep = phba->ep_array[ptcpcnct_out->cid];
+               beiscsi_ep = ep->dd_data;
+               beiscsi_ep->fw_handle = 0;
+               beiscsi_ep->cid_vld = 1;
+               SE_DEBUG(DBG_LVL_8, "mgmt_open_connection Success\n");
+       } else
+               SE_DEBUG(DBG_LVL_1, "mgmt_open_connection Failed\n");
+       spin_unlock(&ctrl->mbox_lock);
+       return status;
+}
diff --git a/drivers/scsi/be2iscsi/be_mgmt.h b/drivers/scsi/be2iscsi/be_mgmt.h
new file mode 100644 (file)
index 0000000..00e816e
--- /dev/null
@@ -0,0 +1,249 @@
+/**
+ * Copyright (C) 2005 - 2009 ServerEngines
+ * 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 version 2
+ * as published by the Free Software Foundation.  The full GNU General
+ * Public License is included in this distribution in the file called COPYING.
+ *
+ * Written by: Jayamohan Kallickal (jayamohank@serverengines.com)
+ *
+ * Contact Information:
+ * linux-drivers@serverengines.com
+ *
+ * ServerEngines
+ * 209 N. Fair Oaks Ave
+ * Sunnyvale, CA 94085
+ *
+ */
+
+#ifndef _BEISCSI_MGMT_
+#define _BEISCSI_MGMT_
+
+#include <linux/types.h>
+#include <linux/list.h>
+#include "be_iscsi.h"
+#include "be_main.h"
+
+/**
+ * Pseudo amap definition in which each bit of the actual structure is defined
+ * as a byte: used to calculate offset/shift/mask of each field
+ */
+struct amap_mcc_sge {
+       u8 pa_lo[32];           /* dword 0 */
+       u8 pa_hi[32];           /* dword 1 */
+       u8 length[32];          /* DWORD 2 */
+} __packed;
+
+/**
+ * Pseudo amap definition in which each bit of the actual structure is defined
+ * as a byte: used to calculate offset/shift/mask of each field
+ */
+struct amap_mcc_wrb_payload {
+       union {
+               struct amap_mcc_sge sgl[19];
+               u8 embedded[59 * 32];   /* DWORDS 57 to 115 */
+       } u;
+} __packed;
+
+/**
+ * Pseudo amap definition in which each bit of the actual structure is defined
+ * as a byte: used to calculate offset/shift/mask of each field
+ */
+struct amap_mcc_wrb {
+       u8 embedded;            /* DWORD 0 */
+       u8 rsvd0[2];            /* DWORD 0 */
+       u8 sge_count[5];        /* DWORD 0 */
+       u8 rsvd1[16];           /* DWORD 0 */
+       u8 special[8];          /* DWORD 0 */
+       u8 payload_length[32];
+       u8 tag[64];             /* DWORD 2 */
+       u8 rsvd2[32];           /* DWORD 4 */
+       struct amap_mcc_wrb_payload payload;
+};
+
+struct mcc_sge {
+       u32 pa_lo;              /* dword 0 */
+       u32 pa_hi;              /* dword 1 */
+       u32 length;             /* DWORD 2 */
+} __packed;
+
+struct mcc_wrb_payload {
+       union {
+               struct mcc_sge sgl[19];
+               u32 embedded[59];       /* DWORDS 57 to 115 */
+       } u;
+} __packed;
+
+#define MCC_WRB_EMBEDDED_MASK                0x00000001
+
+struct mcc_wrb {
+       u32 dw[0];              /* DWORD 0 */
+       u32 payload_length;
+       u32 tag[2];             /* DWORD 2 */
+       u32 rsvd2[1];           /* DWORD 4 */
+       struct mcc_wrb_payload payload;
+};
+
+unsigned char mgmt_epfw_cleanup(struct beiscsi_hba *phba, unsigned short chute);
+int mgmt_open_connection(struct beiscsi_hba *phba, struct sockaddr *dst_addr,
+                        struct beiscsi_endpoint *beiscsi_ep);
+
+unsigned char mgmt_upload_connection(struct beiscsi_hba *phba,
+                                    unsigned short cid,
+                                    unsigned int upload_flag);
+unsigned char mgmt_invalidate_icds(struct beiscsi_hba *phba,
+                                  unsigned int icd, unsigned int cid);
+
+struct iscsi_invalidate_connection_params_in {
+       struct be_cmd_req_hdr hdr;
+       unsigned int session_handle;
+       unsigned short cid;
+       unsigned short unused;
+       unsigned short cleanup_type;
+       unsigned short save_cfg;
+} __packed;
+
+struct iscsi_invalidate_connection_params_out {
+       unsigned int session_handle;
+       unsigned short cid;
+       unsigned short unused;
+} __packed;
+
+union iscsi_invalidate_connection_params {
+       struct iscsi_invalidate_connection_params_in request;
+       struct iscsi_invalidate_connection_params_out response;
+} __packed;
+
+struct invalidate_command_table {
+       unsigned short icd;
+       unsigned short cid;
+} __packed;
+
+struct invalidate_commands_params_in {
+       struct be_cmd_req_hdr hdr;
+       unsigned int ref_handle;
+       unsigned int icd_count;
+       struct invalidate_command_table table[128];
+       unsigned short cleanup_type;
+       unsigned short unused;
+} __packed;
+
+struct invalidate_commands_params_out {
+       unsigned int ref_handle;
+       unsigned int icd_count;
+       unsigned int icd_status[128];
+} __packed;
+
+union invalidate_commands_params {
+       struct invalidate_commands_params_in request;
+       struct invalidate_commands_params_out response;
+} __packed;
+
+struct mgmt_hba_attributes {
+       u8 flashrom_version_string[32];
+       u8 manufacturer_name[32];
+       u32 supported_modes;
+       u8 seeprom_version_lo;
+       u8 seeprom_version_hi;
+       u8 rsvd0[2];
+       u32 fw_cmd_data_struct_version;
+       u32 ep_fw_data_struct_version;
+       u32 future_reserved[12];
+       u32 default_extended_timeout;
+       u8 controller_model_number[32];
+       u8 controller_description[64];
+       u8 controller_serial_number[32];
+       u8 ip_version_string[32];
+       u8 firmware_version_string[32];
+       u8 bios_version_string[32];
+       u8 redboot_version_string[32];
+       u8 driver_version_string[32];
+       u8 fw_on_flash_version_string[32];
+       u32 functionalities_supported;
+       u16 max_cdblength;
+       u8 asic_revision;
+       u8 generational_guid[16];
+       u8 hba_port_count;
+       u16 default_link_down_timeout;
+       u8 iscsi_ver_min_max;
+       u8 multifunction_device;
+       u8 cache_valid;
+       u8 hba_status;
+       u8 max_domains_supported;
+       u8 phy_port;
+       u32 firmware_post_status;
+       u32 hba_mtu[8];
+       u32 future_u32[4];
+} __packed;
+
+struct mgmt_controller_attributes {
+       struct mgmt_hba_attributes hba_attribs;
+       u16 pci_vendor_id;
+       u16 pci_device_id;
+       u16 pci_sub_vendor_id;
+       u16 pci_sub_system_id;
+       u8 pci_bus_number;
+       u8 pci_device_number;
+       u8 pci_function_number;
+       u8 interface_type;
+       u64 unique_identifier;
+       u8 netfilters;
+       u8 rsvd0[3];
+       u8 future_u32[4];
+} __packed;
+
+struct be_mgmt_controller_attributes {
+       struct be_cmd_req_hdr hdr;
+       struct mgmt_controller_attributes params;
+} __packed;
+
+struct be_mgmt_controller_attributes_resp {
+       struct be_cmd_resp_hdr hdr;
+       struct mgmt_controller_attributes params;
+} __packed;
+
+/* configuration management */
+
+#define GET_MGMT_CONTROLLER_WS(phba)    (phba->pmgmt_ws)
+
+/* MGMT CMD flags */
+
+#define MGMT_CMDH_FREE                (1<<0)
+
+/*  --- MGMT_ERROR_CODES --- */
+/*  Error Codes returned in the status field of the CMD response header */
+#define MGMT_STATUS_SUCCESS 0  /* The CMD completed without errors */
+#define MGMT_STATUS_FAILED 1   /* Error status in the Status field of */
+                               /* the CMD_RESPONSE_HEADER  */
+
+#define ISCSI_GET_PDU_TEMPLATE_ADDRESS(pc, pa) {\
+    pa->lo = phba->init_mem[ISCSI_MEM_GLOBAL_HEADER].mem_array[0].\
+                                       bus_address.u.a32.address_lo;  \
+    pa->hi = phba->init_mem[ISCSI_MEM_GLOBAL_HEADER].mem_array[0].\
+                                       bus_address.u.a32.address_hi;  \
+}
+
+struct beiscsi_endpoint {
+       struct beiscsi_hba *phba;
+       struct beiscsi_sess *sess;
+       struct beiscsi_conn *conn;
+       unsigned short ip_type;
+       char dst6_addr[ISCSI_ADDRESS_BUF_LEN];
+       unsigned long dst_addr;
+       unsigned short ep_cid;
+       unsigned int fw_handle;
+       u16 dst_tcpport;
+       u16 cid_vld;
+};
+
+unsigned char mgmt_get_fw_config(struct be_ctrl_info *ctrl,
+                                struct beiscsi_hba *phba);
+
+unsigned char mgmt_invalidate_connection(struct beiscsi_hba *phba,
+                                        struct beiscsi_endpoint *beiscsi_ep,
+                                        unsigned short cid,
+                                        unsigned short issue_reset,
+                                        unsigned short savecfg_flag);
+#endif
diff --git a/drivers/scsi/bfa/Makefile b/drivers/scsi/bfa/Makefile
new file mode 100644 (file)
index 0000000..1d60094
--- /dev/null
@@ -0,0 +1,15 @@
+obj-$(CONFIG_SCSI_BFA_FC) := bfa.o
+
+bfa-y := bfad.o bfad_intr.o bfad_os.o bfad_im.o bfad_attr.o bfad_fwimg.o
+
+bfa-y += bfa_core.o bfa_ioc.o bfa_iocfc.o bfa_fcxp.o bfa_lps.o
+bfa-y += bfa_hw_cb.o bfa_hw_ct.o bfa_intr.o bfa_timer.o bfa_rport.o 
+bfa-y += bfa_fcport.o bfa_port.o bfa_uf.o bfa_sgpg.o bfa_module.o bfa_ioim.o
+bfa-y += bfa_itnim.o bfa_fcpim.o bfa_tskim.o bfa_log.o bfa_log_module.o
+bfa-y += bfa_csdebug.o bfa_sm.o plog.o
+
+bfa-y += fcbuild.o fabric.o fcpim.o vfapi.o fcptm.o bfa_fcs.o bfa_fcs_port.o 
+bfa-y += bfa_fcs_uf.o bfa_fcs_lport.o fab.o fdmi.o ms.o ns.o scn.o loop.o
+bfa-y += lport_api.o n2n.o rport.o rport_api.o rport_ftrs.o vport.o
+
+ccflags-y := -I$(obj) -I$(obj)/include -I$(obj)/include/cna
diff --git a/drivers/scsi/bfa/bfa_callback_priv.h b/drivers/scsi/bfa/bfa_callback_priv.h
new file mode 100644 (file)
index 0000000..1e3265c
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ */
+
+#ifndef __BFA_CALLBACK_PRIV_H__
+#define __BFA_CALLBACK_PRIV_H__
+
+#include <cs/bfa_q.h>
+
+typedef void    (*bfa_cb_cbfn_t) (void *cbarg, bfa_boolean_t complete);
+
+/**
+ * Generic BFA callback element.
+ */
+struct bfa_cb_qe_s {
+       struct list_head         qe;
+       bfa_cb_cbfn_t  cbfn;
+       bfa_boolean_t   once;
+       u32             rsvd;
+       void           *cbarg;
+};
+
+#define bfa_cb_queue(__bfa, __hcb_qe, __cbfn, __cbarg) do {            \
+       (__hcb_qe)->cbfn  = (__cbfn);      \
+       (__hcb_qe)->cbarg = (__cbarg);      \
+       list_add_tail(&(__hcb_qe)->qe, &(__bfa)->comp_q);      \
+} while (0)
+
+#define bfa_cb_dequeue(__hcb_qe)       list_del(&(__hcb_qe)->qe)
+
+#define bfa_cb_queue_once(__bfa, __hcb_qe, __cbfn, __cbarg) do {       \
+       (__hcb_qe)->cbfn  = (__cbfn);      \
+       (__hcb_qe)->cbarg = (__cbarg);      \
+       if (!(__hcb_qe)->once) {      \
+               list_add_tail((__hcb_qe), &(__bfa)->comp_q);      \
+               (__hcb_qe)->once = BFA_TRUE;                            \
+       }                                                               \
+} while (0)
+
+#define bfa_cb_queue_done(__hcb_qe) do {                               \
+       (__hcb_qe)->once = BFA_FALSE;                                   \
+} while (0)
+
+#endif /* __BFA_CALLBACK_PRIV_H__ */
diff --git a/drivers/scsi/bfa/bfa_cb_ioim_macros.h b/drivers/scsi/bfa/bfa_cb_ioim_macros.h
new file mode 100644 (file)
index 0000000..0050c83
--- /dev/null
@@ -0,0 +1,205 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) 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.
+ */
+
+/**
+ *  bfa_cb_ioim_macros.h BFA IOIM driver interface macros.
+ */
+
+#ifndef __BFA_HCB_IOIM_MACROS_H__
+#define __BFA_HCB_IOIM_MACROS_H__
+
+#include <bfa_os_inc.h>
+/*
+ * #include <linux/dma-mapping.h>
+ *
+ * #include <scsi/scsi.h> #include <scsi/scsi_cmnd.h> #include
+ * <scsi/scsi_device.h> #include <scsi/scsi_host.h>
+ */
+#include "bfad_im_compat.h"
+
+/*
+ * task attribute values in FCP-2 FCP_CMND IU
+ */
+#define SIMPLE_Q    0
+#define HEAD_OF_Q   1
+#define ORDERED_Q   2
+#define ACA_Q       4
+#define UNTAGGED    5
+
+static inline lun_t
+bfad_int_to_lun(u32 luno)
+{
+       union {
+               u16        scsi_lun[4];
+               lun_t           bfa_lun;
+       } lun;
+
+       lun.bfa_lun     = 0;
+       lun.scsi_lun[0] = bfa_os_htons(luno);
+
+       return (lun.bfa_lun);
+}
+
+/**
+ * Get LUN for the I/O request
+ */
+#define bfa_cb_ioim_get_lun(__dio)     \
+       bfad_int_to_lun(((struct scsi_cmnd *)__dio)->device->lun)
+
+/**
+ * Get CDB for the I/O request
+ */
+static inline u8 *
+bfa_cb_ioim_get_cdb(struct bfad_ioim_s *dio)
+{
+       struct scsi_cmnd *cmnd = (struct scsi_cmnd *)dio;
+
+       return ((u8 *) cmnd->cmnd);
+}
+
+/**
+ * Get I/O direction (read/write) for the I/O request
+ */
+static inline enum fcp_iodir
+bfa_cb_ioim_get_iodir(struct bfad_ioim_s *dio)
+{
+       struct scsi_cmnd *cmnd = (struct scsi_cmnd *)dio;
+       enum dma_data_direction dmadir;
+
+       dmadir = cmnd->sc_data_direction;
+       if (dmadir == DMA_TO_DEVICE)
+               return FCP_IODIR_WRITE;
+       else if (dmadir == DMA_FROM_DEVICE)
+               return FCP_IODIR_READ;
+       else
+               return FCP_IODIR_NONE;
+}
+
+/**
+ * Get IO size in bytes for the I/O request
+ */
+static inline u32
+bfa_cb_ioim_get_size(struct bfad_ioim_s *dio)
+{
+       struct scsi_cmnd *cmnd = (struct scsi_cmnd *)dio;
+
+       return (scsi_bufflen(cmnd));
+}
+
+/**
+ * Get timeout for the I/O request
+ */
+static inline u8
+bfa_cb_ioim_get_timeout(struct bfad_ioim_s *dio)
+{
+       struct scsi_cmnd *cmnd = (struct scsi_cmnd *)dio;
+       /*
+        * TBD: need a timeout for scsi passthru
+        */
+       if (cmnd->device->host == NULL)
+               return 4;
+
+       return 0;
+}
+
+/**
+ * Get SG element for the I/O request given the SG element index
+ */
+static inline union bfi_addr_u
+bfa_cb_ioim_get_sgaddr(struct bfad_ioim_s *dio, int sgeid)
+{
+       struct scsi_cmnd *cmnd = (struct scsi_cmnd *)dio;
+       struct scatterlist *sge;
+       u64        addr;
+
+       sge = (struct scatterlist *)scsi_sglist(cmnd) + sgeid;
+       addr = (u64) sg_dma_address(sge);
+
+       return (*(union bfi_addr_u *) &addr);
+}
+
+static inline u32
+bfa_cb_ioim_get_sglen(struct bfad_ioim_s *dio, int sgeid)
+{
+       struct scsi_cmnd *cmnd = (struct scsi_cmnd *)dio;
+       struct scatterlist *sge;
+       u32        len;
+
+       sge = (struct scatterlist *)scsi_sglist(cmnd) + sgeid;
+       len = sg_dma_len(sge);
+
+       return len;
+}
+
+/**
+ * Get Command Reference Number for the I/O request. 0 if none.
+ */
+static inline u8
+bfa_cb_ioim_get_crn(struct bfad_ioim_s *dio)
+{
+       return 0;
+}
+
+/**
+ * Get SAM-3 priority for the I/O request. 0 is default.
+ */
+static inline u8
+bfa_cb_ioim_get_priority(struct bfad_ioim_s *dio)
+{
+       return 0;
+}
+
+/**
+ * Get task attributes for the I/O request. Default is FCP_TASK_ATTR_SIMPLE(0).
+ */
+static inline u8
+bfa_cb_ioim_get_taskattr(struct bfad_ioim_s *dio)
+{
+       struct scsi_cmnd *cmnd = (struct scsi_cmnd *)dio;
+       u8         task_attr = UNTAGGED;
+
+       if (cmnd->device->tagged_supported) {
+               switch (cmnd->tag) {
+               case HEAD_OF_QUEUE_TAG:
+                       task_attr = HEAD_OF_Q;
+                       break;
+               case ORDERED_QUEUE_TAG:
+                       task_attr = ORDERED_Q;
+                       break;
+               default:
+                       task_attr = SIMPLE_Q;
+                       break;
+               }
+       }
+
+       return task_attr;
+}
+
+/**
+ * Get CDB length in bytes for the I/O request. Default is FCP_CMND_CDB_LEN(16).
+ */
+static inline u8
+bfa_cb_ioim_get_cdblen(struct bfad_ioim_s *dio)
+{
+       struct scsi_cmnd *cmnd = (struct scsi_cmnd *)dio;
+
+       return (cmnd->cmd_len);
+}
+
+
+
+#endif /* __BFA_HCB_IOIM_MACROS_H__ */
diff --git a/drivers/scsi/bfa/bfa_cee.c b/drivers/scsi/bfa/bfa_cee.c
new file mode 100644 (file)
index 0000000..7a959c3
--- /dev/null
@@ -0,0 +1,492 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ */
+
+#include <defs/bfa_defs_cee.h>
+#include <cs/bfa_trc.h>
+#include <cs/bfa_log.h>
+#include <cs/bfa_debug.h>
+#include <cee/bfa_cee.h>
+#include <bfi/bfi_cee.h>
+#include <bfi/bfi.h>
+#include <bfa_ioc.h>
+#include <cna/bfa_cna_trcmod.h>
+
+BFA_TRC_FILE(CNA, CEE);
+
+#define bfa_ioc_portid(__ioc) ((__ioc)->port_id)
+#define bfa_lpuid(__arg) bfa_ioc_portid(&(__arg)->ioc)
+
+static void     bfa_cee_format_lldp_cfg(struct bfa_cee_lldp_cfg_s *lldp_cfg);
+static void     bfa_cee_format_dcbcx_stats(struct bfa_cee_dcbx_stats_s
+                                          *dcbcx_stats);
+static void     bfa_cee_format_lldp_stats(struct bfa_cee_lldp_stats_s
+                                         *lldp_stats);
+static void     bfa_cee_format_cfg_stats(struct bfa_cee_cfg_stats_s *cfg_stats);
+static void     bfa_cee_format_cee_cfg(void *buffer);
+static void     bfa_cee_format_cee_stats(void *buffer);
+
+static void
+bfa_cee_format_cee_stats(void *buffer)
+{
+       struct bfa_cee_stats_s *cee_stats = buffer;
+       bfa_cee_format_dcbcx_stats(&cee_stats->dcbx_stats);
+       bfa_cee_format_lldp_stats(&cee_stats->lldp_stats);
+       bfa_cee_format_cfg_stats(&cee_stats->cfg_stats);
+}
+
+static void
+bfa_cee_format_cee_cfg(void *buffer)
+{
+       struct bfa_cee_attr_s *cee_cfg = buffer;
+       bfa_cee_format_lldp_cfg(&cee_cfg->lldp_remote);
+}
+
+static void
+bfa_cee_format_dcbcx_stats(struct bfa_cee_dcbx_stats_s *dcbcx_stats)
+{
+       dcbcx_stats->subtlvs_unrecognized =
+               bfa_os_ntohl(dcbcx_stats->subtlvs_unrecognized);
+       dcbcx_stats->negotiation_failed =
+               bfa_os_ntohl(dcbcx_stats->negotiation_failed);
+       dcbcx_stats->remote_cfg_changed =
+               bfa_os_ntohl(dcbcx_stats->remote_cfg_changed);
+       dcbcx_stats->tlvs_received = bfa_os_ntohl(dcbcx_stats->tlvs_received);
+       dcbcx_stats->tlvs_invalid = bfa_os_ntohl(dcbcx_stats->tlvs_invalid);
+       dcbcx_stats->seqno = bfa_os_ntohl(dcbcx_stats->seqno);
+       dcbcx_stats->ackno = bfa_os_ntohl(dcbcx_stats->ackno);
+       dcbcx_stats->recvd_seqno = bfa_os_ntohl(dcbcx_stats->recvd_seqno);
+       dcbcx_stats->recvd_ackno = bfa_os_ntohl(dcbcx_stats->recvd_ackno);
+}
+
+static void
+bfa_cee_format_lldp_stats(struct bfa_cee_lldp_stats_s *lldp_stats)
+{
+       lldp_stats->frames_transmitted =
+               bfa_os_ntohl(lldp_stats->frames_transmitted);
+       lldp_stats->frames_aged_out = bfa_os_ntohl(lldp_stats->frames_aged_out);
+       lldp_stats->frames_discarded =
+               bfa_os_ntohl(lldp_stats->frames_discarded);
+       lldp_stats->frames_in_error = bfa_os_ntohl(lldp_stats->frames_in_error);
+       lldp_stats->frames_rcvd = bfa_os_ntohl(lldp_stats->frames_rcvd);
+       lldp_stats->tlvs_discarded = bfa_os_ntohl(lldp_stats->tlvs_discarded);
+       lldp_stats->tlvs_unrecognized =
+               bfa_os_ntohl(lldp_stats->tlvs_unrecognized);
+}
+
+static void
+bfa_cee_format_cfg_stats(struct bfa_cee_cfg_stats_s *cfg_stats)
+{
+       cfg_stats->cee_status_down = bfa_os_ntohl(cfg_stats->cee_status_down);
+       cfg_stats->cee_status_up = bfa_os_ntohl(cfg_stats->cee_status_up);
+       cfg_stats->cee_hw_cfg_changed =
+               bfa_os_ntohl(cfg_stats->cee_hw_cfg_changed);
+       cfg_stats->recvd_invalid_cfg =
+               bfa_os_ntohl(cfg_stats->recvd_invalid_cfg);
+}
+
+static void
+bfa_cee_format_lldp_cfg(struct bfa_cee_lldp_cfg_s *lldp_cfg)
+{
+       lldp_cfg->time_to_interval = bfa_os_ntohs(lldp_cfg->time_to_interval);
+       lldp_cfg->enabled_system_cap =
+               bfa_os_ntohs(lldp_cfg->enabled_system_cap);
+}
+
+/**
+ * bfa_cee_attr_meminfo()
+ *
+ *
+ * @param[in] void
+ *
+ * @return Size of DMA region
+ */
+static          u32
+bfa_cee_attr_meminfo(void)
+{
+       return BFA_ROUNDUP(sizeof(struct bfa_cee_attr_s), BFA_DMA_ALIGN_SZ);
+}
+
+/**
+ * bfa_cee_stats_meminfo()
+ *
+ *
+ * @param[in] void
+ *
+ * @return Size of DMA region
+ */
+static          u32
+bfa_cee_stats_meminfo(void)
+{
+       return BFA_ROUNDUP(sizeof(struct bfa_cee_stats_s), BFA_DMA_ALIGN_SZ);
+}
+
+/**
+ * bfa_cee_get_attr_isr()
+ *
+ *
+ * @param[in] cee - Pointer to the CEE module
+ *            status - Return status from the f/w
+ *
+ * @return void
+ */
+static void
+bfa_cee_get_attr_isr(struct bfa_cee_s *cee, bfa_status_t status)
+{
+       cee->get_attr_status = status;
+       bfa_trc(cee, 0);
+       if (status == BFA_STATUS_OK) {
+               bfa_trc(cee, 0);
+               /*
+                * The requested data has been copied to the DMA area, *process
+                * it.
+                */
+               memcpy(cee->attr, cee->attr_dma.kva,
+                      sizeof(struct bfa_cee_attr_s));
+               bfa_cee_format_cee_cfg(cee->attr);
+       }
+       cee->get_attr_pending = BFA_FALSE;
+       if (cee->cbfn.get_attr_cbfn) {
+               bfa_trc(cee, 0);
+               cee->cbfn.get_attr_cbfn(cee->cbfn.get_attr_cbarg, status);
+       }
+       bfa_trc(cee, 0);
+}
+
+/**
+ * bfa_cee_get_attr_isr()
+ *
+ *
+ * @param[in] cee - Pointer to the CEE module
+ *            status - Return status from the f/w
+ *
+ * @return void
+ */
+static void
+bfa_cee_get_stats_isr(struct bfa_cee_s *cee, bfa_status_t status)
+{
+       cee->get_stats_status = status;
+       bfa_trc(cee, 0);
+       if (status == BFA_STATUS_OK) {
+               bfa_trc(cee, 0);
+               /*
+                * The requested data has been copied to the DMA area, process
+                * it.
+                */
+               memcpy(cee->stats, cee->stats_dma.kva,
+                      sizeof(struct bfa_cee_stats_s));
+               bfa_cee_format_cee_stats(cee->stats);
+       }
+       cee->get_stats_pending = BFA_FALSE;
+       bfa_trc(cee, 0);
+       if (cee->cbfn.get_stats_cbfn) {
+               bfa_trc(cee, 0);
+               cee->cbfn.get_stats_cbfn(cee->cbfn.get_stats_cbarg, status);
+       }
+       bfa_trc(cee, 0);
+}
+
+/**
+ * bfa_cee_get_attr_isr()
+ *
+ *
+ * @param[in] cee - Pointer to the CEE module
+ *            status - Return status from the f/w
+ *
+ * @return void
+ */
+static void
+bfa_cee_reset_stats_isr(struct bfa_cee_s *cee, bfa_status_t status)
+{
+       cee->reset_stats_status = status;
+       cee->reset_stats_pending = BFA_FALSE;
+       if (cee->cbfn.reset_stats_cbfn)
+               cee->cbfn.reset_stats_cbfn(cee->cbfn.reset_stats_cbarg, status);
+}
+
+/**
+ * bfa_cee_meminfo()
+ *
+ *
+ * @param[in] void
+ *
+ * @return Size of DMA region
+ */
+u32
+bfa_cee_meminfo(void)
+{
+       return (bfa_cee_attr_meminfo() + bfa_cee_stats_meminfo());
+}
+
+/**
+ * bfa_cee_mem_claim()
+ *
+ *
+ * @param[in] cee CEE module pointer
+ *           dma_kva Kernel Virtual Address of CEE DMA Memory
+ *           dma_pa  Physical Address of CEE DMA Memory
+ *
+ * @return void
+ */
+void
+bfa_cee_mem_claim(struct bfa_cee_s *cee, u8 *dma_kva, u64 dma_pa)
+{
+       cee->attr_dma.kva = dma_kva;
+       cee->attr_dma.pa = dma_pa;
+       cee->stats_dma.kva = dma_kva + bfa_cee_attr_meminfo();
+       cee->stats_dma.pa = dma_pa + bfa_cee_attr_meminfo();
+       cee->attr = (struct bfa_cee_attr_s *)dma_kva;
+       cee->stats =
+               (struct bfa_cee_stats_s *)(dma_kva + bfa_cee_attr_meminfo());
+}
+
+/**
+ * bfa_cee_get_attr()
+ *
+ *   Send the request to the f/w to fetch CEE attributes.
+ *
+ * @param[in] Pointer to the CEE module data structure.
+ *
+ * @return Status
+ */
+
+bfa_status_t
+bfa_cee_get_attr(struct bfa_cee_s *cee, struct bfa_cee_attr_s *attr,
+                bfa_cee_get_attr_cbfn_t cbfn, void *cbarg)
+{
+       struct bfi_cee_get_req_s *cmd;
+
+       bfa_assert((cee != NULL) && (cee->ioc != NULL));
+       bfa_trc(cee, 0);
+       if (!bfa_ioc_is_operational(cee->ioc)) {
+               bfa_trc(cee, 0);
+               return BFA_STATUS_IOC_FAILURE;
+       }
+       if (cee->get_attr_pending == BFA_TRUE) {
+               bfa_trc(cee, 0);
+               return BFA_STATUS_DEVBUSY;
+       }
+       cee->get_attr_pending = BFA_TRUE;
+       cmd = (struct bfi_cee_get_req_s *)cee->get_cfg_mb.msg;
+       cee->attr = attr;
+       cee->cbfn.get_attr_cbfn = cbfn;
+       cee->cbfn.get_attr_cbarg = cbarg;
+       bfi_h2i_set(cmd->mh, BFI_MC_CEE, BFI_CEE_H2I_GET_CFG_REQ,
+                   bfa_ioc_portid(cee->ioc));
+       bfa_dma_be_addr_set(cmd->dma_addr, cee->attr_dma.pa);
+       bfa_ioc_mbox_queue(cee->ioc, &cee->get_cfg_mb);
+       bfa_trc(cee, 0);
+
+       return BFA_STATUS_OK;
+}
+
+/**
+ * bfa_cee_get_stats()
+ *
+ *   Send the request to the f/w to fetch CEE statistics.
+ *
+ * @param[in] Pointer to the CEE module data structure.
+ *
+ * @return Status
+ */
+
+bfa_status_t
+bfa_cee_get_stats(struct bfa_cee_s *cee, struct bfa_cee_stats_s *stats,
+                 bfa_cee_get_stats_cbfn_t cbfn, void *cbarg)
+{
+       struct bfi_cee_get_req_s *cmd;
+
+       bfa_assert((cee != NULL) && (cee->ioc != NULL));
+
+       if (!bfa_ioc_is_operational(cee->ioc)) {
+               bfa_trc(cee, 0);
+               return BFA_STATUS_IOC_FAILURE;
+       }
+       if (cee->get_stats_pending == BFA_TRUE) {
+               bfa_trc(cee, 0);
+               return BFA_STATUS_DEVBUSY;
+       }
+       cee->get_stats_pending = BFA_TRUE;
+       cmd = (struct bfi_cee_get_req_s *)cee->get_stats_mb.msg;
+       cee->stats = stats;
+       cee->cbfn.get_stats_cbfn = cbfn;
+       cee->cbfn.get_stats_cbarg = cbarg;
+       bfi_h2i_set(cmd->mh, BFI_MC_CEE, BFI_CEE_H2I_GET_STATS_REQ,
+                   bfa_ioc_portid(cee->ioc));
+       bfa_dma_be_addr_set(cmd->dma_addr, cee->stats_dma.pa);
+       bfa_ioc_mbox_queue(cee->ioc, &cee->get_stats_mb);
+       bfa_trc(cee, 0);
+
+       return BFA_STATUS_OK;
+}
+
+/**
+ * bfa_cee_reset_stats()
+ *
+ *
+ * @param[in] Pointer to the CEE module data structure.
+ *
+ * @return Status
+ */
+
+bfa_status_t
+bfa_cee_reset_stats(struct bfa_cee_s *cee, bfa_cee_reset_stats_cbfn_t cbfn,
+                   void *cbarg)
+{
+       struct bfi_cee_reset_stats_s *cmd;
+
+       bfa_assert((cee != NULL) && (cee->ioc != NULL));
+       if (!bfa_ioc_is_operational(cee->ioc)) {
+               bfa_trc(cee, 0);
+               return BFA_STATUS_IOC_FAILURE;
+       }
+       if (cee->reset_stats_pending == BFA_TRUE) {
+               bfa_trc(cee, 0);
+               return BFA_STATUS_DEVBUSY;
+       }
+       cee->reset_stats_pending = BFA_TRUE;
+       cmd = (struct bfi_cee_reset_stats_s *)cee->reset_stats_mb.msg;
+       cee->cbfn.reset_stats_cbfn = cbfn;
+       cee->cbfn.reset_stats_cbarg = cbarg;
+       bfi_h2i_set(cmd->mh, BFI_MC_CEE, BFI_CEE_H2I_RESET_STATS,
+                   bfa_ioc_portid(cee->ioc));
+       bfa_ioc_mbox_queue(cee->ioc, &cee->reset_stats_mb);
+       bfa_trc(cee, 0);
+       return BFA_STATUS_OK;
+}
+
+/**
+ * bfa_cee_isrs()
+ *
+ *
+ * @param[in] Pointer to the CEE module data structure.
+ *
+ * @return void
+ */
+
+void
+bfa_cee_isr(void *cbarg, struct bfi_mbmsg_s *m)
+{
+       union bfi_cee_i2h_msg_u *msg;
+       struct bfi_cee_get_rsp_s *get_rsp;
+       struct bfa_cee_s *cee = (struct bfa_cee_s *)cbarg;
+       msg = (union bfi_cee_i2h_msg_u *)m;
+       get_rsp = (struct bfi_cee_get_rsp_s *)m;
+       bfa_trc(cee, msg->mh.msg_id);
+       switch (msg->mh.msg_id) {
+       case BFI_CEE_I2H_GET_CFG_RSP:
+               bfa_trc(cee, get_rsp->cmd_status);
+               bfa_cee_get_attr_isr(cee, get_rsp->cmd_status);
+               break;
+       case BFI_CEE_I2H_GET_STATS_RSP:
+               bfa_cee_get_stats_isr(cee, get_rsp->cmd_status);
+               break;
+       case BFI_CEE_I2H_RESET_STATS_RSP:
+               bfa_cee_reset_stats_isr(cee, get_rsp->cmd_status);
+               break;
+       default:
+               bfa_assert(0);
+       }
+}
+
+/**
+ * bfa_cee_hbfail()
+ *
+ *
+ * @param[in] Pointer to the CEE module data structure.
+ *
+ * @return void
+ */
+
+void
+bfa_cee_hbfail(void *arg)
+{
+       struct bfa_cee_s *cee;
+       cee = (struct bfa_cee_s *)arg;
+
+       if (cee->get_attr_pending == BFA_TRUE) {
+               cee->get_attr_status = BFA_STATUS_FAILED;
+               cee->get_attr_pending = BFA_FALSE;
+               if (cee->cbfn.get_attr_cbfn) {
+                       cee->cbfn.get_attr_cbfn(cee->cbfn.get_attr_cbarg,
+                                               BFA_STATUS_FAILED);
+               }
+       }
+       if (cee->get_stats_pending == BFA_TRUE) {
+               cee->get_stats_status = BFA_STATUS_FAILED;
+               cee->get_stats_pending = BFA_FALSE;
+               if (cee->cbfn.get_stats_cbfn) {
+                       cee->cbfn.get_stats_cbfn(cee->cbfn.get_stats_cbarg,
+                                                BFA_STATUS_FAILED);
+               }
+       }
+       if (cee->reset_stats_pending == BFA_TRUE) {
+               cee->reset_stats_status = BFA_STATUS_FAILED;
+               cee->reset_stats_pending = BFA_FALSE;
+               if (cee->cbfn.reset_stats_cbfn) {
+                       cee->cbfn.reset_stats_cbfn(cee->cbfn.reset_stats_cbarg,
+                                                  BFA_STATUS_FAILED);
+               }
+       }
+}
+
+/**
+ * bfa_cee_attach()
+ *
+ *
+ * @param[in] cee - Pointer to the CEE module data structure
+ *            ioc - Pointer to the ioc module data structure
+ *            dev - Pointer to the device driver module data structure
+ *                  The device driver specific mbox ISR functions have
+ *                  this pointer as one of the parameters.
+ *            trcmod -
+ *            logmod -
+ *
+ * @return void
+ */
+void
+bfa_cee_attach(struct bfa_cee_s *cee, struct bfa_ioc_s *ioc, void *dev,
+              struct bfa_trc_mod_s *trcmod, struct bfa_log_mod_s *logmod)
+{
+       bfa_assert(cee != NULL);
+       cee->dev = dev;
+       cee->trcmod = trcmod;
+       cee->logmod = logmod;
+       cee->ioc = ioc;
+
+       bfa_ioc_mbox_regisr(cee->ioc, BFI_MC_CEE, bfa_cee_isr, cee);
+       bfa_ioc_hbfail_init(&cee->hbfail, bfa_cee_hbfail, cee);
+       bfa_ioc_hbfail_register(cee->ioc, &cee->hbfail);
+       bfa_trc(cee, 0);
+}
+
+/**
+ * bfa_cee_detach()
+ *
+ *
+ * @param[in] cee - Pointer to the CEE module data structure
+ *
+ * @return void
+ */
+void
+bfa_cee_detach(struct bfa_cee_s *cee)
+{
+       /*
+        * For now, just check if there is some ioctl pending and mark that as
+        * failed?
+        */
+       /* bfa_cee_hbfail(cee); */
+}
diff --git a/drivers/scsi/bfa/bfa_core.c b/drivers/scsi/bfa/bfa_core.c
new file mode 100644 (file)
index 0000000..44e2d11
--- /dev/null
@@ -0,0 +1,402 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ */
+
+#include <bfa.h>
+#include <defs/bfa_defs_pci.h>
+#include <cs/bfa_debug.h>
+#include <bfa_iocfc.h>
+
+#define DEF_CFG_NUM_FABRICS         1
+#define DEF_CFG_NUM_LPORTS          256
+#define DEF_CFG_NUM_CQS             4
+#define DEF_CFG_NUM_IOIM_REQS       (BFA_IOIM_MAX)
+#define DEF_CFG_NUM_TSKIM_REQS      128
+#define DEF_CFG_NUM_FCXP_REQS       64
+#define DEF_CFG_NUM_UF_BUFS         64
+#define DEF_CFG_NUM_RPORTS          1024
+#define DEF_CFG_NUM_ITNIMS          (DEF_CFG_NUM_RPORTS)
+#define DEF_CFG_NUM_TINS            256
+
+#define DEF_CFG_NUM_SGPGS           2048
+#define DEF_CFG_NUM_REQQ_ELEMS      256
+#define DEF_CFG_NUM_RSPQ_ELEMS      64
+#define DEF_CFG_NUM_SBOOT_TGTS      16
+#define DEF_CFG_NUM_SBOOT_LUNS      16
+
+/**
+ * Use this function query the memory requirement of the BFA library.
+ * This function needs to be called before bfa_attach() to get the
+ * memory required of the BFA layer for a given driver configuration.
+ *
+ * This call will fail, if the cap is out of range compared to pre-defined
+ * values within the BFA library
+ *
+ * @param[in] cfg -    pointer to bfa_ioc_cfg_t. Driver layer should indicate
+ *                     its configuration in this structure.
+ *                     The default values for struct bfa_iocfc_cfg_s can be
+ *                     fetched using bfa_cfg_get_default() API.
+ *
+ *                     If cap's boundary check fails, the library will use
+ *                     the default bfa_cap_t values (and log a warning msg).
+ *
+ * @param[out] meminfo - pointer to bfa_meminfo_t. This content
+ *                     indicates the memory type (see bfa_mem_type_t) and
+ *                     amount of memory required.
+ *
+ *                     Driver should allocate the memory, populate the
+ *                     starting address for each block and provide the same
+ *                     structure as input parameter to bfa_attach() call.
+ *
+ * @return void
+ *
+ * Special Considerations: @note
+ */
+void
+bfa_cfg_get_meminfo(struct bfa_iocfc_cfg_s *cfg, struct bfa_meminfo_s *meminfo)
+{
+       int             i;
+       u32        km_len = 0, dm_len = 0;
+
+       bfa_assert((cfg != NULL) && (meminfo != NULL));
+
+       bfa_os_memset((void *)meminfo, 0, sizeof(struct bfa_meminfo_s));
+       meminfo->meminfo[BFA_MEM_TYPE_KVA - 1].mem_type =
+               BFA_MEM_TYPE_KVA;
+       meminfo->meminfo[BFA_MEM_TYPE_DMA - 1].mem_type =
+               BFA_MEM_TYPE_DMA;
+
+       bfa_iocfc_meminfo(cfg, &km_len, &dm_len);
+
+       for (i = 0; hal_mods[i]; i++)
+               hal_mods[i]->meminfo(cfg, &km_len, &dm_len);
+
+
+       meminfo->meminfo[BFA_MEM_TYPE_KVA - 1].mem_len = km_len;
+       meminfo->meminfo[BFA_MEM_TYPE_DMA - 1].mem_len = dm_len;
+}
+
+/**
+ * Use this function to do attach the driver instance with the BFA
+ * library. This function will not trigger any HW initialization
+ * process (which will be done in bfa_init() call)
+ *
+ * This call will fail, if the cap is out of range compared to
+ * pre-defined values within the BFA library
+ *
+ * @param[out] bfa     Pointer to bfa_t.
+ * @param[in]  bfad    Opaque handle back to the driver's IOC structure
+ * @param[in]  cfg     Pointer to bfa_ioc_cfg_t. Should be same structure
+ *                     that was used in bfa_cfg_get_meminfo().
+ * @param[in]  meminfo Pointer to bfa_meminfo_t. The driver should
+ *                     use the bfa_cfg_get_meminfo() call to
+ *                     find the memory blocks required, allocate the
+ *                     required memory and provide the starting addresses.
+ * @param[in]  pcidev  pointer to struct bfa_pcidev_s
+ *
+ * @return
+ * void
+ *
+ * Special Considerations:
+ *
+ * @note
+ *
+ */
+void
+bfa_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
+              struct bfa_meminfo_s *meminfo, struct bfa_pcidev_s *pcidev)
+{
+       int             i;
+       struct bfa_mem_elem_s *melem;
+
+       bfa->fcs = BFA_FALSE;
+
+       bfa_assert((cfg != NULL) && (meminfo != NULL));
+
+       /**
+        * initialize all memory pointers for iterative allocation
+        */
+       for (i = 0; i < BFA_MEM_TYPE_MAX; i++) {
+               melem = meminfo->meminfo + i;
+               melem->kva_curp = melem->kva;
+               melem->dma_curp = melem->dma;
+       }
+
+       bfa_iocfc_attach(bfa, bfad, cfg, meminfo, pcidev);
+
+       for (i = 0; hal_mods[i]; i++)
+               hal_mods[i]->attach(bfa, bfad, cfg, meminfo, pcidev);
+
+}
+
+/**
+ * Use this function to delete a BFA IOC. IOC should be stopped (by
+ * calling bfa_stop()) before this function call.
+ *
+ * @param[in] bfa - pointer to bfa_t.
+ *
+ * @return
+ * void
+ *
+ * Special Considerations:
+ *
+ * @note
+ */
+void
+bfa_detach(struct bfa_s *bfa)
+{
+       int     i;
+
+       for (i = 0; hal_mods[i]; i++)
+               hal_mods[i]->detach(bfa);
+
+       bfa_iocfc_detach(bfa);
+}
+
+
+void
+bfa_init_trc(struct bfa_s *bfa, struct bfa_trc_mod_s *trcmod)
+{
+       bfa->trcmod = trcmod;
+}
+
+
+void
+bfa_init_log(struct bfa_s *bfa, struct bfa_log_mod_s *logmod)
+{
+       bfa->logm = logmod;
+}
+
+
+void
+bfa_init_aen(struct bfa_s *bfa, struct bfa_aen_s *aen)
+{
+       bfa->aen = aen;
+}
+
+void
+bfa_init_plog(struct bfa_s *bfa, struct bfa_plog_s *plog)
+{
+       bfa->plog = plog;
+}
+
+/**
+ * Initialize IOC.
+ *
+ * This function will return immediately, when the IOC initialization is
+ * completed, the bfa_cb_init() will be called.
+ *
+ * @param[in]  bfa     instance
+ *
+ * @return void
+ *
+ * Special Considerations:
+ *
+ * @note
+ * When this function returns, the driver should register the interrupt service
+ * routine(s) and enable the device interrupts. If this is not done,
+ * bfa_cb_init() will never get called
+ */
+void
+bfa_init(struct bfa_s *bfa)
+{
+       bfa_iocfc_init(bfa);
+}
+
+/**
+ * Use this function initiate the IOC configuration setup. This function
+ * will return immediately.
+ *
+ * @param[in]  bfa     instance
+ *
+ * @return None
+ */
+void
+bfa_start(struct bfa_s *bfa)
+{
+       bfa_iocfc_start(bfa);
+}
+
+/**
+ * Use this function quiese the IOC. This function will return immediately,
+ * when the IOC is actually stopped, the bfa_cb_stop() will be called.
+ *
+ * @param[in]  bfa - pointer to bfa_t.
+ *
+ * @return None
+ *
+ * Special Considerations:
+ * bfa_cb_stop() could be called before or after bfa_stop() returns.
+ *
+ * @note
+ * In case of any failure, we could handle it automatically by doing a
+ * reset and then succeed the bfa_stop() call.
+ */
+void
+bfa_stop(struct bfa_s *bfa)
+{
+       bfa_iocfc_stop(bfa);
+}
+
+void
+bfa_comp_deq(struct bfa_s *bfa, struct list_head *comp_q)
+{
+       INIT_LIST_HEAD(comp_q);
+       list_splice_tail_init(&bfa->comp_q, comp_q);
+}
+
+void
+bfa_comp_process(struct bfa_s *bfa, struct list_head *comp_q)
+{
+       struct list_head        *qe;
+       struct list_head        *qen;
+       struct bfa_cb_qe_s   *hcb_qe;
+
+       list_for_each_safe(qe, qen, comp_q) {
+               hcb_qe = (struct bfa_cb_qe_s *) qe;
+               hcb_qe->cbfn(hcb_qe->cbarg, BFA_TRUE);
+       }
+}
+
+void
+bfa_comp_free(struct bfa_s *bfa, struct list_head *comp_q)
+{
+       struct list_head        *qe;
+       struct bfa_cb_qe_s   *hcb_qe;
+
+       while (!list_empty(comp_q)) {
+               bfa_q_deq(comp_q, &qe);
+               hcb_qe = (struct bfa_cb_qe_s *) qe;
+               hcb_qe->cbfn(hcb_qe->cbarg, BFA_FALSE);
+       }
+}
+
+void
+bfa_attach_fcs(struct bfa_s *bfa)
+{
+       bfa->fcs = BFA_TRUE;
+}
+
+/**
+ * Periodic timer heart beat from driver
+ */
+void
+bfa_timer_tick(struct bfa_s *bfa)
+{
+       bfa_timer_beat(&bfa->timer_mod);
+}
+
+#ifndef BFA_BIOS_BUILD
+/**
+ * Return the list of PCI vendor/device id lists supported by this
+ * BFA instance.
+ */
+void
+bfa_get_pciids(struct bfa_pciid_s **pciids, int *npciids)
+{
+       static struct bfa_pciid_s __pciids[] = {
+               {BFA_PCI_VENDOR_ID_BROCADE, BFA_PCI_DEVICE_ID_FC_8G2P},
+               {BFA_PCI_VENDOR_ID_BROCADE, BFA_PCI_DEVICE_ID_FC_8G1P},
+               {BFA_PCI_VENDOR_ID_BROCADE, BFA_PCI_DEVICE_ID_CT},
+       };
+
+       *npciids = sizeof(__pciids) / sizeof(__pciids[0]);
+       *pciids = __pciids;
+}
+
+/**
+ * Use this function query the default struct bfa_iocfc_cfg_s value (compiled
+ * into BFA layer). The OS driver can then turn back and overwrite entries that
+ * have been configured by the user.
+ *
+ * @param[in] cfg - pointer to bfa_ioc_cfg_t
+ *
+ * @return
+ *     void
+ *
+ * Special Considerations:
+ *     note
+ */
+void
+bfa_cfg_get_default(struct bfa_iocfc_cfg_s *cfg)
+{
+       cfg->fwcfg.num_fabrics = DEF_CFG_NUM_FABRICS;
+       cfg->fwcfg.num_lports = DEF_CFG_NUM_LPORTS;
+       cfg->fwcfg.num_rports = DEF_CFG_NUM_RPORTS;
+       cfg->fwcfg.num_ioim_reqs = DEF_CFG_NUM_IOIM_REQS;
+       cfg->fwcfg.num_tskim_reqs = DEF_CFG_NUM_TSKIM_REQS;
+       cfg->fwcfg.num_fcxp_reqs = DEF_CFG_NUM_FCXP_REQS;
+       cfg->fwcfg.num_uf_bufs = DEF_CFG_NUM_UF_BUFS;
+       cfg->fwcfg.num_cqs = DEF_CFG_NUM_CQS;
+
+       cfg->drvcfg.num_reqq_elems = DEF_CFG_NUM_REQQ_ELEMS;
+       cfg->drvcfg.num_rspq_elems = DEF_CFG_NUM_RSPQ_ELEMS;
+       cfg->drvcfg.num_sgpgs = DEF_CFG_NUM_SGPGS;
+       cfg->drvcfg.num_sboot_tgts = DEF_CFG_NUM_SBOOT_TGTS;
+       cfg->drvcfg.num_sboot_luns = DEF_CFG_NUM_SBOOT_LUNS;
+       cfg->drvcfg.path_tov = BFA_FCPIM_PATHTOV_DEF;
+       cfg->drvcfg.ioc_recover = BFA_FALSE;
+       cfg->drvcfg.delay_comp = BFA_FALSE;
+
+}
+
+void
+bfa_cfg_get_min(struct bfa_iocfc_cfg_s *cfg)
+{
+       bfa_cfg_get_default(cfg);
+       cfg->fwcfg.num_ioim_reqs   = BFA_IOIM_MIN;
+       cfg->fwcfg.num_tskim_reqs  = BFA_TSKIM_MIN;
+       cfg->fwcfg.num_fcxp_reqs   = BFA_FCXP_MIN;
+       cfg->fwcfg.num_uf_bufs     = BFA_UF_MIN;
+       cfg->fwcfg.num_rports      = BFA_RPORT_MIN;
+
+       cfg->drvcfg.num_sgpgs      = BFA_SGPG_MIN;
+       cfg->drvcfg.num_reqq_elems = BFA_REQQ_NELEMS_MIN;
+       cfg->drvcfg.num_rspq_elems = BFA_RSPQ_NELEMS_MIN;
+       cfg->drvcfg.min_cfg        = BFA_TRUE;
+}
+
+void
+bfa_get_attr(struct bfa_s *bfa, struct bfa_ioc_attr_s *ioc_attr)
+{
+       bfa_ioc_get_attr(&bfa->ioc, ioc_attr);
+}
+
+/**
+ * Retrieve firmware trace information on IOC failure.
+ */
+bfa_status_t
+bfa_debug_fwsave(struct bfa_s *bfa, void *trcdata, int *trclen)
+{
+       return bfa_ioc_debug_fwsave(&bfa->ioc, trcdata, trclen);
+}
+
+/**
+ *             Fetch firmware trace data.
+ *
+ * @param[in]          bfa                     BFA instance
+ * @param[out]         trcdata         Firmware trace buffer
+ * @param[in,out]      trclen          Firmware trace buffer len
+ *
+ * @retval BFA_STATUS_OK                       Firmware trace is fetched.
+ * @retval BFA_STATUS_INPROGRESS       Firmware trace fetch is in progress.
+ */
+bfa_status_t
+bfa_debug_fwtrc(struct bfa_s *bfa, void *trcdata, int *trclen)
+{
+       return bfa_ioc_debug_fwtrc(&bfa->ioc, trcdata, trclen);
+}
+#endif
diff --git a/drivers/scsi/bfa/bfa_csdebug.c b/drivers/scsi/bfa/bfa_csdebug.c
new file mode 100644 (file)
index 0000000..1b71d34
--- /dev/null
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ */
+
+#include <cs/bfa_debug.h>
+#include <bfa_os_inc.h>
+#include <cs/bfa_q.h>
+#include <log/bfa_log_hal.h>
+
+/**
+ *  cs_debug_api
+ */
+
+
+void
+bfa_panic(int line, char *file, char *panicstr)
+{
+       bfa_log(NULL, BFA_LOG_HAL_ASSERT, file, line, panicstr);
+       bfa_os_panic();
+}
+
+void
+bfa_sm_panic(struct bfa_log_mod_s *logm, int line, char *file, int event)
+{
+       bfa_log(logm, BFA_LOG_HAL_SM_ASSERT, file, line, event);
+       bfa_os_panic();
+}
+
+int
+bfa_q_is_on_q_func(struct list_head *q, struct list_head *qe)
+{
+       struct list_head        *tqe;
+
+       tqe = bfa_q_next(q);
+       while (tqe != q) {
+               if (tqe == qe)
+                       return (1);
+               tqe = bfa_q_next(tqe);
+               if (tqe == NULL)
+                       break;
+       }
+       return (0);
+}
+
+
diff --git a/drivers/scsi/bfa/bfa_fcpim.c b/drivers/scsi/bfa/bfa_fcpim.c
new file mode 100644 (file)
index 0000000..401babe
--- /dev/null
@@ -0,0 +1,175 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ */
+
+#include <bfa.h>
+#include <log/bfa_log_hal.h>
+
+BFA_TRC_FILE(HAL, FCPIM);
+BFA_MODULE(fcpim);
+
+/**
+ *  hal_fcpim_mod BFA FCP Initiator Mode module
+ */
+
+/**
+ *             Compute and return memory needed by FCP(im) module.
+ */
+static void
+bfa_fcpim_meminfo(struct bfa_iocfc_cfg_s *cfg, u32 *km_len,
+               u32 *dm_len)
+{
+       bfa_itnim_meminfo(cfg, km_len, dm_len);
+
+       /**
+        * IO memory
+        */
+       if (cfg->fwcfg.num_ioim_reqs < BFA_IOIM_MIN)
+               cfg->fwcfg.num_ioim_reqs = BFA_IOIM_MIN;
+       else if (cfg->fwcfg.num_ioim_reqs > BFA_IOIM_MAX)
+               cfg->fwcfg.num_ioim_reqs = BFA_IOIM_MAX;
+
+       *km_len += cfg->fwcfg.num_ioim_reqs *
+         (sizeof(struct bfa_ioim_s) + sizeof(struct bfa_ioim_sp_s));
+
+       *dm_len += cfg->fwcfg.num_ioim_reqs * BFI_IOIM_SNSLEN;
+
+       /**
+        * task management command memory
+        */
+       if (cfg->fwcfg.num_tskim_reqs < BFA_TSKIM_MIN)
+               cfg->fwcfg.num_tskim_reqs = BFA_TSKIM_MIN;
+       *km_len += cfg->fwcfg.num_tskim_reqs * sizeof(struct bfa_tskim_s);
+}
+
+
+static void
+bfa_fcpim_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
+                    struct bfa_meminfo_s *meminfo, struct bfa_pcidev_s *pcidev)
+{
+       struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(bfa);
+
+       bfa_trc(bfa, cfg->drvcfg.path_tov);
+       bfa_trc(bfa, cfg->fwcfg.num_rports);
+       bfa_trc(bfa, cfg->fwcfg.num_ioim_reqs);
+       bfa_trc(bfa, cfg->fwcfg.num_tskim_reqs);
+
+       fcpim->bfa            = bfa;
+       fcpim->num_itnims     = cfg->fwcfg.num_rports;
+       fcpim->num_ioim_reqs  = cfg->fwcfg.num_ioim_reqs;
+       fcpim->num_tskim_reqs = cfg->fwcfg.num_tskim_reqs;
+       fcpim->path_tov       = cfg->drvcfg.path_tov;
+       fcpim->delay_comp         = cfg->drvcfg.delay_comp;
+
+       bfa_itnim_attach(fcpim, meminfo);
+       bfa_tskim_attach(fcpim, meminfo);
+       bfa_ioim_attach(fcpim, meminfo);
+}
+
+static void
+bfa_fcpim_initdone(struct bfa_s *bfa)
+{
+}
+
+static void
+bfa_fcpim_detach(struct bfa_s *bfa)
+{
+       struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(bfa);
+
+       bfa_ioim_detach(fcpim);
+       bfa_tskim_detach(fcpim);
+}
+
+static void
+bfa_fcpim_start(struct bfa_s *bfa)
+{
+}
+
+static void
+bfa_fcpim_stop(struct bfa_s *bfa)
+{
+}
+
+static void
+bfa_fcpim_iocdisable(struct bfa_s *bfa)
+{
+       struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(bfa);
+       struct bfa_itnim_s *itnim;
+       struct list_head        *qe, *qen;
+
+       list_for_each_safe(qe, qen, &fcpim->itnim_q) {
+               itnim = (struct bfa_itnim_s *) qe;
+               bfa_itnim_iocdisable(itnim);
+       }
+}
+
+void
+bfa_fcpim_path_tov_set(struct bfa_s *bfa, u16 path_tov)
+{
+       struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(bfa);
+
+       fcpim->path_tov = path_tov * 1000;
+       if (fcpim->path_tov > BFA_FCPIM_PATHTOV_MAX)
+               fcpim->path_tov = BFA_FCPIM_PATHTOV_MAX;
+}
+
+u16
+bfa_fcpim_path_tov_get(struct bfa_s *bfa)
+{
+       struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(bfa);
+
+       return (fcpim->path_tov / 1000);
+}
+
+bfa_status_t
+bfa_fcpim_get_modstats(struct bfa_s *bfa, struct bfa_fcpim_stats_s *modstats)
+{
+       struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(bfa);
+
+       *modstats = fcpim->stats;
+
+       return BFA_STATUS_OK;
+}
+
+bfa_status_t
+bfa_fcpim_clr_modstats(struct bfa_s *bfa)
+{
+       struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(bfa);
+
+       memset(&fcpim->stats, 0, sizeof(struct bfa_fcpim_stats_s));
+
+       return BFA_STATUS_OK;
+}
+
+void
+bfa_fcpim_qdepth_set(struct bfa_s *bfa, u16 q_depth)
+{
+       struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(bfa);
+
+       bfa_assert(q_depth <= BFA_IOCFC_QDEPTH_MAX);
+
+       fcpim->q_depth = q_depth;
+}
+
+u16
+bfa_fcpim_qdepth_get(struct bfa_s *bfa)
+{
+       struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(bfa);
+
+       return (fcpim->q_depth);
+}
+
+
diff --git a/drivers/scsi/bfa/bfa_fcpim_priv.h b/drivers/scsi/bfa/bfa_fcpim_priv.h
new file mode 100644 (file)
index 0000000..153206c
--- /dev/null
@@ -0,0 +1,188 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ */
+
+#ifndef __BFA_FCPIM_PRIV_H__
+#define __BFA_FCPIM_PRIV_H__
+
+#include <bfa_fcpim.h>
+#include <defs/bfa_defs_fcpim.h>
+#include <cs/bfa_wc.h>
+#include "bfa_sgpg_priv.h"
+
+#define BFA_ITNIM_MIN   32
+#define BFA_ITNIM_MAX   1024
+
+#define BFA_IOIM_MIN    8
+#define BFA_IOIM_MAX    2000
+
+#define BFA_TSKIM_MIN   4
+#define BFA_TSKIM_MAX   512
+#define BFA_FCPIM_PATHTOV_DEF  (30 * 1000)     /* in millisecs */
+#define BFA_FCPIM_PATHTOV_MAX  (90 * 1000)     /* in millisecs */
+
+#define bfa_fcpim_stats(__fcpim, __stats)   \
+    (__fcpim)->stats.__stats ++
+
+struct bfa_fcpim_mod_s {
+       struct bfa_s    *bfa;
+       struct bfa_itnim_s      *itnim_arr;
+       struct bfa_ioim_s       *ioim_arr;
+       struct bfa_ioim_sp_s *ioim_sp_arr;
+       struct bfa_tskim_s      *tskim_arr;
+       struct bfa_dma_s        snsbase;
+       int                     num_itnims;
+       int                     num_ioim_reqs;
+       int                     num_tskim_reqs;
+       u32             path_tov;
+       u16             q_depth;
+       u16             rsvd;
+       struct list_head        itnim_q;        /*  queue of active itnim    */
+       struct list_head        ioim_free_q;    /*  free IO resources        */
+       struct list_head        ioim_resfree_q; /*  IOs waiting for f/w      */
+       struct list_head        ioim_comp_q;    /*  IO global comp Q         */
+       struct list_head        tskim_free_q;
+       u32     ios_active;     /*  current active IOs        */
+       u32     delay_comp;
+       struct bfa_fcpim_stats_s stats;
+};
+
+struct bfa_ioim_s;
+struct bfa_tskim_s;
+
+/**
+ * BFA IO (initiator mode)
+ */
+struct bfa_ioim_s {
+       struct list_head qe;            /*  queue elememt            */
+       bfa_sm_t                sm;     /*  BFA ioim state machine   */
+       struct bfa_s            *bfa;   /*  BFA module               */
+       struct bfa_fcpim_mod_s  *fcpim; /*  parent fcpim module      */
+       struct bfa_itnim_s      *itnim; /*  i-t-n nexus for this IO  */
+       struct bfad_ioim_s      *dio;   /*  driver IO handle         */
+       u16     iotag;          /*  FWI IO tag               */
+       u16     abort_tag;      /*  unqiue abort request tag */
+       u16     nsges;          /*  number of SG elements    */
+       u16     nsgpgs;         /*  number of SG pages       */
+       struct bfa_sgpg_s *sgpg;        /*  first SG page            */
+       struct list_head sgpg_q;                /*  allocated SG pages       */
+       struct bfa_cb_qe_s hcb_qe;      /*  bfa callback qelem       */
+       bfa_cb_cbfn_t io_cbfn;          /*  IO completion handler    */
+       struct bfa_ioim_sp_s *iosp;     /*  slow-path IO handling    */
+};
+
+struct bfa_ioim_sp_s {
+       struct bfi_msg_s        comp_rspmsg;    /*  IO comp f/w response     */
+       u8                      *snsinfo;       /*  sense info for this IO   */
+       struct bfa_sgpg_wqe_s sgpg_wqe; /*  waitq elem for sgpg      */
+       struct bfa_reqq_wait_s reqq_wait;       /*  to wait for room in reqq */
+       bfa_boolean_t           abort_explicit; /*  aborted by OS            */
+       struct bfa_tskim_s      *tskim;         /*  Relevant TM cmd          */
+};
+
+/**
+ * BFA Task management command (initiator mode)
+ */
+struct bfa_tskim_s {
+       struct list_head          qe;
+       bfa_sm_t                sm;
+       struct bfa_s            *bfa;        /*  BFA module  */
+       struct bfa_fcpim_mod_s  *fcpim;      /*  parent fcpim module      */
+       struct bfa_itnim_s      *itnim;      /*  i-t-n nexus for this IO  */
+       struct bfad_tskim_s         *dtsk;   /*  driver task mgmt cmnd    */
+       bfa_boolean_t        notify;         /*  notify itnim on TM comp  */
+       lun_t                lun;            /*  lun if applicable        */
+       enum fcp_tm_cmnd        tm_cmnd;     /*  task management command  */
+       u16             tsk_tag;        /*  FWI IO tag               */
+       u8              tsecs;          /*  timeout in seconds       */
+       struct bfa_reqq_wait_s  reqq_wait;   /*  to wait for room in reqq */
+       struct list_head              io_q;    /*  queue of affected IOs    */
+       struct bfa_wc_s             wc;      /*  waiting counter          */
+       struct bfa_cb_qe_s      hcb_qe;      /*  bfa callback qelem       */
+       enum bfi_tskim_status   tsk_status;  /*  TM status                */
+};
+
+/**
+ * BFA i-t-n (initiator mode)
+ */
+struct bfa_itnim_s {
+       struct list_head    qe;         /*  queue element               */
+       bfa_sm_t          sm;           /*  i-t-n im BFA state machine  */
+       struct bfa_s      *bfa;         /*  bfa instance                */
+       struct bfa_rport_s *rport;      /*  bfa rport                   */
+       void           *ditn;           /*  driver i-t-n structure      */
+       struct bfi_mhdr_s      mhdr;    /*  pre-built mhdr              */
+       u8         msg_no;              /*  itnim/rport firmware handle */
+       u8         reqq;                /*  CQ for requests             */
+       struct bfa_cb_qe_s    hcb_qe;   /*  bfa callback qelem          */
+       struct list_head pending_q;     /*  queue of pending IO requests*/
+       struct list_head io_q;          /*  queue of active IO requests */
+       struct list_head io_cleanup_q;  /*  IO being cleaned up         */
+       struct list_head tsk_q;         /*  queue of active TM commands */
+       struct list_head  delay_comp_q;/*  queue of failed inflight cmds */
+       bfa_boolean_t   seq_rec;        /*  SQER supported              */
+       bfa_boolean_t   is_online;      /*  itnim is ONLINE for IO      */
+       bfa_boolean_t   iotov_active;   /*  IO TOV timer is active       */
+       struct bfa_wc_s        wc;      /*  waiting counter             */
+       struct bfa_timer_s timer;       /*  pending IO TOV               */
+       struct bfa_reqq_wait_s reqq_wait; /*  to wait for room in reqq */
+       struct bfa_fcpim_mod_s *fcpim;  /*  fcpim module                */
+       struct bfa_itnim_hal_stats_s    stats;
+};
+
+#define bfa_itnim_is_online(_itnim) (_itnim)->is_online
+#define BFA_FCPIM_MOD(_hal) (&(_hal)->modules.fcpim_mod)
+#define BFA_IOIM_FROM_TAG(_fcpim, _iotag)      \
+       (&fcpim->ioim_arr[_iotag])
+#define BFA_TSKIM_FROM_TAG(_fcpim, _tmtag)                  \
+    (&fcpim->tskim_arr[_tmtag & (fcpim->num_tskim_reqs - 1)])
+
+/*
+ * function prototypes
+ */
+void            bfa_ioim_attach(struct bfa_fcpim_mod_s *fcpim,
+                                   struct bfa_meminfo_s *minfo);
+void            bfa_ioim_detach(struct bfa_fcpim_mod_s *fcpim);
+void            bfa_ioim_isr(struct bfa_s *bfa, struct bfi_msg_s *msg);
+void            bfa_ioim_good_comp_isr(struct bfa_s *bfa,
+                                       struct bfi_msg_s *msg);
+void            bfa_ioim_cleanup(struct bfa_ioim_s *ioim);
+void            bfa_ioim_cleanup_tm(struct bfa_ioim_s *ioim,
+                                       struct bfa_tskim_s *tskim);
+void            bfa_ioim_iocdisable(struct bfa_ioim_s *ioim);
+void            bfa_ioim_tov(struct bfa_ioim_s *ioim);
+
+void            bfa_tskim_attach(struct bfa_fcpim_mod_s *fcpim,
+                                    struct bfa_meminfo_s *minfo);
+void            bfa_tskim_detach(struct bfa_fcpim_mod_s *fcpim);
+void            bfa_tskim_isr(struct bfa_s *bfa, struct bfi_msg_s *msg);
+void            bfa_tskim_iodone(struct bfa_tskim_s *tskim);
+void            bfa_tskim_iocdisable(struct bfa_tskim_s *tskim);
+void            bfa_tskim_cleanup(struct bfa_tskim_s *tskim);
+
+void            bfa_itnim_meminfo(struct bfa_iocfc_cfg_s *cfg, u32 *km_len,
+                                     u32 *dm_len);
+void            bfa_itnim_attach(struct bfa_fcpim_mod_s *fcpim,
+                                    struct bfa_meminfo_s *minfo);
+void            bfa_itnim_detach(struct bfa_fcpim_mod_s *fcpim);
+void            bfa_itnim_iocdisable(struct bfa_itnim_s *itnim);
+void            bfa_itnim_isr(struct bfa_s *bfa, struct bfi_msg_s *msg);
+void            bfa_itnim_iodone(struct bfa_itnim_s *itnim);
+void            bfa_itnim_tskdone(struct bfa_itnim_s *itnim);
+bfa_boolean_t   bfa_itnim_hold_io(struct bfa_itnim_s *itnim);
+
+#endif /* __BFA_FCPIM_PRIV_H__ */
+
diff --git a/drivers/scsi/bfa/bfa_fcport.c b/drivers/scsi/bfa/bfa_fcport.c
new file mode 100644 (file)
index 0000000..9924359
--- /dev/null
@@ -0,0 +1,1671 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ */
+
+#include <bfa.h>
+#include <bfa_svc.h>
+#include <bfi/bfi_pport.h>
+#include <cs/bfa_debug.h>
+#include <aen/bfa_aen.h>
+#include <cs/bfa_plog.h>
+#include <aen/bfa_aen_port.h>
+
+BFA_TRC_FILE(HAL, PPORT);
+BFA_MODULE(pport);
+
+#define bfa_pport_callback(__pport, __event) do {                      \
+       if ((__pport)->bfa->fcs) {      \
+               (__pport)->event_cbfn((__pport)->event_cbarg, (__event));      \
+       } else {                                                        \
+               (__pport)->hcb_event = (__event);      \
+               bfa_cb_queue((__pport)->bfa, &(__pport)->hcb_qe,        \
+               __bfa_cb_port_event, (__pport));      \
+       }                                                               \
+} while (0)
+
+/*
+ * The port is considered disabled if corresponding physical port or IOC are
+ * disabled explicitly
+ */
+#define BFA_PORT_IS_DISABLED(bfa) \
+       ((bfa_pport_is_disabled(bfa) == BFA_TRUE) || \
+       (bfa_ioc_is_disabled(&bfa->ioc) == BFA_TRUE))
+
+/*
+ * forward declarations
+ */
+static bfa_boolean_t bfa_pport_send_enable(struct bfa_pport_s *port);
+static bfa_boolean_t bfa_pport_send_disable(struct bfa_pport_s *port);
+static void     bfa_pport_update_linkinfo(struct bfa_pport_s *pport);
+static void     bfa_pport_reset_linkinfo(struct bfa_pport_s *pport);
+static void     bfa_pport_set_wwns(struct bfa_pport_s *port);
+static void     __bfa_cb_port_event(void *cbarg, bfa_boolean_t complete);
+static void     __bfa_cb_port_stats(void *cbarg, bfa_boolean_t complete);
+static void     __bfa_cb_port_stats_clr(void *cbarg, bfa_boolean_t complete);
+static void     bfa_port_stats_timeout(void *cbarg);
+static void     bfa_port_stats_clr_timeout(void *cbarg);
+
+/**
+ *  bfa_pport_private
+ */
+
+/**
+ * BFA port state machine events
+ */
+enum bfa_pport_sm_event {
+       BFA_PPORT_SM_START = 1, /*  start port state machine */
+       BFA_PPORT_SM_STOP = 2,  /*  stop port state machine */
+       BFA_PPORT_SM_ENABLE = 3,        /*  enable port */
+       BFA_PPORT_SM_DISABLE = 4,       /*  disable port state machine */
+       BFA_PPORT_SM_FWRSP = 5, /*  firmware enable/disable rsp */
+       BFA_PPORT_SM_LINKUP = 6,        /*  firmware linkup event */
+       BFA_PPORT_SM_LINKDOWN = 7,      /*  firmware linkup down */
+       BFA_PPORT_SM_QRESUME = 8,       /*  CQ space available */
+       BFA_PPORT_SM_HWFAIL = 9,        /*  IOC h/w failure */
+};
+
+static void     bfa_pport_sm_uninit(struct bfa_pport_s *pport,
+                                   enum bfa_pport_sm_event event);
+static void     bfa_pport_sm_enabling_qwait(struct bfa_pport_s *pport,
+                                           enum bfa_pport_sm_event event);
+static void     bfa_pport_sm_enabling(struct bfa_pport_s *pport,
+                                     enum bfa_pport_sm_event event);
+static void     bfa_pport_sm_linkdown(struct bfa_pport_s *pport,
+                                     enum bfa_pport_sm_event event);
+static void     bfa_pport_sm_linkup(struct bfa_pport_s *pport,
+                                   enum bfa_pport_sm_event event);
+static void     bfa_pport_sm_disabling(struct bfa_pport_s *pport,
+                                      enum bfa_pport_sm_event event);
+static void     bfa_pport_sm_disabling_qwait(struct bfa_pport_s *pport,
+                                            enum bfa_pport_sm_event event);
+static void     bfa_pport_sm_disabled(struct bfa_pport_s *pport,
+                                     enum bfa_pport_sm_event event);
+static void     bfa_pport_sm_stopped(struct bfa_pport_s *pport,
+                                    enum bfa_pport_sm_event event);
+static void     bfa_pport_sm_iocdown(struct bfa_pport_s *pport,
+                                    enum bfa_pport_sm_event event);
+static void     bfa_pport_sm_iocfail(struct bfa_pport_s *pport,
+                                    enum bfa_pport_sm_event event);
+
+static struct bfa_sm_table_s hal_pport_sm_table[] = {
+       {BFA_SM(bfa_pport_sm_uninit), BFA_PPORT_ST_UNINIT},
+       {BFA_SM(bfa_pport_sm_enabling_qwait), BFA_PPORT_ST_ENABLING_QWAIT},
+       {BFA_SM(bfa_pport_sm_enabling), BFA_PPORT_ST_ENABLING},
+       {BFA_SM(bfa_pport_sm_linkdown), BFA_PPORT_ST_LINKDOWN},
+       {BFA_SM(bfa_pport_sm_linkup), BFA_PPORT_ST_LINKUP},
+       {BFA_SM(bfa_pport_sm_disabling_qwait),
+        BFA_PPORT_ST_DISABLING_QWAIT},
+       {BFA_SM(bfa_pport_sm_disabling), BFA_PPORT_ST_DISABLING},
+       {BFA_SM(bfa_pport_sm_disabled), BFA_PPORT_ST_DISABLED},
+       {BFA_SM(bfa_pport_sm_stopped), BFA_PPORT_ST_STOPPED},
+       {BFA_SM(bfa_pport_sm_iocdown), BFA_PPORT_ST_IOCDOWN},
+       {BFA_SM(bfa_pport_sm_iocfail), BFA_PPORT_ST_IOCDOWN},
+};
+
+static void
+bfa_pport_aen_post(struct bfa_pport_s *pport, enum bfa_port_aen_event event)
+{
+       union bfa_aen_data_u aen_data;
+       struct bfa_log_mod_s *logmod = pport->bfa->logm;
+       wwn_t           pwwn = pport->pwwn;
+       char            pwwn_ptr[BFA_STRING_32];
+       struct bfa_ioc_attr_s ioc_attr;
+
+       wwn2str(pwwn_ptr, pwwn);
+       switch (event) {
+       case BFA_PORT_AEN_ONLINE:
+               bfa_log(logmod, BFA_AEN_PORT_ONLINE, pwwn_ptr);
+               break;
+       case BFA_PORT_AEN_OFFLINE:
+               bfa_log(logmod, BFA_AEN_PORT_OFFLINE, pwwn_ptr);
+               break;
+       case BFA_PORT_AEN_ENABLE:
+               bfa_log(logmod, BFA_AEN_PORT_ENABLE, pwwn_ptr);
+               break;
+       case BFA_PORT_AEN_DISABLE:
+               bfa_log(logmod, BFA_AEN_PORT_DISABLE, pwwn_ptr);
+               break;
+       case BFA_PORT_AEN_DISCONNECT:
+               bfa_log(logmod, BFA_AEN_PORT_DISCONNECT, pwwn_ptr);
+               break;
+       case BFA_PORT_AEN_QOS_NEG:
+               bfa_log(logmod, BFA_AEN_PORT_QOS_NEG, pwwn_ptr);
+               break;
+       default:
+               break;
+       }
+
+       bfa_ioc_get_attr(&pport->bfa->ioc, &ioc_attr);
+       aen_data.port.ioc_type = ioc_attr.ioc_type;
+       aen_data.port.pwwn = pwwn;
+}
+
+static void
+bfa_pport_sm_uninit(struct bfa_pport_s *pport, enum bfa_pport_sm_event event)
+{
+       bfa_trc(pport->bfa, event);
+
+       switch (event) {
+       case BFA_PPORT_SM_START:
+               /**
+                * Start event after IOC is configured and BFA is started.
+                */
+               if (bfa_pport_send_enable(pport))
+                       bfa_sm_set_state(pport, bfa_pport_sm_enabling);
+               else
+                       bfa_sm_set_state(pport, bfa_pport_sm_enabling_qwait);
+               break;
+
+       case BFA_PPORT_SM_ENABLE:
+               /**
+                * Port is persistently configured to be in enabled state. Do
+                * not change state. Port enabling is done when START event is
+                * received.
+                */
+               break;
+
+       case BFA_PPORT_SM_DISABLE:
+               /**
+                * If a port is persistently configured to be disabled, the
+                * first event will a port disable request.
+                */
+               bfa_sm_set_state(pport, bfa_pport_sm_disabled);
+               break;
+
+       case BFA_PPORT_SM_HWFAIL:
+               bfa_sm_set_state(pport, bfa_pport_sm_iocdown);
+               break;
+
+       default:
+               bfa_sm_fault(pport->bfa, event);
+       }
+}
+
+static void
+bfa_pport_sm_enabling_qwait(struct bfa_pport_s *pport,
+                           enum bfa_pport_sm_event event)
+{
+       bfa_trc(pport->bfa, event);
+
+       switch (event) {
+       case BFA_PPORT_SM_QRESUME:
+               bfa_sm_set_state(pport, bfa_pport_sm_enabling);
+               bfa_pport_send_enable(pport);
+               break;
+
+       case BFA_PPORT_SM_STOP:
+               bfa_reqq_wcancel(&pport->reqq_wait);
+               bfa_sm_set_state(pport, bfa_pport_sm_stopped);
+               break;
+
+       case BFA_PPORT_SM_ENABLE:
+               /**
+                * Already enable is in progress.
+                */
+               break;
+
+       case BFA_PPORT_SM_DISABLE:
+               /**
+                * Just send disable request to firmware when room becomes
+                * available in request queue.
+                */
+               bfa_sm_set_state(pport, bfa_pport_sm_disabled);
+               bfa_reqq_wcancel(&pport->reqq_wait);
+               bfa_plog_str(pport->bfa->plog, BFA_PL_MID_HAL,
+                            BFA_PL_EID_PORT_DISABLE, 0, "Port Disable");
+               bfa_pport_aen_post(pport, BFA_PORT_AEN_DISABLE);
+               break;
+
+       case BFA_PPORT_SM_LINKUP:
+       case BFA_PPORT_SM_LINKDOWN:
+               /**
+                * Possible to get link events when doing back-to-back
+                * enable/disables.
+                */
+               break;
+
+       case BFA_PPORT_SM_HWFAIL:
+               bfa_reqq_wcancel(&pport->reqq_wait);
+               bfa_sm_set_state(pport, bfa_pport_sm_iocdown);
+               break;
+
+       default:
+               bfa_sm_fault(pport->bfa, event);
+       }
+}
+
+static void
+bfa_pport_sm_enabling(struct bfa_pport_s *pport, enum bfa_pport_sm_event event)
+{
+       bfa_trc(pport->bfa, event);
+
+       switch (event) {
+       case BFA_PPORT_SM_FWRSP:
+       case BFA_PPORT_SM_LINKDOWN:
+               bfa_sm_set_state(pport, bfa_pport_sm_linkdown);
+               break;
+
+       case BFA_PPORT_SM_LINKUP:
+               bfa_pport_update_linkinfo(pport);
+               bfa_sm_set_state(pport, bfa_pport_sm_linkup);
+
+               bfa_assert(pport->event_cbfn);
+               bfa_pport_callback(pport, BFA_PPORT_LINKUP);
+               break;
+
+       case BFA_PPORT_SM_ENABLE:
+               /**
+                * Already being enabled.
+                */
+               break;
+
+       case BFA_PPORT_SM_DISABLE:
+               if (bfa_pport_send_disable(pport))
+                       bfa_sm_set_state(pport, bfa_pport_sm_disabling);
+               else
+                       bfa_sm_set_state(pport, bfa_pport_sm_disabling_qwait);
+
+               bfa_plog_str(pport->bfa->plog, BFA_PL_MID_HAL,
+                            BFA_PL_EID_PORT_DISABLE, 0, "Port Disable");
+               bfa_pport_aen_post(pport, BFA_PORT_AEN_DISABLE);
+               break;
+
+       case BFA_PPORT_SM_STOP:
+               bfa_sm_set_state(pport, bfa_pport_sm_stopped);
+               break;
+
+       case BFA_PPORT_SM_HWFAIL:
+               bfa_sm_set_state(pport, bfa_pport_sm_iocdown);
+               break;
+
+       default:
+               bfa_sm_fault(pport->bfa, event);
+       }
+}
+
+static void
+bfa_pport_sm_linkdown(struct bfa_pport_s *pport, enum bfa_pport_sm_event event)
+{
+       bfa_trc(pport->bfa, event);
+
+       switch (event) {
+       case BFA_PPORT_SM_LINKUP:
+               bfa_pport_update_linkinfo(pport);
+               bfa_sm_set_state(pport, bfa_pport_sm_linkup);
+               bfa_assert(pport->event_cbfn);
+               bfa_plog_str(pport->bfa->plog, BFA_PL_MID_HAL,
+                            BFA_PL_EID_PORT_ST_CHANGE, 0, "Port Linkup");
+               bfa_pport_callback(pport, BFA_PPORT_LINKUP);
+               bfa_pport_aen_post(pport, BFA_PORT_AEN_ONLINE);
+               /**
+                * If QoS is enabled and it is not online,
+                * Send a separate event.
+                */
+               if ((pport->cfg.qos_enabled)
+                   && (bfa_os_ntohl(pport->qos_attr.state) != BFA_QOS_ONLINE))
+                       bfa_pport_aen_post(pport, BFA_PORT_AEN_QOS_NEG);
+
+               break;
+
+       case BFA_PPORT_SM_LINKDOWN:
+               /**
+                * Possible to get link down event.
+                */
+               break;
+
+       case BFA_PPORT_SM_ENABLE:
+               /**
+                * Already enabled.
+                */
+               break;
+
+       case BFA_PPORT_SM_DISABLE:
+               if (bfa_pport_send_disable(pport))
+                       bfa_sm_set_state(pport, bfa_pport_sm_disabling);
+               else
+                       bfa_sm_set_state(pport, bfa_pport_sm_disabling_qwait);
+
+               bfa_plog_str(pport->bfa->plog, BFA_PL_MID_HAL,
+                            BFA_PL_EID_PORT_DISABLE, 0, "Port Disable");
+               bfa_pport_aen_post(pport, BFA_PORT_AEN_DISABLE);
+               break;
+
+       case BFA_PPORT_SM_STOP:
+               bfa_sm_set_state(pport, bfa_pport_sm_stopped);
+               break;
+
+       case BFA_PPORT_SM_HWFAIL:
+               bfa_sm_set_state(pport, bfa_pport_sm_iocdown);
+               break;
+
+       default:
+               bfa_sm_fault(pport->bfa, event);
+       }
+}
+
+static void
+bfa_pport_sm_linkup(struct bfa_pport_s *pport, enum bfa_pport_sm_event event)
+{
+       bfa_trc(pport->bfa, event);
+
+       switch (event) {
+       case BFA_PPORT_SM_ENABLE:
+               /**
+                * Already enabled.
+                */
+               break;
+
+       case BFA_PPORT_SM_DISABLE:
+               if (bfa_pport_send_disable(pport))
+                       bfa_sm_set_state(pport, bfa_pport_sm_disabling);
+               else
+                       bfa_sm_set_state(pport, bfa_pport_sm_disabling_qwait);
+
+               bfa_pport_reset_linkinfo(pport);
+               bfa_pport_callback(pport, BFA_PPORT_LINKDOWN);
+               bfa_plog_str(pport->bfa->plog, BFA_PL_MID_HAL,
+                            BFA_PL_EID_PORT_DISABLE, 0, "Port Disable");
+               bfa_pport_aen_post(pport, BFA_PORT_AEN_OFFLINE);
+               bfa_pport_aen_post(pport, BFA_PORT_AEN_DISABLE);
+               break;
+
+       case BFA_PPORT_SM_LINKDOWN:
+               bfa_sm_set_state(pport, bfa_pport_sm_linkdown);
+               bfa_pport_reset_linkinfo(pport);
+               bfa_pport_callback(pport, BFA_PPORT_LINKDOWN);
+               bfa_plog_str(pport->bfa->plog, BFA_PL_MID_HAL,
+                            BFA_PL_EID_PORT_ST_CHANGE, 0, "Port Linkdown");
+               if (BFA_PORT_IS_DISABLED(pport->bfa)) {
+                       bfa_pport_aen_post(pport, BFA_PORT_AEN_OFFLINE);
+               } else {
+                       bfa_pport_aen_post(pport, BFA_PORT_AEN_DISCONNECT);
+               }
+               break;
+
+       case BFA_PPORT_SM_STOP:
+               bfa_sm_set_state(pport, bfa_pport_sm_stopped);
+               bfa_pport_reset_linkinfo(pport);
+               if (BFA_PORT_IS_DISABLED(pport->bfa)) {
+                       bfa_pport_aen_post(pport, BFA_PORT_AEN_OFFLINE);
+               } else {
+                       bfa_pport_aen_post(pport, BFA_PORT_AEN_DISCONNECT);
+               }
+               break;
+
+       case BFA_PPORT_SM_HWFAIL:
+               bfa_sm_set_state(pport, bfa_pport_sm_iocdown);
+               bfa_pport_reset_linkinfo(pport);
+               bfa_pport_callback(pport, BFA_PPORT_LINKDOWN);
+               if (BFA_PORT_IS_DISABLED(pport->bfa)) {
+                       bfa_pport_aen_post(pport, BFA_PORT_AEN_OFFLINE);
+               } else {
+                       bfa_pport_aen_post(pport, BFA_PORT_AEN_DISCONNECT);
+               }
+               break;
+
+       default:
+               bfa_sm_fault(pport->bfa, event);
+       }
+}
+
+static void
+bfa_pport_sm_disabling_qwait(struct bfa_pport_s *pport,
+                            enum bfa_pport_sm_event event)
+{
+       bfa_trc(pport->bfa, event);
+
+       switch (event) {
+       case BFA_PPORT_SM_QRESUME:
+               bfa_sm_set_state(pport, bfa_pport_sm_disabling);
+               bfa_pport_send_disable(pport);
+               break;
+
+       case BFA_PPORT_SM_STOP:
+               bfa_sm_set_state(pport, bfa_pport_sm_stopped);
+               bfa_reqq_wcancel(&pport->reqq_wait);
+               break;
+
+       case BFA_PPORT_SM_DISABLE:
+               /**
+                * Already being disabled.
+                */
+               break;
+
+       case BFA_PPORT_SM_LINKUP:
+       case BFA_PPORT_SM_LINKDOWN:
+               /**
+                * Possible to get link events when doing back-to-back
+                * enable/disables.
+                */
+               break;
+
+       case BFA_PPORT_SM_HWFAIL:
+               bfa_sm_set_state(pport, bfa_pport_sm_iocfail);
+               bfa_reqq_wcancel(&pport->reqq_wait);
+               break;
+
+       default:
+               bfa_sm_fault(pport->bfa, event);
+       }
+}
+
+static void
+bfa_pport_sm_disabling(struct bfa_pport_s *pport, enum bfa_pport_sm_event event)
+{
+       bfa_trc(pport->bfa, event);
+
+       switch (event) {
+       case BFA_PPORT_SM_FWRSP:
+               bfa_sm_set_state(pport, bfa_pport_sm_disabled);
+               break;
+
+       case BFA_PPORT_SM_DISABLE:
+               /**
+                * Already being disabled.
+                */
+               break;
+
+       case BFA_PPORT_SM_ENABLE:
+               if (bfa_pport_send_enable(pport))
+                       bfa_sm_set_state(pport, bfa_pport_sm_enabling);
+               else
+                       bfa_sm_set_state(pport, bfa_pport_sm_enabling_qwait);
+
+               bfa_plog_str(pport->bfa->plog, BFA_PL_MID_HAL,
+                            BFA_PL_EID_PORT_ENABLE, 0, "Port Enable");
+               bfa_pport_aen_post(pport, BFA_PORT_AEN_ENABLE);
+               break;
+
+       case BFA_PPORT_SM_STOP:
+               bfa_sm_set_state(pport, bfa_pport_sm_stopped);
+               break;
+
+       case BFA_PPORT_SM_LINKUP:
+       case BFA_PPORT_SM_LINKDOWN:
+               /**
+                * Possible to get link events when doing back-to-back
+                * enable/disables.
+                */
+               break;
+
+       case BFA_PPORT_SM_HWFAIL:
+               bfa_sm_set_state(pport, bfa_pport_sm_iocfail);
+               break;
+
+       default:
+               bfa_sm_fault(pport->bfa, event);
+       }
+}
+
+static void
+bfa_pport_sm_disabled(struct bfa_pport_s *pport, enum bfa_pport_sm_event event)
+{
+       bfa_trc(pport->bfa, event);
+
+       switch (event) {
+       case BFA_PPORT_SM_START:
+               /**
+                * Ignore start event for a port that is disabled.
+                */
+               break;
+
+       case BFA_PPORT_SM_STOP:
+               bfa_sm_set_state(pport, bfa_pport_sm_stopped);
+               break;
+
+       case BFA_PPORT_SM_ENABLE:
+               if (bfa_pport_send_enable(pport))
+                       bfa_sm_set_state(pport, bfa_pport_sm_enabling);
+               else
+                       bfa_sm_set_state(pport, bfa_pport_sm_enabling_qwait);
+
+               bfa_plog_str(pport->bfa->plog, BFA_PL_MID_HAL,
+                            BFA_PL_EID_PORT_ENABLE, 0, "Port Enable");
+               bfa_pport_aen_post(pport, BFA_PORT_AEN_ENABLE);
+               break;
+
+       case BFA_PPORT_SM_DISABLE:
+               /**
+                * Already disabled.
+                */
+               break;
+
+       case BFA_PPORT_SM_HWFAIL:
+               bfa_sm_set_state(pport, bfa_pport_sm_iocfail);
+               break;
+
+       default:
+               bfa_sm_fault(pport->bfa, event);
+       }
+}
+
+static void
+bfa_pport_sm_stopped(struct bfa_pport_s *pport, enum bfa_pport_sm_event event)
+{
+       bfa_trc(pport->bfa, event);
+
+       switch (event) {
+       case BFA_PPORT_SM_START:
+               if (bfa_pport_send_enable(pport))
+                       bfa_sm_set_state(pport, bfa_pport_sm_enabling);
+               else
+                       bfa_sm_set_state(pport, bfa_pport_sm_enabling_qwait);
+               break;
+
+       default:
+               /**
+                * Ignore all other events.
+                */
+               ;
+       }
+}
+
+/**
+ * Port is enabled. IOC is down/failed.
+ */
+static void
+bfa_pport_sm_iocdown(struct bfa_pport_s *pport, enum bfa_pport_sm_event event)
+{
+       bfa_trc(pport->bfa, event);
+
+       switch (event) {
+       case BFA_PPORT_SM_START:
+               if (bfa_pport_send_enable(pport))
+                       bfa_sm_set_state(pport, bfa_pport_sm_enabling);
+               else
+                       bfa_sm_set_state(pport, bfa_pport_sm_enabling_qwait);
+               break;
+
+       default:
+               /**
+                * Ignore all events.
+                */
+               ;
+       }
+}
+
+/**
+ * Port is disabled. IOC is down/failed.
+ */
+static void
+bfa_pport_sm_iocfail(struct bfa_pport_s *pport, enum bfa_pport_sm_event event)
+{
+       bfa_trc(pport->bfa, event);
+
+       switch (event) {
+       case BFA_PPORT_SM_START:
+               bfa_sm_set_state(pport, bfa_pport_sm_disabled);
+               break;
+
+       case BFA_PPORT_SM_ENABLE:
+               bfa_sm_set_state(pport, bfa_pport_sm_iocdown);
+               break;
+
+       default:
+               /**
+                * Ignore all events.
+                */
+               ;
+       }
+}
+
+
+
+/**
+ *  bfa_pport_private
+ */
+
+static void
+__bfa_cb_port_event(void *cbarg, bfa_boolean_t complete)
+{
+       struct bfa_pport_s *pport = cbarg;
+
+       if (complete)
+               pport->event_cbfn(pport->event_cbarg, pport->hcb_event);
+}
+
+#define PPORT_STATS_DMA_SZ (BFA_ROUNDUP(sizeof(union bfa_pport_stats_u), \
+                                                       BFA_CACHELINE_SZ))
+
+static void
+bfa_pport_meminfo(struct bfa_iocfc_cfg_s *cfg, u32 *ndm_len,
+                 u32 *dm_len)
+{
+       *dm_len += PPORT_STATS_DMA_SZ;
+}
+
+static void
+bfa_pport_qresume(void *cbarg)
+{
+       struct bfa_pport_s *port = cbarg;
+
+       bfa_sm_send_event(port, BFA_PPORT_SM_QRESUME);
+}
+
+static void
+bfa_pport_mem_claim(struct bfa_pport_s *pport, struct bfa_meminfo_s *meminfo)
+{
+       u8        *dm_kva;
+       u64        dm_pa;
+
+       dm_kva = bfa_meminfo_dma_virt(meminfo);
+       dm_pa = bfa_meminfo_dma_phys(meminfo);
+
+       pport->stats_kva = dm_kva;
+       pport->stats_pa = dm_pa;
+       pport->stats = (union bfa_pport_stats_u *)dm_kva;
+
+       dm_kva += PPORT_STATS_DMA_SZ;
+       dm_pa += PPORT_STATS_DMA_SZ;
+
+       bfa_meminfo_dma_virt(meminfo) = dm_kva;
+       bfa_meminfo_dma_phys(meminfo) = dm_pa;
+}
+
+/**
+ * Memory initialization.
+ */
+static void
+bfa_pport_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
+                struct bfa_meminfo_s *meminfo, struct bfa_pcidev_s *pcidev)
+{
+       struct bfa_pport_s *pport = BFA_PORT_MOD(bfa);
+       struct bfa_pport_cfg_s *port_cfg = &pport->cfg;
+
+       bfa_os_memset(pport, 0, sizeof(struct bfa_pport_s));
+       pport->bfa = bfa;
+
+       bfa_pport_mem_claim(pport, meminfo);
+
+       bfa_sm_set_state(pport, bfa_pport_sm_uninit);
+
+       /**
+        * initialize and set default configuration
+        */
+       port_cfg->topology = BFA_PPORT_TOPOLOGY_P2P;
+       port_cfg->speed = BFA_PPORT_SPEED_AUTO;
+       port_cfg->trunked = BFA_FALSE;
+       port_cfg->maxfrsize = 0;
+
+       port_cfg->trl_def_speed = BFA_PPORT_SPEED_1GBPS;
+
+       bfa_reqq_winit(&pport->reqq_wait, bfa_pport_qresume, pport);
+}
+
+static void
+bfa_pport_initdone(struct bfa_s *bfa)
+{
+       struct bfa_pport_s *pport = BFA_PORT_MOD(bfa);
+
+       /**
+        * Initialize port attributes from IOC hardware data.
+        */
+       bfa_pport_set_wwns(pport);
+       if (pport->cfg.maxfrsize == 0)
+               pport->cfg.maxfrsize = bfa_ioc_maxfrsize(&bfa->ioc);
+       pport->cfg.rx_bbcredit = bfa_ioc_rx_bbcredit(&bfa->ioc);
+       pport->speed_sup = bfa_ioc_speed_sup(&bfa->ioc);
+
+       bfa_assert(pport->cfg.maxfrsize);
+       bfa_assert(pport->cfg.rx_bbcredit);
+       bfa_assert(pport->speed_sup);
+}
+
+static void
+bfa_pport_detach(struct bfa_s *bfa)
+{
+}
+
+/**
+ * Called when IOC is ready.
+ */
+static void
+bfa_pport_start(struct bfa_s *bfa)
+{
+       bfa_sm_send_event(BFA_PORT_MOD(bfa), BFA_PPORT_SM_START);
+}
+
+/**
+ * Called before IOC is stopped.
+ */
+static void
+bfa_pport_stop(struct bfa_s *bfa)
+{
+       bfa_sm_send_event(BFA_PORT_MOD(bfa), BFA_PPORT_SM_STOP);
+}
+
+/**
+ * Called when IOC failure is detected.
+ */
+static void
+bfa_pport_iocdisable(struct bfa_s *bfa)
+{
+       bfa_sm_send_event(BFA_PORT_MOD(bfa), BFA_PPORT_SM_HWFAIL);
+}
+
+static void
+bfa_pport_update_linkinfo(struct bfa_pport_s *pport)
+{
+       struct bfi_pport_event_s *pevent = pport->event_arg.i2hmsg.event;
+
+       pport->speed = pevent->link_state.speed;
+       pport->topology = pevent->link_state.topology;
+
+       if (pport->topology == BFA_PPORT_TOPOLOGY_LOOP)
+               pport->myalpa = pevent->link_state.tl.loop_info.myalpa;
+
+       /*
+        * QoS Details
+        */
+       bfa_os_assign(pport->qos_attr, pevent->link_state.qos_attr);
+       bfa_os_assign(pport->qos_vc_attr, pevent->link_state.qos_vc_attr);
+
+       bfa_trc(pport->bfa, pport->speed);
+       bfa_trc(pport->bfa, pport->topology);
+}
+
+static void
+bfa_pport_reset_linkinfo(struct bfa_pport_s *pport)
+{
+       pport->speed = BFA_PPORT_SPEED_UNKNOWN;
+       pport->topology = BFA_PPORT_TOPOLOGY_NONE;
+}
+
+/**
+ * Send port enable message to firmware.
+ */
+static          bfa_boolean_t
+bfa_pport_send_enable(struct bfa_pport_s *port)
+{
+       struct bfi_pport_enable_req_s *m;
+
+       /**
+        * Increment message tag before queue check, so that responses to old
+        * requests are discarded.
+        */
+       port->msgtag++;
+
+       /**
+        * check for room in queue to send request now
+        */
+       m = bfa_reqq_next(port->bfa, BFA_REQQ_PORT);
+       if (!m) {
+               bfa_reqq_wait(port->bfa, BFA_REQQ_PORT, &port->reqq_wait);
+               return BFA_FALSE;
+       }
+
+       bfi_h2i_set(m->mh, BFI_MC_FC_PORT, BFI_PPORT_H2I_ENABLE_REQ,
+                   bfa_lpuid(port->bfa));
+       m->nwwn = port->nwwn;
+       m->pwwn = port->pwwn;
+       m->port_cfg = port->cfg;
+       m->msgtag = port->msgtag;
+       m->port_cfg.maxfrsize = bfa_os_htons(port->cfg.maxfrsize);
+       bfa_dma_be_addr_set(m->stats_dma_addr, port->stats_pa);
+       bfa_trc(port->bfa, m->stats_dma_addr.a32.addr_lo);
+       bfa_trc(port->bfa, m->stats_dma_addr.a32.addr_hi);
+
+       /**
+        * queue I/O message to firmware
+        */
+       bfa_reqq_produce(port->bfa, BFA_REQQ_PORT);
+       return BFA_TRUE;
+}
+
+/**
+ * Send port disable message to firmware.
+ */
+static          bfa_boolean_t
+bfa_pport_send_disable(struct bfa_pport_s *port)
+{
+       bfi_pport_disable_req_t *m;
+
+       /**
+        * Increment message tag before queue check, so that responses to old
+        * requests are discarded.
+        */
+       port->msgtag++;
+
+       /**
+        * check for room in queue to send request now
+        */
+       m = bfa_reqq_next(port->bfa, BFA_REQQ_PORT);
+       if (!m) {
+               bfa_reqq_wait(port->bfa, BFA_REQQ_PORT, &port->reqq_wait);
+               return BFA_FALSE;
+       }
+
+       bfi_h2i_set(m->mh, BFI_MC_FC_PORT, BFI_PPORT_H2I_DISABLE_REQ,
+                   bfa_lpuid(port->bfa));
+       m->msgtag = port->msgtag;
+
+       /**
+        * queue I/O message to firmware
+        */
+       bfa_reqq_produce(port->bfa, BFA_REQQ_PORT);
+
+       return BFA_TRUE;
+}
+
+static void
+bfa_pport_set_wwns(struct bfa_pport_s *port)
+{
+       port->pwwn = bfa_ioc_get_pwwn(&port->bfa->ioc);
+       port->nwwn = bfa_ioc_get_nwwn(&port->bfa->ioc);
+
+       bfa_trc(port->bfa, port->pwwn);
+       bfa_trc(port->bfa, port->nwwn);
+}
+
+static void
+bfa_port_send_txcredit(void *port_cbarg)
+{
+
+       struct bfa_pport_s *port = port_cbarg;
+       struct bfi_pport_set_svc_params_req_s *m;
+
+       /**
+        * check for room in queue to send request now
+        */
+       m = bfa_reqq_next(port->bfa, BFA_REQQ_PORT);
+       if (!m) {
+               bfa_trc(port->bfa, port->cfg.tx_bbcredit);
+               return;
+       }
+
+       bfi_h2i_set(m->mh, BFI_MC_FC_PORT, BFI_PPORT_H2I_SET_SVC_PARAMS_REQ,
+                   bfa_lpuid(port->bfa));
+       m->tx_bbcredit = bfa_os_htons((u16) port->cfg.tx_bbcredit);
+
+       /**
+        * queue I/O message to firmware
+        */
+       bfa_reqq_produce(port->bfa, BFA_REQQ_PORT);
+}
+
+
+
+/**
+ *  bfa_pport_public
+ */
+
+/**
+ * Firmware message handler.
+ */
+void
+bfa_pport_isr(struct bfa_s *bfa, struct bfi_msg_s *msg)
+{
+       struct bfa_pport_s *pport = BFA_PORT_MOD(bfa);
+       union bfi_pport_i2h_msg_u i2hmsg;
+
+       i2hmsg.msg = msg;
+       pport->event_arg.i2hmsg = i2hmsg;
+
+       switch (msg->mhdr.msg_id) {
+       case BFI_PPORT_I2H_ENABLE_RSP:
+               if (pport->msgtag == i2hmsg.enable_rsp->msgtag)
+                       bfa_sm_send_event(pport, BFA_PPORT_SM_FWRSP);
+               break;
+
+       case BFI_PPORT_I2H_DISABLE_RSP:
+               if (pport->msgtag == i2hmsg.enable_rsp->msgtag)
+                       bfa_sm_send_event(pport, BFA_PPORT_SM_FWRSP);
+               break;
+
+       case BFI_PPORT_I2H_EVENT:
+               switch (i2hmsg.event->link_state.linkstate) {
+               case BFA_PPORT_LINKUP:
+                       bfa_sm_send_event(pport, BFA_PPORT_SM_LINKUP);
+                       break;
+               case BFA_PPORT_LINKDOWN:
+                       bfa_sm_send_event(pport, BFA_PPORT_SM_LINKDOWN);
+                       break;
+               case BFA_PPORT_TRUNK_LINKDOWN:
+                       /** todo: event notification */
+                       break;
+               }
+               break;
+
+       case BFI_PPORT_I2H_GET_STATS_RSP:
+       case BFI_PPORT_I2H_GET_QOS_STATS_RSP:
+               /*
+                * check for timer pop before processing the rsp
+                */
+               if (pport->stats_busy == BFA_FALSE
+                   || pport->stats_status == BFA_STATUS_ETIMER)
+                       break;
+
+               bfa_timer_stop(&pport->timer);
+               pport->stats_status = i2hmsg.getstats_rsp->status;
+               bfa_cb_queue(pport->bfa, &pport->hcb_qe, __bfa_cb_port_stats,
+                            pport);
+               break;
+       case BFI_PPORT_I2H_CLEAR_STATS_RSP:
+       case BFI_PPORT_I2H_CLEAR_QOS_STATS_RSP:
+               /*
+                * check for timer pop before processing the rsp
+                */
+               if (pport->stats_busy == BFA_FALSE
+                   || pport->stats_status == BFA_STATUS_ETIMER)
+                       break;
+
+               bfa_timer_stop(&pport->timer);
+               pport->stats_status = BFA_STATUS_OK;
+               bfa_cb_queue(pport->bfa, &pport->hcb_qe,
+                            __bfa_cb_port_stats_clr, pport);
+               break;
+
+       default:
+               bfa_assert(0);
+       }
+}
+
+
+
+/**
+ *  bfa_pport_api
+ */
+
+/**
+ * Registered callback for port events.
+ */
+void
+bfa_pport_event_register(struct bfa_s *bfa,
+                        void (*cbfn) (void *cbarg, bfa_pport_event_t event),
+                        void *cbarg)
+{
+       struct bfa_pport_s *pport = BFA_PORT_MOD(bfa);
+
+       pport->event_cbfn = cbfn;
+       pport->event_cbarg = cbarg;
+}
+
+bfa_status_t
+bfa_pport_enable(struct bfa_s *bfa)
+{
+       struct bfa_pport_s *pport = BFA_PORT_MOD(bfa);
+
+       if (pport->diag_busy)
+               return (BFA_STATUS_DIAG_BUSY);
+       else if (bfa_sm_cmp_state
+                (BFA_PORT_MOD(bfa), bfa_pport_sm_disabling_qwait))
+               return (BFA_STATUS_DEVBUSY);
+
+       bfa_sm_send_event(BFA_PORT_MOD(bfa), BFA_PPORT_SM_ENABLE);
+       return BFA_STATUS_OK;
+}
+
+bfa_status_t
+bfa_pport_disable(struct bfa_s *bfa)
+{
+       bfa_sm_send_event(BFA_PORT_MOD(bfa), BFA_PPORT_SM_DISABLE);
+       return BFA_STATUS_OK;
+}
+
+/**
+ * Configure port speed.
+ */
+bfa_status_t
+bfa_pport_cfg_speed(struct bfa_s *bfa, enum bfa_pport_speed speed)
+{
+       struct bfa_pport_s *pport = BFA_PORT_MOD(bfa);
+
+       bfa_trc(bfa, speed);
+
+       if ((speed != BFA_PPORT_SPEED_AUTO) && (speed > pport->speed_sup)) {
+               bfa_trc(bfa, pport->speed_sup);
+               return BFA_STATUS_UNSUPP_SPEED;
+       }
+
+       pport->cfg.speed = speed;
+
+       return (BFA_STATUS_OK);
+}
+
+/**
+ * Get current speed.
+ */
+enum bfa_pport_speed
+bfa_pport_get_speed(struct bfa_s *bfa)
+{
+       struct bfa_pport_s *port = BFA_PORT_MOD(bfa);
+
+       return port->speed;
+}
+
+/**
+ * Configure port topology.
+ */
+bfa_status_t
+bfa_pport_cfg_topology(struct bfa_s *bfa, enum bfa_pport_topology topology)
+{
+       struct bfa_pport_s *pport = BFA_PORT_MOD(bfa);
+
+       bfa_trc(bfa, topology);
+       bfa_trc(bfa, pport->cfg.topology);
+
+       switch (topology) {
+       case BFA_PPORT_TOPOLOGY_P2P:
+       case BFA_PPORT_TOPOLOGY_LOOP:
+       case BFA_PPORT_TOPOLOGY_AUTO:
+               break;
+
+       default:
+               return BFA_STATUS_EINVAL;
+       }
+
+       pport->cfg.topology = topology;
+       return (BFA_STATUS_OK);
+}
+
+/**
+ * Get current topology.
+ */
+enum bfa_pport_topology
+bfa_pport_get_topology(struct bfa_s *bfa)
+{
+       struct bfa_pport_s *port = BFA_PORT_MOD(bfa);
+
+       return port->topology;
+}
+
+bfa_status_t
+bfa_pport_cfg_hardalpa(struct bfa_s *bfa, u8 alpa)
+{
+       struct bfa_pport_s *pport = BFA_PORT_MOD(bfa);
+
+       bfa_trc(bfa, alpa);
+       bfa_trc(bfa, pport->cfg.cfg_hardalpa);
+       bfa_trc(bfa, pport->cfg.hardalpa);
+
+       pport->cfg.cfg_hardalpa = BFA_TRUE;
+       pport->cfg.hardalpa = alpa;
+
+       return (BFA_STATUS_OK);
+}
+
+bfa_status_t
+bfa_pport_clr_hardalpa(struct bfa_s *bfa)
+{
+       struct bfa_pport_s *pport = BFA_PORT_MOD(bfa);
+
+       bfa_trc(bfa, pport->cfg.cfg_hardalpa);
+       bfa_trc(bfa, pport->cfg.hardalpa);
+
+       pport->cfg.cfg_hardalpa = BFA_FALSE;
+       return (BFA_STATUS_OK);
+}
+
+bfa_boolean_t
+bfa_pport_get_hardalpa(struct bfa_s *bfa, u8 *alpa)
+{
+       struct bfa_pport_s *port = BFA_PORT_MOD(bfa);
+
+       *alpa = port->cfg.hardalpa;
+       return port->cfg.cfg_hardalpa;
+}
+
+u8
+bfa_pport_get_myalpa(struct bfa_s *bfa)
+{
+       struct bfa_pport_s *port = BFA_PORT_MOD(bfa);
+
+       return port->myalpa;
+}
+
+bfa_status_t
+bfa_pport_cfg_maxfrsize(struct bfa_s *bfa, u16 maxfrsize)
+{
+       struct bfa_pport_s *pport = BFA_PORT_MOD(bfa);
+
+       bfa_trc(bfa, maxfrsize);
+       bfa_trc(bfa, pport->cfg.maxfrsize);
+
+       /*
+        * with in range
+        */
+       if ((maxfrsize > FC_MAX_PDUSZ) || (maxfrsize < FC_MIN_PDUSZ))
+               return (BFA_STATUS_INVLD_DFSZ);
+
+       /*
+        * power of 2, if not the max frame size of 2112
+        */
+       if ((maxfrsize != FC_MAX_PDUSZ) && (maxfrsize & (maxfrsize - 1)))
+               return (BFA_STATUS_INVLD_DFSZ);
+
+       pport->cfg.maxfrsize = maxfrsize;
+       return (BFA_STATUS_OK);
+}
+
+u16
+bfa_pport_get_maxfrsize(struct bfa_s *bfa)
+{
+       struct bfa_pport_s *port = BFA_PORT_MOD(bfa);
+
+       return port->cfg.maxfrsize;
+}
+
+u32
+bfa_pport_mypid(struct bfa_s *bfa)
+{
+       struct bfa_pport_s *port = BFA_PORT_MOD(bfa);
+
+       return port->mypid;
+}
+
+u8
+bfa_pport_get_rx_bbcredit(struct bfa_s *bfa)
+{
+       struct bfa_pport_s *port = BFA_PORT_MOD(bfa);
+
+       return port->cfg.rx_bbcredit;
+}
+
+void
+bfa_pport_set_tx_bbcredit(struct bfa_s *bfa, u16 tx_bbcredit)
+{
+       struct bfa_pport_s *port = BFA_PORT_MOD(bfa);
+
+       port->cfg.tx_bbcredit = (u8) tx_bbcredit;
+       bfa_port_send_txcredit(port);
+}
+
+/**
+ * Get port attributes.
+ */
+
+wwn_t
+bfa_pport_get_wwn(struct bfa_s *bfa, bfa_boolean_t node)
+{
+       struct bfa_pport_s *pport = BFA_PORT_MOD(bfa);
+       if (node)
+               return pport->nwwn;
+       else
+               return pport->pwwn;
+}
+
+void
+bfa_pport_get_attr(struct bfa_s *bfa, struct bfa_pport_attr_s *attr)
+{
+       struct bfa_pport_s *pport = BFA_PORT_MOD(bfa);
+
+       bfa_os_memset(attr, 0, sizeof(struct bfa_pport_attr_s));
+
+       attr->nwwn = pport->nwwn;
+       attr->pwwn = pport->pwwn;
+
+       bfa_os_memcpy(&attr->pport_cfg, &pport->cfg,
+                     sizeof(struct bfa_pport_cfg_s));
+       /*
+        * speed attributes
+        */
+       attr->pport_cfg.speed = pport->cfg.speed;
+       attr->speed_supported = pport->speed_sup;
+       attr->speed = pport->speed;
+       attr->cos_supported = FC_CLASS_3;
+
+       /*
+        * topology attributes
+        */
+       attr->pport_cfg.topology = pport->cfg.topology;
+       attr->topology = pport->topology;
+
+       /*
+        * beacon attributes
+        */
+       attr->beacon = pport->beacon;
+       attr->link_e2e_beacon = pport->link_e2e_beacon;
+       attr->plog_enabled = bfa_plog_get_setting(pport->bfa->plog);
+
+       attr->pport_cfg.path_tov = bfa_fcpim_path_tov_get(bfa);
+       attr->pport_cfg.q_depth = bfa_fcpim_qdepth_get(bfa);
+       attr->port_state = bfa_sm_to_state(hal_pport_sm_table, pport->sm);
+       if (bfa_ioc_is_disabled(&pport->bfa->ioc))
+               attr->port_state = BFA_PPORT_ST_IOCDIS;
+       else if (bfa_ioc_fw_mismatch(&pport->bfa->ioc))
+               attr->port_state = BFA_PPORT_ST_FWMISMATCH;
+}
+
+static void
+bfa_port_stats_query(void *cbarg)
+{
+       struct bfa_pport_s *port = (struct bfa_pport_s *)cbarg;
+       bfi_pport_get_stats_req_t *msg;
+
+       msg = bfa_reqq_next(port->bfa, BFA_REQQ_PORT);
+
+       if (!msg) {
+               port->stats_qfull = BFA_TRUE;
+               bfa_reqq_winit(&port->stats_reqq_wait, bfa_port_stats_query,
+                              port);
+               bfa_reqq_wait(port->bfa, BFA_REQQ_PORT, &port->stats_reqq_wait);
+               return;
+       }
+       port->stats_qfull = BFA_FALSE;
+
+       bfa_os_memset(msg, 0, sizeof(bfi_pport_get_stats_req_t));
+       bfi_h2i_set(msg->mh, BFI_MC_FC_PORT, BFI_PPORT_H2I_GET_STATS_REQ,
+                   bfa_lpuid(port->bfa));
+       bfa_reqq_produce(port->bfa, BFA_REQQ_PORT);
+
+       return;
+}
+
+static void
+bfa_port_stats_clear(void *cbarg)
+{
+       struct bfa_pport_s *port = (struct bfa_pport_s *)cbarg;
+       bfi_pport_clear_stats_req_t *msg;
+
+       msg = bfa_reqq_next(port->bfa, BFA_REQQ_PORT);
+
+       if (!msg) {
+               port->stats_qfull = BFA_TRUE;
+               bfa_reqq_winit(&port->stats_reqq_wait, bfa_port_stats_clear,
+                              port);
+               bfa_reqq_wait(port->bfa, BFA_REQQ_PORT, &port->stats_reqq_wait);
+               return;
+       }
+       port->stats_qfull = BFA_FALSE;
+
+       bfa_os_memset(msg, 0, sizeof(bfi_pport_clear_stats_req_t));
+       bfi_h2i_set(msg->mh, BFI_MC_FC_PORT, BFI_PPORT_H2I_CLEAR_STATS_REQ,
+                   bfa_lpuid(port->bfa));
+       bfa_reqq_produce(port->bfa, BFA_REQQ_PORT);
+       return;
+}
+
+static void
+bfa_port_qos_stats_clear(void *cbarg)
+{
+       struct bfa_pport_s *port = (struct bfa_pport_s *)cbarg;
+       bfi_pport_clear_qos_stats_req_t *msg;
+
+       msg = bfa_reqq_next(port->bfa, BFA_REQQ_PORT);
+
+       if (!msg) {
+               port->stats_qfull = BFA_TRUE;
+               bfa_reqq_winit(&port->stats_reqq_wait, bfa_port_qos_stats_clear,
+                              port);
+               bfa_reqq_wait(port->bfa, BFA_REQQ_PORT, &port->stats_reqq_wait);
+               return;
+       }
+       port->stats_qfull = BFA_FALSE;
+
+       bfa_os_memset(msg, 0, sizeof(bfi_pport_clear_qos_stats_req_t));
+       bfi_h2i_set(msg->mh, BFI_MC_FC_PORT, BFI_PPORT_H2I_CLEAR_QOS_STATS_REQ,
+                   bfa_lpuid(port->bfa));
+       bfa_reqq_produce(port->bfa, BFA_REQQ_PORT);
+       return;
+}
+
+static void
+bfa_pport_stats_swap(union bfa_pport_stats_u *d, union bfa_pport_stats_u *s)
+{
+       u32       *dip = (u32 *) d;
+       u32       *sip = (u32 *) s;
+       int             i;
+
+       /*
+        * Do 64 bit fields swap first
+        */
+       for (i = 0;
+            i <
+            ((sizeof(union bfa_pport_stats_u) -
+              sizeof(struct bfa_qos_stats_s)) / sizeof(u32)); i = i + 2) {
+#ifdef __BIGENDIAN
+               dip[i] = bfa_os_ntohl(sip[i]);
+               dip[i + 1] = bfa_os_ntohl(sip[i + 1]);
+#else
+               dip[i] = bfa_os_ntohl(sip[i + 1]);
+               dip[i + 1] = bfa_os_ntohl(sip[i]);
+#endif
+       }
+
+       /*
+        * Now swap the 32 bit fields
+        */
+       for (; i < (sizeof(union bfa_pport_stats_u) / sizeof(u32)); ++i)
+               dip[i] = bfa_os_ntohl(sip[i]);
+}
+
+static void
+__bfa_cb_port_stats_clr(void *cbarg, bfa_boolean_t complete)
+{
+       struct bfa_pport_s *port = cbarg;
+
+       if (complete) {
+               port->stats_cbfn(port->stats_cbarg, port->stats_status);
+       } else {
+               port->stats_busy = BFA_FALSE;
+               port->stats_status = BFA_STATUS_OK;
+       }
+}
+
+static void
+bfa_port_stats_clr_timeout(void *cbarg)
+{
+       struct bfa_pport_s *port = (struct bfa_pport_s *)cbarg;
+
+       bfa_trc(port->bfa, port->stats_qfull);
+
+       if (port->stats_qfull) {
+               bfa_reqq_wcancel(&port->stats_reqq_wait);
+               port->stats_qfull = BFA_FALSE;
+       }
+
+       port->stats_status = BFA_STATUS_ETIMER;
+       bfa_cb_queue(port->bfa, &port->hcb_qe, __bfa_cb_port_stats_clr, port);
+}
+
+static void
+__bfa_cb_port_stats(void *cbarg, bfa_boolean_t complete)
+{
+       struct bfa_pport_s *port = cbarg;
+
+       if (complete) {
+               if (port->stats_status == BFA_STATUS_OK)
+                       bfa_pport_stats_swap(port->stats_ret, port->stats);
+               port->stats_cbfn(port->stats_cbarg, port->stats_status);
+       } else {
+               port->stats_busy = BFA_FALSE;
+               port->stats_status = BFA_STATUS_OK;
+       }
+}
+
+static void
+bfa_port_stats_timeout(void *cbarg)
+{
+       struct bfa_pport_s *port = (struct bfa_pport_s *)cbarg;
+
+       bfa_trc(port->bfa, port->stats_qfull);
+
+       if (port->stats_qfull) {
+               bfa_reqq_wcancel(&port->stats_reqq_wait);
+               port->stats_qfull = BFA_FALSE;
+       }
+
+       port->stats_status = BFA_STATUS_ETIMER;
+       bfa_cb_queue(port->bfa, &port->hcb_qe, __bfa_cb_port_stats, port);
+}
+
+#define BFA_PORT_STATS_TOV     1000
+
+/**
+ * Fetch port attributes.
+ */
+bfa_status_t
+bfa_pport_get_stats(struct bfa_s *bfa, union bfa_pport_stats_u *stats,
+                   bfa_cb_pport_t cbfn, void *cbarg)
+{
+       struct bfa_pport_s *port = BFA_PORT_MOD(bfa);
+
+       if (port->stats_busy) {
+               bfa_trc(bfa, port->stats_busy);
+               return (BFA_STATUS_DEVBUSY);
+       }
+
+       port->stats_busy = BFA_TRUE;
+       port->stats_ret = stats;
+       port->stats_cbfn = cbfn;
+       port->stats_cbarg = cbarg;
+
+       bfa_port_stats_query(port);
+
+       bfa_timer_start(bfa, &port->timer, bfa_port_stats_timeout, port,
+                       BFA_PORT_STATS_TOV);
+       return (BFA_STATUS_OK);
+}
+
+bfa_status_t
+bfa_pport_clear_stats(struct bfa_s *bfa, bfa_cb_pport_t cbfn, void *cbarg)
+{
+       struct bfa_pport_s *port = BFA_PORT_MOD(bfa);
+
+       if (port->stats_busy) {
+               bfa_trc(bfa, port->stats_busy);
+               return (BFA_STATUS_DEVBUSY);
+       }
+
+       port->stats_busy = BFA_TRUE;
+       port->stats_cbfn = cbfn;
+       port->stats_cbarg = cbarg;
+
+       bfa_port_stats_clear(port);
+
+       bfa_timer_start(bfa, &port->timer, bfa_port_stats_clr_timeout, port,
+                       BFA_PORT_STATS_TOV);
+       return (BFA_STATUS_OK);
+}
+
+bfa_status_t
+bfa_pport_trunk_enable(struct bfa_s *bfa, u8 bitmap)
+{
+       struct bfa_pport_s *pport = BFA_PORT_MOD(bfa);
+
+       bfa_trc(bfa, bitmap);
+       bfa_trc(bfa, pport->cfg.trunked);
+       bfa_trc(bfa, pport->cfg.trunk_ports);
+
+       if (!bitmap || (bitmap & (bitmap - 1)))
+               return BFA_STATUS_EINVAL;
+
+       pport->cfg.trunked = BFA_TRUE;
+       pport->cfg.trunk_ports = bitmap;
+
+       return BFA_STATUS_OK;
+}
+
+void
+bfa_pport_qos_get_attr(struct bfa_s *bfa, struct bfa_qos_attr_s *qos_attr)
+{
+       struct bfa_pport_s *pport = BFA_PORT_MOD(bfa);
+
+       qos_attr->state = bfa_os_ntohl(pport->qos_attr.state);
+       qos_attr->total_bb_cr = bfa_os_ntohl(pport->qos_attr.total_bb_cr);
+}
+
+void
+bfa_pport_qos_get_vc_attr(struct bfa_s *bfa,
+                         struct bfa_qos_vc_attr_s *qos_vc_attr)
+{
+       struct bfa_pport_s *pport = BFA_PORT_MOD(bfa);
+       struct bfa_qos_vc_attr_s *bfa_vc_attr = &pport->qos_vc_attr;
+       u32        i = 0;
+
+       qos_vc_attr->total_vc_count = bfa_os_ntohs(bfa_vc_attr->total_vc_count);
+       qos_vc_attr->shared_credit = bfa_os_ntohs(bfa_vc_attr->shared_credit);
+       qos_vc_attr->elp_opmode_flags =
+               bfa_os_ntohl(bfa_vc_attr->elp_opmode_flags);
+
+       /*
+        * Individual VC info
+        */
+       while (i < qos_vc_attr->total_vc_count) {
+               qos_vc_attr->vc_info[i].vc_credit =
+                       bfa_vc_attr->vc_info[i].vc_credit;
+               qos_vc_attr->vc_info[i].borrow_credit =
+                       bfa_vc_attr->vc_info[i].borrow_credit;
+               qos_vc_attr->vc_info[i].priority =
+                       bfa_vc_attr->vc_info[i].priority;
+               ++i;
+       }
+}
+
+/**
+ * Fetch QoS Stats.
+ */
+bfa_status_t
+bfa_pport_get_qos_stats(struct bfa_s *bfa, union bfa_pport_stats_u *stats,
+                       bfa_cb_pport_t cbfn, void *cbarg)
+{
+       /*
+        * QoS stats is embedded in port stats
+        */
+       return (bfa_pport_get_stats(bfa, stats, cbfn, cbarg));
+}
+
+bfa_status_t
+bfa_pport_clear_qos_stats(struct bfa_s *bfa, bfa_cb_pport_t cbfn, void *cbarg)
+{
+       struct bfa_pport_s *port = BFA_PORT_MOD(bfa);
+
+       if (port->stats_busy) {
+               bfa_trc(bfa, port->stats_busy);
+               return (BFA_STATUS_DEVBUSY);
+       }
+
+       port->stats_busy = BFA_TRUE;
+       port->stats_cbfn = cbfn;
+       port->stats_cbarg = cbarg;
+
+       bfa_port_qos_stats_clear(port);
+
+       bfa_timer_start(bfa, &port->timer, bfa_port_stats_clr_timeout, port,
+                       BFA_PORT_STATS_TOV);
+       return (BFA_STATUS_OK);
+}
+
+/**
+ * Fetch port attributes.
+ */
+bfa_status_t
+bfa_pport_trunk_disable(struct bfa_s *bfa)
+{
+       return (BFA_STATUS_OK);
+}
+
+bfa_boolean_t
+bfa_pport_trunk_query(struct bfa_s *bfa, u32 *bitmap)
+{
+       struct bfa_pport_s *port = BFA_PORT_MOD(bfa);
+
+       *bitmap = port->cfg.trunk_ports;
+       return port->cfg.trunked;
+}
+
+bfa_boolean_t
+bfa_pport_is_disabled(struct bfa_s *bfa)
+{
+       struct bfa_pport_s *port = BFA_PORT_MOD(bfa);
+
+       return (bfa_sm_to_state(hal_pport_sm_table, port->sm) ==
+               BFA_PPORT_ST_DISABLED);
+
+}
+
+bfa_boolean_t
+bfa_pport_is_ratelim(struct bfa_s *bfa)
+{
+       struct bfa_pport_s *pport = BFA_PORT_MOD(bfa);
+
+return (pport->cfg.ratelimit ? BFA_TRUE : BFA_FALSE);
+
+}
+
+void
+bfa_pport_cfg_qos(struct bfa_s *bfa, bfa_boolean_t on_off)
+{
+       struct bfa_pport_s *pport = BFA_PORT_MOD(bfa);
+
+       bfa_trc(bfa, on_off);
+       bfa_trc(bfa, pport->cfg.qos_enabled);
+
+       pport->cfg.qos_enabled = on_off;
+}
+
+void
+bfa_pport_cfg_ratelim(struct bfa_s *bfa, bfa_boolean_t on_off)
+{
+       struct bfa_pport_s *pport = BFA_PORT_MOD(bfa);
+
+       bfa_trc(bfa, on_off);
+       bfa_trc(bfa, pport->cfg.ratelimit);
+
+       pport->cfg.ratelimit = on_off;
+       if (pport->cfg.trl_def_speed == BFA_PPORT_SPEED_UNKNOWN)
+               pport->cfg.trl_def_speed = BFA_PPORT_SPEED_1GBPS;
+}
+
+/**
+ * Configure default minimum ratelim speed
+ */
+bfa_status_t
+bfa_pport_cfg_ratelim_speed(struct bfa_s *bfa, enum bfa_pport_speed speed)
+{
+       struct bfa_pport_s *pport = BFA_PORT_MOD(bfa);
+
+       bfa_trc(bfa, speed);
+
+       /*
+        * Auto and speeds greater than the supported speed, are invalid
+        */
+       if ((speed == BFA_PPORT_SPEED_AUTO) || (speed > pport->speed_sup)) {
+               bfa_trc(bfa, pport->speed_sup);
+               return BFA_STATUS_UNSUPP_SPEED;
+       }
+
+       pport->cfg.trl_def_speed = speed;
+
+       return (BFA_STATUS_OK);
+}
+
+/**
+ * Get default minimum ratelim speed
+ */
+enum bfa_pport_speed
+bfa_pport_get_ratelim_speed(struct bfa_s *bfa)
+{
+       struct bfa_pport_s *pport = BFA_PORT_MOD(bfa);
+
+       bfa_trc(bfa, pport->cfg.trl_def_speed);
+       return (pport->cfg.trl_def_speed);
+
+}
+
+void
+bfa_pport_busy(struct bfa_s *bfa, bfa_boolean_t status)
+{
+       struct bfa_pport_s *pport = BFA_PORT_MOD(bfa);
+
+       bfa_trc(bfa, status);
+       bfa_trc(bfa, pport->diag_busy);
+
+       pport->diag_busy = status;
+}
+
+void
+bfa_pport_beacon(struct bfa_s *bfa, bfa_boolean_t beacon,
+                bfa_boolean_t link_e2e_beacon)
+{
+       struct bfa_pport_s *pport = BFA_PORT_MOD(bfa);
+
+       bfa_trc(bfa, beacon);
+       bfa_trc(bfa, link_e2e_beacon);
+       bfa_trc(bfa, pport->beacon);
+       bfa_trc(bfa, pport->link_e2e_beacon);
+
+       pport->beacon = beacon;
+       pport->link_e2e_beacon = link_e2e_beacon;
+}
+
+bfa_boolean_t
+bfa_pport_is_linkup(struct bfa_s *bfa)
+{
+       return bfa_sm_cmp_state(BFA_PORT_MOD(bfa), bfa_pport_sm_linkup);
+}
+
+
diff --git a/drivers/scsi/bfa/bfa_fcs.c b/drivers/scsi/bfa/bfa_fcs.c
new file mode 100644 (file)
index 0000000..7cb39a3
--- /dev/null
@@ -0,0 +1,182 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) 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.
+ */
+
+/**
+ *  bfa_fcs.c BFA FCS main
+ */
+
+#include <fcs/bfa_fcs.h>
+#include "fcs_port.h"
+#include "fcs_uf.h"
+#include "fcs_vport.h"
+#include "fcs_rport.h"
+#include "fcs_fabric.h"
+#include "fcs_fcpim.h"
+#include "fcs_fcptm.h"
+#include "fcbuild.h"
+#include "fcs.h"
+#include "bfad_drv.h"
+#include <fcb/bfa_fcb.h>
+
+/**
+ * FCS sub-modules
+ */
+struct bfa_fcs_mod_s {
+       void            (*modinit) (struct bfa_fcs_s *fcs);
+       void            (*modexit) (struct bfa_fcs_s *fcs);
+};
+
+#define BFA_FCS_MODULE(_mod) { _mod ## _modinit, _mod ## _modexit }
+
+static struct bfa_fcs_mod_s fcs_modules[] = {
+       BFA_FCS_MODULE(bfa_fcs_pport),
+       BFA_FCS_MODULE(bfa_fcs_uf),
+       BFA_FCS_MODULE(bfa_fcs_fabric),
+       BFA_FCS_MODULE(bfa_fcs_vport),
+       BFA_FCS_MODULE(bfa_fcs_rport),
+       BFA_FCS_MODULE(bfa_fcs_fcpim),
+};
+
+/**
+ *  fcs_api BFA FCS API
+ */
+
+static void
+bfa_fcs_exit_comp(void *fcs_cbarg)
+{
+       struct bfa_fcs_s *fcs = fcs_cbarg;
+       struct bfad_s *bfad = fcs->bfad;
+
+       complete(&bfad->comp);
+}
+
+
+
+/**
+ *  fcs_api BFA FCS API
+ */
+
+/**
+ *             FCS instance initialization.
+ *
+ *     param[in]               fcs             FCS instance
+ *     param[in]               bfa             BFA instance
+ *     param[in]               bfad            BFA driver instance
+ *
+ *     return None
+ */
+void
+bfa_fcs_init(struct bfa_fcs_s *fcs, struct bfa_s *bfa, struct bfad_s *bfad,
+                       bfa_boolean_t min_cfg)
+{
+       int             i;
+       struct bfa_fcs_mod_s  *mod;
+
+       fcs->bfa = bfa;
+       fcs->bfad = bfad;
+       fcs->min_cfg = min_cfg;
+
+       bfa_attach_fcs(bfa);
+       fcbuild_init();
+
+       for (i = 0; i < sizeof(fcs_modules) / sizeof(fcs_modules[0]); i++) {
+               mod = &fcs_modules[i];
+               mod->modinit(fcs);
+       }
+}
+
+/**
+ * Start FCS operations.
+ */
+void
+bfa_fcs_start(struct bfa_fcs_s *fcs)
+{
+       bfa_fcs_fabric_modstart(fcs);
+}
+
+/**
+ *             FCS driver details initialization.
+ *
+ *     param[in]               fcs             FCS instance
+ *     param[in]               driver_info     Driver Details
+ *
+ *     return None
+ */
+void
+bfa_fcs_driver_info_init(struct bfa_fcs_s *fcs,
+                       struct bfa_fcs_driver_info_s *driver_info)
+{
+
+       fcs->driver_info = *driver_info;
+
+       bfa_fcs_fabric_psymb_init(&fcs->fabric);
+}
+
+/**
+ *             FCS instance cleanup and exit.
+ *
+ *     param[in]               fcs                     FCS instance
+ *     return None
+ */
+void
+bfa_fcs_exit(struct bfa_fcs_s *fcs)
+{
+       struct bfa_fcs_mod_s  *mod;
+       int             nmods, i;
+
+       bfa_wc_init(&fcs->wc, bfa_fcs_exit_comp, fcs);
+
+       nmods = sizeof(fcs_modules) / sizeof(fcs_modules[0]);
+
+       for (i = 0; i < nmods; i++) {
+               bfa_wc_up(&fcs->wc);
+
+               mod = &fcs_modules[i];
+               mod->modexit(fcs);
+       }
+
+       bfa_wc_wait(&fcs->wc);
+}
+
+
+void
+bfa_fcs_trc_init(struct bfa_fcs_s *fcs, struct bfa_trc_mod_s *trcmod)
+{
+       fcs->trcmod = trcmod;
+}
+
+
+void
+bfa_fcs_log_init(struct bfa_fcs_s *fcs, struct bfa_log_mod_s *logmod)
+{
+       fcs->logm = logmod;
+}
+
+
+void
+bfa_fcs_aen_init(struct bfa_fcs_s *fcs, struct bfa_aen_s *aen)
+{
+       fcs->aen = aen;
+}
+
+void
+bfa_fcs_modexit_comp(struct bfa_fcs_s *fcs)
+{
+       bfa_wc_down(&fcs->wc);
+}
+
+
diff --git a/drivers/scsi/bfa/bfa_fcs_lport.c b/drivers/scsi/bfa/bfa_fcs_lport.c
new file mode 100644 (file)
index 0000000..8975ed0
--- /dev/null
@@ -0,0 +1,940 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) 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.
+ */
+
+/**
+ *  bfa_fcs_port.c BFA FCS port
+ */
+
+#include <fcs/bfa_fcs.h>
+#include <fcs/bfa_fcs_lport.h>
+#include <fcs/bfa_fcs_rport.h>
+#include <fcb/bfa_fcb_port.h>
+#include <bfa_svc.h>
+#include <log/bfa_log_fcs.h>
+#include "fcs.h"
+#include "fcs_lport.h"
+#include "fcs_vport.h"
+#include "fcs_rport.h"
+#include "fcs_fcxp.h"
+#include "fcs_trcmod.h"
+#include "lport_priv.h"
+#include <aen/bfa_aen_lport.h>
+
+BFA_TRC_FILE(FCS, PORT);
+
+/**
+ * Forward declarations
+ */
+
+static void     bfa_fcs_port_aen_post(struct bfa_fcs_port_s *port,
+                                     enum bfa_lport_aen_event event);
+static void     bfa_fcs_port_send_ls_rjt(struct bfa_fcs_port_s *port,
+                       struct fchs_s *rx_fchs, u8 reason_code,
+                       u8 reason_code_expl);
+static void     bfa_fcs_port_plogi(struct bfa_fcs_port_s *port,
+                       struct fchs_s *rx_fchs,
+                       struct fc_logi_s *plogi);
+static void     bfa_fcs_port_online_actions(struct bfa_fcs_port_s *port);
+static void     bfa_fcs_port_offline_actions(struct bfa_fcs_port_s *port);
+static void     bfa_fcs_port_unknown_init(struct bfa_fcs_port_s *port);
+static void     bfa_fcs_port_unknown_online(struct bfa_fcs_port_s *port);
+static void     bfa_fcs_port_unknown_offline(struct bfa_fcs_port_s *port);
+static void     bfa_fcs_port_deleted(struct bfa_fcs_port_s *port);
+static void     bfa_fcs_port_echo(struct bfa_fcs_port_s *port,
+                       struct fchs_s *rx_fchs,
+                       struct fc_echo_s *echo, u16 len);
+static void     bfa_fcs_port_rnid(struct bfa_fcs_port_s *port,
+                       struct fchs_s *rx_fchs,
+                       struct fc_rnid_cmd_s *rnid, u16 len);
+static void     bfa_fs_port_get_gen_topo_data(struct bfa_fcs_port_s *port,
+                       struct fc_rnid_general_topology_data_s *gen_topo_data);
+
+static struct {
+       void            (*init) (struct bfa_fcs_port_s *port);
+       void            (*online) (struct bfa_fcs_port_s *port);
+       void            (*offline) (struct bfa_fcs_port_s *port);
+} __port_action[] = {
+       {
+       bfa_fcs_port_unknown_init, bfa_fcs_port_unknown_online,
+                       bfa_fcs_port_unknown_offline}, {
+       bfa_fcs_port_fab_init, bfa_fcs_port_fab_online,
+                       bfa_fcs_port_fab_offline}, {
+       bfa_fcs_port_loop_init, bfa_fcs_port_loop_online,
+                       bfa_fcs_port_loop_offline}, {
+bfa_fcs_port_n2n_init, bfa_fcs_port_n2n_online,
+                       bfa_fcs_port_n2n_offline},};
+
+/**
+ *  fcs_port_sm FCS logical port state machine
+ */
+
+enum bfa_fcs_port_event {
+       BFA_FCS_PORT_SM_CREATE = 1,
+       BFA_FCS_PORT_SM_ONLINE = 2,
+       BFA_FCS_PORT_SM_OFFLINE = 3,
+       BFA_FCS_PORT_SM_DELETE = 4,
+       BFA_FCS_PORT_SM_DELRPORT = 5,
+};
+
+static void     bfa_fcs_port_sm_uninit(struct bfa_fcs_port_s *port,
+                                      enum bfa_fcs_port_event event);
+static void     bfa_fcs_port_sm_init(struct bfa_fcs_port_s *port,
+                                    enum bfa_fcs_port_event event);
+static void     bfa_fcs_port_sm_online(struct bfa_fcs_port_s *port,
+                                      enum bfa_fcs_port_event event);
+static void     bfa_fcs_port_sm_offline(struct bfa_fcs_port_s *port,
+                                       enum bfa_fcs_port_event event);
+static void     bfa_fcs_port_sm_deleting(struct bfa_fcs_port_s *port,
+                                        enum bfa_fcs_port_event event);
+
+static void
+bfa_fcs_port_sm_uninit(struct bfa_fcs_port_s *port,
+                       enum bfa_fcs_port_event event)
+{
+       bfa_trc(port->fcs, port->port_cfg.pwwn);
+       bfa_trc(port->fcs, event);
+
+       switch (event) {
+       case BFA_FCS_PORT_SM_CREATE:
+               bfa_sm_set_state(port, bfa_fcs_port_sm_init);
+               break;
+
+       default:
+               bfa_assert(0);
+       }
+}
+
+static void
+bfa_fcs_port_sm_init(struct bfa_fcs_port_s *port, enum bfa_fcs_port_event event)
+{
+       bfa_trc(port->fcs, port->port_cfg.pwwn);
+       bfa_trc(port->fcs, event);
+
+       switch (event) {
+       case BFA_FCS_PORT_SM_ONLINE:
+               bfa_sm_set_state(port, bfa_fcs_port_sm_online);
+               bfa_fcs_port_online_actions(port);
+               break;
+
+       case BFA_FCS_PORT_SM_DELETE:
+               bfa_sm_set_state(port, bfa_fcs_port_sm_uninit);
+               bfa_fcs_port_deleted(port);
+               break;
+
+       default:
+               bfa_assert(0);
+       }
+}
+
+static void
+bfa_fcs_port_sm_online(struct bfa_fcs_port_s *port,
+                       enum bfa_fcs_port_event event)
+{
+       struct bfa_fcs_rport_s *rport;
+       struct list_head *qe, *qen;
+
+       bfa_trc(port->fcs, port->port_cfg.pwwn);
+       bfa_trc(port->fcs, event);
+
+       switch (event) {
+       case BFA_FCS_PORT_SM_OFFLINE:
+               bfa_sm_set_state(port, bfa_fcs_port_sm_offline);
+               bfa_fcs_port_offline_actions(port);
+               break;
+
+       case BFA_FCS_PORT_SM_DELETE:
+
+               __port_action[port->fabric->fab_type].offline(port);
+
+               if (port->num_rports == 0) {
+                       bfa_sm_set_state(port, bfa_fcs_port_sm_uninit);
+                       bfa_fcs_port_deleted(port);
+               } else {
+                       bfa_sm_set_state(port, bfa_fcs_port_sm_deleting);
+                       list_for_each_safe(qe, qen, &port->rport_q) {
+                               rport = (struct bfa_fcs_rport_s *)qe;
+                               bfa_fcs_rport_delete(rport);
+                       }
+               }
+               break;
+
+       case BFA_FCS_PORT_SM_DELRPORT:
+               break;
+
+       default:
+               bfa_assert(0);
+       }
+}
+
+static void
+bfa_fcs_port_sm_offline(struct bfa_fcs_port_s *port,
+                       enum bfa_fcs_port_event event)
+{
+       struct bfa_fcs_rport_s *rport;
+       struct list_head *qe, *qen;
+
+       bfa_trc(port->fcs, port->port_cfg.pwwn);
+       bfa_trc(port->fcs, event);
+
+       switch (event) {
+       case BFA_FCS_PORT_SM_ONLINE:
+               bfa_sm_set_state(port, bfa_fcs_port_sm_online);
+               bfa_fcs_port_online_actions(port);
+               break;
+
+       case BFA_FCS_PORT_SM_DELETE:
+               if (port->num_rports == 0) {
+                       bfa_sm_set_state(port, bfa_fcs_port_sm_uninit);
+                       bfa_fcs_port_deleted(port);
+               } else {
+                       bfa_sm_set_state(port, bfa_fcs_port_sm_deleting);
+                       list_for_each_safe(qe, qen, &port->rport_q) {
+                               rport = (struct bfa_fcs_rport_s *)qe;
+                               bfa_fcs_rport_delete(rport);
+                       }
+               }
+               break;
+
+       case BFA_FCS_PORT_SM_DELRPORT:
+       case BFA_FCS_PORT_SM_OFFLINE:
+               break;
+
+       default:
+               bfa_assert(0);
+       }
+}
+
+static void
+bfa_fcs_port_sm_deleting(struct bfa_fcs_port_s *port,
+                        enum bfa_fcs_port_event event)
+{
+       bfa_trc(port->fcs, port->port_cfg.pwwn);
+       bfa_trc(port->fcs, event);
+
+       switch (event) {
+       case BFA_FCS_PORT_SM_DELRPORT:
+               if (port->num_rports == 0) {
+                       bfa_sm_set_state(port, bfa_fcs_port_sm_uninit);
+                       bfa_fcs_port_deleted(port);
+               }
+               break;
+
+       default:
+               bfa_assert(0);
+       }
+}
+
+
+
+/**
+ *  fcs_port_pvt
+ */
+
+/**
+ * Send AEN notification
+ */
+static void
+bfa_fcs_port_aen_post(struct bfa_fcs_port_s *port,
+                     enum bfa_lport_aen_event event)
+{
+       union bfa_aen_data_u aen_data;
+       struct bfa_log_mod_s *logmod = port->fcs->logm;
+       enum bfa_port_role role = port->port_cfg.roles;
+       wwn_t           lpwwn = bfa_fcs_port_get_pwwn(port);
+       char            lpwwn_ptr[BFA_STRING_32];
+       char           *role_str[BFA_PORT_ROLE_FCP_MAX / 2 + 1] =
+               { "Initiator", "Target", "IPFC" };
+
+       wwn2str(lpwwn_ptr, lpwwn);
+
+       bfa_assert(role <= BFA_PORT_ROLE_FCP_MAX);
+
+       switch (event) {
+       case BFA_LPORT_AEN_ONLINE:
+               bfa_log(logmod, BFA_AEN_LPORT_ONLINE, lpwwn_ptr,
+                       role_str[role / 2]);
+               break;
+       case BFA_LPORT_AEN_OFFLINE:
+               bfa_log(logmod, BFA_AEN_LPORT_OFFLINE, lpwwn_ptr,
+                       role_str[role / 2]);
+               break;
+       case BFA_LPORT_AEN_NEW:
+               bfa_log(logmod, BFA_AEN_LPORT_NEW, lpwwn_ptr,
+                       role_str[role / 2]);
+               break;
+       case BFA_LPORT_AEN_DELETE:
+               bfa_log(logmod, BFA_AEN_LPORT_DELETE, lpwwn_ptr,
+                       role_str[role / 2]);
+               break;
+       case BFA_LPORT_AEN_DISCONNECT:
+               bfa_log(logmod, BFA_AEN_LPORT_DISCONNECT, lpwwn_ptr,
+                       role_str[role / 2]);
+               break;
+       default:
+               break;
+       }
+
+       aen_data.lport.vf_id = port->fabric->vf_id;
+       aen_data.lport.roles = role;
+       aen_data.lport.ppwwn =
+               bfa_fcs_port_get_pwwn(bfa_fcs_get_base_port(port->fcs));
+       aen_data.lport.lpwwn = lpwwn;
+}
+
+/*
+ * Send a LS reject
+ */
+static void
+bfa_fcs_port_send_ls_rjt(struct bfa_fcs_port_s *port, struct fchs_s *rx_fchs,
+                        u8 reason_code, u8 reason_code_expl)
+{
+       struct fchs_s          fchs;
+       struct bfa_fcxp_s *fcxp;
+       struct bfa_rport_s *bfa_rport = NULL;
+       int             len;
+
+       bfa_trc(port->fcs, rx_fchs->s_id);
+
+       fcxp = bfa_fcs_fcxp_alloc(port->fcs);
+       if (!fcxp)
+               return;
+
+       len = fc_ls_rjt_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), rx_fchs->s_id,
+                             bfa_fcs_port_get_fcid(port), rx_fchs->ox_id,
+                             reason_code, reason_code_expl);
+
+       bfa_fcxp_send(fcxp, bfa_rport, port->fabric->vf_id, port->lp_tag,
+                     BFA_FALSE, FC_CLASS_3, len, &fchs, NULL, NULL,
+                     FC_MAX_PDUSZ, 0);
+}
+
+/**
+ * Process incoming plogi from a remote port.
+ */
+static void
+bfa_fcs_port_plogi(struct bfa_fcs_port_s *port, struct fchs_s *rx_fchs,
+                       struct fc_logi_s *plogi)
+{
+       struct bfa_fcs_rport_s *rport;
+
+       bfa_trc(port->fcs, rx_fchs->d_id);
+       bfa_trc(port->fcs, rx_fchs->s_id);
+
+       /*
+        * If min cfg mode is enabled, drop any incoming PLOGIs
+        */
+       if (__fcs_min_cfg(port->fcs)) {
+               bfa_trc(port->fcs, rx_fchs->s_id);
+               return;
+       }
+
+       if (fc_plogi_parse(rx_fchs) != FC_PARSE_OK) {
+               bfa_trc(port->fcs, rx_fchs->s_id);
+               /*
+                * send a LS reject
+                */
+               bfa_fcs_port_send_ls_rjt(port, rx_fchs,
+                                        FC_LS_RJT_RSN_PROTOCOL_ERROR,
+                                        FC_LS_RJT_EXP_SPARMS_ERR_OPTIONS);
+               return;
+       }
+
+       /**
+* Direct Attach P2P mode : verify address assigned by the r-port.
+        */
+       if ((!bfa_fcs_fabric_is_switched(port->fabric))
+           &&
+           (memcmp
+            ((void *)&bfa_fcs_port_get_pwwn(port), (void *)&plogi->port_name,
+             sizeof(wwn_t)) < 0)) {
+               if (BFA_FCS_PID_IS_WKA(rx_fchs->d_id)) {
+                       /*
+                        * Address assigned to us cannot be a WKA
+                        */
+                       bfa_fcs_port_send_ls_rjt(port, rx_fchs,
+                                       FC_LS_RJT_RSN_PROTOCOL_ERROR,
+                                       FC_LS_RJT_EXP_INVALID_NPORT_ID);
+                       return;
+               }
+               port->pid = rx_fchs->d_id;
+       }
+
+       /**
+        * First, check if we know the device by pwwn.
+        */
+       rport = bfa_fcs_port_get_rport_by_pwwn(port, plogi->port_name);
+       if (rport) {
+               /**
+                * Direct Attach P2P mode: handle address assigned by the rport.
+                */
+               if ((!bfa_fcs_fabric_is_switched(port->fabric))
+                   &&
+                   (memcmp
+                    ((void *)&bfa_fcs_port_get_pwwn(port),
+                     (void *)&plogi->port_name, sizeof(wwn_t)) < 0)) {
+                       port->pid = rx_fchs->d_id;
+                       rport->pid = rx_fchs->s_id;
+               }
+               bfa_fcs_rport_plogi(rport, rx_fchs, plogi);
+               return;
+       }
+
+       /**
+        * Next, lookup rport by PID.
+        */
+       rport = bfa_fcs_port_get_rport_by_pid(port, rx_fchs->s_id);
+       if (!rport) {
+               /**
+                * Inbound PLOGI from a new device.
+                */
+               bfa_fcs_rport_plogi_create(port, rx_fchs, plogi);
+               return;
+       }
+
+       /**
+        * Rport is known only by PID.
+        */
+       if (rport->pwwn) {
+               /**
+                * This is a different device with the same pid. Old device
+                * disappeared. Send implicit LOGO to old device.
+                */
+               bfa_assert(rport->pwwn != plogi->port_name);
+               bfa_fcs_rport_logo_imp(rport);
+
+               /**
+                * Inbound PLOGI from a new device (with old PID).
+                */
+               bfa_fcs_rport_plogi_create(port, rx_fchs, plogi);
+               return;
+       }
+
+       /**
+        * PLOGI crossing each other.
+        */
+       bfa_assert(rport->pwwn == WWN_NULL);
+       bfa_fcs_rport_plogi(rport, rx_fchs, plogi);
+}
+
+/*
+ * Process incoming ECHO.
+ * Since it does not require a login, it is processed here.
+ */
+static void
+bfa_fcs_port_echo(struct bfa_fcs_port_s *port, struct fchs_s *rx_fchs,
+                       struct fc_echo_s *echo, u16 rx_len)
+{
+       struct fchs_s          fchs;
+       struct bfa_fcxp_s *fcxp;
+       struct bfa_rport_s *bfa_rport = NULL;
+       int             len, pyld_len;
+
+       bfa_trc(port->fcs, rx_fchs->s_id);
+       bfa_trc(port->fcs, rx_fchs->d_id);
+       bfa_trc(port->fcs, rx_len);
+
+       fcxp = bfa_fcs_fcxp_alloc(port->fcs);
+       if (!fcxp)
+               return;
+
+       len = fc_ls_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), rx_fchs->s_id,
+                             bfa_fcs_port_get_fcid(port), rx_fchs->ox_id);
+
+       /*
+        * Copy the payload (if any) from the echo frame
+        */
+       pyld_len = rx_len - sizeof(struct fchs_s);
+       bfa_trc(port->fcs, pyld_len);
+
+       if (pyld_len > len)
+               memcpy(((u8 *) bfa_fcxp_get_reqbuf(fcxp)) +
+                      sizeof(struct fc_echo_s), (echo + 1),
+                      (pyld_len - sizeof(struct fc_echo_s)));
+
+       bfa_fcxp_send(fcxp, bfa_rport, port->fabric->vf_id, port->lp_tag,
+                     BFA_FALSE, FC_CLASS_3, pyld_len, &fchs, NULL, NULL,
+                     FC_MAX_PDUSZ, 0);
+}
+
+/*
+ * Process incoming RNID.
+ * Since it does not require a login, it is processed here.
+ */
+static void
+bfa_fcs_port_rnid(struct bfa_fcs_port_s *port, struct fchs_s *rx_fchs,
+                       struct fc_rnid_cmd_s *rnid, u16 rx_len)
+{
+       struct fc_rnid_common_id_data_s common_id_data;
+       struct fc_rnid_general_topology_data_s gen_topo_data;
+       struct fchs_s          fchs;
+       struct bfa_fcxp_s *fcxp;
+       struct bfa_rport_s *bfa_rport = NULL;
+       u16        len;
+       u32        data_format;
+
+       bfa_trc(port->fcs, rx_fchs->s_id);
+       bfa_trc(port->fcs, rx_fchs->d_id);
+       bfa_trc(port->fcs, rx_len);
+
+       fcxp = bfa_fcs_fcxp_alloc(port->fcs);
+       if (!fcxp)
+               return;
+
+       /*
+        * Check Node Indentification Data Format
+        * We only support General Topology Discovery Format.
+        * For any other requested Data Formats, we return Common Node Id Data
+        * only, as per FC-LS.
+        */
+       bfa_trc(port->fcs, rnid->node_id_data_format);
+       if (rnid->node_id_data_format == RNID_NODEID_DATA_FORMAT_DISCOVERY) {
+               data_format = RNID_NODEID_DATA_FORMAT_DISCOVERY;
+               /*
+                * Get General topology data for this port
+                */
+               bfa_fs_port_get_gen_topo_data(port, &gen_topo_data);
+       } else {
+               data_format = RNID_NODEID_DATA_FORMAT_COMMON;
+       }
+
+       /*
+        * Copy the Node Id Info
+        */
+       common_id_data.port_name = bfa_fcs_port_get_pwwn(port);
+       common_id_data.node_name = bfa_fcs_port_get_nwwn(port);
+
+       len = fc_rnid_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), rx_fchs->s_id,
+                               bfa_fcs_port_get_fcid(port), rx_fchs->ox_id,
+                               data_format, &common_id_data, &gen_topo_data);
+
+       bfa_fcxp_send(fcxp, bfa_rport, port->fabric->vf_id, port->lp_tag,
+                     BFA_FALSE, FC_CLASS_3, len, &fchs, NULL, NULL,
+                     FC_MAX_PDUSZ, 0);
+
+       return;
+}
+
+/*
+ *  Fill out General Topolpgy Discovery Data for RNID ELS.
+ */
+static void
+bfa_fs_port_get_gen_topo_data(struct bfa_fcs_port_s *port,
+                       struct fc_rnid_general_topology_data_s *gen_topo_data)
+{
+
+       bfa_os_memset(gen_topo_data, 0,
+                     sizeof(struct fc_rnid_general_topology_data_s));
+
+       gen_topo_data->asso_type = bfa_os_htonl(RNID_ASSOCIATED_TYPE_HOST);
+       gen_topo_data->phy_port_num = 0;        /* @todo */
+       gen_topo_data->num_attached_nodes = bfa_os_htonl(1);
+}
+
+static void
+bfa_fcs_port_online_actions(struct bfa_fcs_port_s *port)
+{
+       bfa_trc(port->fcs, port->fabric->oper_type);
+
+       __port_action[port->fabric->fab_type].init(port);
+       __port_action[port->fabric->fab_type].online(port);
+
+       bfa_fcs_port_aen_post(port, BFA_LPORT_AEN_ONLINE);
+       bfa_fcb_port_online(port->fcs->bfad, port->port_cfg.roles,
+                       port->fabric->vf_drv, (port->vport == NULL) ?
+                       NULL : port->vport->vport_drv);
+}
+
+static void
+bfa_fcs_port_offline_actions(struct bfa_fcs_port_s *port)
+{
+       struct list_head *qe, *qen;
+       struct bfa_fcs_rport_s *rport;
+
+       bfa_trc(port->fcs, port->fabric->oper_type);
+
+       __port_action[port->fabric->fab_type].offline(port);
+
+       if (bfa_fcs_fabric_is_online(port->fabric) == BFA_TRUE) {
+               bfa_fcs_port_aen_post(port, BFA_LPORT_AEN_DISCONNECT);
+       } else {
+               bfa_fcs_port_aen_post(port, BFA_LPORT_AEN_OFFLINE);
+       }
+       bfa_fcb_port_offline(port->fcs->bfad, port->port_cfg.roles,
+                       port->fabric->vf_drv,
+                       (port->vport == NULL) ? NULL : port->vport->vport_drv);
+
+       list_for_each_safe(qe, qen, &port->rport_q) {
+               rport = (struct bfa_fcs_rport_s *)qe;
+               bfa_fcs_rport_offline(rport);
+       }
+}
+
+static void
+bfa_fcs_port_unknown_init(struct bfa_fcs_port_s *port)
+{
+       bfa_assert(0);
+}
+
+static void
+bfa_fcs_port_unknown_online(struct bfa_fcs_port_s *port)
+{
+       bfa_assert(0);
+}
+
+static void
+bfa_fcs_port_unknown_offline(struct bfa_fcs_port_s *port)
+{
+       bfa_assert(0);
+}
+
+static void
+bfa_fcs_port_deleted(struct bfa_fcs_port_s *port)
+{
+       bfa_fcs_port_aen_post(port, BFA_LPORT_AEN_DELETE);
+
+       /*
+        * Base port will be deleted by the OS driver
+        */
+       if (port->vport) {
+               bfa_fcb_port_delete(port->fcs->bfad, port->port_cfg.roles,
+                       port->fabric->vf_drv,
+                       port->vport ? port->vport->vport_drv : NULL);
+               bfa_fcs_vport_delete_comp(port->vport);
+       } else {
+               bfa_fcs_fabric_port_delete_comp(port->fabric);
+       }
+}
+
+
+
+/**
+ *  fcs_lport_api BFA FCS port API
+ */
+/**
+ *   Module initialization
+ */
+void
+bfa_fcs_port_modinit(struct bfa_fcs_s *fcs)
+{
+
+}
+
+/**
+ *   Module cleanup
+ */
+void
+bfa_fcs_port_modexit(struct bfa_fcs_s *fcs)
+{
+       bfa_fcs_modexit_comp(fcs);
+}
+
+/**
+ *             Unsolicited frame receive handling.
+ */
+void
+bfa_fcs_port_uf_recv(struct bfa_fcs_port_s *lport, struct fchs_s *fchs,
+                       u16 len)
+{
+       u32        pid = fchs->s_id;
+       struct bfa_fcs_rport_s *rport = NULL;
+       struct fc_els_cmd_s   *els_cmd = (struct fc_els_cmd_s *) (fchs + 1);
+
+       bfa_stats(lport, uf_recvs);
+
+       if (!bfa_fcs_port_is_online(lport)) {
+               bfa_stats(lport, uf_recv_drops);
+               return;
+       }
+
+       /**
+        * First, handle ELSs that donot require a login.
+        */
+       /*
+        * Handle PLOGI first
+        */
+       if ((fchs->type == FC_TYPE_ELS) &&
+               (els_cmd->els_code == FC_ELS_PLOGI)) {
+               bfa_fcs_port_plogi(lport, fchs, (struct fc_logi_s *) els_cmd);
+               return;
+       }
+
+       /*
+        * Handle ECHO separately.
+        */
+       if ((fchs->type == FC_TYPE_ELS) && (els_cmd->els_code == FC_ELS_ECHO)) {
+               bfa_fcs_port_echo(lport, fchs,
+                       (struct fc_echo_s *) els_cmd, len);
+               return;
+       }
+
+       /*
+        * Handle RNID separately.
+        */
+       if ((fchs->type == FC_TYPE_ELS) && (els_cmd->els_code == FC_ELS_RNID)) {
+               bfa_fcs_port_rnid(lport, fchs,
+                       (struct fc_rnid_cmd_s *) els_cmd, len);
+               return;
+       }
+
+       /**
+        * look for a matching remote port ID
+        */
+       rport = bfa_fcs_port_get_rport_by_pid(lport, pid);
+       if (rport) {
+               bfa_trc(rport->fcs, fchs->s_id);
+               bfa_trc(rport->fcs, fchs->d_id);
+               bfa_trc(rport->fcs, fchs->type);
+
+               bfa_fcs_rport_uf_recv(rport, fchs, len);
+               return;
+       }
+
+       /**
+        * Only handles ELS frames for now.
+        */
+       if (fchs->type != FC_TYPE_ELS) {
+               bfa_trc(lport->fcs, fchs->type);
+               bfa_assert(0);
+               return;
+       }
+
+       bfa_trc(lport->fcs, els_cmd->els_code);
+       if (els_cmd->els_code == FC_ELS_RSCN) {
+               bfa_fcs_port_scn_process_rscn(lport, fchs, len);
+               return;
+       }
+
+       if (els_cmd->els_code == FC_ELS_LOGO) {
+               /**
+                * @todo Handle LOGO frames received.
+                */
+               bfa_trc(lport->fcs, els_cmd->els_code);
+               return;
+       }
+
+       if (els_cmd->els_code == FC_ELS_PRLI) {
+               /**
+                * @todo Handle PRLI frames received.
+                */
+               bfa_trc(lport->fcs, els_cmd->els_code);
+               return;
+       }
+
+       /**
+        * Unhandled ELS frames. Send a LS_RJT.
+        */
+       bfa_fcs_port_send_ls_rjt(lport, fchs, FC_LS_RJT_RSN_CMD_NOT_SUPP,
+                                FC_LS_RJT_EXP_NO_ADDL_INFO);
+
+}
+
+/**
+ *   PID based Lookup for a R-Port in the Port R-Port Queue
+ */
+struct bfa_fcs_rport_s *
+bfa_fcs_port_get_rport_by_pid(struct bfa_fcs_port_s *port, u32 pid)
+{
+       struct bfa_fcs_rport_s *rport;
+       struct list_head *qe;
+
+       list_for_each(qe, &port->rport_q) {
+               rport = (struct bfa_fcs_rport_s *)qe;
+               if (rport->pid == pid)
+                       return rport;
+       }
+
+       bfa_trc(port->fcs, pid);
+       return NULL;
+}
+
+/**
+ *   PWWN based Lookup for a R-Port in the Port R-Port Queue
+ */
+struct bfa_fcs_rport_s *
+bfa_fcs_port_get_rport_by_pwwn(struct bfa_fcs_port_s *port, wwn_t pwwn)
+{
+       struct bfa_fcs_rport_s *rport;
+       struct list_head *qe;
+
+       list_for_each(qe, &port->rport_q) {
+               rport = (struct bfa_fcs_rport_s *)qe;
+               if (wwn_is_equal(rport->pwwn, pwwn))
+                       return rport;
+       }
+
+       bfa_trc(port->fcs, pwwn);
+       return (NULL);
+}
+
+/**
+ *   NWWN based Lookup for a R-Port in the Port R-Port Queue
+ */
+struct bfa_fcs_rport_s *
+bfa_fcs_port_get_rport_by_nwwn(struct bfa_fcs_port_s *port, wwn_t nwwn)
+{
+       struct bfa_fcs_rport_s *rport;
+       struct list_head *qe;
+
+       list_for_each(qe, &port->rport_q) {
+               rport = (struct bfa_fcs_rport_s *)qe;
+               if (wwn_is_equal(rport->nwwn, nwwn))
+                       return rport;
+       }
+
+       bfa_trc(port->fcs, nwwn);
+       return (NULL);
+}
+
+/**
+ * Called by rport module when new rports are discovered.
+ */
+void
+bfa_fcs_port_add_rport(struct bfa_fcs_port_s *port,
+                      struct bfa_fcs_rport_s *rport)
+{
+       list_add_tail(&rport->qe, &port->rport_q);
+       port->num_rports++;
+}
+
+/**
+ * Called by rport module to when rports are deleted.
+ */
+void
+bfa_fcs_port_del_rport(struct bfa_fcs_port_s *port,
+                      struct bfa_fcs_rport_s *rport)
+{
+       bfa_assert(bfa_q_is_on_q(&port->rport_q, rport));
+       list_del(&rport->qe);
+       port->num_rports--;
+
+       bfa_sm_send_event(port, BFA_FCS_PORT_SM_DELRPORT);
+}
+
+/**
+ * Called by fabric for base port when fabric login is complete.
+ * Called by vport for virtual ports when FDISC is complete.
+ */
+void
+bfa_fcs_port_online(struct bfa_fcs_port_s *port)
+{
+       bfa_sm_send_event(port, BFA_FCS_PORT_SM_ONLINE);
+}
+
+/**
+ * Called by fabric for base port when fabric goes offline.
+ * Called by vport for virtual ports when virtual port becomes offline.
+ */
+void
+bfa_fcs_port_offline(struct bfa_fcs_port_s *port)
+{
+       bfa_sm_send_event(port, BFA_FCS_PORT_SM_OFFLINE);
+}
+
+/**
+ * Called by fabric to delete base lport and associated resources.
+ *
+ * Called by vport to delete lport and associated resources. Should call
+ * bfa_fcs_vport_delete_comp() for vports on completion.
+ */
+void
+bfa_fcs_port_delete(struct bfa_fcs_port_s *port)
+{
+       bfa_sm_send_event(port, BFA_FCS_PORT_SM_DELETE);
+}
+
+/**
+ * Called by fabric in private loop topology to process LIP event.
+ */
+void
+bfa_fcs_port_lip(struct bfa_fcs_port_s *port)
+{
+}
+
+/**
+ * Return TRUE if port is online, else return FALSE
+ */
+bfa_boolean_t
+bfa_fcs_port_is_online(struct bfa_fcs_port_s *port)
+{
+       return (bfa_sm_cmp_state(port, bfa_fcs_port_sm_online));
+}
+
+/**
+ * Logical port initialization of base or virtual port.
+ * Called by fabric for base port or by vport for virtual ports.
+ */
+void
+bfa_fcs_lport_init(struct bfa_fcs_port_s *lport, struct bfa_fcs_s *fcs,
+                  u16 vf_id, struct bfa_port_cfg_s *port_cfg,
+                  struct bfa_fcs_vport_s *vport)
+{
+       lport->fcs = fcs;
+       lport->fabric = bfa_fcs_vf_lookup(fcs, vf_id);
+       bfa_os_assign(lport->port_cfg, *port_cfg);
+       lport->vport = vport;
+       lport->lp_tag = (vport) ? bfa_lps_get_tag(vport->lps) :
+                        bfa_lps_get_tag(lport->fabric->lps);
+
+       INIT_LIST_HEAD(&lport->rport_q);
+       lport->num_rports = 0;
+
+       lport->bfad_port =
+               bfa_fcb_port_new(fcs->bfad, lport, lport->port_cfg.roles,
+                               lport->fabric->vf_drv,
+                               vport ? vport->vport_drv : NULL);
+       bfa_fcs_port_aen_post(lport, BFA_LPORT_AEN_NEW);
+
+       bfa_sm_set_state(lport, bfa_fcs_port_sm_uninit);
+       bfa_sm_send_event(lport, BFA_FCS_PORT_SM_CREATE);
+}
+
+
+
+/**
+ *  fcs_lport_api
+ */
+
+void
+bfa_fcs_port_get_attr(struct bfa_fcs_port_s *port,
+                     struct bfa_port_attr_s *port_attr)
+{
+       if (bfa_sm_cmp_state(port, bfa_fcs_port_sm_online))
+               port_attr->pid = port->pid;
+       else
+               port_attr->pid = 0;
+
+       port_attr->port_cfg = port->port_cfg;
+
+       if (port->fabric) {
+               port_attr->port_type = bfa_fcs_fabric_port_type(port->fabric);
+               port_attr->loopback = bfa_fcs_fabric_is_loopback(port->fabric);
+               port_attr->fabric_name = bfa_fcs_port_get_fabric_name(port);
+               memcpy(port_attr->fabric_ip_addr,
+                      bfa_fcs_port_get_fabric_ipaddr(port),
+                      BFA_FCS_FABRIC_IPADDR_SZ);
+
+               if (port->vport != NULL)
+                       port_attr->port_type = BFA_PPORT_TYPE_VPORT;
+
+       } else {
+               port_attr->port_type = BFA_PPORT_TYPE_UNKNOWN;
+               port_attr->state = BFA_PORT_UNINIT;
+       }
+
+}
+
+
diff --git a/drivers/scsi/bfa/bfa_fcs_port.c b/drivers/scsi/bfa/bfa_fcs_port.c
new file mode 100644 (file)
index 0000000..9c4b24e
--- /dev/null
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) 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.
+ */
+
+/**
+ *  bfa_fcs_pport.c BFA FCS PPORT ( physical port)
+ */
+
+#include <fcs/bfa_fcs.h>
+#include <bfa_svc.h>
+#include <fcs/bfa_fcs_fabric.h>
+#include "fcs_trcmod.h"
+#include "fcs.h"
+#include "fcs_fabric.h"
+#include "fcs_port.h"
+
+BFA_TRC_FILE(FCS, PPORT);
+
+static void
+bfa_fcs_pport_event_handler(void *cbarg, bfa_pport_event_t event)
+{
+       struct bfa_fcs_s      *fcs = cbarg;
+
+       bfa_trc(fcs, event);
+
+       switch (event) {
+       case BFA_PPORT_LINKUP:
+               bfa_fcs_fabric_link_up(&fcs->fabric);
+               break;
+
+       case BFA_PPORT_LINKDOWN:
+               bfa_fcs_fabric_link_down(&fcs->fabric);
+               break;
+
+       case BFA_PPORT_TRUNK_LINKDOWN:
+               bfa_assert(0);
+               break;
+
+       default:
+               bfa_assert(0);
+       }
+}
+
+void
+bfa_fcs_pport_modinit(struct bfa_fcs_s *fcs)
+{
+       bfa_pport_event_register(fcs->bfa, bfa_fcs_pport_event_handler,
+                                    fcs);
+}
+
+void
+bfa_fcs_pport_modexit(struct bfa_fcs_s *fcs)
+{
+       bfa_fcs_modexit_comp(fcs);
+}
diff --git a/drivers/scsi/bfa/bfa_fcs_uf.c b/drivers/scsi/bfa/bfa_fcs_uf.c
new file mode 100644 (file)
index 0000000..ad01db6
--- /dev/null
@@ -0,0 +1,105 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) 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.
+ */
+
+/**
+ *  bfa_fcs_uf.c BFA FCS UF ( Unsolicited Frames)
+ */
+
+#include <fcs/bfa_fcs.h>
+#include <bfa_svc.h>
+#include <fcs/bfa_fcs_fabric.h>
+#include "fcs.h"
+#include "fcs_trcmod.h"
+#include "fcs_fabric.h"
+#include "fcs_uf.h"
+
+BFA_TRC_FILE(FCS, UF);
+
+/**
+ *             BFA callback for unsolicited frame receive handler.
+ *
+ * @param[in]          cbarg           callback arg for receive handler
+ * @param[in]          uf              unsolicited frame descriptor
+ *
+ * @return None
+ */
+static void
+bfa_fcs_uf_recv(void *cbarg, struct bfa_uf_s *uf)
+{
+       struct bfa_fcs_s      *fcs = (struct bfa_fcs_s *) cbarg;
+       struct fchs_s         *fchs = bfa_uf_get_frmbuf(uf);
+       u16        len = bfa_uf_get_frmlen(uf);
+       struct fc_vft_s       *vft;
+       struct bfa_fcs_fabric_s *fabric;
+
+       /**
+        * check for VFT header
+        */
+       if (fchs->routing == FC_RTG_EXT_HDR &&
+               fchs->cat_info == FC_CAT_VFT_HDR) {
+               bfa_stats(fcs, uf.tagged);
+               vft = bfa_uf_get_frmbuf(uf);
+               if (fcs->port_vfid == vft->vf_id)
+                       fabric = &fcs->fabric;
+               else
+                       fabric = bfa_fcs_vf_lookup(fcs, (u16) vft->vf_id);
+
+               /**
+                * drop frame if vfid is unknown
+                */
+               if (!fabric) {
+                       bfa_assert(0);
+                       bfa_stats(fcs, uf.vfid_unknown);
+                       bfa_uf_free(uf);
+                       return;
+               }
+
+               /**
+                * skip vft header
+                */
+               fchs = (struct fchs_s *) (vft + 1);
+               len -= sizeof(struct fc_vft_s);
+
+               bfa_trc(fcs, vft->vf_id);
+       } else {
+               bfa_stats(fcs, uf.untagged);
+               fabric = &fcs->fabric;
+       }
+
+       bfa_trc(fcs, ((u32 *) fchs)[0]);
+       bfa_trc(fcs, ((u32 *) fchs)[1]);
+       bfa_trc(fcs, ((u32 *) fchs)[2]);
+       bfa_trc(fcs, ((u32 *) fchs)[3]);
+       bfa_trc(fcs, ((u32 *) fchs)[4]);
+       bfa_trc(fcs, ((u32 *) fchs)[5]);
+       bfa_trc(fcs, len);
+
+       bfa_fcs_fabric_uf_recv(fabric, fchs, len);
+       bfa_uf_free(uf);
+}
+
+void
+bfa_fcs_uf_modinit(struct bfa_fcs_s *fcs)
+{
+       bfa_uf_recv_register(fcs->bfa, bfa_fcs_uf_recv, fcs);
+}
+
+void
+bfa_fcs_uf_modexit(struct bfa_fcs_s *fcs)
+{
+       bfa_fcs_modexit_comp(fcs);
+}
diff --git a/drivers/scsi/bfa/bfa_fcxp.c b/drivers/scsi/bfa/bfa_fcxp.c
new file mode 100644 (file)
index 0000000..4754a0e
--- /dev/null
@@ -0,0 +1,782 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ */
+
+#include <bfa.h>
+#include <bfi/bfi_uf.h>
+#include <cs/bfa_debug.h>
+
+BFA_TRC_FILE(HAL, FCXP);
+BFA_MODULE(fcxp);
+
+/**
+ * forward declarations
+ */
+static void     __bfa_fcxp_send_cbfn(void *cbarg, bfa_boolean_t complete);
+static void     hal_fcxp_rx_plog(struct bfa_s *bfa, struct bfa_fcxp_s *fcxp,
+                                struct bfi_fcxp_send_rsp_s *fcxp_rsp);
+static void     hal_fcxp_tx_plog(struct bfa_s *bfa, u32 reqlen,
+                                struct bfa_fcxp_s *fcxp, struct fchs_s *fchs);
+static void    bfa_fcxp_qresume(void *cbarg);
+static void    bfa_fcxp_queue(struct bfa_fcxp_s *fcxp,
+                              struct bfi_fcxp_send_req_s *send_req);
+
+/**
+ *  fcxp_pvt BFA FCXP private functions
+ */
+
+static void
+claim_fcxp_req_rsp_mem(struct bfa_fcxp_mod_s *mod, struct bfa_meminfo_s *mi)
+{
+       u8        *dm_kva = NULL;
+       u64        dm_pa;
+       u32        buf_pool_sz;
+
+       dm_kva = bfa_meminfo_dma_virt(mi);
+       dm_pa = bfa_meminfo_dma_phys(mi);
+
+       buf_pool_sz = mod->req_pld_sz * mod->num_fcxps;
+
+       /*
+        * Initialize the fcxp req payload list
+        */
+       mod->req_pld_list_kva = dm_kva;
+       mod->req_pld_list_pa = dm_pa;
+       dm_kva += buf_pool_sz;
+       dm_pa += buf_pool_sz;
+       bfa_os_memset(mod->req_pld_list_kva, 0, buf_pool_sz);
+
+       /*
+        * Initialize the fcxp rsp payload list
+        */
+       buf_pool_sz = mod->rsp_pld_sz * mod->num_fcxps;
+       mod->rsp_pld_list_kva = dm_kva;
+       mod->rsp_pld_list_pa = dm_pa;
+       dm_kva += buf_pool_sz;
+       dm_pa += buf_pool_sz;
+       bfa_os_memset(mod->rsp_pld_list_kva, 0, buf_pool_sz);
+
+       bfa_meminfo_dma_virt(mi) = dm_kva;
+       bfa_meminfo_dma_phys(mi) = dm_pa;
+}
+
+static void
+claim_fcxps_mem(struct bfa_fcxp_mod_s *mod, struct bfa_meminfo_s *mi)
+{
+       u16        i;
+       struct bfa_fcxp_s *fcxp;
+
+       fcxp = (struct bfa_fcxp_s *) bfa_meminfo_kva(mi);
+       bfa_os_memset(fcxp, 0, sizeof(struct bfa_fcxp_s) * mod->num_fcxps);
+
+       INIT_LIST_HEAD(&mod->fcxp_free_q);
+       INIT_LIST_HEAD(&mod->fcxp_active_q);
+
+       mod->fcxp_list = fcxp;
+
+       for (i = 0; i < mod->num_fcxps; i++) {
+               fcxp->fcxp_mod = mod;
+               fcxp->fcxp_tag = i;
+
+               list_add_tail(&fcxp->qe, &mod->fcxp_free_q);
+               bfa_reqq_winit(&fcxp->reqq_wqe, bfa_fcxp_qresume, fcxp);
+               fcxp->reqq_waiting = BFA_FALSE;
+
+               fcxp = fcxp + 1;
+       }
+
+       bfa_meminfo_kva(mi) = (void *)fcxp;
+}
+
+static void
+bfa_fcxp_meminfo(struct bfa_iocfc_cfg_s *cfg, u32 *ndm_len,
+               u32 *dm_len)
+{
+       u16        num_fcxp_reqs = cfg->fwcfg.num_fcxp_reqs;
+
+       if (num_fcxp_reqs == 0)
+               return;
+
+       /*
+        * Account for req/rsp payload
+        */
+       *dm_len += BFA_FCXP_MAX_IBUF_SZ * num_fcxp_reqs;
+       if (cfg->drvcfg.min_cfg)
+               *dm_len += BFA_FCXP_MAX_IBUF_SZ * num_fcxp_reqs;
+       else
+               *dm_len += BFA_FCXP_MAX_LBUF_SZ * num_fcxp_reqs;
+
+       /*
+        * Account for fcxp structs
+        */
+       *ndm_len += sizeof(struct bfa_fcxp_s) * num_fcxp_reqs;
+}
+
+static void
+bfa_fcxp_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
+                   struct bfa_meminfo_s *meminfo, struct bfa_pcidev_s *pcidev)
+{
+       struct bfa_fcxp_mod_s *mod = BFA_FCXP_MOD(bfa);
+
+       bfa_os_memset(mod, 0, sizeof(struct bfa_fcxp_mod_s));
+       mod->bfa = bfa;
+       mod->num_fcxps = cfg->fwcfg.num_fcxp_reqs;
+
+       /**
+        * Initialize FCXP request and response payload sizes.
+        */
+       mod->req_pld_sz = mod->rsp_pld_sz = BFA_FCXP_MAX_IBUF_SZ;
+       if (!cfg->drvcfg.min_cfg)
+               mod->rsp_pld_sz = BFA_FCXP_MAX_LBUF_SZ;
+
+       INIT_LIST_HEAD(&mod->wait_q);
+
+       claim_fcxp_req_rsp_mem(mod, meminfo);
+       claim_fcxps_mem(mod, meminfo);
+}
+
+static void
+bfa_fcxp_initdone(struct bfa_s *bfa)
+{
+}
+
+static void
+bfa_fcxp_detach(struct bfa_s *bfa)
+{
+}
+
+static void
+bfa_fcxp_start(struct bfa_s *bfa)
+{
+}
+
+static void
+bfa_fcxp_stop(struct bfa_s *bfa)
+{
+}
+
+static void
+bfa_fcxp_iocdisable(struct bfa_s *bfa)
+{
+       struct bfa_fcxp_mod_s *mod = BFA_FCXP_MOD(bfa);
+       struct bfa_fcxp_s *fcxp;
+       struct list_head        *qe, *qen;
+
+       list_for_each_safe(qe, qen, &mod->fcxp_active_q) {
+               fcxp = (struct bfa_fcxp_s *) qe;
+               if (fcxp->caller == NULL) {
+                       fcxp->send_cbfn(fcxp->caller, fcxp, fcxp->send_cbarg,
+                                       BFA_STATUS_IOC_FAILURE, 0, 0, NULL);
+                       bfa_fcxp_free(fcxp);
+               } else {
+                       fcxp->rsp_status = BFA_STATUS_IOC_FAILURE;
+                       bfa_cb_queue(bfa, &fcxp->hcb_qe,
+                                     __bfa_fcxp_send_cbfn, fcxp);
+               }
+       }
+}
+
+static struct bfa_fcxp_s *
+bfa_fcxp_get(struct bfa_fcxp_mod_s *fm)
+{
+       struct bfa_fcxp_s *fcxp;
+
+       bfa_q_deq(&fm->fcxp_free_q, &fcxp);
+
+       if (fcxp)
+               list_add_tail(&fcxp->qe, &fm->fcxp_active_q);
+
+       return (fcxp);
+}
+
+static void
+bfa_fcxp_put(struct bfa_fcxp_s *fcxp)
+{
+       struct bfa_fcxp_mod_s *mod = fcxp->fcxp_mod;
+       struct bfa_fcxp_wqe_s *wqe;
+
+       bfa_q_deq(&mod->wait_q, &wqe);
+       if (wqe) {
+               bfa_trc(mod->bfa, fcxp->fcxp_tag);
+               wqe->alloc_cbfn(wqe->alloc_cbarg, fcxp);
+               return;
+       }
+
+       bfa_assert(bfa_q_is_on_q(&mod->fcxp_active_q, fcxp));
+       list_del(&fcxp->qe);
+       list_add_tail(&fcxp->qe, &mod->fcxp_free_q);
+}
+
+static void
+bfa_fcxp_null_comp(void *bfad_fcxp, struct bfa_fcxp_s *fcxp, void *cbarg,
+                      bfa_status_t req_status, u32 rsp_len,
+                      u32 resid_len, struct fchs_s *rsp_fchs)
+{
+       /**discarded fcxp completion */
+}
+
+static void
+__bfa_fcxp_send_cbfn(void *cbarg, bfa_boolean_t complete)
+{
+       struct bfa_fcxp_s *fcxp = cbarg;
+
+       if (complete) {
+               fcxp->send_cbfn(fcxp->caller, fcxp, fcxp->send_cbarg,
+                               fcxp->rsp_status, fcxp->rsp_len,
+                               fcxp->residue_len, &fcxp->rsp_fchs);
+       } else {
+               bfa_fcxp_free(fcxp);
+       }
+}
+
+static void
+hal_fcxp_send_comp(struct bfa_s *bfa, struct bfi_fcxp_send_rsp_s *fcxp_rsp)
+{
+       struct bfa_fcxp_mod_s   *mod = BFA_FCXP_MOD(bfa);
+       struct bfa_fcxp_s       *fcxp;
+       u16             fcxp_tag = bfa_os_ntohs(fcxp_rsp->fcxp_tag);
+
+       bfa_trc(bfa, fcxp_tag);
+
+       fcxp_rsp->rsp_len = bfa_os_ntohl(fcxp_rsp->rsp_len);
+
+       /**
+        * @todo f/w should not set residue to non-0 when everything
+        *       is received.
+        */
+       if (fcxp_rsp->req_status == BFA_STATUS_OK)
+               fcxp_rsp->residue_len = 0;
+       else
+               fcxp_rsp->residue_len = bfa_os_ntohl(fcxp_rsp->residue_len);
+
+       fcxp = BFA_FCXP_FROM_TAG(mod, fcxp_tag);
+
+       bfa_assert(fcxp->send_cbfn != NULL);
+
+       hal_fcxp_rx_plog(mod->bfa, fcxp, fcxp_rsp);
+
+       if (fcxp->send_cbfn != NULL) {
+               if (fcxp->caller == NULL) {
+                       bfa_trc(mod->bfa, fcxp->fcxp_tag);
+
+                       fcxp->send_cbfn(fcxp->caller, fcxp, fcxp->send_cbarg,
+                                       fcxp_rsp->req_status, fcxp_rsp->rsp_len,
+                                       fcxp_rsp->residue_len, &fcxp_rsp->fchs);
+                       /*
+                        * fcxp automatically freed on return from the callback
+                        */
+                       bfa_fcxp_free(fcxp);
+               } else {
+                       bfa_trc(mod->bfa, fcxp->fcxp_tag);
+                       fcxp->rsp_status = fcxp_rsp->req_status;
+                       fcxp->rsp_len = fcxp_rsp->rsp_len;
+                       fcxp->residue_len = fcxp_rsp->residue_len;
+                       fcxp->rsp_fchs = fcxp_rsp->fchs;
+
+                       bfa_cb_queue(bfa, &fcxp->hcb_qe,
+                                     __bfa_fcxp_send_cbfn, fcxp);
+               }
+       } else {
+               bfa_trc(bfa, fcxp_tag);
+       }
+}
+
+static void
+hal_fcxp_set_local_sges(struct bfi_sge_s *sge, u32 reqlen, u64 req_pa)
+{
+       union bfi_addr_u      sga_zero = { {0} };
+
+       sge->sg_len = reqlen;
+       sge->flags = BFI_SGE_DATA_LAST;
+       bfa_dma_addr_set(sge[0].sga, req_pa);
+       bfa_sge_to_be(sge);
+       sge++;
+
+       sge->sga = sga_zero;
+       sge->sg_len = reqlen;
+       sge->flags = BFI_SGE_PGDLEN;
+       bfa_sge_to_be(sge);
+}
+
+static void
+hal_fcxp_tx_plog(struct bfa_s *bfa, u32 reqlen, struct bfa_fcxp_s *fcxp,
+                struct fchs_s *fchs)
+{
+       /*
+        * TODO: TX ox_id
+        */
+       if (reqlen > 0) {
+               if (fcxp->use_ireqbuf) {
+                       u32        pld_w0 =
+                               *((u32 *) BFA_FCXP_REQ_PLD(fcxp));
+
+                       bfa_plog_fchdr_and_pl(bfa->plog, BFA_PL_MID_HAL_FCXP,
+                               BFA_PL_EID_TX,
+                               reqlen + sizeof(struct fchs_s), fchs, pld_w0);
+               } else {
+                       bfa_plog_fchdr(bfa->plog, BFA_PL_MID_HAL_FCXP,
+                               BFA_PL_EID_TX, reqlen + sizeof(struct fchs_s),
+                               fchs);
+               }
+       } else {
+               bfa_plog_fchdr(bfa->plog, BFA_PL_MID_HAL_FCXP, BFA_PL_EID_TX,
+                              reqlen + sizeof(struct fchs_s), fchs);
+       }
+}
+
+static void
+hal_fcxp_rx_plog(struct bfa_s *bfa, struct bfa_fcxp_s *fcxp,
+                struct bfi_fcxp_send_rsp_s *fcxp_rsp)
+{
+       if (fcxp_rsp->rsp_len > 0) {
+               if (fcxp->use_irspbuf) {
+                       u32        pld_w0 =
+                               *((u32 *) BFA_FCXP_RSP_PLD(fcxp));
+
+                       bfa_plog_fchdr_and_pl(bfa->plog, BFA_PL_MID_HAL_FCXP,
+                                             BFA_PL_EID_RX,
+                                             (u16) fcxp_rsp->rsp_len,
+                                             &fcxp_rsp->fchs, pld_w0);
+               } else {
+                       bfa_plog_fchdr(bfa->plog, BFA_PL_MID_HAL_FCXP,
+                                      BFA_PL_EID_RX,
+                                      (u16) fcxp_rsp->rsp_len,
+                                      &fcxp_rsp->fchs);
+               }
+       } else {
+               bfa_plog_fchdr(bfa->plog, BFA_PL_MID_HAL_FCXP, BFA_PL_EID_RX,
+                              (u16) fcxp_rsp->rsp_len, &fcxp_rsp->fchs);
+       }
+}
+
+/**
+ * Handler to resume sending fcxp when space in available in cpe queue.
+ */
+static void
+bfa_fcxp_qresume(void *cbarg)
+{
+       struct bfa_fcxp_s               *fcxp = cbarg;
+       struct bfa_s                    *bfa = fcxp->fcxp_mod->bfa;
+       struct bfi_fcxp_send_req_s      *send_req;
+
+       fcxp->reqq_waiting = BFA_FALSE;
+       send_req = bfa_reqq_next(bfa, BFA_REQQ_FCXP);
+       bfa_fcxp_queue(fcxp, send_req);
+}
+
+/**
+ * Queue fcxp send request to foimrware.
+ */
+static void
+bfa_fcxp_queue(struct bfa_fcxp_s *fcxp, struct bfi_fcxp_send_req_s *send_req)
+{
+       struct bfa_s                    *bfa = fcxp->fcxp_mod->bfa;
+       struct bfa_fcxp_req_info_s      *reqi = &fcxp->req_info;
+       struct bfa_fcxp_rsp_info_s      *rspi = &fcxp->rsp_info;
+       struct bfa_rport_s              *rport = reqi->bfa_rport;
+
+       bfi_h2i_set(send_req->mh, BFI_MC_FCXP, BFI_FCXP_H2I_SEND_REQ,
+                       bfa_lpuid(bfa));
+
+       send_req->fcxp_tag = bfa_os_htons(fcxp->fcxp_tag);
+       if (rport) {
+               send_req->rport_fw_hndl = rport->fw_handle;
+               send_req->max_frmsz = bfa_os_htons(rport->rport_info.max_frmsz);
+               if (send_req->max_frmsz == 0)
+                       send_req->max_frmsz = bfa_os_htons(FC_MAX_PDUSZ);
+       } else {
+               send_req->rport_fw_hndl = 0;
+               send_req->max_frmsz = bfa_os_htons(FC_MAX_PDUSZ);
+       }
+
+       send_req->vf_id = bfa_os_htons(reqi->vf_id);
+       send_req->lp_tag = reqi->lp_tag;
+       send_req->class = reqi->class;
+       send_req->rsp_timeout = rspi->rsp_timeout;
+       send_req->cts = reqi->cts;
+       send_req->fchs = reqi->fchs;
+
+       send_req->req_len = bfa_os_htonl(reqi->req_tot_len);
+       send_req->rsp_maxlen = bfa_os_htonl(rspi->rsp_maxlen);
+
+       /*
+        * setup req sgles
+        */
+       if (fcxp->use_ireqbuf == 1) {
+               hal_fcxp_set_local_sges(send_req->req_sge, reqi->req_tot_len,
+                                       BFA_FCXP_REQ_PLD_PA(fcxp));
+       } else {
+               if (fcxp->nreq_sgles > 0) {
+                       bfa_assert(fcxp->nreq_sgles == 1);
+                       hal_fcxp_set_local_sges(send_req->req_sge,
+                                               reqi->req_tot_len,
+                                               fcxp->req_sga_cbfn(fcxp->caller,
+                                                                  0));
+               } else {
+                       bfa_assert(reqi->req_tot_len == 0);
+                       hal_fcxp_set_local_sges(send_req->rsp_sge, 0, 0);
+               }
+       }
+
+       /*
+        * setup rsp sgles
+        */
+       if (fcxp->use_irspbuf == 1) {
+               bfa_assert(rspi->rsp_maxlen <= BFA_FCXP_MAX_LBUF_SZ);
+
+               hal_fcxp_set_local_sges(send_req->rsp_sge, rspi->rsp_maxlen,
+                                       BFA_FCXP_RSP_PLD_PA(fcxp));
+
+       } else {
+               if (fcxp->nrsp_sgles > 0) {
+                       bfa_assert(fcxp->nrsp_sgles == 1);
+                       hal_fcxp_set_local_sges(send_req->rsp_sge,
+                                               rspi->rsp_maxlen,
+                                               fcxp->rsp_sga_cbfn(fcxp->caller,
+                                                                  0));
+               } else {
+                       bfa_assert(rspi->rsp_maxlen == 0);
+                       hal_fcxp_set_local_sges(send_req->rsp_sge, 0, 0);
+               }
+       }
+
+       hal_fcxp_tx_plog(bfa, reqi->req_tot_len, fcxp, &reqi->fchs);
+
+       bfa_reqq_produce(bfa, BFA_REQQ_FCXP);
+
+       bfa_trc(bfa, bfa_reqq_pi(bfa, BFA_REQQ_FCXP));
+       bfa_trc(bfa, bfa_reqq_ci(bfa, BFA_REQQ_FCXP));
+}
+
+
+/**
+ *  hal_fcxp_api BFA FCXP API
+ */
+
+/**
+ * Allocate an FCXP instance to send a response or to send a request
+ * that has a response. Request/response buffers are allocated by caller.
+ *
+ * @param[in]  bfa             BFA bfa instance
+ * @param[in]  nreq_sgles      Number of SG elements required for request
+ *                             buffer. 0, if fcxp internal buffers are used.
+ *                             Use bfa_fcxp_get_reqbuf() to get the
+ *                             internal req buffer.
+ * @param[in]  req_sgles       SG elements describing request buffer. Will be
+ *                             copied in by BFA and hence can be freed on
+ *                             return from this function.
+ * @param[in]  get_req_sga     function ptr to be called to get a request SG
+ *                             Address (given the sge index).
+ * @param[in]  get_req_sglen   function ptr to be called to get a request SG
+ *                             len (given the sge index).
+ * @param[in]  get_rsp_sga     function ptr to be called to get a response SG
+ *                             Address (given the sge index).
+ * @param[in]  get_rsp_sglen   function ptr to be called to get a response SG
+ *                             len (given the sge index).
+ *
+ * @return FCXP instance. NULL on failure.
+ */
+struct bfa_fcxp_s *
+bfa_fcxp_alloc(void *caller, struct bfa_s *bfa, int nreq_sgles,
+                       int nrsp_sgles, bfa_fcxp_get_sgaddr_t req_sga_cbfn,
+                       bfa_fcxp_get_sglen_t req_sglen_cbfn,
+                       bfa_fcxp_get_sgaddr_t rsp_sga_cbfn,
+                       bfa_fcxp_get_sglen_t rsp_sglen_cbfn)
+{
+       struct bfa_fcxp_s *fcxp = NULL;
+       u32        nreq_sgpg, nrsp_sgpg;
+
+       bfa_assert(bfa != NULL);
+
+       fcxp = bfa_fcxp_get(BFA_FCXP_MOD(bfa));
+       if (fcxp == NULL)
+               return (NULL);
+
+       bfa_trc(bfa, fcxp->fcxp_tag);
+
+       fcxp->caller = caller;
+
+       if (nreq_sgles == 0) {
+               fcxp->use_ireqbuf = 1;
+       } else {
+               bfa_assert(req_sga_cbfn != NULL);
+               bfa_assert(req_sglen_cbfn != NULL);
+
+               fcxp->use_ireqbuf = 0;
+               fcxp->req_sga_cbfn = req_sga_cbfn;
+               fcxp->req_sglen_cbfn = req_sglen_cbfn;
+
+               fcxp->nreq_sgles = nreq_sgles;
+
+               /*
+                * alloc required sgpgs
+                */
+               if (nreq_sgles > BFI_SGE_INLINE) {
+                       nreq_sgpg = BFA_SGPG_NPAGE(nreq_sgles);
+
+                       if (bfa_sgpg_malloc
+                           (bfa, &fcxp->req_sgpg_q, nreq_sgpg)
+                           != BFA_STATUS_OK) {
+                               /* bfa_sgpg_wait(bfa, &fcxp->req_sgpg_wqe,
+                               nreq_sgpg); */
+                               /*
+                                * TODO
+                                */
+                       }
+               }
+       }
+
+       if (nrsp_sgles == 0) {
+               fcxp->use_irspbuf = 1;
+       } else {
+               bfa_assert(rsp_sga_cbfn != NULL);
+               bfa_assert(rsp_sglen_cbfn != NULL);
+
+               fcxp->use_irspbuf = 0;
+               fcxp->rsp_sga_cbfn = rsp_sga_cbfn;
+               fcxp->rsp_sglen_cbfn = rsp_sglen_cbfn;
+
+               fcxp->nrsp_sgles = nrsp_sgles;
+               /*
+                * alloc required sgpgs
+                */
+               if (nrsp_sgles > BFI_SGE_INLINE) {
+                       nrsp_sgpg = BFA_SGPG_NPAGE(nreq_sgles);
+
+                       if (bfa_sgpg_malloc
+                           (bfa, &fcxp->rsp_sgpg_q, nrsp_sgpg)
+                           != BFA_STATUS_OK) {
+                               /* bfa_sgpg_wait(bfa, &fcxp->rsp_sgpg_wqe,
+                               nrsp_sgpg); */
+                               /*
+                                * TODO
+                                */
+                       }
+               }
+       }
+
+       return (fcxp);
+}
+
+/**
+ * Get the internal request buffer pointer
+ *
+ * @param[in]  fcxp    BFA fcxp pointer
+ *
+ * @return             pointer to the internal request buffer
+ */
+void *
+bfa_fcxp_get_reqbuf(struct bfa_fcxp_s *fcxp)
+{
+       struct bfa_fcxp_mod_s *mod = fcxp->fcxp_mod;
+       void    *reqbuf;
+
+       bfa_assert(fcxp->use_ireqbuf == 1);
+       reqbuf = ((u8 *)mod->req_pld_list_kva) +
+                       fcxp->fcxp_tag * mod->req_pld_sz;
+       return reqbuf;
+}
+
+u32
+bfa_fcxp_get_reqbufsz(struct bfa_fcxp_s *fcxp)
+{
+       struct bfa_fcxp_mod_s *mod = fcxp->fcxp_mod;
+
+       return mod->req_pld_sz;
+}
+
+/**
+ * Get the internal response buffer pointer
+ *
+ * @param[in]  fcxp    BFA fcxp pointer
+ *
+ * @return             pointer to the internal request buffer
+ */
+void *
+bfa_fcxp_get_rspbuf(struct bfa_fcxp_s *fcxp)
+{
+       struct bfa_fcxp_mod_s *mod = fcxp->fcxp_mod;
+       void    *rspbuf;
+
+       bfa_assert(fcxp->use_irspbuf == 1);
+
+       rspbuf = ((u8 *)mod->rsp_pld_list_kva) +
+                       fcxp->fcxp_tag * mod->rsp_pld_sz;
+       return rspbuf;
+}
+
+/**
+ *             Free the BFA FCXP
+ *
+ * @param[in]  fcxp                    BFA fcxp pointer
+ *
+ * @return             void
+ */
+void
+bfa_fcxp_free(struct bfa_fcxp_s *fcxp)
+{
+       struct bfa_fcxp_mod_s *mod = fcxp->fcxp_mod;
+
+       bfa_assert(fcxp != NULL);
+       bfa_trc(mod->bfa, fcxp->fcxp_tag);
+       bfa_fcxp_put(fcxp);
+}
+
+/**
+ * Send a FCXP request
+ *
+ * @param[in]  fcxp    BFA fcxp pointer
+ * @param[in]  rport   BFA rport pointer. Could be left NULL for WKA rports
+ * @param[in]  vf_id   virtual Fabric ID
+ * @param[in]  lp_tag  lport tag
+ * @param[in]  cts     use Continous sequence
+ * @param[in]  cos     fc Class of Service
+ * @param[in]  reqlen  request length, does not include FCHS length
+ * @param[in]  fchs    fc Header Pointer. The header content will be copied
+ *                     in by BFA.
+ *
+ * @param[in]  cbfn    call back function to be called on receiving
+ *                                                             the response
+ * @param[in]  cbarg   arg for cbfn
+ * @param[in]  rsp_timeout
+ *                     response timeout
+ *
+ * @return             bfa_status_t
+ */
+void
+bfa_fcxp_send(struct bfa_fcxp_s *fcxp, struct bfa_rport_s *rport,
+               u16 vf_id, u8 lp_tag, bfa_boolean_t cts, enum fc_cos cos,
+               u32 reqlen, struct fchs_s *fchs, bfa_cb_fcxp_send_t cbfn,
+               void *cbarg, u32 rsp_maxlen, u8 rsp_timeout)
+{
+       struct bfa_s                    *bfa  = fcxp->fcxp_mod->bfa;
+       struct bfa_fcxp_req_info_s      *reqi = &fcxp->req_info;
+       struct bfa_fcxp_rsp_info_s      *rspi = &fcxp->rsp_info;
+       struct bfi_fcxp_send_req_s      *send_req;
+
+       bfa_trc(bfa, fcxp->fcxp_tag);
+
+       /**
+        * setup request/response info
+        */
+       reqi->bfa_rport = rport;
+       reqi->vf_id = vf_id;
+       reqi->lp_tag = lp_tag;
+       reqi->class = cos;
+       rspi->rsp_timeout = rsp_timeout;
+       reqi->cts = cts;
+       reqi->fchs = *fchs;
+       reqi->req_tot_len = reqlen;
+       rspi->rsp_maxlen = rsp_maxlen;
+       fcxp->send_cbfn = cbfn ? cbfn : bfa_fcxp_null_comp;
+       fcxp->send_cbarg = cbarg;
+
+       /**
+        * If no room in CPE queue, wait for
+        */
+       send_req = bfa_reqq_next(bfa, BFA_REQQ_FCXP);
+       if (!send_req) {
+               bfa_trc(bfa, fcxp->fcxp_tag);
+               fcxp->reqq_waiting = BFA_TRUE;
+               bfa_reqq_wait(bfa, BFA_REQQ_FCXP, &fcxp->reqq_wqe);
+               return;
+       }
+
+       bfa_fcxp_queue(fcxp, send_req);
+}
+
+/**
+ * Abort a BFA FCXP
+ *
+ * @param[in]  fcxp    BFA fcxp pointer
+ *
+ * @return             void
+ */
+bfa_status_t
+bfa_fcxp_abort(struct bfa_fcxp_s *fcxp)
+{
+       bfa_assert(0);
+       return (BFA_STATUS_OK);
+}
+
+void
+bfa_fcxp_alloc_wait(struct bfa_s *bfa, struct bfa_fcxp_wqe_s *wqe,
+                       bfa_fcxp_alloc_cbfn_t alloc_cbfn, void *alloc_cbarg)
+{
+       struct bfa_fcxp_mod_s *mod = BFA_FCXP_MOD(bfa);
+
+       bfa_assert(list_empty(&mod->fcxp_free_q));
+
+       wqe->alloc_cbfn = alloc_cbfn;
+       wqe->alloc_cbarg = alloc_cbarg;
+       list_add_tail(&wqe->qe, &mod->wait_q);
+}
+
+void
+bfa_fcxp_walloc_cancel(struct bfa_s *bfa, struct bfa_fcxp_wqe_s *wqe)
+{
+       struct bfa_fcxp_mod_s *mod = BFA_FCXP_MOD(bfa);
+
+       bfa_assert(bfa_q_is_on_q(&mod->wait_q, wqe));
+       list_del(&wqe->qe);
+}
+
+void
+bfa_fcxp_discard(struct bfa_fcxp_s *fcxp)
+{
+       /**
+        * If waiting for room in request queue, cancel reqq wait
+        * and free fcxp.
+        */
+       if (fcxp->reqq_waiting) {
+               fcxp->reqq_waiting = BFA_FALSE;
+               bfa_reqq_wcancel(&fcxp->reqq_wqe);
+               bfa_fcxp_free(fcxp);
+               return;
+       }
+
+       fcxp->send_cbfn = bfa_fcxp_null_comp;
+}
+
+
+
+/**
+ *  hal_fcxp_public BFA FCXP public functions
+ */
+
+void
+bfa_fcxp_isr(struct bfa_s *bfa, struct bfi_msg_s *msg)
+{
+       switch (msg->mhdr.msg_id) {
+       case BFI_FCXP_I2H_SEND_RSP:
+               hal_fcxp_send_comp(bfa, (struct bfi_fcxp_send_rsp_s *) msg);
+               break;
+
+       default:
+               bfa_trc(bfa, msg->mhdr.msg_id);
+               bfa_assert(0);
+       }
+}
+
+u32
+bfa_fcxp_get_maxrsp(struct bfa_s *bfa)
+{
+       struct bfa_fcxp_mod_s *mod = BFA_FCXP_MOD(bfa);
+
+       return mod->rsp_pld_sz;
+}
+
+
diff --git a/drivers/scsi/bfa/bfa_fcxp_priv.h b/drivers/scsi/bfa/bfa_fcxp_priv.h
new file mode 100644 (file)
index 0000000..4cda493
--- /dev/null
@@ -0,0 +1,138 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ */
+
+#ifndef __BFA_FCXP_PRIV_H__
+#define __BFA_FCXP_PRIV_H__
+
+#include <cs/bfa_sm.h>
+#include <protocol/fc.h>
+#include <bfa_svc.h>
+#include <bfi/bfi_fcxp.h>
+
+#define BFA_FCXP_MIN           (1)
+#define BFA_FCXP_MAX_IBUF_SZ   (2 * 1024 + 256)
+#define BFA_FCXP_MAX_LBUF_SZ   (4 * 1024 + 256)
+
+struct bfa_fcxp_mod_s {
+       struct bfa_s      *bfa;         /*  backpointer to BFA */
+       struct bfa_fcxp_s *fcxp_list;   /*  array of FCXPs */
+       u16        num_fcxps;   /*  max num FCXP requests */
+       struct list_head fcxp_free_q;   /*  free FCXPs */
+       struct list_head fcxp_active_q; /*  active FCXPs */
+       void    *req_pld_list_kva;      /*  list of FCXP req pld */
+       u64 req_pld_list_pa;    /*  list of FCXP req pld */
+       void *rsp_pld_list_kva;         /*  list of FCXP resp pld */
+       u64 rsp_pld_list_pa;    /*  list of FCXP resp pld */
+       struct list_head  wait_q;               /*  wait queue for free fcxp */
+       u32     req_pld_sz;
+       u32     rsp_pld_sz;
+};
+
+#define BFA_FCXP_MOD(__bfa)            (&(__bfa)->modules.fcxp_mod)
+#define BFA_FCXP_FROM_TAG(__mod, __tag)        (&(__mod)->fcxp_list[__tag])
+
+typedef void    (*fcxp_send_cb_t) (struct bfa_s *ioc, struct bfa_fcxp_s *fcxp,
+                                  void *cb_arg, bfa_status_t req_status,
+                                  u32 rsp_len, u32 resid_len,
+                                  struct fchs_s *rsp_fchs);
+
+/**
+ * Information needed for a FCXP request
+ */
+struct bfa_fcxp_req_info_s {
+       struct bfa_rport_s *bfa_rport;  /*  Pointer to the bfa rport that was
+                                        *returned from bfa_rport_create().
+                                        *This could be left NULL for WKA or for
+                                        *FCXP interactions before the rport
+                                        *nexus is established
+                                        */
+       struct fchs_s   fchs;   /*  request FC header structure */
+       u8 cts;         /*  continous sequence */
+       u8 class;               /*  FC class for the request/response */
+       u16 max_frmsz;  /*  max send frame size */
+       u16 vf_id;              /*  vsan tag if applicable */
+       u8      lp_tag;         /*  lport tag */
+       u32 req_tot_len;        /*  request payload total length */
+};
+
+struct bfa_fcxp_rsp_info_s {
+       struct fchs_s rsp_fchs;         /*  Response frame's FC header will
+                                        * be *sent back in this field */
+       u8         rsp_timeout; /*  timeout in seconds, 0-no response
+                                        */
+       u8         rsvd2[3];
+       u32        rsp_maxlen;  /*  max response length expected */
+};
+
+struct bfa_fcxp_s {
+       struct list_head        qe;             /*  fcxp queue element */
+       bfa_sm_t        sm;             /*  state machine */
+       void            *caller;        /*  driver or fcs */
+       struct bfa_fcxp_mod_s *fcxp_mod;
+                                       /*  back pointer to fcxp mod */
+       u16        fcxp_tag;    /*  internal tag */
+       struct bfa_fcxp_req_info_s req_info;
+                                       /*  request info */
+       struct bfa_fcxp_rsp_info_s rsp_info;
+                                       /*  response info */
+       u8      use_ireqbuf;    /*  use internal req buf */
+       u8         use_irspbuf; /*  use internal rsp buf */
+       u32        nreq_sgles;  /*  num request SGLEs */
+       u32        nrsp_sgles;  /*  num response SGLEs */
+       struct list_head req_sgpg_q;    /*  SG pages for request buf */
+       struct list_head req_sgpg_wqe;  /*  wait queue for req SG page */
+       struct list_head rsp_sgpg_q;    /*  SG pages for response buf */
+       struct list_head rsp_sgpg_wqe;  /*  wait queue for rsp SG page */
+
+       bfa_fcxp_get_sgaddr_t req_sga_cbfn;
+                                       /*  SG elem addr user function */
+       bfa_fcxp_get_sglen_t req_sglen_cbfn;
+                                       /*  SG elem len user function */
+       bfa_fcxp_get_sgaddr_t rsp_sga_cbfn;
+                                       /*  SG elem addr user function */
+       bfa_fcxp_get_sglen_t rsp_sglen_cbfn;
+                                       /*  SG elem len user function */
+       bfa_cb_fcxp_send_t send_cbfn;   /*  send completion callback */
+       void            *send_cbarg;    /*  callback arg */
+       struct bfa_sge_s   req_sge[BFA_FCXP_MAX_SGES];
+                                       /*  req SG elems */
+       struct bfa_sge_s   rsp_sge[BFA_FCXP_MAX_SGES];
+                                       /*  rsp SG elems */
+       u8         rsp_status;  /*  comp: rsp status */
+       u32        rsp_len;     /*  comp: actual response len */
+       u32        residue_len; /*  comp: residual rsp length */
+       struct fchs_s          rsp_fchs;        /*  comp: response fchs */
+       struct bfa_cb_qe_s    hcb_qe;   /*  comp: callback qelem */
+       struct bfa_reqq_wait_s  reqq_wqe;
+       bfa_boolean_t   reqq_waiting;
+};
+
+#define BFA_FCXP_REQ_PLD(_fcxp)        (bfa_fcxp_get_reqbuf(_fcxp))
+
+#define BFA_FCXP_RSP_FCHS(_fcxp)       (&((_fcxp)->rsp_info.fchs))
+#define BFA_FCXP_RSP_PLD(_fcxp)        (bfa_fcxp_get_rspbuf(_fcxp))
+
+#define BFA_FCXP_REQ_PLD_PA(_fcxp)                                     \
+       ((_fcxp)->fcxp_mod->req_pld_list_pa +                           \
+               ((_fcxp)->fcxp_mod->req_pld_sz  * (_fcxp)->fcxp_tag))
+
+#define BFA_FCXP_RSP_PLD_PA(_fcxp)                                     \
+       ((_fcxp)->fcxp_mod->rsp_pld_list_pa +                           \
+               ((_fcxp)->fcxp_mod->rsp_pld_sz * (_fcxp)->fcxp_tag))
+
+void   bfa_fcxp_isr(struct bfa_s *bfa, struct bfi_msg_s *msg);
+#endif /* __BFA_FCXP_PRIV_H__ */
diff --git a/drivers/scsi/bfa/bfa_fwimg_priv.h b/drivers/scsi/bfa/bfa_fwimg_priv.h
new file mode 100644 (file)
index 0000000..1ec1355
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ */
+
+#ifndef __BFA_FWIMG_PRIV_H__
+#define __BFA_FWIMG_PRIV_H__
+
+#define        BFI_FLASH_CHUNK_SZ              256     /*  Flash chunk size */
+#define        BFI_FLASH_CHUNK_SZ_WORDS        (BFI_FLASH_CHUNK_SZ/sizeof(u32))
+
+extern u32 *bfi_image_ct_get_chunk(u32 off);
+extern u32 bfi_image_ct_size;
+extern u32 *bfi_image_cb_get_chunk(u32 off);
+extern u32 bfi_image_cb_size;
+extern u32 *bfi_image_cb;
+extern u32 *bfi_image_ct;
+
+#endif /* __BFA_FWIMG_PRIV_H__ */
diff --git a/drivers/scsi/bfa/bfa_hw_cb.c b/drivers/scsi/bfa/bfa_hw_cb.c
new file mode 100644 (file)
index 0000000..ede1438
--- /dev/null
@@ -0,0 +1,142 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ */
+
+#include <bfa_priv.h>
+#include <bfi/bfi_cbreg.h>
+
+void
+bfa_hwcb_reginit(struct bfa_s *bfa)
+{
+       struct bfa_iocfc_regs_s *bfa_regs = &bfa->iocfc.bfa_regs;
+       bfa_os_addr_t           kva = bfa_ioc_bar0(&bfa->ioc);
+       int                     i, q, fn = bfa_ioc_pcifn(&bfa->ioc);
+
+       if (fn == 0) {
+               bfa_regs->intr_status = (kva + HOSTFN0_INT_STATUS);
+               bfa_regs->intr_mask   = (kva + HOSTFN0_INT_MSK);
+       } else {
+               bfa_regs->intr_status = (kva + HOSTFN1_INT_STATUS);
+               bfa_regs->intr_mask   = (kva + HOSTFN1_INT_MSK);
+       }
+
+       for (i = 0; i < BFI_IOC_MAX_CQS; i++) {
+               /*
+                * CPE registers
+                */
+               q = CPE_Q_NUM(fn, i);
+               bfa_regs->cpe_q_pi[i] = (kva + CPE_Q_PI(q));
+               bfa_regs->cpe_q_ci[i] = (kva + CPE_Q_CI(q));
+               bfa_regs->cpe_q_depth[i] = (kva + CPE_Q_DEPTH(q));
+
+               /*
+                * RME registers
+                */
+               q = CPE_Q_NUM(fn, i);
+               bfa_regs->rme_q_pi[i] = (kva + RME_Q_PI(q));
+               bfa_regs->rme_q_ci[i] = (kva + RME_Q_CI(q));
+               bfa_regs->rme_q_depth[i] = (kva + RME_Q_DEPTH(q));
+       }
+}
+
+void
+bfa_hwcb_rspq_ack(struct bfa_s *bfa, int rspq)
+{
+}
+
+static void
+bfa_hwcb_rspq_ack_msix(struct bfa_s *bfa, int rspq)
+{
+       bfa_reg_write(bfa->iocfc.bfa_regs.intr_status,
+               __HFN_INT_RME_Q0 << RME_Q_NUM(bfa_ioc_pcifn(&bfa->ioc), rspq));
+}
+
+void
+bfa_hwcb_msix_getvecs(struct bfa_s *bfa, u32 *msix_vecs_bmap,
+                u32 *num_vecs, u32 *max_vec_bit)
+{
+#define __HFN_NUMINTS  13
+       if (bfa_ioc_pcifn(&bfa->ioc) == 0) {
+               *msix_vecs_bmap = (__HFN_INT_CPE_Q0 | __HFN_INT_CPE_Q1 |
+                                  __HFN_INT_CPE_Q2 | __HFN_INT_CPE_Q3 |
+                                  __HFN_INT_RME_Q0 | __HFN_INT_RME_Q1 |
+                                  __HFN_INT_RME_Q2 | __HFN_INT_RME_Q3 |
+                                  __HFN_INT_MBOX_LPU0);
+               *max_vec_bit = __HFN_INT_MBOX_LPU0;
+       } else {
+               *msix_vecs_bmap = (__HFN_INT_CPE_Q4 | __HFN_INT_CPE_Q5 |
+                                  __HFN_INT_CPE_Q6 | __HFN_INT_CPE_Q7 |
+                                  __HFN_INT_RME_Q4 | __HFN_INT_RME_Q5 |
+                                  __HFN_INT_RME_Q6 | __HFN_INT_RME_Q7 |
+                                  __HFN_INT_MBOX_LPU1);
+               *max_vec_bit = __HFN_INT_MBOX_LPU1;
+       }
+
+       *msix_vecs_bmap |= (__HFN_INT_ERR_EMC | __HFN_INT_ERR_LPU0 |
+                           __HFN_INT_ERR_LPU1 | __HFN_INT_ERR_PSS);
+       *num_vecs = __HFN_NUMINTS;
+}
+
+/**
+ * No special setup required for crossbow -- vector assignments are implicit.
+ */
+void
+bfa_hwcb_msix_init(struct bfa_s *bfa, int nvecs)
+{
+       int i;
+
+       bfa_assert((nvecs == 1) || (nvecs == __HFN_NUMINTS));
+
+       bfa->msix.nvecs = nvecs;
+       if (nvecs == 1) {
+               for (i = 0; i < BFA_MSIX_CB_MAX; i++)
+                       bfa->msix.handler[i] = bfa_msix_all;
+               return;
+       }
+
+       for (i = BFA_MSIX_CPE_Q0; i <= BFA_MSIX_CPE_Q7; i++)
+               bfa->msix.handler[i] = bfa_msix_reqq;
+
+       for (i = BFA_MSIX_RME_Q0; i <= BFA_MSIX_RME_Q7; i++)
+               bfa->msix.handler[i] = bfa_msix_rspq;
+
+       for (; i < BFA_MSIX_CB_MAX; i++)
+               bfa->msix.handler[i] = bfa_msix_lpu_err;
+}
+
+/**
+ * Crossbow -- dummy, interrupts are masked
+ */
+void
+bfa_hwcb_msix_install(struct bfa_s *bfa)
+{
+}
+
+void
+bfa_hwcb_msix_uninstall(struct bfa_s *bfa)
+{
+}
+
+/**
+ * No special enable/disable -- vector assignments are implicit.
+ */
+void
+bfa_hwcb_isr_mode_set(struct bfa_s *bfa, bfa_boolean_t msix)
+{
+       bfa->iocfc.hwif.hw_rspq_ack = bfa_hwcb_rspq_ack_msix;
+}
+
+
diff --git a/drivers/scsi/bfa/bfa_hw_ct.c b/drivers/scsi/bfa/bfa_hw_ct.c
new file mode 100644 (file)
index 0000000..51ae574
--- /dev/null
@@ -0,0 +1,162 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ */
+
+#include <bfa_priv.h>
+#include <bfi/bfi_ctreg.h>
+#include <bfa_ioc.h>
+
+BFA_TRC_FILE(HAL, IOCFC_CT);
+
+static u32 __ct_msix_err_vec_reg[] = {
+       HOST_MSIX_ERR_INDEX_FN0,
+       HOST_MSIX_ERR_INDEX_FN1,
+       HOST_MSIX_ERR_INDEX_FN2,
+       HOST_MSIX_ERR_INDEX_FN3,
+};
+
+static void
+bfa_hwct_msix_lpu_err_set(struct bfa_s *bfa, bfa_boolean_t msix, int vec)
+{
+       int fn = bfa_ioc_pcifn(&bfa->ioc);
+       bfa_os_addr_t kva = bfa_ioc_bar0(&bfa->ioc);
+
+       if (msix)
+               bfa_reg_write(kva + __ct_msix_err_vec_reg[fn], vec);
+       else
+               bfa_reg_write(kva + __ct_msix_err_vec_reg[fn], 0);
+}
+
+/**
+ * Dummy interrupt handler for handling spurious interrupt during chip-reinit.
+ */
+static void
+bfa_hwct_msix_dummy(struct bfa_s *bfa, int vec)
+{
+}
+
+void
+bfa_hwct_reginit(struct bfa_s *bfa)
+{
+       struct bfa_iocfc_regs_s *bfa_regs = &bfa->iocfc.bfa_regs;
+       bfa_os_addr_t           kva = bfa_ioc_bar0(&bfa->ioc);
+       int                     i, q, fn = bfa_ioc_pcifn(&bfa->ioc);
+
+       if (fn == 0) {
+               bfa_regs->intr_status = (kva + HOSTFN0_INT_STATUS);
+               bfa_regs->intr_mask   = (kva + HOSTFN0_INT_MSK);
+       } else {
+               bfa_regs->intr_status = (kva + HOSTFN1_INT_STATUS);
+               bfa_regs->intr_mask   = (kva + HOSTFN1_INT_MSK);
+       }
+
+       for (i = 0; i < BFI_IOC_MAX_CQS; i++) {
+               /*
+                * CPE registers
+                */
+               q = CPE_Q_NUM(fn, i);
+               bfa_regs->cpe_q_pi[i] = (kva + CPE_PI_PTR_Q(q << 5));
+               bfa_regs->cpe_q_ci[i] = (kva + CPE_CI_PTR_Q(q << 5));
+               bfa_regs->cpe_q_depth[i] = (kva + CPE_DEPTH_Q(q << 5));
+               bfa_regs->cpe_q_ctrl[i] = (kva + CPE_QCTRL_Q(q << 5));
+
+               /*
+                * RME registers
+                */
+               q = CPE_Q_NUM(fn, i);
+               bfa_regs->rme_q_pi[i] = (kva + RME_PI_PTR_Q(q << 5));
+               bfa_regs->rme_q_ci[i] = (kva + RME_CI_PTR_Q(q << 5));
+               bfa_regs->rme_q_depth[i] = (kva + RME_DEPTH_Q(q << 5));
+               bfa_regs->rme_q_ctrl[i] = (kva + RME_QCTRL_Q(q << 5));
+       }
+}
+
+void
+bfa_hwct_rspq_ack(struct bfa_s *bfa, int rspq)
+{
+       u32     r32;
+
+       r32 = bfa_reg_read(bfa->iocfc.bfa_regs.rme_q_ctrl[rspq]);
+       bfa_reg_write(bfa->iocfc.bfa_regs.rme_q_ctrl[rspq], r32);
+}
+
+void
+bfa_hwct_msix_getvecs(struct bfa_s *bfa, u32 *msix_vecs_bmap,
+                u32 *num_vecs, u32 *max_vec_bit)
+{
+       *msix_vecs_bmap = (1 << BFA_MSIX_CT_MAX) - 1;
+       *max_vec_bit = (1 << (BFA_MSIX_CT_MAX - 1));
+       *num_vecs = BFA_MSIX_CT_MAX;
+}
+
+/**
+ * Setup MSI-X vector for catapult
+ */
+void
+bfa_hwct_msix_init(struct bfa_s *bfa, int nvecs)
+{
+       bfa_assert((nvecs == 1) || (nvecs == BFA_MSIX_CT_MAX));
+       bfa_trc(bfa, nvecs);
+
+       bfa->msix.nvecs = nvecs;
+       bfa_hwct_msix_uninstall(bfa);
+}
+
+void
+bfa_hwct_msix_install(struct bfa_s *bfa)
+{
+       int i;
+
+       if (bfa->msix.nvecs == 0)
+               return;
+
+       if (bfa->msix.nvecs == 1) {
+               for (i = 0; i < BFA_MSIX_CT_MAX; i++)
+                       bfa->msix.handler[i] = bfa_msix_all;
+               return;
+       }
+
+       for (i = BFA_MSIX_CPE_Q0; i <= BFA_MSIX_CPE_Q3; i++)
+               bfa->msix.handler[i] = bfa_msix_reqq;
+
+       for (; i <= BFA_MSIX_RME_Q3; i++)
+               bfa->msix.handler[i] = bfa_msix_rspq;
+
+       bfa_assert(i == BFA_MSIX_LPU_ERR);
+       bfa->msix.handler[BFA_MSIX_LPU_ERR] = bfa_msix_lpu_err;
+}
+
+void
+bfa_hwct_msix_uninstall(struct bfa_s *bfa)
+{
+       int i;
+
+       for (i = 0; i < BFA_MSIX_CT_MAX; i++)
+               bfa->msix.handler[i] = bfa_hwct_msix_dummy;
+}
+
+/**
+ * Enable MSI-X vectors
+ */
+void
+bfa_hwct_isr_mode_set(struct bfa_s *bfa, bfa_boolean_t msix)
+{
+       bfa_trc(bfa, 0);
+       bfa_hwct_msix_lpu_err_set(bfa, msix, BFA_MSIX_LPU_ERR);
+       bfa_ioc_isr_mode_set(&bfa->ioc, msix);
+}
+
+
diff --git a/drivers/scsi/bfa/bfa_intr.c b/drivers/scsi/bfa/bfa_intr.c
new file mode 100644 (file)
index 0000000..0ca1257
--- /dev/null
@@ -0,0 +1,218 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ */
+#include <bfa.h>
+#include <bfi/bfi_cbreg.h>
+#include <bfa_port_priv.h>
+#include <bfa_intr_priv.h>
+#include <cs/bfa_debug.h>
+
+BFA_TRC_FILE(HAL, INTR);
+
+static void
+bfa_msix_errint(struct bfa_s *bfa, u32 intr)
+{
+       bfa_ioc_error_isr(&bfa->ioc);
+}
+
+static void
+bfa_msix_lpu(struct bfa_s *bfa)
+{
+       bfa_ioc_mbox_isr(&bfa->ioc);
+}
+
+void
+bfa_msix_all(struct bfa_s *bfa, int vec)
+{
+       bfa_intx(bfa);
+}
+
+/**
+ *  hal_intr_api
+ */
+bfa_boolean_t
+bfa_intx(struct bfa_s *bfa)
+{
+       u32        intr, qintr;
+       int             queue;
+
+       intr = bfa_reg_read(bfa->iocfc.bfa_regs.intr_status);
+       if (!intr)
+               return BFA_FALSE;
+
+       /**
+        * RME completion queue interrupt
+        */
+       qintr = intr & __HFN_INT_RME_MASK;
+       bfa_reg_write(bfa->iocfc.bfa_regs.intr_status, qintr);
+
+       for (queue = 0; queue < BFI_IOC_MAX_CQS_ASIC; queue ++) {
+               if (intr & (__HFN_INT_RME_Q0 << queue))
+                       bfa_msix_rspq(bfa, queue & (BFI_IOC_MAX_CQS - 1));
+       }
+       intr &= ~qintr;
+       if (!intr)
+               return BFA_TRUE;
+
+       /**
+        * CPE completion queue interrupt
+        */
+       qintr = intr & __HFN_INT_CPE_MASK;
+       bfa_reg_write(bfa->iocfc.bfa_regs.intr_status, qintr);
+
+       for (queue = 0; queue < BFI_IOC_MAX_CQS_ASIC; queue++) {
+               if (intr & (__HFN_INT_CPE_Q0 << queue))
+                       bfa_msix_reqq(bfa, queue & (BFI_IOC_MAX_CQS - 1));
+       }
+       intr &= ~qintr;
+       if (!intr)
+               return BFA_TRUE;
+
+       bfa_msix_lpu_err(bfa, intr);
+
+       return BFA_TRUE;
+}
+
+void
+bfa_isr_enable(struct bfa_s *bfa)
+{
+       u32        intr_unmask;
+       int             pci_func = bfa_ioc_pcifn(&bfa->ioc);
+
+       bfa_trc(bfa, pci_func);
+
+       bfa_msix_install(bfa);
+       intr_unmask = (__HFN_INT_ERR_EMC | __HFN_INT_ERR_LPU0 |
+                      __HFN_INT_ERR_LPU1 | __HFN_INT_ERR_PSS);
+
+       if (pci_func == 0)
+               intr_unmask |= (__HFN_INT_CPE_Q0 | __HFN_INT_CPE_Q1 |
+                               __HFN_INT_CPE_Q2 | __HFN_INT_CPE_Q3 |
+                               __HFN_INT_RME_Q0 | __HFN_INT_RME_Q1 |
+                               __HFN_INT_RME_Q2 | __HFN_INT_RME_Q3 |
+                               __HFN_INT_MBOX_LPU0);
+       else
+               intr_unmask |= (__HFN_INT_CPE_Q4 | __HFN_INT_CPE_Q5 |
+                               __HFN_INT_CPE_Q6 | __HFN_INT_CPE_Q7 |
+                               __HFN_INT_RME_Q4 | __HFN_INT_RME_Q5 |
+                               __HFN_INT_RME_Q6 | __HFN_INT_RME_Q7 |
+                               __HFN_INT_MBOX_LPU1);
+
+       bfa_reg_write(bfa->iocfc.bfa_regs.intr_status, intr_unmask);
+       bfa_reg_write(bfa->iocfc.bfa_regs.intr_mask, ~intr_unmask);
+       bfa_isr_mode_set(bfa, bfa->msix.nvecs != 0);
+}
+
+void
+bfa_isr_disable(struct bfa_s *bfa)
+{
+       bfa_isr_mode_set(bfa, BFA_FALSE);
+       bfa_reg_write(bfa->iocfc.bfa_regs.intr_mask, -1L);
+       bfa_msix_uninstall(bfa);
+}
+
+void
+bfa_msix_reqq(struct bfa_s *bfa, int qid)
+{
+       struct list_head                *waitq, *qe, *qen;
+       struct bfa_reqq_wait_s  *wqe;
+
+       qid &= (BFI_IOC_MAX_CQS - 1);
+
+       waitq = bfa_reqq(bfa, qid);
+       list_for_each_safe(qe, qen, waitq) {
+               /**
+                * Callback only as long as there is room in request queue
+                */
+               if (bfa_reqq_full(bfa, qid))
+                       break;
+
+               list_del(qe);
+               wqe = (struct bfa_reqq_wait_s *) qe;
+               wqe->qresume(wqe->cbarg);
+       }
+}
+
+void
+bfa_isr_unhandled(struct bfa_s *bfa, struct bfi_msg_s *m)
+{
+       bfa_trc(bfa, m->mhdr.msg_class);
+       bfa_trc(bfa, m->mhdr.msg_id);
+       bfa_trc(bfa, m->mhdr.mtag.i2htok);
+       bfa_assert(0);
+       bfa_trc_stop(bfa->trcmod);
+}
+
+void
+bfa_msix_rspq(struct bfa_s *bfa, int rsp_qid)
+{
+       struct bfi_msg_s      *m;
+       u32        pi, ci;
+
+       bfa_trc_fp(bfa, rsp_qid);
+
+       rsp_qid &= (BFI_IOC_MAX_CQS - 1);
+
+       bfa->iocfc.hwif.hw_rspq_ack(bfa, rsp_qid);
+
+       ci = bfa_rspq_ci(bfa, rsp_qid);
+       pi = bfa_rspq_pi(bfa, rsp_qid);
+
+       bfa_trc_fp(bfa, ci);
+       bfa_trc_fp(bfa, pi);
+
+       if (bfa->rme_process) {
+               while (ci != pi) {
+                       m = bfa_rspq_elem(bfa, rsp_qid, ci);
+                       bfa_assert_fp(m->mhdr.msg_class < BFI_MC_MAX);
+
+                       bfa_isrs[m->mhdr.msg_class] (bfa, m);
+
+                       CQ_INCR(ci, bfa->iocfc.cfg.drvcfg.num_rspq_elems);
+               }
+       }
+
+       /**
+        * update CI
+        */
+       bfa_rspq_ci(bfa, rsp_qid) = pi;
+       bfa_reg_write(bfa->iocfc.bfa_regs.rme_q_ci[rsp_qid], pi);
+       bfa_os_mmiowb();
+}
+
+void
+bfa_msix_lpu_err(struct bfa_s *bfa, int vec)
+{
+       u32 intr;
+
+       intr = bfa_reg_read(bfa->iocfc.bfa_regs.intr_status);
+
+       if (intr & (__HFN_INT_MBOX_LPU0 | __HFN_INT_MBOX_LPU1))
+               bfa_msix_lpu(bfa);
+
+       if (intr & (__HFN_INT_ERR_EMC |
+                   __HFN_INT_ERR_LPU0 | __HFN_INT_ERR_LPU1 |
+                   __HFN_INT_ERR_PSS))
+               bfa_msix_errint(bfa, intr);
+}
+
+void
+bfa_isr_bind(enum bfi_mclass mc, bfa_isr_func_t isr_func)
+{
+       bfa_isrs[mc] = isr_func;
+}
+
+
diff --git a/drivers/scsi/bfa/bfa_intr_priv.h b/drivers/scsi/bfa/bfa_intr_priv.h
new file mode 100644 (file)
index 0000000..8ce6e6b
--- /dev/null
@@ -0,0 +1,115 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ */
+
+#ifndef __BFA_INTR_PRIV_H__
+#define __BFA_INTR_PRIV_H__
+
+/**
+ * Message handler
+ */
+typedef void (*bfa_isr_func_t) (struct bfa_s *bfa, struct bfi_msg_s *m);
+void bfa_isr_unhandled(struct bfa_s *bfa, struct bfi_msg_s *m);
+void bfa_isr_bind(enum bfi_mclass mc, bfa_isr_func_t isr_func);
+
+
+#define bfa_reqq_pi(__bfa, __reqq)     (__bfa)->iocfc.req_cq_pi[__reqq]
+#define bfa_reqq_ci(__bfa, __reqq)                                     \
+       *(u32 *)((__bfa)->iocfc.req_cq_shadow_ci[__reqq].kva)
+
+#define bfa_reqq_full(__bfa, __reqq)                           \
+       (((bfa_reqq_pi(__bfa, __reqq) + 1) &                    \
+         ((__bfa)->iocfc.cfg.drvcfg.num_reqq_elems - 1)) ==    \
+        bfa_reqq_ci(__bfa, __reqq))
+
+#define bfa_reqq_next(__bfa, __reqq)                           \
+       (bfa_reqq_full(__bfa, __reqq) ? NULL :                  \
+        ((void *)((struct bfi_msg_s *)((__bfa)->iocfc.req_cq_ba[__reqq].kva) \
+                         + bfa_reqq_pi((__bfa), (__reqq)))))
+
+#define bfa_reqq_produce(__bfa, __reqq)        do {                            \
+       (__bfa)->iocfc.req_cq_pi[__reqq]++;                             \
+       (__bfa)->iocfc.req_cq_pi[__reqq] &=                             \
+               ((__bfa)->iocfc.cfg.drvcfg.num_reqq_elems - 1);      \
+       bfa_reg_write((__bfa)->iocfc.bfa_regs.cpe_q_pi[__reqq],         \
+                               (__bfa)->iocfc.req_cq_pi[__reqq]);      \
+       bfa_os_mmiowb();      \
+} while (0)
+
+#define bfa_rspq_pi(__bfa, __rspq)                                     \
+       *(u32 *)((__bfa)->iocfc.rsp_cq_shadow_pi[__rspq].kva)
+
+#define bfa_rspq_ci(__bfa, __rspq)     (__bfa)->iocfc.rsp_cq_ci[__rspq]
+#define bfa_rspq_elem(__bfa, __rspq, __ci)                             \
+       &((struct bfi_msg_s *)((__bfa)->iocfc.rsp_cq_ba[__rspq].kva))[__ci]
+
+#define CQ_INCR(__index, __size)                                       \
+                       (__index)++; (__index) &= ((__size) - 1)
+
+/**
+ * Queue element to wait for room in request queue. FIFO order is
+ * maintained when fullfilling requests.
+ */
+struct bfa_reqq_wait_s {
+       struct list_head        qe;
+       void            (*qresume) (void *cbarg);
+       void            *cbarg;
+};
+
+/**
+ * Circular queue usage assignments
+ */
+enum {
+       BFA_REQQ_IOC    = 0,    /*  all low-priority IOC msgs   */
+       BFA_REQQ_FCXP   = 0,    /*  all FCXP messages           */
+       BFA_REQQ_LPS    = 0,    /*  all lport service msgs      */
+       BFA_REQQ_PORT   = 0,    /*  all port messages           */
+       BFA_REQQ_FLASH  = 0,    /*  for flash module            */
+       BFA_REQQ_DIAG   = 0,    /*  for diag module             */
+       BFA_REQQ_RPORT  = 0,    /*  all port messages           */
+       BFA_REQQ_SBOOT  = 0,    /*  all san boot messages       */
+       BFA_REQQ_QOS_LO = 1,    /*  all low priority IO */
+       BFA_REQQ_QOS_MD = 2,    /*  all medium priority IO      */
+       BFA_REQQ_QOS_HI = 3,    /*  all high priority IO        */
+};
+
+static inline void
+bfa_reqq_winit(struct bfa_reqq_wait_s *wqe, void (*qresume) (void *cbarg),
+                       void *cbarg)
+{
+       wqe->qresume = qresume;
+       wqe->cbarg = cbarg;
+}
+
+#define bfa_reqq(__bfa, __reqq)        &(__bfa)->reqq_waitq[__reqq]
+
+/**
+ * static inline void
+ * bfa_reqq_wait(struct bfa_s *bfa, int reqq, struct bfa_reqq_wait_s *wqe)
+ */
+#define bfa_reqq_wait(__bfa, __reqq, __wqe) do {                       \
+                                                                       \
+               struct list_head *waitq = bfa_reqq(__bfa, __reqq);      \
+                                                                       \
+               bfa_assert(((__reqq) < BFI_IOC_MAX_CQS));      \
+               bfa_assert((__wqe)->qresume && (__wqe)->cbarg);      \
+                                                                       \
+               list_add_tail(&(__wqe)->qe, waitq);      \
+} while (0)
+
+#define bfa_reqq_wcancel(__wqe)        list_del(&(__wqe)->qe)
+
+#endif /* __BFA_INTR_PRIV_H__ */
diff --git a/drivers/scsi/bfa/bfa_ioc.c b/drivers/scsi/bfa/bfa_ioc.c
new file mode 100644 (file)
index 0000000..1493489
--- /dev/null
@@ -0,0 +1,2382 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ */
+
+#include <bfa.h>
+#include <bfa_ioc.h>
+#include <bfa_fwimg_priv.h>
+#include <bfa_trcmod_priv.h>
+#include <cs/bfa_debug.h>
+#include <bfi/bfi_ioc.h>
+#include <bfi/bfi_ctreg.h>
+#include <aen/bfa_aen_ioc.h>
+#include <aen/bfa_aen.h>
+#include <log/bfa_log_hal.h>
+#include <defs/bfa_defs_pci.h>
+
+BFA_TRC_FILE(HAL, IOC);
+
+/**
+ * IOC local definitions
+ */
+#define BFA_IOC_TOV            2000    /* msecs */
+#define BFA_IOC_HB_TOV         1000    /* msecs */
+#define BFA_IOC_HB_FAIL_MAX    4
+#define BFA_IOC_HWINIT_MAX     2
+#define BFA_IOC_FWIMG_MINSZ     (16 * 1024)
+#define BFA_IOC_TOV_RECOVER    (BFA_IOC_HB_FAIL_MAX * BFA_IOC_HB_TOV \
+                               + BFA_IOC_TOV)
+
+#define bfa_ioc_timer_start(__ioc)                                     \
+       bfa_timer_begin((__ioc)->timer_mod, &(__ioc)->ioc_timer,        \
+                       bfa_ioc_timeout, (__ioc), BFA_IOC_TOV)
+#define bfa_ioc_timer_stop(__ioc)   bfa_timer_stop(&(__ioc)->ioc_timer)
+
+#define BFA_DBG_FWTRC_ENTS     (BFI_IOC_TRC_ENTS)
+#define BFA_DBG_FWTRC_LEN                                      \
+       (BFA_DBG_FWTRC_ENTS * sizeof(struct bfa_trc_s) +        \
+        (sizeof(struct bfa_trc_mod_s) -                        \
+         BFA_TRC_MAX * sizeof(struct bfa_trc_s)))
+#define BFA_DBG_FWTRC_OFF(_fn) (BFI_IOC_TRC_OFF + BFA_DBG_FWTRC_LEN * (_fn))
+#define bfa_ioc_stats(_ioc, _stats)    (_ioc)->stats._stats ++
+
+#define BFA_FLASH_CHUNK_NO(off)         (off / BFI_FLASH_CHUNK_SZ_WORDS)
+#define BFA_FLASH_OFFSET_IN_CHUNK(off)  (off % BFI_FLASH_CHUNK_SZ_WORDS)
+#define BFA_FLASH_CHUNK_ADDR(chunkno)   (chunkno * BFI_FLASH_CHUNK_SZ_WORDS)
+bfa_boolean_t   bfa_auto_recover = BFA_FALSE;
+
+/*
+ * forward declarations
+ */
+static void     bfa_ioc_aen_post(struct bfa_ioc_s *bfa,
+                                enum bfa_ioc_aen_event event);
+static void     bfa_ioc_hw_sem_get(struct bfa_ioc_s *ioc);
+static void     bfa_ioc_hw_sem_release(struct bfa_ioc_s *ioc);
+static void     bfa_ioc_hw_sem_get_cancel(struct bfa_ioc_s *ioc);
+static void     bfa_ioc_hwinit(struct bfa_ioc_s *ioc, bfa_boolean_t force);
+static void     bfa_ioc_timeout(void *ioc);
+static void     bfa_ioc_send_enable(struct bfa_ioc_s *ioc);
+static void     bfa_ioc_send_disable(struct bfa_ioc_s *ioc);
+static void     bfa_ioc_send_getattr(struct bfa_ioc_s *ioc);
+static void     bfa_ioc_hb_monitor(struct bfa_ioc_s *ioc);
+static void     bfa_ioc_hb_stop(struct bfa_ioc_s *ioc);
+static void     bfa_ioc_reset(struct bfa_ioc_s *ioc, bfa_boolean_t force);
+static void     bfa_ioc_mbox_poll(struct bfa_ioc_s *ioc);
+static void     bfa_ioc_mbox_hbfail(struct bfa_ioc_s *ioc);
+static void     bfa_ioc_recover(struct bfa_ioc_s *ioc);
+static bfa_boolean_t bfa_ioc_firmware_lock(struct bfa_ioc_s *ioc);
+static void     bfa_ioc_firmware_unlock(struct bfa_ioc_s *ioc);
+static void     bfa_ioc_disable_comp(struct bfa_ioc_s *ioc);
+static void     bfa_ioc_lpu_stop(struct bfa_ioc_s *ioc);
+
+/**
+ *  bfa_ioc_sm
+ */
+
+/**
+ * IOC state machine events
+ */
+enum ioc_event {
+       IOC_E_ENABLE = 1,       /*  IOC enable request */
+       IOC_E_DISABLE = 2,      /*  IOC disable request */
+       IOC_E_TIMEOUT = 3,      /*  f/w response timeout */
+       IOC_E_FWREADY = 4,      /*  f/w initialization done */
+       IOC_E_FWRSP_GETATTR = 5,        /*  IOC get attribute response */
+       IOC_E_FWRSP_ENABLE = 6, /*  enable f/w response */
+       IOC_E_FWRSP_DISABLE = 7,        /*  disable f/w response */
+       IOC_E_HBFAIL = 8,       /*  heartbeat failure */
+       IOC_E_HWERROR = 9,      /*  hardware error interrupt */
+       IOC_E_SEMLOCKED = 10,   /*  h/w semaphore is locked */
+       IOC_E_DETACH = 11,      /*  driver detach cleanup */
+};
+
+bfa_fsm_state_decl(bfa_ioc, reset, struct bfa_ioc_s, enum ioc_event);
+bfa_fsm_state_decl(bfa_ioc, fwcheck, struct bfa_ioc_s, enum ioc_event);
+bfa_fsm_state_decl(bfa_ioc, mismatch, struct bfa_ioc_s, enum ioc_event);
+bfa_fsm_state_decl(bfa_ioc, semwait, struct bfa_ioc_s, enum ioc_event);
+bfa_fsm_state_decl(bfa_ioc, hwinit, struct bfa_ioc_s, enum ioc_event);
+bfa_fsm_state_decl(bfa_ioc, enabling, struct bfa_ioc_s, enum ioc_event);
+bfa_fsm_state_decl(bfa_ioc, getattr, struct bfa_ioc_s, enum ioc_event);
+bfa_fsm_state_decl(bfa_ioc, op, struct bfa_ioc_s, enum ioc_event);
+bfa_fsm_state_decl(bfa_ioc, initfail, struct bfa_ioc_s, enum ioc_event);
+bfa_fsm_state_decl(bfa_ioc, hbfail, struct bfa_ioc_s, enum ioc_event);
+bfa_fsm_state_decl(bfa_ioc, disabling, struct bfa_ioc_s, enum ioc_event);
+bfa_fsm_state_decl(bfa_ioc, disabled, struct bfa_ioc_s, enum ioc_event);
+
+static struct bfa_sm_table_s ioc_sm_table[] = {
+       {BFA_SM(bfa_ioc_sm_reset), BFA_IOC_RESET},
+       {BFA_SM(bfa_ioc_sm_fwcheck), BFA_IOC_FWMISMATCH},
+       {BFA_SM(bfa_ioc_sm_mismatch), BFA_IOC_FWMISMATCH},
+       {BFA_SM(bfa_ioc_sm_semwait), BFA_IOC_SEMWAIT},
+       {BFA_SM(bfa_ioc_sm_hwinit), BFA_IOC_HWINIT},
+       {BFA_SM(bfa_ioc_sm_enabling), BFA_IOC_HWINIT},
+       {BFA_SM(bfa_ioc_sm_getattr), BFA_IOC_GETATTR},
+       {BFA_SM(bfa_ioc_sm_op), BFA_IOC_OPERATIONAL},
+       {BFA_SM(bfa_ioc_sm_initfail), BFA_IOC_INITFAIL},
+       {BFA_SM(bfa_ioc_sm_hbfail), BFA_IOC_HBFAIL},
+       {BFA_SM(bfa_ioc_sm_disabling), BFA_IOC_DISABLING},
+       {BFA_SM(bfa_ioc_sm_disabled), BFA_IOC_DISABLED},
+};
+
+/**
+ * Reset entry actions -- initialize state machine
+ */
+static void
+bfa_ioc_sm_reset_entry(struct bfa_ioc_s *ioc)
+{
+       ioc->retry_count = 0;
+       ioc->auto_recover = bfa_auto_recover;
+}
+
+/**
+ * Beginning state. IOC is in reset state.
+ */
+static void
+bfa_ioc_sm_reset(struct bfa_ioc_s *ioc, enum ioc_event event)
+{
+       bfa_trc(ioc, event);
+
+       switch (event) {
+       case IOC_E_ENABLE:
+               bfa_fsm_set_state(ioc, bfa_ioc_sm_fwcheck);
+               break;
+
+       case IOC_E_DISABLE:
+               bfa_ioc_disable_comp(ioc);
+               break;
+
+       case IOC_E_DETACH:
+               break;
+
+       default:
+               bfa_sm_fault(ioc, event);
+       }
+}
+
+/**
+ * Semaphore should be acquired for version check.
+ */
+static void
+bfa_ioc_sm_fwcheck_entry(struct bfa_ioc_s *ioc)
+{
+       bfa_ioc_hw_sem_get(ioc);
+}
+
+/**
+ * Awaiting h/w semaphore to continue with version check.
+ */
+static void
+bfa_ioc_sm_fwcheck(struct bfa_ioc_s *ioc, enum ioc_event event)
+{
+       bfa_trc(ioc, event);
+
+       switch (event) {
+       case IOC_E_SEMLOCKED:
+               if (bfa_ioc_firmware_lock(ioc)) {
+                       ioc->retry_count = 0;
+                       bfa_fsm_set_state(ioc, bfa_ioc_sm_hwinit);
+               } else {
+                       bfa_ioc_hw_sem_release(ioc);
+                       bfa_fsm_set_state(ioc, bfa_ioc_sm_mismatch);
+               }
+               break;
+
+       case IOC_E_DISABLE:
+               bfa_ioc_disable_comp(ioc);
+               /*
+                * fall through
+                */
+
+       case IOC_E_DETACH:
+               bfa_ioc_hw_sem_get_cancel(ioc);
+               bfa_fsm_set_state(ioc, bfa_ioc_sm_reset);
+               break;
+
+       case IOC_E_FWREADY:
+               break;
+
+       default:
+               bfa_sm_fault(ioc, event);
+       }
+}
+
+/**
+ * Notify enable completion callback and generate mismatch AEN.
+ */
+static void
+bfa_ioc_sm_mismatch_entry(struct bfa_ioc_s *ioc)
+{
+       /**
+        * Provide enable completion callback and AEN notification only once.
+        */
+       if (ioc->retry_count == 0) {
+               ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_IOC_FAILURE);
+               bfa_ioc_aen_post(ioc, BFA_IOC_AEN_FWMISMATCH);
+       }
+       ioc->retry_count++;
+       bfa_ioc_timer_start(ioc);
+}
+
+/**
+ * Awaiting firmware version match.
+ */
+static void
+bfa_ioc_sm_mismatch(struct bfa_ioc_s *ioc, enum ioc_event event)
+{
+       bfa_trc(ioc, event);
+
+       switch (event) {
+       case IOC_E_TIMEOUT:
+               bfa_fsm_set_state(ioc, bfa_ioc_sm_fwcheck);
+               break;
+
+       case IOC_E_DISABLE:
+               bfa_ioc_disable_comp(ioc);
+               /*
+                * fall through
+                */
+
+       case IOC_E_DETACH:
+               bfa_ioc_timer_stop(ioc);
+               bfa_fsm_set_state(ioc, bfa_ioc_sm_reset);
+               break;
+
+       case IOC_E_FWREADY:
+               break;
+
+       default:
+               bfa_sm_fault(ioc, event);
+       }
+}
+
+/**
+ * Request for semaphore.
+ */
+static void
+bfa_ioc_sm_semwait_entry(struct bfa_ioc_s *ioc)
+{
+       bfa_ioc_hw_sem_get(ioc);
+}
+
+/**
+ * Awaiting semaphore for h/w initialzation.
+ */
+static void
+bfa_ioc_sm_semwait(struct bfa_ioc_s *ioc, enum ioc_event event)
+{
+       bfa_trc(ioc, event);
+
+       switch (event) {
+       case IOC_E_SEMLOCKED:
+               ioc->retry_count = 0;
+               bfa_fsm_set_state(ioc, bfa_ioc_sm_hwinit);
+               break;
+
+       case IOC_E_DISABLE:
+               bfa_ioc_hw_sem_get_cancel(ioc);
+               bfa_fsm_set_state(ioc, bfa_ioc_sm_disabled);
+               break;
+
+       default:
+               bfa_sm_fault(ioc, event);
+       }
+}
+
+
+static void
+bfa_ioc_sm_hwinit_entry(struct bfa_ioc_s *ioc)
+{
+       bfa_ioc_timer_start(ioc);
+       bfa_ioc_reset(ioc, BFA_FALSE);
+}
+
+/**
+ * Hardware is being initialized. Interrupts are enabled.
+ * Holding hardware semaphore lock.
+ */
+static void
+bfa_ioc_sm_hwinit(struct bfa_ioc_s *ioc, enum ioc_event event)
+{
+       bfa_trc(ioc, event);
+
+       switch (event) {
+       case IOC_E_FWREADY:
+               bfa_ioc_timer_stop(ioc);
+               bfa_fsm_set_state(ioc, bfa_ioc_sm_enabling);
+               break;
+
+       case IOC_E_HWERROR:
+               bfa_ioc_timer_stop(ioc);
+               /*
+                * fall through
+                */
+
+       case IOC_E_TIMEOUT:
+               ioc->retry_count++;
+               if (ioc->retry_count < BFA_IOC_HWINIT_MAX) {
+                       bfa_ioc_timer_start(ioc);
+                       bfa_ioc_reset(ioc, BFA_TRUE);
+                       break;
+               }
+
+               bfa_ioc_hw_sem_release(ioc);
+               bfa_fsm_set_state(ioc, bfa_ioc_sm_initfail);
+               break;
+
+       case IOC_E_DISABLE:
+               bfa_ioc_hw_sem_release(ioc);
+               bfa_ioc_timer_stop(ioc);
+               bfa_fsm_set_state(ioc, bfa_ioc_sm_disabled);
+               break;
+
+       default:
+               bfa_sm_fault(ioc, event);
+       }
+}
+
+
+static void
+bfa_ioc_sm_enabling_entry(struct bfa_ioc_s *ioc)
+{
+       bfa_ioc_timer_start(ioc);
+       bfa_ioc_send_enable(ioc);
+}
+
+/**
+ * Host IOC function is being enabled, awaiting response from firmware.
+ * Semaphore is acquired.
+ */
+static void
+bfa_ioc_sm_enabling(struct bfa_ioc_s *ioc, enum ioc_event event)
+{
+       bfa_trc(ioc, event);
+
+       switch (event) {
+       case IOC_E_FWRSP_ENABLE:
+               bfa_ioc_timer_stop(ioc);
+               bfa_ioc_hw_sem_release(ioc);
+               bfa_fsm_set_state(ioc, bfa_ioc_sm_getattr);
+               break;
+
+       case IOC_E_HWERROR:
+               bfa_ioc_timer_stop(ioc);
+               /*
+                * fall through
+                */
+
+       case IOC_E_TIMEOUT:
+               ioc->retry_count++;
+               if (ioc->retry_count < BFA_IOC_HWINIT_MAX) {
+                       bfa_reg_write(ioc->ioc_regs.ioc_fwstate,
+                                     BFI_IOC_UNINIT);
+                       bfa_fsm_set_state(ioc, bfa_ioc_sm_hwinit);
+                       break;
+               }
+
+               bfa_ioc_hw_sem_release(ioc);
+               bfa_fsm_set_state(ioc, bfa_ioc_sm_initfail);
+               break;
+
+       case IOC_E_DISABLE:
+               bfa_ioc_timer_stop(ioc);
+               bfa_ioc_hw_sem_release(ioc);
+               bfa_fsm_set_state(ioc, bfa_ioc_sm_disabled);
+               break;
+
+       case IOC_E_FWREADY:
+               bfa_ioc_send_enable(ioc);
+               break;
+
+       default:
+               bfa_sm_fault(ioc, event);
+       }
+}
+
+
+static void
+bfa_ioc_sm_getattr_entry(struct bfa_ioc_s *ioc)
+{
+       bfa_ioc_timer_start(ioc);
+       bfa_ioc_send_getattr(ioc);
+}
+
+/**
+ * IOC configuration in progress. Timer is active.
+ */
+static void
+bfa_ioc_sm_getattr(struct bfa_ioc_s *ioc, enum ioc_event event)
+{
+       bfa_trc(ioc, event);
+
+       switch (event) {
+       case IOC_E_FWRSP_GETATTR:
+               bfa_ioc_timer_stop(ioc);
+               bfa_fsm_set_state(ioc, bfa_ioc_sm_op);
+               break;
+
+       case IOC_E_HWERROR:
+               bfa_ioc_timer_stop(ioc);
+               /*
+                * fall through
+                */
+
+       case IOC_E_TIMEOUT:
+               bfa_fsm_set_state(ioc, bfa_ioc_sm_initfail);
+               break;
+
+       case IOC_E_DISABLE:
+               bfa_ioc_timer_stop(ioc);
+               bfa_fsm_set_state(ioc, bfa_ioc_sm_disabled);
+               break;
+
+       default:
+               bfa_sm_fault(ioc, event);
+       }
+}
+
+
+static void
+bfa_ioc_sm_op_entry(struct bfa_ioc_s *ioc)
+{
+       ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_OK);
+       bfa_ioc_hb_monitor(ioc);
+       bfa_ioc_aen_post(ioc, BFA_IOC_AEN_ENABLE);
+}
+
+static void
+bfa_ioc_sm_op(struct bfa_ioc_s *ioc, enum ioc_event event)
+{
+       bfa_trc(ioc, event);
+
+       switch (event) {
+       case IOC_E_ENABLE:
+               break;
+
+       case IOC_E_DISABLE:
+               bfa_ioc_hb_stop(ioc);
+               bfa_fsm_set_state(ioc, bfa_ioc_sm_disabling);
+               break;
+
+       case IOC_E_HWERROR:
+       case IOC_E_FWREADY:
+               /**
+                * Hard error or IOC recovery by other function.
+                * Treat it same as heartbeat failure.
+                */
+               bfa_ioc_hb_stop(ioc);
+               /*
+                * !!! fall through !!!
+                */
+
+       case IOC_E_HBFAIL:
+               bfa_fsm_set_state(ioc, bfa_ioc_sm_hbfail);
+               break;
+
+       default:
+               bfa_sm_fault(ioc, event);
+       }
+}
+
+
+static void
+bfa_ioc_sm_disabling_entry(struct bfa_ioc_s *ioc)
+{
+       bfa_ioc_aen_post(ioc, BFA_IOC_AEN_DISABLE);
+       bfa_ioc_timer_start(ioc);
+       bfa_ioc_send_disable(ioc);
+}
+
+/**
+ * IOC is being disabled
+ */
+static void
+bfa_ioc_sm_disabling(struct bfa_ioc_s *ioc, enum ioc_event event)
+{
+       bfa_trc(ioc, event);
+
+       switch (event) {
+       case IOC_E_HWERROR:
+       case IOC_E_FWRSP_DISABLE:
+               bfa_ioc_timer_stop(ioc);
+               /*
+                * !!! fall through !!!
+                */
+
+       case IOC_E_TIMEOUT:
+               bfa_fsm_set_state(ioc, bfa_ioc_sm_disabled);
+               break;
+
+       default:
+               bfa_sm_fault(ioc, event);
+       }
+}
+
+/**
+ * IOC disable completion entry.
+ */
+static void
+bfa_ioc_sm_disabled_entry(struct bfa_ioc_s *ioc)
+{
+       bfa_ioc_disable_comp(ioc);
+}
+
+static void
+bfa_ioc_sm_disabled(struct bfa_ioc_s *ioc, enum ioc_event event)
+{
+       bfa_trc(ioc, event);
+
+       switch (event) {
+       case IOC_E_ENABLE:
+               bfa_fsm_set_state(ioc, bfa_ioc_sm_semwait);
+               break;
+
+       case IOC_E_DISABLE:
+               ioc->cbfn->disable_cbfn(ioc->bfa);
+               break;
+
+       case IOC_E_FWREADY:
+               break;
+
+       case IOC_E_DETACH:
+               bfa_ioc_firmware_unlock(ioc);
+               bfa_fsm_set_state(ioc, bfa_ioc_sm_reset);
+               break;
+
+       default:
+               bfa_sm_fault(ioc, event);
+       }
+}
+
+
+static void
+bfa_ioc_sm_initfail_entry(struct bfa_ioc_s *ioc)
+{
+       ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_IOC_FAILURE);
+       bfa_ioc_timer_start(ioc);
+}
+
+/**
+ * Hardware initialization failed.
+ */
+static void
+bfa_ioc_sm_initfail(struct bfa_ioc_s *ioc, enum ioc_event event)
+{
+       bfa_trc(ioc, event);
+
+       switch (event) {
+       case IOC_E_DISABLE:
+               bfa_ioc_timer_stop(ioc);
+               bfa_fsm_set_state(ioc, bfa_ioc_sm_disabled);
+               break;
+
+       case IOC_E_DETACH:
+               bfa_ioc_timer_stop(ioc);
+               bfa_ioc_firmware_unlock(ioc);
+               bfa_fsm_set_state(ioc, bfa_ioc_sm_reset);
+               break;
+
+       case IOC_E_TIMEOUT:
+               bfa_fsm_set_state(ioc, bfa_ioc_sm_semwait);
+               break;
+
+       default:
+               bfa_sm_fault(ioc, event);
+       }
+}
+
+
+static void
+bfa_ioc_sm_hbfail_entry(struct bfa_ioc_s *ioc)
+{
+       struct list_head *qe;
+       struct bfa_ioc_hbfail_notify_s *notify;
+
+       /**
+        * Mark IOC as failed in hardware and stop firmware.
+        */
+       bfa_ioc_lpu_stop(ioc);
+       bfa_reg_write(ioc->ioc_regs.ioc_fwstate, BFI_IOC_HBFAIL);
+
+       if (ioc->pcidev.device_id == BFA_PCI_DEVICE_ID_CT) {
+               bfa_reg_write(ioc->ioc_regs.ll_halt, __FW_INIT_HALT_P);
+               /*
+                * Wait for halt to take effect
+                */
+               bfa_reg_read(ioc->ioc_regs.ll_halt);
+       }
+
+       /**
+        * Notify driver and common modules registered for notification.
+        */
+       ioc->cbfn->hbfail_cbfn(ioc->bfa);
+       list_for_each(qe, &ioc->hb_notify_q) {
+               notify = (struct bfa_ioc_hbfail_notify_s *)qe;
+               notify->cbfn(notify->cbarg);
+       }
+
+       /**
+        * Flush any queued up mailbox requests.
+        */
+       bfa_ioc_mbox_hbfail(ioc);
+       bfa_ioc_aen_post(ioc, BFA_IOC_AEN_HBFAIL);
+
+       /**
+        * Trigger auto-recovery after a delay.
+        */
+       if (ioc->auto_recover) {
+               bfa_timer_begin(ioc->timer_mod, &ioc->ioc_timer,
+                               bfa_ioc_timeout, ioc, BFA_IOC_TOV_RECOVER);
+       }
+}
+
+/**
+ * IOC heartbeat failure.
+ */
+static void
+bfa_ioc_sm_hbfail(struct bfa_ioc_s *ioc, enum ioc_event event)
+{
+       bfa_trc(ioc, event);
+
+       switch (event) {
+
+       case IOC_E_ENABLE:
+               ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_IOC_FAILURE);
+               break;
+
+       case IOC_E_DISABLE:
+               if (ioc->auto_recover)
+                       bfa_ioc_timer_stop(ioc);
+               bfa_fsm_set_state(ioc, bfa_ioc_sm_disabled);
+               break;
+
+       case IOC_E_TIMEOUT:
+               bfa_fsm_set_state(ioc, bfa_ioc_sm_semwait);
+               break;
+
+       case IOC_E_FWREADY:
+               /**
+                * Recovery is already initiated by other function.
+                */
+               break;
+
+       default:
+               bfa_sm_fault(ioc, event);
+       }
+}
+
+
+
+/**
+ *  bfa_ioc_pvt BFA IOC private functions
+ */
+
+static void
+bfa_ioc_disable_comp(struct bfa_ioc_s *ioc)
+{
+       struct list_head *qe;
+       struct bfa_ioc_hbfail_notify_s *notify;
+
+       ioc->cbfn->disable_cbfn(ioc->bfa);
+
+       /**
+        * Notify common modules registered for notification.
+        */
+       list_for_each(qe, &ioc->hb_notify_q) {
+               notify = (struct bfa_ioc_hbfail_notify_s *)qe;
+               notify->cbfn(notify->cbarg);
+       }
+}
+
+static void
+bfa_ioc_sem_timeout(void *ioc_arg)
+{
+       struct bfa_ioc_s *ioc = (struct bfa_ioc_s *)ioc_arg;
+
+       bfa_ioc_hw_sem_get(ioc);
+}
+
+static void
+bfa_ioc_usage_sem_get(struct bfa_ioc_s *ioc)
+{
+       u32        r32;
+       int             cnt = 0;
+#define BFA_SEM_SPINCNT        1000
+
+       do {
+               r32 = bfa_reg_read(ioc->ioc_regs.ioc_usage_sem_reg);
+               cnt++;
+               if (cnt > BFA_SEM_SPINCNT)
+                       break;
+       } while (r32 != 0);
+       bfa_assert(cnt < BFA_SEM_SPINCNT);
+}
+
+static void
+bfa_ioc_usage_sem_release(struct bfa_ioc_s *ioc)
+{
+       bfa_reg_write(ioc->ioc_regs.ioc_usage_sem_reg, 1);
+}
+
+static void
+bfa_ioc_hw_sem_get(struct bfa_ioc_s *ioc)
+{
+       u32        r32;
+
+       /**
+        * First read to the semaphore register will return 0, subsequent reads
+        * will return 1. Semaphore is released by writing 0 to the register
+        */
+       r32 = bfa_reg_read(ioc->ioc_regs.ioc_sem_reg);
+       if (r32 == 0) {
+               bfa_fsm_send_event(ioc, IOC_E_SEMLOCKED);
+               return;
+       }
+
+       bfa_timer_begin(ioc->timer_mod, &ioc->sem_timer, bfa_ioc_sem_timeout,
+                       ioc, BFA_IOC_TOV);
+}
+
+static void
+bfa_ioc_hw_sem_release(struct bfa_ioc_s *ioc)
+{
+       bfa_reg_write(ioc->ioc_regs.ioc_sem_reg, 1);
+}
+
+static void
+bfa_ioc_hw_sem_get_cancel(struct bfa_ioc_s *ioc)
+{
+       bfa_timer_stop(&ioc->sem_timer);
+}
+
+/**
+ * Initialize LPU local memory (aka secondary memory / SRAM)
+ */
+static void
+bfa_ioc_lmem_init(struct bfa_ioc_s *ioc)
+{
+       u32        pss_ctl;
+       int             i;
+#define PSS_LMEM_INIT_TIME  10000
+
+       pss_ctl = bfa_reg_read(ioc->ioc_regs.pss_ctl_reg);
+       pss_ctl &= ~__PSS_LMEM_RESET;
+       pss_ctl |= __PSS_LMEM_INIT_EN;
+       pss_ctl |= __PSS_I2C_CLK_DIV(3UL); /* i2c workaround 12.5khz clock */
+       bfa_reg_write(ioc->ioc_regs.pss_ctl_reg, pss_ctl);
+
+       /**
+        * wait for memory initialization to be complete
+        */
+       i = 0;
+       do {
+               pss_ctl = bfa_reg_read(ioc->ioc_regs.pss_ctl_reg);
+               i++;
+       } while (!(pss_ctl & __PSS_LMEM_INIT_DONE) && (i < PSS_LMEM_INIT_TIME));
+
+       /**
+        * If memory initialization is not successful, IOC timeout will catch
+        * such failures.
+        */
+       bfa_assert(pss_ctl & __PSS_LMEM_INIT_DONE);
+       bfa_trc(ioc, pss_ctl);
+
+       pss_ctl &= ~(__PSS_LMEM_INIT_DONE | __PSS_LMEM_INIT_EN);
+       bfa_reg_write(ioc->ioc_regs.pss_ctl_reg, pss_ctl);
+}
+
+static void
+bfa_ioc_lpu_start(struct bfa_ioc_s *ioc)
+{
+       u32        pss_ctl;
+
+       /**
+        * Take processor out of reset.
+        */
+       pss_ctl = bfa_reg_read(ioc->ioc_regs.pss_ctl_reg);
+       pss_ctl &= ~__PSS_LPU0_RESET;
+
+       bfa_reg_write(ioc->ioc_regs.pss_ctl_reg, pss_ctl);
+}
+
+static void
+bfa_ioc_lpu_stop(struct bfa_ioc_s *ioc)
+{
+       u32        pss_ctl;
+
+       /**
+        * Put processors in reset.
+        */
+       pss_ctl = bfa_reg_read(ioc->ioc_regs.pss_ctl_reg);
+       pss_ctl |= (__PSS_LPU0_RESET | __PSS_LPU1_RESET);
+
+       bfa_reg_write(ioc->ioc_regs.pss_ctl_reg, pss_ctl);
+}
+
+/**
+ * Get driver and firmware versions.
+ */
+static void
+bfa_ioc_fwver_get(struct bfa_ioc_s *ioc, struct bfi_ioc_image_hdr_s *fwhdr)
+{
+       u32        pgnum, pgoff;
+       u32        loff = 0;
+       int             i;
+       u32       *fwsig = (u32 *) fwhdr;
+
+       pgnum = bfa_ioc_smem_pgnum(ioc, loff);
+       pgoff = bfa_ioc_smem_pgoff(ioc, loff);
+       bfa_reg_write(ioc->ioc_regs.host_page_num_fn, pgnum);
+
+       for (i = 0; i < (sizeof(struct bfi_ioc_image_hdr_s) / sizeof(u32));
+            i++) {
+               fwsig[i] = bfa_mem_read(ioc->ioc_regs.smem_page_start, loff);
+               loff += sizeof(u32);
+       }
+}
+
+static u32 *
+bfa_ioc_fwimg_get_chunk(struct bfa_ioc_s *ioc, u32 off)
+{
+       if (ioc->ctdev)
+               return bfi_image_ct_get_chunk(off);
+       return bfi_image_cb_get_chunk(off);
+}
+
+static          u32
+bfa_ioc_fwimg_get_size(struct bfa_ioc_s *ioc)
+{
+return (ioc->ctdev) ? bfi_image_ct_size : bfi_image_cb_size;
+}
+
+/**
+ * Returns TRUE if same.
+ */
+static          bfa_boolean_t
+bfa_ioc_fwver_cmp(struct bfa_ioc_s *ioc, struct bfi_ioc_image_hdr_s *fwhdr)
+{
+       struct bfi_ioc_image_hdr_s *drv_fwhdr;
+       int             i;
+
+       drv_fwhdr =
+               (struct bfi_ioc_image_hdr_s *)bfa_ioc_fwimg_get_chunk(ioc, 0);
+
+       for (i = 0; i < BFI_IOC_MD5SUM_SZ; i++) {
+               if (fwhdr->md5sum[i] != drv_fwhdr->md5sum[i]) {
+                       bfa_trc(ioc, i);
+                       bfa_trc(ioc, fwhdr->md5sum[i]);
+                       bfa_trc(ioc, drv_fwhdr->md5sum[i]);
+                       return BFA_FALSE;
+               }
+       }
+
+       bfa_trc(ioc, fwhdr->md5sum[0]);
+       return BFA_TRUE;
+}
+
+/**
+ * Return true if current running version is valid. Firmware signature and
+ * execution context (driver/bios) must match.
+ */
+static          bfa_boolean_t
+bfa_ioc_fwver_valid(struct bfa_ioc_s *ioc)
+{
+       struct bfi_ioc_image_hdr_s fwhdr, *drv_fwhdr;
+
+       /**
+        * If bios/efi boot (flash based) -- return true
+        */
+       if (bfa_ioc_fwimg_get_size(ioc) < BFA_IOC_FWIMG_MINSZ)
+               return BFA_TRUE;
+
+       bfa_ioc_fwver_get(ioc, &fwhdr);
+       drv_fwhdr =
+               (struct bfi_ioc_image_hdr_s *)bfa_ioc_fwimg_get_chunk(ioc, 0);
+
+       if (fwhdr.signature != drv_fwhdr->signature) {
+               bfa_trc(ioc, fwhdr.signature);
+               bfa_trc(ioc, drv_fwhdr->signature);
+               return BFA_FALSE;
+       }
+
+       if (fwhdr.exec != drv_fwhdr->exec) {
+               bfa_trc(ioc, fwhdr.exec);
+               bfa_trc(ioc, drv_fwhdr->exec);
+               return BFA_FALSE;
+       }
+
+       return bfa_ioc_fwver_cmp(ioc, &fwhdr);
+}
+
+/**
+ * Return true if firmware of current driver matches the running firmware.
+ */
+static          bfa_boolean_t
+bfa_ioc_firmware_lock(struct bfa_ioc_s *ioc)
+{
+       enum bfi_ioc_state ioc_fwstate;
+       u32        usecnt;
+       struct bfi_ioc_image_hdr_s fwhdr;
+
+       /**
+        * Firmware match check is relevant only for CNA.
+        */
+       if (!ioc->cna)
+               return BFA_TRUE;
+
+       /**
+        * If bios boot (flash based) -- do not increment usage count
+        */
+       if (bfa_ioc_fwimg_get_size(ioc) < BFA_IOC_FWIMG_MINSZ)
+               return BFA_TRUE;
+
+       bfa_ioc_usage_sem_get(ioc);
+       usecnt = bfa_reg_read(ioc->ioc_regs.ioc_usage_reg);
+
+       /**
+        * If usage count is 0, always return TRUE.
+        */
+       if (usecnt == 0) {
+               bfa_reg_write(ioc->ioc_regs.ioc_usage_reg, 1);
+               bfa_ioc_usage_sem_release(ioc);
+               bfa_trc(ioc, usecnt);
+               return BFA_TRUE;
+       }
+
+       ioc_fwstate = bfa_reg_read(ioc->ioc_regs.ioc_fwstate);
+       bfa_trc(ioc, ioc_fwstate);
+
+       /**
+        * Use count cannot be non-zero and chip in uninitialized state.
+        */
+       bfa_assert(ioc_fwstate != BFI_IOC_UNINIT);
+
+       /**
+        * Check if another driver with a different firmware is active
+        */
+       bfa_ioc_fwver_get(ioc, &fwhdr);
+       if (!bfa_ioc_fwver_cmp(ioc, &fwhdr)) {
+               bfa_ioc_usage_sem_release(ioc);
+               bfa_trc(ioc, usecnt);
+               return BFA_FALSE;
+       }
+
+       /**
+        * Same firmware version. Increment the reference count.
+        */
+       usecnt++;
+       bfa_reg_write(ioc->ioc_regs.ioc_usage_reg, usecnt);
+       bfa_ioc_usage_sem_release(ioc);
+       bfa_trc(ioc, usecnt);
+       return BFA_TRUE;
+}
+
+static void
+bfa_ioc_firmware_unlock(struct bfa_ioc_s *ioc)
+{
+       u32        usecnt;
+
+       /**
+        * Firmware lock is relevant only for CNA.
+        * If bios boot (flash based) -- do not decrement usage count
+        */
+       if (!ioc->cna || (bfa_ioc_fwimg_get_size(ioc) < BFA_IOC_FWIMG_MINSZ))
+               return;
+
+       /**
+        * decrement usage count
+        */
+       bfa_ioc_usage_sem_get(ioc);
+       usecnt = bfa_reg_read(ioc->ioc_regs.ioc_usage_reg);
+       bfa_assert(usecnt > 0);
+
+       usecnt--;
+       bfa_reg_write(ioc->ioc_regs.ioc_usage_reg, usecnt);
+       bfa_trc(ioc, usecnt);
+
+       bfa_ioc_usage_sem_release(ioc);
+}
+
+/**
+ * Conditionally flush any pending message from firmware at start.
+ */
+static void
+bfa_ioc_msgflush(struct bfa_ioc_s *ioc)
+{
+       u32        r32;
+
+       r32 = bfa_reg_read(ioc->ioc_regs.lpu_mbox_cmd);
+       if (r32)
+               bfa_reg_write(ioc->ioc_regs.lpu_mbox_cmd, 1);
+}
+
+
+static void
+bfa_ioc_hwinit(struct bfa_ioc_s *ioc, bfa_boolean_t force)
+{
+       enum bfi_ioc_state ioc_fwstate;
+       bfa_boolean_t   fwvalid;
+
+       ioc_fwstate = bfa_reg_read(ioc->ioc_regs.ioc_fwstate);
+
+       if (force)
+               ioc_fwstate = BFI_IOC_UNINIT;
+
+       bfa_trc(ioc, ioc_fwstate);
+
+       /**
+        * check if firmware is valid
+        */
+       fwvalid = (ioc_fwstate == BFI_IOC_UNINIT) ?
+                       BFA_FALSE : bfa_ioc_fwver_valid(ioc);
+
+       if (!fwvalid) {
+               bfa_ioc_boot(ioc, BFI_BOOT_TYPE_NORMAL, ioc->pcidev.device_id);
+               return;
+       }
+
+       /**
+        * If hardware initialization is in progress (initialized by other IOC),
+        * just wait for an initialization completion interrupt.
+        */
+       if (ioc_fwstate == BFI_IOC_INITING) {
+               bfa_trc(ioc, ioc_fwstate);
+               ioc->cbfn->reset_cbfn(ioc->bfa);
+               return;
+       }
+
+       /**
+        * If IOC function is disabled and firmware version is same,
+        * just re-enable IOC.
+        */
+       if (ioc_fwstate == BFI_IOC_DISABLED || ioc_fwstate == BFI_IOC_OP) {
+               bfa_trc(ioc, ioc_fwstate);
+
+               /**
+                * When using MSI-X any pending firmware ready event should
+                * be flushed. Otherwise MSI-X interrupts are not delivered.
+                */
+               bfa_ioc_msgflush(ioc);
+               ioc->cbfn->reset_cbfn(ioc->bfa);
+               bfa_fsm_send_event(ioc, IOC_E_FWREADY);
+               return;
+       }
+
+       /**
+        * Initialize the h/w for any other states.
+        */
+       bfa_ioc_boot(ioc, BFI_BOOT_TYPE_NORMAL, ioc->pcidev.device_id);
+}
+
+static void
+bfa_ioc_timeout(void *ioc_arg)
+{
+       struct bfa_ioc_s *ioc = (struct bfa_ioc_s *)ioc_arg;
+
+       bfa_trc(ioc, 0);
+       bfa_fsm_send_event(ioc, IOC_E_TIMEOUT);
+}
+
+void
+bfa_ioc_mbox_send(struct bfa_ioc_s *ioc, void *ioc_msg, int len)
+{
+       u32       *msgp = (u32 *) ioc_msg;
+       u32        i;
+
+       bfa_trc(ioc, msgp[0]);
+       bfa_trc(ioc, len);
+
+       bfa_assert(len <= BFI_IOC_MSGLEN_MAX);
+
+       /*
+        * first write msg to mailbox registers
+        */
+       for (i = 0; i < len / sizeof(u32); i++)
+               bfa_reg_write(ioc->ioc_regs.hfn_mbox + i * sizeof(u32),
+                             bfa_os_wtole(msgp[i]));
+
+       for (; i < BFI_IOC_MSGLEN_MAX / sizeof(u32); i++)
+               bfa_reg_write(ioc->ioc_regs.hfn_mbox + i * sizeof(u32), 0);
+
+       /*
+        * write 1 to mailbox CMD to trigger LPU event
+        */
+       bfa_reg_write(ioc->ioc_regs.hfn_mbox_cmd, 1);
+       (void)bfa_reg_read(ioc->ioc_regs.hfn_mbox_cmd);
+}
+
+static void
+bfa_ioc_send_enable(struct bfa_ioc_s *ioc)
+{
+       struct bfi_ioc_ctrl_req_s enable_req;
+
+       bfi_h2i_set(enable_req.mh, BFI_MC_IOC, BFI_IOC_H2I_ENABLE_REQ,
+                   bfa_ioc_portid(ioc));
+       enable_req.ioc_class = ioc->ioc_mc;
+       bfa_ioc_mbox_send(ioc, &enable_req, sizeof(struct bfi_ioc_ctrl_req_s));
+}
+
+static void
+bfa_ioc_send_disable(struct bfa_ioc_s *ioc)
+{
+       struct bfi_ioc_ctrl_req_s disable_req;
+
+       bfi_h2i_set(disable_req.mh, BFI_MC_IOC, BFI_IOC_H2I_DISABLE_REQ,
+                   bfa_ioc_portid(ioc));
+       bfa_ioc_mbox_send(ioc, &disable_req, sizeof(struct bfi_ioc_ctrl_req_s));
+}
+
+static void
+bfa_ioc_send_getattr(struct bfa_ioc_s *ioc)
+{
+       struct bfi_ioc_getattr_req_s attr_req;
+
+       bfi_h2i_set(attr_req.mh, BFI_MC_IOC, BFI_IOC_H2I_GETATTR_REQ,
+                   bfa_ioc_portid(ioc));
+       bfa_dma_be_addr_set(attr_req.attr_addr, ioc->attr_dma.pa);
+       bfa_ioc_mbox_send(ioc, &attr_req, sizeof(attr_req));
+}
+
+static void
+bfa_ioc_hb_check(void *cbarg)
+{
+       struct bfa_ioc_s *ioc = cbarg;
+       u32        hb_count;
+
+       hb_count = bfa_reg_read(ioc->ioc_regs.heartbeat);
+       if (ioc->hb_count == hb_count) {
+               ioc->hb_fail++;
+       } else {
+               ioc->hb_count = hb_count;
+               ioc->hb_fail = 0;
+       }
+
+       if (ioc->hb_fail >= BFA_IOC_HB_FAIL_MAX) {
+               bfa_log(ioc->logm, BFA_LOG_HAL_HEARTBEAT_FAILURE, hb_count);
+               ioc->hb_fail = 0;
+               bfa_ioc_recover(ioc);
+               return;
+       }
+
+       bfa_ioc_mbox_poll(ioc);
+       bfa_timer_begin(ioc->timer_mod, &ioc->ioc_timer, bfa_ioc_hb_check, ioc,
+                       BFA_IOC_HB_TOV);
+}
+
+static void
+bfa_ioc_hb_monitor(struct bfa_ioc_s *ioc)
+{
+       ioc->hb_fail = 0;
+       ioc->hb_count = bfa_reg_read(ioc->ioc_regs.heartbeat);
+       bfa_timer_begin(ioc->timer_mod, &ioc->ioc_timer, bfa_ioc_hb_check, ioc,
+                       BFA_IOC_HB_TOV);
+}
+
+static void
+bfa_ioc_hb_stop(struct bfa_ioc_s *ioc)
+{
+       bfa_timer_stop(&ioc->ioc_timer);
+}
+
+/**
+ * Host to LPU mailbox message addresses
+ */
+static struct {
+       u32        hfn_mbox, lpu_mbox, hfn_pgn;
+} iocreg_fnreg[] = {
+       {
+       HOSTFN0_LPU_MBOX0_0, LPU_HOSTFN0_MBOX0_0, HOST_PAGE_NUM_FN0}, {
+       HOSTFN1_LPU_MBOX0_8, LPU_HOSTFN1_MBOX0_8, HOST_PAGE_NUM_FN1}, {
+       HOSTFN2_LPU_MBOX0_0, LPU_HOSTFN2_MBOX0_0, HOST_PAGE_NUM_FN2}, {
+       HOSTFN3_LPU_MBOX0_8, LPU_HOSTFN3_MBOX0_8, HOST_PAGE_NUM_FN3}
+};
+
+/**
+ * Host <-> LPU mailbox command/status registers - port 0
+ */
+static struct {
+       u32        hfn, lpu;
+} iocreg_mbcmd_p0[] = {
+       {
+       HOSTFN0_LPU0_MBOX0_CMD_STAT, LPU0_HOSTFN0_MBOX0_CMD_STAT}, {
+       HOSTFN1_LPU0_MBOX0_CMD_STAT, LPU0_HOSTFN1_MBOX0_CMD_STAT}, {
+       HOSTFN2_LPU0_MBOX0_CMD_STAT, LPU0_HOSTFN2_MBOX0_CMD_STAT}, {
+       HOSTFN3_LPU0_MBOX0_CMD_STAT, LPU0_HOSTFN3_MBOX0_CMD_STAT}
+};
+
+/**
+ * Host <-> LPU mailbox command/status registers - port 1
+ */
+static struct {
+       u32        hfn, lpu;
+} iocreg_mbcmd_p1[] = {
+       {
+       HOSTFN0_LPU1_MBOX0_CMD_STAT, LPU1_HOSTFN0_MBOX0_CMD_STAT}, {
+       HOSTFN1_LPU1_MBOX0_CMD_STAT, LPU1_HOSTFN1_MBOX0_CMD_STAT}, {
+       HOSTFN2_LPU1_MBOX0_CMD_STAT, LPU1_HOSTFN2_MBOX0_CMD_STAT}, {
+       HOSTFN3_LPU1_MBOX0_CMD_STAT, LPU1_HOSTFN3_MBOX0_CMD_STAT}
+};
+
+/**
+ * Shared IRQ handling in INTX mode
+ */
+static struct {
+       u32        isr, msk;
+} iocreg_shirq_next[] = {
+       {
+       HOSTFN1_INT_STATUS, HOSTFN1_INT_MSK}, {
+       HOSTFN2_INT_STATUS, HOSTFN2_INT_MSK}, {
+       HOSTFN3_INT_STATUS, HOSTFN3_INT_MSK}, {
+HOSTFN0_INT_STATUS, HOSTFN0_INT_MSK},};
+
+static void
+bfa_ioc_reg_init(struct bfa_ioc_s *ioc)
+{
+       bfa_os_addr_t   rb;
+       int             pcifn = bfa_ioc_pcifn(ioc);
+
+       rb = bfa_ioc_bar0(ioc);
+
+       ioc->ioc_regs.hfn_mbox = rb + iocreg_fnreg[pcifn].hfn_mbox;
+       ioc->ioc_regs.lpu_mbox = rb + iocreg_fnreg[pcifn].lpu_mbox;
+       ioc->ioc_regs.host_page_num_fn = rb + iocreg_fnreg[pcifn].hfn_pgn;
+
+       if (ioc->port_id == 0) {
+               ioc->ioc_regs.heartbeat = rb + BFA_IOC0_HBEAT_REG;
+               ioc->ioc_regs.ioc_fwstate = rb + BFA_IOC0_STATE_REG;
+               ioc->ioc_regs.hfn_mbox_cmd = rb + iocreg_mbcmd_p0[pcifn].hfn;
+               ioc->ioc_regs.lpu_mbox_cmd = rb + iocreg_mbcmd_p0[pcifn].lpu;
+               ioc->ioc_regs.ll_halt = rb + FW_INIT_HALT_P0;
+       } else {
+               ioc->ioc_regs.heartbeat = (rb + BFA_IOC1_HBEAT_REG);
+               ioc->ioc_regs.ioc_fwstate = (rb + BFA_IOC1_STATE_REG);
+               ioc->ioc_regs.hfn_mbox_cmd = rb + iocreg_mbcmd_p1[pcifn].hfn;
+               ioc->ioc_regs.lpu_mbox_cmd = rb + iocreg_mbcmd_p1[pcifn].lpu;
+               ioc->ioc_regs.ll_halt = rb + FW_INIT_HALT_P1;
+       }
+
+       /**
+        * Shared IRQ handling in INTX mode
+        */
+       ioc->ioc_regs.shirq_isr_next = rb + iocreg_shirq_next[pcifn].isr;
+       ioc->ioc_regs.shirq_msk_next = rb + iocreg_shirq_next[pcifn].msk;
+
+       /*
+        * PSS control registers
+        */
+       ioc->ioc_regs.pss_ctl_reg = (rb + PSS_CTL_REG);
+       ioc->ioc_regs.app_pll_fast_ctl_reg = (rb + APP_PLL_425_CTL_REG);
+       ioc->ioc_regs.app_pll_slow_ctl_reg = (rb + APP_PLL_312_CTL_REG);
+
+       /*
+        * IOC semaphore registers and serialization
+        */
+       ioc->ioc_regs.ioc_sem_reg = (rb + HOST_SEM0_REG);
+       ioc->ioc_regs.ioc_usage_sem_reg = (rb + HOST_SEM1_REG);
+       ioc->ioc_regs.ioc_usage_reg = (rb + BFA_FW_USE_COUNT);
+
+       /**
+        * sram memory access
+        */
+       ioc->ioc_regs.smem_page_start = (rb + PSS_SMEM_PAGE_START);
+       ioc->ioc_regs.smem_pg0 = BFI_IOC_SMEM_PG0_CB;
+       if (ioc->pcidev.device_id == BFA_PCI_DEVICE_ID_CT)
+               ioc->ioc_regs.smem_pg0 = BFI_IOC_SMEM_PG0_CT;
+}
+
+/**
+ *      Initiate a full firmware download.
+ */
+static void
+bfa_ioc_download_fw(struct bfa_ioc_s *ioc, u32 boot_type,
+                   u32 boot_param)
+{
+       u32       *fwimg;
+       u32        pgnum, pgoff;
+       u32        loff = 0;
+       u32        chunkno = 0;
+       u32        i;
+
+       /**
+        * Initialize LMEM first before code download
+        */
+       bfa_ioc_lmem_init(ioc);
+
+       /**
+        * Flash based firmware boot
+        */
+       bfa_trc(ioc, bfa_ioc_fwimg_get_size(ioc));
+       if (bfa_ioc_fwimg_get_size(ioc) < BFA_IOC_FWIMG_MINSZ)
+               boot_type = BFI_BOOT_TYPE_FLASH;
+       fwimg = bfa_ioc_fwimg_get_chunk(ioc, chunkno);
+       fwimg[BFI_BOOT_TYPE_OFF / sizeof(u32)] = bfa_os_swap32(boot_type);
+       fwimg[BFI_BOOT_PARAM_OFF / sizeof(u32)] =
+               bfa_os_swap32(boot_param);
+
+       pgnum = bfa_ioc_smem_pgnum(ioc, loff);
+       pgoff = bfa_ioc_smem_pgoff(ioc, loff);
+
+       bfa_reg_write(ioc->ioc_regs.host_page_num_fn, pgnum);
+
+       for (i = 0; i < bfa_ioc_fwimg_get_size(ioc); i++) {
+
+               if (BFA_FLASH_CHUNK_NO(i) != chunkno) {
+                       chunkno = BFA_FLASH_CHUNK_NO(i);
+                       fwimg = bfa_ioc_fwimg_get_chunk(ioc,
+                                       BFA_FLASH_CHUNK_ADDR(chunkno));
+               }
+
+               /**
+                * write smem
+                */
+               bfa_mem_write(ioc->ioc_regs.smem_page_start, loff,
+                             fwimg[BFA_FLASH_OFFSET_IN_CHUNK(i)]);
+
+               loff += sizeof(u32);
+
+               /**
+                * handle page offset wrap around
+                */
+               loff = PSS_SMEM_PGOFF(loff);
+               if (loff == 0) {
+                       pgnum++;
+                       bfa_reg_write(ioc->ioc_regs.host_page_num_fn, pgnum);
+               }
+       }
+
+       bfa_reg_write(ioc->ioc_regs.host_page_num_fn,
+                     bfa_ioc_smem_pgnum(ioc, 0));
+}
+
+static void
+bfa_ioc_reset(struct bfa_ioc_s *ioc, bfa_boolean_t force)
+{
+       bfa_ioc_hwinit(ioc, force);
+}
+
+/**
+ * Update BFA configuration from firmware configuration.
+ */
+static void
+bfa_ioc_getattr_reply(struct bfa_ioc_s *ioc)
+{
+       struct bfi_ioc_attr_s *attr = ioc->attr;
+
+       attr->adapter_prop = bfa_os_ntohl(attr->adapter_prop);
+       attr->maxfrsize = bfa_os_ntohs(attr->maxfrsize);
+
+       bfa_fsm_send_event(ioc, IOC_E_FWRSP_GETATTR);
+}
+
+/**
+ * Attach time initialization of mbox logic.
+ */
+static void
+bfa_ioc_mbox_attach(struct bfa_ioc_s *ioc)
+{
+       struct bfa_ioc_mbox_mod_s *mod = &ioc->mbox_mod;
+       int             mc;
+
+       INIT_LIST_HEAD(&mod->cmd_q);
+       for (mc = 0; mc < BFI_MC_MAX; mc++) {
+               mod->mbhdlr[mc].cbfn = NULL;
+               mod->mbhdlr[mc].cbarg = ioc->bfa;
+       }
+}
+
+/**
+ * Mbox poll timer -- restarts any pending mailbox requests.
+ */
+static void
+bfa_ioc_mbox_poll(struct bfa_ioc_s *ioc)
+{
+       struct bfa_ioc_mbox_mod_s *mod = &ioc->mbox_mod;
+       struct bfa_mbox_cmd_s *cmd;
+       u32        stat;
+
+       /**
+        * If no command pending, do nothing
+        */
+       if (list_empty(&mod->cmd_q))
+               return;
+
+       /**
+        * If previous command is not yet fetched by firmware, do nothing
+        */
+       stat = bfa_reg_read(ioc->ioc_regs.hfn_mbox_cmd);
+       if (stat)
+               return;
+
+       /**
+        * Enqueue command to firmware.
+        */
+       bfa_q_deq(&mod->cmd_q, &cmd);
+       bfa_ioc_mbox_send(ioc, cmd->msg, sizeof(cmd->msg));
+}
+
+/**
+ * Cleanup any pending requests.
+ */
+static void
+bfa_ioc_mbox_hbfail(struct bfa_ioc_s *ioc)
+{
+       struct bfa_ioc_mbox_mod_s *mod = &ioc->mbox_mod;
+       struct bfa_mbox_cmd_s *cmd;
+
+       while (!list_empty(&mod->cmd_q))
+               bfa_q_deq(&mod->cmd_q, &cmd);
+}
+
+/**
+ * Initialize IOC to port mapping.
+ */
+
+#define FNC_PERS_FN_SHIFT(__fn)        ((__fn) * 8)
+static void
+bfa_ioc_map_port(struct bfa_ioc_s *ioc)
+{
+       bfa_os_addr_t   rb = ioc->pcidev.pci_bar_kva;
+       u32        r32;
+
+       /**
+        * For crossbow, port id is same as pci function.
+        */
+       if (ioc->pcidev.device_id != BFA_PCI_DEVICE_ID_CT) {
+               ioc->port_id = bfa_ioc_pcifn(ioc);
+               return;
+       }
+
+       /**
+        * For catapult, base port id on personality register and IOC type
+        */
+       r32 = bfa_reg_read(rb + FNC_PERS_REG);
+       r32 >>= FNC_PERS_FN_SHIFT(bfa_ioc_pcifn(ioc));
+       ioc->port_id = (r32 & __F0_PORT_MAP_MK) >> __F0_PORT_MAP_SH;
+
+       bfa_trc(ioc, bfa_ioc_pcifn(ioc));
+       bfa_trc(ioc, ioc->port_id);
+}
+
+
+
+/**
+ *  bfa_ioc_public
+ */
+
+/**
+* Set interrupt mode for a function: INTX or MSIX
+ */
+void
+bfa_ioc_isr_mode_set(struct bfa_ioc_s *ioc, bfa_boolean_t msix)
+{
+       bfa_os_addr_t   rb = ioc->pcidev.pci_bar_kva;
+       u32        r32, mode;
+
+       r32 = bfa_reg_read(rb + FNC_PERS_REG);
+       bfa_trc(ioc, r32);
+
+       mode = (r32 >> FNC_PERS_FN_SHIFT(bfa_ioc_pcifn(ioc))) &
+               __F0_INTX_STATUS;
+
+       /**
+        * If already in desired mode, do not change anything
+        */
+       if (!msix && mode)
+               return;
+
+       if (msix)
+               mode = __F0_INTX_STATUS_MSIX;
+       else
+               mode = __F0_INTX_STATUS_INTA;
+
+       r32 &= ~(__F0_INTX_STATUS << FNC_PERS_FN_SHIFT(bfa_ioc_pcifn(ioc)));
+       r32 |= (mode << FNC_PERS_FN_SHIFT(bfa_ioc_pcifn(ioc)));
+       bfa_trc(ioc, r32);
+
+       bfa_reg_write(rb + FNC_PERS_REG, r32);
+}
+
+bfa_status_t
+bfa_ioc_pll_init(struct bfa_ioc_s *ioc)
+{
+       bfa_os_addr_t   rb = ioc->pcidev.pci_bar_kva;
+       u32        pll_sclk, pll_fclk, r32;
+
+       if (ioc->pcidev.device_id == BFA_PCI_DEVICE_ID_CT) {
+               pll_sclk =
+                       __APP_PLL_312_ENABLE | __APP_PLL_312_LRESETN |
+                       __APP_PLL_312_RSEL200500 | __APP_PLL_312_P0_1(0U) |
+                       __APP_PLL_312_JITLMT0_1(3U) |
+                       __APP_PLL_312_CNTLMT0_1(1U);
+               pll_fclk =
+                       __APP_PLL_425_ENABLE | __APP_PLL_425_LRESETN |
+                       __APP_PLL_425_RSEL200500 | __APP_PLL_425_P0_1(0U) |
+                       __APP_PLL_425_JITLMT0_1(3U) |
+                       __APP_PLL_425_CNTLMT0_1(1U);
+
+               /**
+                *      For catapult, choose operational mode FC/FCoE
+                */
+               if (ioc->fcmode) {
+                       bfa_reg_write((rb + OP_MODE), 0);
+                       bfa_reg_write((rb + ETH_MAC_SER_REG),
+                                     __APP_EMS_CMLCKSEL | __APP_EMS_REFCKBUFEN2
+                                     | __APP_EMS_CHANNEL_SEL);
+               } else {
+                       ioc->pllinit = BFA_TRUE;
+                       bfa_reg_write((rb + OP_MODE), __GLOBAL_FCOE_MODE);
+                       bfa_reg_write((rb + ETH_MAC_SER_REG),
+                                     __APP_EMS_REFCKBUFEN1);
+               }
+       } else {
+               pll_sclk =
+                       __APP_PLL_312_ENABLE | __APP_PLL_312_LRESETN |
+                       __APP_PLL_312_P0_1(3U) | __APP_PLL_312_JITLMT0_1(3U) |
+                       __APP_PLL_312_CNTLMT0_1(3U);
+               pll_fclk =
+                       __APP_PLL_425_ENABLE | __APP_PLL_425_LRESETN |
+                       __APP_PLL_425_RSEL200500 | __APP_PLL_425_P0_1(3U) |
+                       __APP_PLL_425_JITLMT0_1(3U) |
+                       __APP_PLL_425_CNTLMT0_1(3U);
+       }
+
+       bfa_reg_write((rb + BFA_IOC0_STATE_REG), BFI_IOC_UNINIT);
+       bfa_reg_write((rb + BFA_IOC1_STATE_REG), BFI_IOC_UNINIT);
+
+       bfa_reg_write((rb + HOSTFN0_INT_MSK), 0xffffffffU);
+       bfa_reg_write((rb + HOSTFN1_INT_MSK), 0xffffffffU);
+       bfa_reg_write((rb + HOSTFN0_INT_STATUS), 0xffffffffU);
+       bfa_reg_write((rb + HOSTFN1_INT_STATUS), 0xffffffffU);
+       bfa_reg_write((rb + HOSTFN0_INT_MSK), 0xffffffffU);
+       bfa_reg_write((rb + HOSTFN1_INT_MSK), 0xffffffffU);
+
+       bfa_reg_write(ioc->ioc_regs.app_pll_slow_ctl_reg,
+                     __APP_PLL_312_LOGIC_SOFT_RESET);
+       bfa_reg_write(ioc->ioc_regs.app_pll_slow_ctl_reg,
+                     __APP_PLL_312_BYPASS | __APP_PLL_312_LOGIC_SOFT_RESET);
+       bfa_reg_write(ioc->ioc_regs.app_pll_fast_ctl_reg,
+                     __APP_PLL_425_LOGIC_SOFT_RESET);
+       bfa_reg_write(ioc->ioc_regs.app_pll_fast_ctl_reg,
+                     __APP_PLL_425_BYPASS | __APP_PLL_425_LOGIC_SOFT_RESET);
+       bfa_os_udelay(2);
+       bfa_reg_write(ioc->ioc_regs.app_pll_slow_ctl_reg,
+                     __APP_PLL_312_LOGIC_SOFT_RESET);
+       bfa_reg_write(ioc->ioc_regs.app_pll_fast_ctl_reg,
+                     __APP_PLL_425_LOGIC_SOFT_RESET);
+
+       bfa_reg_write(ioc->ioc_regs.app_pll_slow_ctl_reg,
+                     pll_sclk | __APP_PLL_312_LOGIC_SOFT_RESET);
+       bfa_reg_write(ioc->ioc_regs.app_pll_fast_ctl_reg,
+                     pll_fclk | __APP_PLL_425_LOGIC_SOFT_RESET);
+
+       /**
+        * Wait for PLLs to lock.
+        */
+       bfa_os_udelay(2000);
+       bfa_reg_write((rb + HOSTFN0_INT_STATUS), 0xffffffffU);
+       bfa_reg_write((rb + HOSTFN1_INT_STATUS), 0xffffffffU);
+
+       bfa_reg_write(ioc->ioc_regs.app_pll_slow_ctl_reg, pll_sclk);
+       bfa_reg_write(ioc->ioc_regs.app_pll_fast_ctl_reg, pll_fclk);
+
+       if (ioc->pcidev.device_id == BFA_PCI_DEVICE_ID_CT) {
+               bfa_reg_write((rb + MBIST_CTL_REG), __EDRAM_BISTR_START);
+               bfa_os_udelay(1000);
+               r32 = bfa_reg_read((rb + MBIST_STAT_REG));
+               bfa_trc(ioc, r32);
+       }
+
+       return BFA_STATUS_OK;
+}
+
+/**
+ * Interface used by diag module to do firmware boot with memory test
+ * as the entry vector.
+ */
+void
+bfa_ioc_boot(struct bfa_ioc_s *ioc, u32 boot_type, u32 boot_param)
+{
+       bfa_os_addr_t   rb;
+
+       bfa_ioc_stats(ioc, ioc_boots);
+
+       if (bfa_ioc_pll_init(ioc) != BFA_STATUS_OK)
+               return;
+
+       /**
+        * Initialize IOC state of all functions on a chip reset.
+        */
+       rb = ioc->pcidev.pci_bar_kva;
+       if (boot_param == BFI_BOOT_TYPE_MEMTEST) {
+               bfa_reg_write((rb + BFA_IOC0_STATE_REG), BFI_IOC_MEMTEST);
+               bfa_reg_write((rb + BFA_IOC1_STATE_REG), BFI_IOC_MEMTEST);
+       } else {
+               bfa_reg_write((rb + BFA_IOC0_STATE_REG), BFI_IOC_INITING);
+               bfa_reg_write((rb + BFA_IOC1_STATE_REG), BFI_IOC_INITING);
+       }
+
+       bfa_ioc_download_fw(ioc, boot_type, boot_param);
+
+       /**
+        * Enable interrupts just before starting LPU
+        */
+       ioc->cbfn->reset_cbfn(ioc->bfa);
+       bfa_ioc_lpu_start(ioc);
+}
+
+/**
+ * Enable/disable IOC failure auto recovery.
+ */
+void
+bfa_ioc_auto_recover(bfa_boolean_t auto_recover)
+{
+       bfa_auto_recover = BFA_FALSE;
+}
+
+
+bfa_boolean_t
+bfa_ioc_is_operational(struct bfa_ioc_s *ioc)
+{
+       return bfa_fsm_cmp_state(ioc, bfa_ioc_sm_op);
+}
+
+void
+bfa_ioc_msgget(struct bfa_ioc_s *ioc, void *mbmsg)
+{
+       u32       *msgp = mbmsg;
+       u32        r32;
+       int             i;
+
+       /**
+        * read the MBOX msg
+        */
+       for (i = 0; i < (sizeof(union bfi_ioc_i2h_msg_u) / sizeof(u32));
+            i++) {
+               r32 = bfa_reg_read(ioc->ioc_regs.lpu_mbox +
+                                  i * sizeof(u32));
+               msgp[i] = bfa_os_htonl(r32);
+       }
+
+       /**
+        * turn off mailbox interrupt by clearing mailbox status
+        */
+       bfa_reg_write(ioc->ioc_regs.lpu_mbox_cmd, 1);
+       bfa_reg_read(ioc->ioc_regs.lpu_mbox_cmd);
+}
+
+void
+bfa_ioc_isr(struct bfa_ioc_s *ioc, struct bfi_mbmsg_s *m)
+{
+       union bfi_ioc_i2h_msg_u *msg;
+
+       msg = (union bfi_ioc_i2h_msg_u *)m;
+
+       bfa_ioc_stats(ioc, ioc_isrs);
+
+       switch (msg->mh.msg_id) {
+       case BFI_IOC_I2H_HBEAT:
+               break;
+
+       case BFI_IOC_I2H_READY_EVENT:
+               bfa_fsm_send_event(ioc, IOC_E_FWREADY);
+               break;
+
+       case BFI_IOC_I2H_ENABLE_REPLY:
+               bfa_fsm_send_event(ioc, IOC_E_FWRSP_ENABLE);
+               break;
+
+       case BFI_IOC_I2H_DISABLE_REPLY:
+               bfa_fsm_send_event(ioc, IOC_E_FWRSP_DISABLE);
+               break;
+
+       case BFI_IOC_I2H_GETATTR_REPLY:
+               bfa_ioc_getattr_reply(ioc);
+               break;
+
+       default:
+               bfa_trc(ioc, msg->mh.msg_id);
+               bfa_assert(0);
+       }
+}
+
+/**
+ * IOC attach time initialization and setup.
+ *
+ * @param[in]  ioc     memory for IOC
+ * @param[in]  bfa     driver instance structure
+ * @param[in]  trcmod  kernel trace module
+ * @param[in]  aen     kernel aen event module
+ * @param[in]  logm    kernel logging module
+ */
+void
+bfa_ioc_attach(struct bfa_ioc_s *ioc, void *bfa, struct bfa_ioc_cbfn_s *cbfn,
+              struct bfa_timer_mod_s *timer_mod, struct bfa_trc_mod_s *trcmod,
+              struct bfa_aen_s *aen, struct bfa_log_mod_s *logm)
+{
+       ioc->bfa = bfa;
+       ioc->cbfn = cbfn;
+       ioc->timer_mod = timer_mod;
+       ioc->trcmod = trcmod;
+       ioc->aen = aen;
+       ioc->logm = logm;
+       ioc->fcmode = BFA_FALSE;
+       ioc->pllinit = BFA_FALSE;
+       ioc->dbg_fwsave_once = BFA_TRUE;
+
+       bfa_ioc_mbox_attach(ioc);
+       INIT_LIST_HEAD(&ioc->hb_notify_q);
+
+       bfa_fsm_set_state(ioc, bfa_ioc_sm_reset);
+}
+
+/**
+ * Driver detach time IOC cleanup.
+ */
+void
+bfa_ioc_detach(struct bfa_ioc_s *ioc)
+{
+       bfa_fsm_send_event(ioc, IOC_E_DETACH);
+}
+
+/**
+ * Setup IOC PCI properties.
+ *
+ * @param[in]  pcidev  PCI device information for this IOC
+ */
+void
+bfa_ioc_pci_init(struct bfa_ioc_s *ioc, struct bfa_pcidev_s *pcidev,
+                enum bfi_mclass mc)
+{
+       ioc->ioc_mc = mc;
+       ioc->pcidev = *pcidev;
+       ioc->ctdev = (ioc->pcidev.device_id == BFA_PCI_DEVICE_ID_CT);
+       ioc->cna = ioc->ctdev && !ioc->fcmode;
+
+       bfa_ioc_map_port(ioc);
+       bfa_ioc_reg_init(ioc);
+}
+
+/**
+ * Initialize IOC dma memory
+ *
+ * @param[in]  dm_kva  kernel virtual address of IOC dma memory
+ * @param[in]  dm_pa   physical address of IOC dma memory
+ */
+void
+bfa_ioc_mem_claim(struct bfa_ioc_s *ioc, u8 *dm_kva, u64 dm_pa)
+{
+       /**
+        * dma memory for firmware attribute
+        */
+       ioc->attr_dma.kva = dm_kva;
+       ioc->attr_dma.pa = dm_pa;
+       ioc->attr = (struct bfi_ioc_attr_s *)dm_kva;
+}
+
+/**
+ * Return size of dma memory required.
+ */
+u32
+bfa_ioc_meminfo(void)
+{
+       return BFA_ROUNDUP(sizeof(struct bfi_ioc_attr_s), BFA_DMA_ALIGN_SZ);
+}
+
+void
+bfa_ioc_enable(struct bfa_ioc_s *ioc)
+{
+       bfa_ioc_stats(ioc, ioc_enables);
+       ioc->dbg_fwsave_once = BFA_TRUE;
+
+       bfa_fsm_send_event(ioc, IOC_E_ENABLE);
+}
+
+void
+bfa_ioc_disable(struct bfa_ioc_s *ioc)
+{
+       bfa_ioc_stats(ioc, ioc_disables);
+       bfa_fsm_send_event(ioc, IOC_E_DISABLE);
+}
+
+/**
+ * Returns memory required for saving firmware trace in case of crash.
+ * Driver must call this interface to allocate memory required for
+ * automatic saving of firmware trace. Driver should call
+ * bfa_ioc_debug_memclaim() right after bfa_ioc_attach() to setup this
+ * trace memory.
+ */
+int
+bfa_ioc_debug_trcsz(bfa_boolean_t auto_recover)
+{
+return (auto_recover) ? BFA_DBG_FWTRC_LEN : 0;
+}
+
+/**
+ * Initialize memory for saving firmware trace. Driver must initialize
+ * trace memory before call bfa_ioc_enable().
+ */
+void
+bfa_ioc_debug_memclaim(struct bfa_ioc_s *ioc, void *dbg_fwsave)
+{
+       bfa_assert(ioc->auto_recover);
+       ioc->dbg_fwsave = dbg_fwsave;
+       ioc->dbg_fwsave_len = bfa_ioc_debug_trcsz(ioc->auto_recover);
+}
+
+u32
+bfa_ioc_smem_pgnum(struct bfa_ioc_s *ioc, u32 fmaddr)
+{
+       return PSS_SMEM_PGNUM(ioc->ioc_regs.smem_pg0, fmaddr);
+}
+
+u32
+bfa_ioc_smem_pgoff(struct bfa_ioc_s *ioc, u32 fmaddr)
+{
+       return PSS_SMEM_PGOFF(fmaddr);
+}
+
+/**
+ * Register mailbox message handler functions
+ *
+ * @param[in]  ioc             IOC instance
+ * @param[in]  mcfuncs         message class handler functions
+ */
+void
+bfa_ioc_mbox_register(struct bfa_ioc_s *ioc, bfa_ioc_mbox_mcfunc_t *mcfuncs)
+{
+       struct bfa_ioc_mbox_mod_s *mod = &ioc->mbox_mod;
+       int             mc;
+
+       for (mc = 0; mc < BFI_MC_MAX; mc++)
+               mod->mbhdlr[mc].cbfn = mcfuncs[mc];
+}
+
+/**
+ * Register mailbox message handler function, to be called by common modules
+ */
+void
+bfa_ioc_mbox_regisr(struct bfa_ioc_s *ioc, enum bfi_mclass mc,
+                   bfa_ioc_mbox_mcfunc_t cbfn, void *cbarg)
+{
+       struct bfa_ioc_mbox_mod_s *mod = &ioc->mbox_mod;
+
+       mod->mbhdlr[mc].cbfn = cbfn;
+       mod->mbhdlr[mc].cbarg = cbarg;
+}
+
+/**
+ * Queue a mailbox command request to firmware. Waits if mailbox is busy.
+ * Responsibility of caller to serialize
+ *
+ * @param[in]  ioc     IOC instance
+ * @param[i]   cmd     Mailbox command
+ */
+void
+bfa_ioc_mbox_queue(struct bfa_ioc_s *ioc, struct bfa_mbox_cmd_s *cmd)
+{
+       struct bfa_ioc_mbox_mod_s *mod = &ioc->mbox_mod;
+       u32        stat;
+
+       /**
+        * If a previous command is pending, queue new command
+        */
+       if (!list_empty(&mod->cmd_q)) {
+               list_add_tail(&cmd->qe, &mod->cmd_q);
+               return;
+       }
+
+       /**
+        * If mailbox is busy, queue command for poll timer
+        */
+       stat = bfa_reg_read(ioc->ioc_regs.hfn_mbox_cmd);
+       if (stat) {
+               list_add_tail(&cmd->qe, &mod->cmd_q);
+               return;
+       }
+
+       /**
+        * mailbox is free -- queue command to firmware
+        */
+       bfa_ioc_mbox_send(ioc, cmd->msg, sizeof(cmd->msg));
+}
+
+/**
+ * Handle mailbox interrupts
+ */
+void
+bfa_ioc_mbox_isr(struct bfa_ioc_s *ioc)
+{
+       struct bfa_ioc_mbox_mod_s *mod = &ioc->mbox_mod;
+       struct bfi_mbmsg_s m;
+       int             mc;
+
+       bfa_ioc_msgget(ioc, &m);
+
+       /**
+        * Treat IOC message class as special.
+        */
+       mc = m.mh.msg_class;
+       if (mc == BFI_MC_IOC) {
+               bfa_ioc_isr(ioc, &m);
+               return;
+       }
+
+       if ((mc > BFI_MC_MAX) || (mod->mbhdlr[mc].cbfn == NULL))
+               return;
+
+       mod->mbhdlr[mc].cbfn(mod->mbhdlr[mc].cbarg, &m);
+}
+
+void
+bfa_ioc_error_isr(struct bfa_ioc_s *ioc)
+{
+       bfa_fsm_send_event(ioc, IOC_E_HWERROR);
+}
+
+#ifndef BFA_BIOS_BUILD
+
+/**
+ * return true if IOC is disabled
+ */
+bfa_boolean_t
+bfa_ioc_is_disabled(struct bfa_ioc_s *ioc)
+{
+       return (bfa_fsm_cmp_state(ioc, bfa_ioc_sm_disabling)
+               || bfa_fsm_cmp_state(ioc, bfa_ioc_sm_disabled));
+}
+
+/**
+ * return true if IOC firmware is different.
+ */
+bfa_boolean_t
+bfa_ioc_fw_mismatch(struct bfa_ioc_s *ioc)
+{
+       return (bfa_fsm_cmp_state(ioc, bfa_ioc_sm_reset)
+               || bfa_fsm_cmp_state(ioc, bfa_ioc_sm_fwcheck)
+               || bfa_fsm_cmp_state(ioc, bfa_ioc_sm_mismatch));
+}
+
+#define bfa_ioc_state_disabled(__sm)           \
+       (((__sm) == BFI_IOC_UNINIT) ||          \
+        ((__sm) == BFI_IOC_INITING) ||         \
+        ((__sm) == BFI_IOC_HWINIT) ||          \
+        ((__sm) == BFI_IOC_DISABLED) ||        \
+        ((__sm) == BFI_IOC_HBFAIL) ||          \
+        ((__sm) == BFI_IOC_CFG_DISABLED))
+
+/**
+ * Check if adapter is disabled -- both IOCs should be in a disabled
+ * state.
+ */
+bfa_boolean_t
+bfa_ioc_adapter_is_disabled(struct bfa_ioc_s *ioc)
+{
+       u32        ioc_state;
+       bfa_os_addr_t   rb = ioc->pcidev.pci_bar_kva;
+
+       if (!bfa_fsm_cmp_state(ioc, bfa_ioc_sm_disabled))
+               return BFA_FALSE;
+
+       ioc_state = bfa_reg_read(rb + BFA_IOC0_STATE_REG);
+       if (!bfa_ioc_state_disabled(ioc_state))
+               return BFA_FALSE;
+
+       ioc_state = bfa_reg_read(rb + BFA_IOC1_STATE_REG);
+       if (!bfa_ioc_state_disabled(ioc_state))
+               return BFA_FALSE;
+
+       return BFA_TRUE;
+}
+
+/**
+ * Add to IOC heartbeat failure notification queue. To be used by common
+ * modules such as
+ */
+void
+bfa_ioc_hbfail_register(struct bfa_ioc_s *ioc,
+                       struct bfa_ioc_hbfail_notify_s *notify)
+{
+       list_add_tail(&notify->qe, &ioc->hb_notify_q);
+}
+
+#define BFA_MFG_NAME "Brocade"
+void
+bfa_ioc_get_adapter_attr(struct bfa_ioc_s *ioc,
+                        struct bfa_adapter_attr_s *ad_attr)
+{
+       struct bfi_ioc_attr_s *ioc_attr;
+       char            model[BFA_ADAPTER_MODEL_NAME_LEN];
+
+       ioc_attr = ioc->attr;
+       bfa_os_memcpy((void *)&ad_attr->serial_num,
+                     (void *)ioc_attr->brcd_serialnum,
+                     BFA_ADAPTER_SERIAL_NUM_LEN);
+
+       bfa_os_memcpy(&ad_attr->fw_ver, ioc_attr->fw_version, BFA_VERSION_LEN);
+       bfa_os_memcpy(&ad_attr->optrom_ver, ioc_attr->optrom_version,
+                     BFA_VERSION_LEN);
+       bfa_os_memcpy(&ad_attr->manufacturer, BFA_MFG_NAME,
+                     BFA_ADAPTER_MFG_NAME_LEN);
+       bfa_os_memcpy(&ad_attr->vpd, &ioc_attr->vpd,
+                     sizeof(struct bfa_mfg_vpd_s));
+
+       ad_attr->nports = BFI_ADAPTER_GETP(NPORTS, ioc_attr->adapter_prop);
+       ad_attr->max_speed = BFI_ADAPTER_GETP(SPEED, ioc_attr->adapter_prop);
+
+       /**
+        * model name
+        */
+       if (BFI_ADAPTER_GETP(SPEED, ioc_attr->adapter_prop) == 10) {
+               strcpy(model, "BR-10?0");
+               model[5] = '0' + ad_attr->nports;
+       } else {
+               strcpy(model, "Brocade-??5");
+               model[8] =
+                       '0' + BFI_ADAPTER_GETP(SPEED, ioc_attr->adapter_prop);
+               model[9] = '0' + ad_attr->nports;
+       }
+
+       if (BFI_ADAPTER_IS_SPECIAL(ioc_attr->adapter_prop))
+               ad_attr->prototype = 1;
+       else
+               ad_attr->prototype = 0;
+
+       bfa_os_memcpy(&ad_attr->model, model, BFA_ADAPTER_MODEL_NAME_LEN);
+       bfa_os_memcpy(&ad_attr->model_descr, &ad_attr->model,
+                     BFA_ADAPTER_MODEL_NAME_LEN);
+
+       ad_attr->pwwn = bfa_ioc_get_pwwn(ioc);
+       ad_attr->mac = bfa_ioc_get_mac(ioc);
+
+       ad_attr->pcie_gen = ioc_attr->pcie_gen;
+       ad_attr->pcie_lanes = ioc_attr->pcie_lanes;
+       ad_attr->pcie_lanes_orig = ioc_attr->pcie_lanes_orig;
+       ad_attr->asic_rev = ioc_attr->asic_rev;
+       ad_attr->hw_ver[0] = 'R';
+       ad_attr->hw_ver[1] = 'e';
+       ad_attr->hw_ver[2] = 'v';
+       ad_attr->hw_ver[3] = '-';
+       ad_attr->hw_ver[4] = ioc_attr->asic_rev;
+       ad_attr->hw_ver[5] = '\0';
+
+       ad_attr->cna_capable = ioc->cna;
+}
+
+void
+bfa_ioc_get_attr(struct bfa_ioc_s *ioc, struct bfa_ioc_attr_s *ioc_attr)
+{
+       bfa_os_memset((void *)ioc_attr, 0, sizeof(struct bfa_ioc_attr_s));
+
+       ioc_attr->state = bfa_sm_to_state(ioc_sm_table, ioc->fsm);
+       ioc_attr->port_id = ioc->port_id;
+
+       if (!ioc->ctdev)
+               ioc_attr->ioc_type = BFA_IOC_TYPE_FC;
+       else if (ioc->ioc_mc == BFI_MC_IOCFC)
+               ioc_attr->ioc_type = BFA_IOC_TYPE_FCoE;
+       else if (ioc->ioc_mc == BFI_MC_LL)
+               ioc_attr->ioc_type = BFA_IOC_TYPE_LL;
+
+       bfa_ioc_get_adapter_attr(ioc, &ioc_attr->adapter_attr);
+
+       ioc_attr->pci_attr.device_id = ioc->pcidev.device_id;
+       ioc_attr->pci_attr.pcifn = ioc->pcidev.pci_func;
+       ioc_attr->pci_attr.chip_rev[0] = 'R';
+       ioc_attr->pci_attr.chip_rev[1] = 'e';
+       ioc_attr->pci_attr.chip_rev[2] = 'v';
+       ioc_attr->pci_attr.chip_rev[3] = '-';
+       ioc_attr->pci_attr.chip_rev[4] = ioc_attr->adapter_attr.asic_rev;
+       ioc_attr->pci_attr.chip_rev[5] = '\0';
+}
+
+/**
+ *  hal_wwn_public
+ */
+wwn_t
+bfa_ioc_get_pwwn(struct bfa_ioc_s *ioc)
+{
+       union {
+               wwn_t           wwn;
+               u8         byte[sizeof(wwn_t)];
+       }
+       w;
+
+       w.wwn = ioc->attr->mfg_wwn;
+
+       if (bfa_ioc_portid(ioc) == 1)
+               w.byte[7]++;
+
+       return w.wwn;
+}
+
+wwn_t
+bfa_ioc_get_nwwn(struct bfa_ioc_s *ioc)
+{
+       union {
+               wwn_t           wwn;
+               u8         byte[sizeof(wwn_t)];
+       }
+       w;
+
+       w.wwn = ioc->attr->mfg_wwn;
+
+       if (bfa_ioc_portid(ioc) == 1)
+               w.byte[7]++;
+
+       w.byte[0] = 0x20;
+
+       return w.wwn;
+}
+
+wwn_t
+bfa_ioc_get_wwn_naa5(struct bfa_ioc_s *ioc, u16 inst)
+{
+       union {
+               wwn_t           wwn;
+               u8         byte[sizeof(wwn_t)];
+       }
+       w              , w5;
+
+       bfa_trc(ioc, inst);
+
+       w.wwn = ioc->attr->mfg_wwn;
+       w5.byte[0] = 0x50 | w.byte[2] >> 4;
+       w5.byte[1] = w.byte[2] << 4 | w.byte[3] >> 4;
+       w5.byte[2] = w.byte[3] << 4 | w.byte[4] >> 4;
+       w5.byte[3] = w.byte[4] << 4 | w.byte[5] >> 4;
+       w5.byte[4] = w.byte[5] << 4 | w.byte[6] >> 4;
+       w5.byte[5] = w.byte[6] << 4 | w.byte[7] >> 4;
+       w5.byte[6] = w.byte[7] << 4 | (inst & 0x0f00) >> 8;
+       w5.byte[7] = (inst & 0xff);
+
+       return w5.wwn;
+}
+
+u64
+bfa_ioc_get_adid(struct bfa_ioc_s *ioc)
+{
+       return ioc->attr->mfg_wwn;
+}
+
+mac_t
+bfa_ioc_get_mac(struct bfa_ioc_s *ioc)
+{
+       mac_t           mac;
+
+       mac = ioc->attr->mfg_mac;
+       mac.mac[MAC_ADDRLEN - 1] += bfa_ioc_pcifn(ioc);
+
+       return mac;
+}
+
+void
+bfa_ioc_set_fcmode(struct bfa_ioc_s *ioc)
+{
+       ioc->fcmode = BFA_TRUE;
+       ioc->port_id = bfa_ioc_pcifn(ioc);
+}
+
+bfa_boolean_t
+bfa_ioc_get_fcmode(struct bfa_ioc_s *ioc)
+{
+       return ioc->fcmode || (ioc->pcidev.device_id != BFA_PCI_DEVICE_ID_CT);
+}
+
+/**
+ * Return true if interrupt should be claimed.
+ */
+bfa_boolean_t
+bfa_ioc_intx_claim(struct bfa_ioc_s *ioc)
+{
+       u32        isr, msk;
+
+       /**
+        * Always claim if not catapult.
+        */
+       if (!ioc->ctdev)
+               return BFA_TRUE;
+
+       /**
+        * FALSE if next device is claiming interrupt.
+        * TRUE if next device is not interrupting or not present.
+        */
+       msk = bfa_reg_read(ioc->ioc_regs.shirq_msk_next);
+       isr = bfa_reg_read(ioc->ioc_regs.shirq_isr_next);
+       return !(isr & ~msk);
+}
+
+/**
+ * Send AEN notification
+ */
+static void
+bfa_ioc_aen_post(struct bfa_ioc_s *ioc, enum bfa_ioc_aen_event event)
+{
+       union bfa_aen_data_u aen_data;
+       struct bfa_log_mod_s *logmod = ioc->logm;
+       s32         inst_num = 0;
+       struct bfa_ioc_attr_s ioc_attr;
+
+       switch (event) {
+       case BFA_IOC_AEN_HBGOOD:
+               bfa_log(logmod, BFA_AEN_IOC_HBGOOD, inst_num);
+               break;
+       case BFA_IOC_AEN_HBFAIL:
+               bfa_log(logmod, BFA_AEN_IOC_HBFAIL, inst_num);
+               break;
+       case BFA_IOC_AEN_ENABLE:
+               bfa_log(logmod, BFA_AEN_IOC_ENABLE, inst_num);
+               break;
+       case BFA_IOC_AEN_DISABLE:
+               bfa_log(logmod, BFA_AEN_IOC_DISABLE, inst_num);
+               break;
+       case BFA_IOC_AEN_FWMISMATCH:
+               bfa_log(logmod, BFA_AEN_IOC_FWMISMATCH, inst_num);
+               break;
+       default:
+               break;
+       }
+
+       memset(&aen_data.ioc.pwwn, 0, sizeof(aen_data.ioc.pwwn));
+       memset(&aen_data.ioc.mac, 0, sizeof(aen_data.ioc.mac));
+       bfa_ioc_get_attr(ioc, &ioc_attr);
+       switch (ioc_attr.ioc_type) {
+       case BFA_IOC_TYPE_FC:
+               aen_data.ioc.pwwn = bfa_ioc_get_pwwn(ioc);
+               break;
+       case BFA_IOC_TYPE_FCoE:
+               aen_data.ioc.pwwn = bfa_ioc_get_pwwn(ioc);
+               aen_data.ioc.mac = bfa_ioc_get_mac(ioc);
+               break;
+       case BFA_IOC_TYPE_LL:
+               aen_data.ioc.mac = bfa_ioc_get_mac(ioc);
+               break;
+       default:
+               bfa_assert(ioc_attr.ioc_type == BFA_IOC_TYPE_FC);
+               break;
+       }
+       aen_data.ioc.ioc_type = ioc_attr.ioc_type;
+}
+
+/**
+ * Retrieve saved firmware trace from a prior IOC failure.
+ */
+bfa_status_t
+bfa_ioc_debug_fwsave(struct bfa_ioc_s *ioc, void *trcdata, int *trclen)
+{
+       int             tlen;
+
+       if (ioc->dbg_fwsave_len == 0)
+               return BFA_STATUS_ENOFSAVE;
+
+       tlen = *trclen;
+       if (tlen > ioc->dbg_fwsave_len)
+               tlen = ioc->dbg_fwsave_len;
+
+       bfa_os_memcpy(trcdata, ioc->dbg_fwsave, tlen);
+       *trclen = tlen;
+       return BFA_STATUS_OK;
+}
+
+/**
+ * Retrieve saved firmware trace from a prior IOC failure.
+ */
+bfa_status_t
+bfa_ioc_debug_fwtrc(struct bfa_ioc_s *ioc, void *trcdata, int *trclen)
+{
+       u32        pgnum;
+       u32        loff = BFA_DBG_FWTRC_OFF(bfa_ioc_portid(ioc));
+       int             i, tlen;
+       u32       *tbuf = trcdata, r32;
+
+       bfa_trc(ioc, *trclen);
+
+       pgnum = bfa_ioc_smem_pgnum(ioc, loff);
+       loff = bfa_ioc_smem_pgoff(ioc, loff);
+       bfa_reg_write(ioc->ioc_regs.host_page_num_fn, pgnum);
+
+       tlen = *trclen;
+       if (tlen > BFA_DBG_FWTRC_LEN)
+               tlen = BFA_DBG_FWTRC_LEN;
+       tlen /= sizeof(u32);
+
+       bfa_trc(ioc, tlen);
+
+       for (i = 0; i < tlen; i++) {
+               r32 = bfa_mem_read(ioc->ioc_regs.smem_page_start, loff);
+               tbuf[i] = bfa_os_ntohl(r32);
+               loff += sizeof(u32);
+
+               /**
+                * handle page offset wrap around
+                */
+               loff = PSS_SMEM_PGOFF(loff);
+               if (loff == 0) {
+                       pgnum++;
+                       bfa_reg_write(ioc->ioc_regs.host_page_num_fn, pgnum);
+               }
+       }
+       bfa_reg_write(ioc->ioc_regs.host_page_num_fn,
+                     bfa_ioc_smem_pgnum(ioc, 0));
+       bfa_trc(ioc, pgnum);
+
+       *trclen = tlen * sizeof(u32);
+       return BFA_STATUS_OK;
+}
+
+/**
+ * Save firmware trace if configured.
+ */
+static void
+bfa_ioc_debug_save(struct bfa_ioc_s *ioc)
+{
+       int             tlen;
+
+       if (ioc->dbg_fwsave_len) {
+               tlen = ioc->dbg_fwsave_len;
+               bfa_ioc_debug_fwtrc(ioc, ioc->dbg_fwsave, &tlen);
+       }
+}
+
+/**
+ * Firmware failure detected. Start recovery actions.
+ */
+static void
+bfa_ioc_recover(struct bfa_ioc_s *ioc)
+{
+       if (ioc->dbg_fwsave_once) {
+               ioc->dbg_fwsave_once = BFA_FALSE;
+               bfa_ioc_debug_save(ioc);
+       }
+
+       bfa_ioc_stats(ioc, ioc_hbfails);
+       bfa_fsm_send_event(ioc, IOC_E_HBFAIL);
+}
+
+#else
+
+static void
+bfa_ioc_aen_post(struct bfa_ioc_s *ioc, enum bfa_ioc_aen_event event)
+{
+}
+
+static void
+bfa_ioc_recover(struct bfa_ioc_s *ioc)
+{
+       bfa_assert(0);
+}
+
+#endif
+
+
diff --git a/drivers/scsi/bfa/bfa_ioc.h b/drivers/scsi/bfa/bfa_ioc.h
new file mode 100644 (file)
index 0000000..58efd4b
--- /dev/null
@@ -0,0 +1,259 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ */
+
+#ifndef __BFA_IOC_H__
+#define __BFA_IOC_H__
+
+#include <cs/bfa_sm.h>
+#include <bfi/bfi.h>
+#include <bfi/bfi_ioc.h>
+#include <bfi/bfi_boot.h>
+#include <bfa_timer.h>
+
+/**
+ * PCI device information required by IOC
+ */
+struct bfa_pcidev_s {
+       int             pci_slot;
+       u8         pci_func;
+       u16     device_id;
+       bfa_os_addr_t   pci_bar_kva;
+};
+
+/**
+ * Structure used to remember the DMA-able memory block's KVA and Physical
+ * Address
+ */
+struct bfa_dma_s {
+       void            *kva;   /*! Kernel virtual address      */
+       u64     pa;     /*! Physical address            */
+};
+
+#define BFA_DMA_ALIGN_SZ       256
+#define BFA_ROUNDUP(_l, _s)    (((_l) + ((_s) - 1)) & ~((_s) - 1))
+
+
+
+#define bfa_dma_addr_set(dma_addr, pa) \
+               __bfa_dma_addr_set(&dma_addr, (u64)pa)
+
+static inline void
+__bfa_dma_addr_set(union bfi_addr_u *dma_addr, u64 pa)
+{
+       dma_addr->a32.addr_lo = (u32) pa;
+       dma_addr->a32.addr_hi = (u32) (bfa_os_u32(pa));
+}
+
+
+#define bfa_dma_be_addr_set(dma_addr, pa)      \
+               __bfa_dma_be_addr_set(&dma_addr, (u64)pa)
+static inline void
+__bfa_dma_be_addr_set(union bfi_addr_u *dma_addr, u64 pa)
+{
+       dma_addr->a32.addr_lo = (u32) bfa_os_htonl(pa);
+       dma_addr->a32.addr_hi = (u32) bfa_os_htonl(bfa_os_u32(pa));
+}
+
+struct bfa_ioc_regs_s {
+       bfa_os_addr_t   hfn_mbox_cmd;
+       bfa_os_addr_t   hfn_mbox;
+       bfa_os_addr_t   lpu_mbox_cmd;
+       bfa_os_addr_t   lpu_mbox;
+       bfa_os_addr_t   pss_ctl_reg;
+       bfa_os_addr_t   app_pll_fast_ctl_reg;
+       bfa_os_addr_t   app_pll_slow_ctl_reg;
+       bfa_os_addr_t   ioc_sem_reg;
+       bfa_os_addr_t   ioc_usage_sem_reg;
+       bfa_os_addr_t   ioc_usage_reg;
+       bfa_os_addr_t   host_page_num_fn;
+       bfa_os_addr_t   heartbeat;
+       bfa_os_addr_t   ioc_fwstate;
+       bfa_os_addr_t   ll_halt;
+       bfa_os_addr_t   shirq_isr_next;
+       bfa_os_addr_t   shirq_msk_next;
+       bfa_os_addr_t   smem_page_start;
+       u32     smem_pg0;
+};
+
+#define bfa_reg_read(_raddr)   bfa_os_reg_read(_raddr)
+#define bfa_reg_write(_raddr, _val)    bfa_os_reg_write(_raddr, _val)
+#define bfa_mem_read(_raddr, _off)     bfa_os_mem_read(_raddr, _off)
+#define bfa_mem_write(_raddr, _off, _val)      \
+                                       bfa_os_mem_write(_raddr, _off, _val)
+/**
+ * IOC Mailbox structures
+ */
+struct bfa_mbox_cmd_s {
+       struct list_head                qe;
+       u32     msg[BFI_IOC_MSGSZ];
+};
+
+/**
+ * IOC mailbox module
+ */
+typedef void (*bfa_ioc_mbox_mcfunc_t)(void *cbarg, struct bfi_mbmsg_s *m);
+struct bfa_ioc_mbox_mod_s {
+       struct list_head        cmd_q;          /*  pending mbox queue  */
+       int             nmclass;        /*  number of handlers */
+       struct {
+               bfa_ioc_mbox_mcfunc_t   cbfn;   /*  message handlers    */
+               void                    *cbarg;
+       } mbhdlr[BFI_MC_MAX];
+};
+
+/**
+ * IOC callback function interfaces
+ */
+typedef void (*bfa_ioc_enable_cbfn_t)(void *bfa, enum bfa_status status);
+typedef void (*bfa_ioc_disable_cbfn_t)(void *bfa);
+typedef void (*bfa_ioc_hbfail_cbfn_t)(void *bfa);
+typedef void (*bfa_ioc_reset_cbfn_t)(void *bfa);
+struct bfa_ioc_cbfn_s {
+       bfa_ioc_enable_cbfn_t   enable_cbfn;
+       bfa_ioc_disable_cbfn_t  disable_cbfn;
+       bfa_ioc_hbfail_cbfn_t   hbfail_cbfn;
+       bfa_ioc_reset_cbfn_t    reset_cbfn;
+};
+
+/**
+ * Heartbeat failure notification queue element.
+ */
+struct bfa_ioc_hbfail_notify_s {
+       struct list_head                qe;
+       bfa_ioc_hbfail_cbfn_t   cbfn;
+       void                    *cbarg;
+};
+
+/**
+ * Initialize a heartbeat failure notification structure
+ */
+#define bfa_ioc_hbfail_init(__notify, __cbfn, __cbarg) do {    \
+       (__notify)->cbfn = (__cbfn);      \
+       (__notify)->cbarg = (__cbarg);      \
+} while (0)
+
+struct bfa_ioc_s {
+       bfa_fsm_t               fsm;
+       struct bfa_s            *bfa;
+       struct bfa_pcidev_s     pcidev;
+       struct bfa_timer_mod_s  *timer_mod;
+       struct bfa_timer_s      ioc_timer;
+       struct bfa_timer_s      sem_timer;
+       u32             hb_count;
+       u32             hb_fail;
+       u32             retry_count;
+       struct list_head                hb_notify_q;
+       void                    *dbg_fwsave;
+       int                     dbg_fwsave_len;
+       bfa_boolean_t           dbg_fwsave_once;
+       enum bfi_mclass         ioc_mc;
+       struct bfa_ioc_regs_s   ioc_regs;
+       struct bfa_trc_mod_s    *trcmod;
+       struct bfa_aen_s        *aen;
+       struct bfa_log_mod_s    *logm;
+       struct bfa_ioc_drv_stats_s      stats;
+       bfa_boolean_t           auto_recover;
+       bfa_boolean_t           fcmode;
+       bfa_boolean_t           ctdev;
+       bfa_boolean_t           cna;
+       bfa_boolean_t           pllinit;
+       u8                      port_id;
+
+       struct bfa_dma_s        attr_dma;
+       struct bfi_ioc_attr_s   *attr;
+       struct bfa_ioc_cbfn_s   *cbfn;
+       struct bfa_ioc_mbox_mod_s mbox_mod;
+};
+
+#define bfa_ioc_pcifn(__ioc)           (__ioc)->pcidev.pci_func
+#define bfa_ioc_devid(__ioc)           (__ioc)->pcidev.device_id
+#define bfa_ioc_bar0(__ioc)            (__ioc)->pcidev.pci_bar_kva
+#define bfa_ioc_portid(__ioc)          ((__ioc)->port_id)
+#define bfa_ioc_fetch_stats(__ioc, __stats) \
+               ((__stats)->drv_stats) = (__ioc)->stats
+#define bfa_ioc_clr_stats(__ioc)       \
+               bfa_os_memset(&(__ioc)->stats, 0, sizeof((__ioc)->stats))
+#define bfa_ioc_maxfrsize(__ioc)       (__ioc)->attr->maxfrsize
+#define bfa_ioc_rx_bbcredit(__ioc)     (__ioc)->attr->rx_bbcredit
+#define bfa_ioc_speed_sup(__ioc)       \
+       BFI_ADAPTER_GETP(SPEED, (__ioc)->attr->adapter_prop)
+
+/**
+ * IOC mailbox interface
+ */
+void bfa_ioc_mbox_queue(struct bfa_ioc_s *ioc, struct bfa_mbox_cmd_s *cmd);
+void bfa_ioc_mbox_register(struct bfa_ioc_s *ioc,
+               bfa_ioc_mbox_mcfunc_t *mcfuncs);
+void bfa_ioc_mbox_isr(struct bfa_ioc_s *ioc);
+void bfa_ioc_mbox_send(struct bfa_ioc_s *ioc, void *ioc_msg, int len);
+void bfa_ioc_msgget(struct bfa_ioc_s *ioc, void *mbmsg);
+void bfa_ioc_mbox_regisr(struct bfa_ioc_s *ioc, enum bfi_mclass mc,
+               bfa_ioc_mbox_mcfunc_t cbfn, void *cbarg);
+
+/**
+ * IOC interfaces
+ */
+void bfa_ioc_attach(struct bfa_ioc_s *ioc, void *bfa,
+               struct bfa_ioc_cbfn_s *cbfn, struct bfa_timer_mod_s *timer_mod,
+               struct bfa_trc_mod_s *trcmod,
+               struct bfa_aen_s *aen, struct bfa_log_mod_s *logm);
+void bfa_ioc_detach(struct bfa_ioc_s *ioc);
+void bfa_ioc_pci_init(struct bfa_ioc_s *ioc, struct bfa_pcidev_s *pcidev,
+               enum bfi_mclass mc);
+u32 bfa_ioc_meminfo(void);
+void bfa_ioc_mem_claim(struct bfa_ioc_s *ioc,  u8 *dm_kva, u64 dm_pa);
+void bfa_ioc_enable(struct bfa_ioc_s *ioc);
+void bfa_ioc_disable(struct bfa_ioc_s *ioc);
+bfa_boolean_t bfa_ioc_intx_claim(struct bfa_ioc_s *ioc);
+
+void bfa_ioc_boot(struct bfa_ioc_s *ioc, u32 boot_type, u32 boot_param);
+void bfa_ioc_isr(struct bfa_ioc_s *ioc, struct bfi_mbmsg_s *msg);
+void bfa_ioc_error_isr(struct bfa_ioc_s *ioc);
+void bfa_ioc_isr_mode_set(struct bfa_ioc_s *ioc, bfa_boolean_t intx);
+bfa_status_t bfa_ioc_pll_init(struct bfa_ioc_s *ioc);
+bfa_boolean_t bfa_ioc_is_operational(struct bfa_ioc_s *ioc);
+bfa_boolean_t bfa_ioc_is_disabled(struct bfa_ioc_s *ioc);
+bfa_boolean_t bfa_ioc_fw_mismatch(struct bfa_ioc_s *ioc);
+bfa_boolean_t bfa_ioc_adapter_is_disabled(struct bfa_ioc_s *ioc);
+void bfa_ioc_cfg_complete(struct bfa_ioc_s *ioc);
+void bfa_ioc_get_attr(struct bfa_ioc_s *ioc, struct bfa_ioc_attr_s *ioc_attr);
+void bfa_ioc_get_adapter_attr(struct bfa_ioc_s *ioc,
+               struct bfa_adapter_attr_s *ad_attr);
+int bfa_ioc_debug_trcsz(bfa_boolean_t auto_recover);
+void bfa_ioc_debug_memclaim(struct bfa_ioc_s *ioc, void *dbg_fwsave);
+bfa_status_t bfa_ioc_debug_fwsave(struct bfa_ioc_s *ioc, void *trcdata,
+               int *trclen);
+bfa_status_t bfa_ioc_debug_fwtrc(struct bfa_ioc_s *ioc, void *trcdata,
+                                int *trclen);
+u32 bfa_ioc_smem_pgnum(struct bfa_ioc_s *ioc, u32 fmaddr);
+u32 bfa_ioc_smem_pgoff(struct bfa_ioc_s *ioc, u32 fmaddr);
+void bfa_ioc_set_fcmode(struct bfa_ioc_s *ioc);
+bfa_boolean_t bfa_ioc_get_fcmode(struct bfa_ioc_s *ioc);
+void bfa_ioc_hbfail_register(struct bfa_ioc_s *ioc,
+       struct bfa_ioc_hbfail_notify_s *notify);
+
+/*
+ * bfa mfg wwn API functions
+ */
+wwn_t bfa_ioc_get_pwwn(struct bfa_ioc_s *ioc);
+wwn_t bfa_ioc_get_nwwn(struct bfa_ioc_s *ioc);
+wwn_t bfa_ioc_get_wwn_naa5(struct bfa_ioc_s *ioc, u16 inst);
+mac_t bfa_ioc_get_mac(struct bfa_ioc_s *ioc);
+u64 bfa_ioc_get_adid(struct bfa_ioc_s *ioc);
+
+#endif /* __BFA_IOC_H__ */
+
diff --git a/drivers/scsi/bfa/bfa_iocfc.c b/drivers/scsi/bfa/bfa_iocfc.c
new file mode 100644 (file)
index 0000000..12350b0
--- /dev/null
@@ -0,0 +1,872 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ */
+
+#include <cs/bfa_debug.h>
+#include <bfa_priv.h>
+#include <log/bfa_log_hal.h>
+#include <bfi/bfi_boot.h>
+#include <bfi/bfi_cbreg.h>
+#include <aen/bfa_aen_ioc.h>
+#include <defs/bfa_defs_iocfc.h>
+#include <defs/bfa_defs_pci.h>
+#include "bfa_callback_priv.h"
+#include "bfad_drv.h"
+
+BFA_TRC_FILE(HAL, IOCFC);
+
+/**
+ * IOC local definitions
+ */
+#define BFA_IOCFC_TOV          5000    /* msecs */
+
+enum {
+       BFA_IOCFC_ACT_NONE      = 0,
+       BFA_IOCFC_ACT_INIT      = 1,
+       BFA_IOCFC_ACT_STOP      = 2,
+       BFA_IOCFC_ACT_DISABLE   = 3,
+};
+
+/*
+ * forward declarations
+ */
+static void bfa_iocfc_enable_cbfn(void *bfa_arg, enum bfa_status status);
+static void bfa_iocfc_disable_cbfn(void *bfa_arg);
+static void bfa_iocfc_hbfail_cbfn(void *bfa_arg);
+static void bfa_iocfc_reset_cbfn(void *bfa_arg);
+static void bfa_iocfc_stats_clear(void *bfa_arg);
+static void bfa_iocfc_stats_swap(struct bfa_fw_stats_s *d,
+                       struct bfa_fw_stats_s *s);
+static void bfa_iocfc_stats_clr_cb(void *bfa_arg, bfa_boolean_t complete);
+static void bfa_iocfc_stats_clr_timeout(void *bfa_arg);
+static void bfa_iocfc_stats_cb(void *bfa_arg, bfa_boolean_t complete);
+static void bfa_iocfc_stats_timeout(void *bfa_arg);
+
+static struct bfa_ioc_cbfn_s bfa_iocfc_cbfn;
+
+/**
+ *  bfa_ioc_pvt BFA IOC private functions
+ */
+
+static void
+bfa_iocfc_cqs_sz(struct bfa_iocfc_cfg_s *cfg, u32 *dm_len)
+{
+       int             i, per_reqq_sz, per_rspq_sz;
+
+       per_reqq_sz = BFA_ROUNDUP((cfg->drvcfg.num_reqq_elems * BFI_LMSG_SZ),
+                                                       BFA_DMA_ALIGN_SZ);
+       per_rspq_sz = BFA_ROUNDUP((cfg->drvcfg.num_rspq_elems * BFI_LMSG_SZ),
+                                                       BFA_DMA_ALIGN_SZ);
+
+       /*
+        * Calculate CQ size
+        */
+       for (i = 0; i < cfg->fwcfg.num_cqs; i++) {
+               *dm_len = *dm_len + per_reqq_sz;
+               *dm_len = *dm_len + per_rspq_sz;
+       }
+
+       /*
+        * Calculate Shadow CI/PI size
+        */
+       for (i = 0; i < cfg->fwcfg.num_cqs; i++)
+               *dm_len += (2 * BFA_CACHELINE_SZ);
+}
+
+static void
+bfa_iocfc_fw_cfg_sz(struct bfa_iocfc_cfg_s *cfg, u32 *dm_len)
+{
+       *dm_len +=
+               BFA_ROUNDUP(sizeof(struct bfi_iocfc_cfg_s), BFA_CACHELINE_SZ);
+       *dm_len +=
+               BFA_ROUNDUP(sizeof(struct bfi_iocfc_cfgrsp_s),
+                           BFA_CACHELINE_SZ);
+       *dm_len += BFA_ROUNDUP(sizeof(struct bfa_fw_stats_s), BFA_CACHELINE_SZ);
+}
+
+/**
+ * Use the Mailbox interface to send BFI_IOCFC_H2I_CFG_REQ
+ */
+static void
+bfa_iocfc_send_cfg(void *bfa_arg)
+{
+       struct bfa_s *bfa = bfa_arg;
+       struct bfa_iocfc_s *iocfc = &bfa->iocfc;
+       struct bfi_iocfc_cfg_req_s cfg_req;
+       struct bfi_iocfc_cfg_s *cfg_info = iocfc->cfginfo;
+       struct bfa_iocfc_cfg_s  *cfg = &iocfc->cfg;
+       int             i;
+
+       bfa_assert(cfg->fwcfg.num_cqs <= BFI_IOC_MAX_CQS);
+       bfa_trc(bfa, cfg->fwcfg.num_cqs);
+
+       iocfc->cfgdone = BFA_FALSE;
+       bfa_iocfc_reset_queues(bfa);
+
+       /**
+        * initialize IOC configuration info
+        */
+       cfg_info->endian_sig = BFI_IOC_ENDIAN_SIG;
+       cfg_info->num_cqs = cfg->fwcfg.num_cqs;
+
+       bfa_dma_be_addr_set(cfg_info->cfgrsp_addr, iocfc->cfgrsp_dma.pa);
+       bfa_dma_be_addr_set(cfg_info->stats_addr, iocfc->stats_pa);
+
+       /**
+        * dma map REQ and RSP circular queues and shadow pointers
+        */
+       for (i = 0; i < cfg->fwcfg.num_cqs; i++) {
+               bfa_dma_be_addr_set(cfg_info->req_cq_ba[i],
+                                      iocfc->req_cq_ba[i].pa);
+               bfa_dma_be_addr_set(cfg_info->req_shadow_ci[i],
+                                      iocfc->req_cq_shadow_ci[i].pa);
+               cfg_info->req_cq_elems[i] =
+                       bfa_os_htons(cfg->drvcfg.num_reqq_elems);
+
+               bfa_dma_be_addr_set(cfg_info->rsp_cq_ba[i],
+                                      iocfc->rsp_cq_ba[i].pa);
+               bfa_dma_be_addr_set(cfg_info->rsp_shadow_pi[i],
+                                      iocfc->rsp_cq_shadow_pi[i].pa);
+               cfg_info->rsp_cq_elems[i] =
+                       bfa_os_htons(cfg->drvcfg.num_rspq_elems);
+       }
+
+       /**
+        * dma map IOC configuration itself
+        */
+       bfi_h2i_set(cfg_req.mh, BFI_MC_IOCFC, BFI_IOCFC_H2I_CFG_REQ,
+                       bfa_lpuid(bfa));
+       bfa_dma_be_addr_set(cfg_req.ioc_cfg_dma_addr, iocfc->cfg_info.pa);
+
+       bfa_ioc_mbox_send(&bfa->ioc, &cfg_req,
+                       sizeof(struct bfi_iocfc_cfg_req_s));
+}
+
+static void
+bfa_iocfc_init_mem(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
+                   struct bfa_pcidev_s *pcidev)
+{
+       struct bfa_iocfc_s      *iocfc = &bfa->iocfc;
+
+       bfa->bfad = bfad;
+       iocfc->bfa = bfa;
+       iocfc->action = BFA_IOCFC_ACT_NONE;
+
+       bfa_os_assign(iocfc->cfg, *cfg);
+
+       /**
+        * Initialize chip specific handlers.
+        */
+       if (bfa_ioc_devid(&bfa->ioc) == BFA_PCI_DEVICE_ID_CT) {
+               iocfc->hwif.hw_reginit = bfa_hwct_reginit;
+               iocfc->hwif.hw_rspq_ack = bfa_hwct_rspq_ack;
+               iocfc->hwif.hw_msix_init = bfa_hwct_msix_init;
+               iocfc->hwif.hw_msix_install = bfa_hwct_msix_install;
+               iocfc->hwif.hw_msix_uninstall = bfa_hwct_msix_uninstall;
+               iocfc->hwif.hw_isr_mode_set = bfa_hwct_isr_mode_set;
+               iocfc->hwif.hw_msix_getvecs = bfa_hwct_msix_getvecs;
+       } else {
+               iocfc->hwif.hw_reginit = bfa_hwcb_reginit;
+               iocfc->hwif.hw_rspq_ack = bfa_hwcb_rspq_ack;
+               iocfc->hwif.hw_msix_init = bfa_hwcb_msix_init;
+               iocfc->hwif.hw_msix_install = bfa_hwcb_msix_install;
+               iocfc->hwif.hw_msix_uninstall = bfa_hwcb_msix_uninstall;
+               iocfc->hwif.hw_isr_mode_set = bfa_hwcb_isr_mode_set;
+               iocfc->hwif.hw_msix_getvecs = bfa_hwcb_msix_getvecs;
+       }
+
+       iocfc->hwif.hw_reginit(bfa);
+       bfa->msix.nvecs = 0;
+}
+
+static void
+bfa_iocfc_mem_claim(struct bfa_s *bfa, struct bfa_iocfc_cfg_s *cfg,
+                     struct bfa_meminfo_s *meminfo)
+{
+       u8        *dm_kva;
+       u64        dm_pa;
+       int             i, per_reqq_sz, per_rspq_sz;
+       struct bfa_iocfc_s  *iocfc = &bfa->iocfc;
+       int             dbgsz;
+
+       dm_kva = bfa_meminfo_dma_virt(meminfo);
+       dm_pa = bfa_meminfo_dma_phys(meminfo);
+
+       /*
+        * First allocate dma memory for IOC.
+        */
+       bfa_ioc_mem_claim(&bfa->ioc, dm_kva, dm_pa);
+       dm_kva += bfa_ioc_meminfo();
+       dm_pa  += bfa_ioc_meminfo();
+
+       /*
+        * Claim DMA-able memory for the request/response queues and for shadow
+        * ci/pi registers
+        */
+       per_reqq_sz = BFA_ROUNDUP((cfg->drvcfg.num_reqq_elems * BFI_LMSG_SZ),
+                                                       BFA_DMA_ALIGN_SZ);
+       per_rspq_sz = BFA_ROUNDUP((cfg->drvcfg.num_rspq_elems * BFI_LMSG_SZ),
+                                                       BFA_DMA_ALIGN_SZ);
+
+       for (i = 0; i < cfg->fwcfg.num_cqs; i++) {
+               iocfc->req_cq_ba[i].kva = dm_kva;
+               iocfc->req_cq_ba[i].pa = dm_pa;
+               bfa_os_memset(dm_kva, 0, per_reqq_sz);
+               dm_kva += per_reqq_sz;
+               dm_pa += per_reqq_sz;
+
+               iocfc->rsp_cq_ba[i].kva = dm_kva;
+               iocfc->rsp_cq_ba[i].pa = dm_pa;
+               bfa_os_memset(dm_kva, 0, per_rspq_sz);
+               dm_kva += per_rspq_sz;
+               dm_pa += per_rspq_sz;
+       }
+
+       for (i = 0; i < cfg->fwcfg.num_cqs; i++) {
+               iocfc->req_cq_shadow_ci[i].kva = dm_kva;
+               iocfc->req_cq_shadow_ci[i].pa = dm_pa;
+               dm_kva += BFA_CACHELINE_SZ;
+               dm_pa += BFA_CACHELINE_SZ;
+
+               iocfc->rsp_cq_shadow_pi[i].kva = dm_kva;
+               iocfc->rsp_cq_shadow_pi[i].pa = dm_pa;
+               dm_kva += BFA_CACHELINE_SZ;
+               dm_pa += BFA_CACHELINE_SZ;
+       }
+
+       /*
+        * Claim DMA-able memory for the config info page
+        */
+       bfa->iocfc.cfg_info.kva = dm_kva;
+       bfa->iocfc.cfg_info.pa = dm_pa;
+       bfa->iocfc.cfginfo = (struct bfi_iocfc_cfg_s *) dm_kva;
+       dm_kva += BFA_ROUNDUP(sizeof(struct bfi_iocfc_cfg_s), BFA_CACHELINE_SZ);
+       dm_pa += BFA_ROUNDUP(sizeof(struct bfi_iocfc_cfg_s), BFA_CACHELINE_SZ);
+
+       /*
+        * Claim DMA-able memory for the config response
+        */
+       bfa->iocfc.cfgrsp_dma.kva = dm_kva;
+       bfa->iocfc.cfgrsp_dma.pa = dm_pa;
+       bfa->iocfc.cfgrsp = (struct bfi_iocfc_cfgrsp_s *) dm_kva;
+
+       dm_kva +=
+               BFA_ROUNDUP(sizeof(struct bfi_iocfc_cfgrsp_s),
+                           BFA_CACHELINE_SZ);
+       dm_pa += BFA_ROUNDUP(sizeof(struct bfi_iocfc_cfgrsp_s),
+                            BFA_CACHELINE_SZ);
+
+       /*
+        * Claim DMA-able memory for iocfc stats
+        */
+       bfa->iocfc.stats_kva = dm_kva;
+       bfa->iocfc.stats_pa = dm_pa;
+       bfa->iocfc.fw_stats = (struct bfa_fw_stats_s *) dm_kva;
+       dm_kva += BFA_ROUNDUP(sizeof(struct bfa_fw_stats_s), BFA_CACHELINE_SZ);
+       dm_pa += BFA_ROUNDUP(sizeof(struct bfa_fw_stats_s), BFA_CACHELINE_SZ);
+
+       bfa_meminfo_dma_virt(meminfo) = dm_kva;
+       bfa_meminfo_dma_phys(meminfo) = dm_pa;
+
+       dbgsz = bfa_ioc_debug_trcsz(bfa_auto_recover);
+       if (dbgsz > 0) {
+               bfa_ioc_debug_memclaim(&bfa->ioc, bfa_meminfo_kva(meminfo));
+               bfa_meminfo_kva(meminfo) += dbgsz;
+       }
+}
+
+/**
+ * BFA submodules initialization completion notification.
+ */
+static void
+bfa_iocfc_initdone_submod(struct bfa_s *bfa)
+{
+       int             i;
+
+       for (i = 0; hal_mods[i]; i++)
+               hal_mods[i]->initdone(bfa);
+}
+
+/**
+ * Start BFA submodules.
+ */
+static void
+bfa_iocfc_start_submod(struct bfa_s *bfa)
+{
+       int             i;
+
+       bfa->rme_process = BFA_TRUE;
+
+       for (i = 0; hal_mods[i]; i++)
+               hal_mods[i]->start(bfa);
+}
+
+/**
+ * Disable BFA submodules.
+ */
+static void
+bfa_iocfc_disable_submod(struct bfa_s *bfa)
+{
+       int             i;
+
+       for (i = 0; hal_mods[i]; i++)
+               hal_mods[i]->iocdisable(bfa);
+}
+
+static void
+bfa_iocfc_init_cb(void *bfa_arg, bfa_boolean_t complete)
+{
+       struct bfa_s    *bfa = bfa_arg;
+
+       if (complete) {
+               if (bfa->iocfc.cfgdone)
+                       bfa_cb_init(bfa->bfad, BFA_STATUS_OK);
+               else
+                       bfa_cb_init(bfa->bfad, BFA_STATUS_FAILED);
+       } else
+               bfa->iocfc.action = BFA_IOCFC_ACT_NONE;
+}
+
+static void
+bfa_iocfc_stop_cb(void *bfa_arg, bfa_boolean_t compl)
+{
+       struct bfa_s  *bfa = bfa_arg;
+       struct bfad_s *bfad = bfa->bfad;
+
+       if (compl)
+               complete(&bfad->comp);
+
+       else
+               bfa->iocfc.action = BFA_IOCFC_ACT_NONE;
+}
+
+static void
+bfa_iocfc_disable_cb(void *bfa_arg, bfa_boolean_t compl)
+{
+       struct bfa_s  *bfa = bfa_arg;
+       struct bfad_s *bfad = bfa->bfad;
+
+       if (compl)
+               complete(&bfad->disable_comp);
+}
+
+/**
+ * Update BFA configuration from firmware configuration.
+ */
+static void
+bfa_iocfc_cfgrsp(struct bfa_s *bfa)
+{
+       struct bfa_iocfc_s              *iocfc   = &bfa->iocfc;
+       struct bfi_iocfc_cfgrsp_s       *cfgrsp  = iocfc->cfgrsp;
+       struct bfa_iocfc_fwcfg_s        *fwcfg   = &cfgrsp->fwcfg;
+       struct bfi_iocfc_cfg_s          *cfginfo = iocfc->cfginfo;
+
+       fwcfg->num_cqs        = fwcfg->num_cqs;
+       fwcfg->num_ioim_reqs  = bfa_os_ntohs(fwcfg->num_ioim_reqs);
+       fwcfg->num_tskim_reqs = bfa_os_ntohs(fwcfg->num_tskim_reqs);
+       fwcfg->num_fcxp_reqs  = bfa_os_ntohs(fwcfg->num_fcxp_reqs);
+       fwcfg->num_uf_bufs    = bfa_os_ntohs(fwcfg->num_uf_bufs);
+       fwcfg->num_rports     = bfa_os_ntohs(fwcfg->num_rports);
+
+       cfginfo->intr_attr.coalesce = cfgrsp->intr_attr.coalesce;
+       cfginfo->intr_attr.delay    = bfa_os_ntohs(cfgrsp->intr_attr.delay);
+       cfginfo->intr_attr.latency  = bfa_os_ntohs(cfgrsp->intr_attr.latency);
+
+       iocfc->cfgdone = BFA_TRUE;
+
+       /**
+        * Configuration is complete - initialize/start submodules
+        */
+       if (iocfc->action == BFA_IOCFC_ACT_INIT)
+               bfa_cb_queue(bfa, &iocfc->init_hcb_qe, bfa_iocfc_init_cb, bfa);
+       else
+               bfa_iocfc_start_submod(bfa);
+}
+
+static void
+bfa_iocfc_stats_clear(void *bfa_arg)
+{
+       struct bfa_s            *bfa = bfa_arg;
+       struct bfa_iocfc_s      *iocfc = &bfa->iocfc;
+       struct bfi_iocfc_stats_req_s stats_req;
+
+       bfa_timer_start(bfa, &iocfc->stats_timer,
+                           bfa_iocfc_stats_clr_timeout, bfa,
+                           BFA_IOCFC_TOV);
+
+       bfi_h2i_set(stats_req.mh, BFI_MC_IOCFC, BFI_IOCFC_H2I_CLEAR_STATS_REQ,
+               bfa_lpuid(bfa));
+       bfa_ioc_mbox_send(&bfa->ioc, &stats_req,
+               sizeof(struct bfi_iocfc_stats_req_s));
+}
+
+static void
+bfa_iocfc_stats_swap(struct bfa_fw_stats_s *d, struct bfa_fw_stats_s *s)
+{
+       u32       *dip = (u32 *) d;
+       u32       *sip = (u32 *) s;
+       int             i;
+
+       for (i = 0; i < (sizeof(struct bfa_fw_stats_s) / sizeof(u32)); i++)
+               dip[i] = bfa_os_ntohl(sip[i]);
+}
+
+static void
+bfa_iocfc_stats_clr_cb(void *bfa_arg, bfa_boolean_t complete)
+{
+       struct bfa_s *bfa = bfa_arg;
+       struct bfa_iocfc_s *iocfc = &bfa->iocfc;
+
+       if (complete) {
+               bfa_ioc_clr_stats(&bfa->ioc);
+               iocfc->stats_cbfn(iocfc->stats_cbarg, iocfc->stats_status);
+       } else {
+               iocfc->stats_busy = BFA_FALSE;
+               iocfc->stats_status = BFA_STATUS_OK;
+       }
+}
+
+static void
+bfa_iocfc_stats_clr_timeout(void *bfa_arg)
+{
+       struct bfa_s            *bfa = bfa_arg;
+       struct bfa_iocfc_s      *iocfc = &bfa->iocfc;
+
+       bfa_trc(bfa, 0);
+
+       iocfc->stats_status = BFA_STATUS_ETIMER;
+       bfa_cb_queue(bfa, &iocfc->stats_hcb_qe, bfa_iocfc_stats_clr_cb, bfa);
+}
+
+static void
+bfa_iocfc_stats_cb(void *bfa_arg, bfa_boolean_t complete)
+{
+       struct bfa_s            *bfa = bfa_arg;
+       struct bfa_iocfc_s      *iocfc = &bfa->iocfc;
+
+       if (complete) {
+               if (iocfc->stats_status == BFA_STATUS_OK) {
+                       bfa_os_memset(iocfc->stats_ret, 0,
+                               sizeof(*iocfc->stats_ret));
+                       bfa_iocfc_stats_swap(&iocfc->stats_ret->fw_stats,
+                               iocfc->fw_stats);
+               }
+               iocfc->stats_cbfn(iocfc->stats_cbarg, iocfc->stats_status);
+       } else {
+               iocfc->stats_busy = BFA_FALSE;
+               iocfc->stats_status = BFA_STATUS_OK;
+       }
+}
+
+static void
+bfa_iocfc_stats_timeout(void *bfa_arg)
+{
+       struct bfa_s            *bfa = bfa_arg;
+       struct bfa_iocfc_s      *iocfc = &bfa->iocfc;
+
+       bfa_trc(bfa, 0);
+
+       iocfc->stats_status = BFA_STATUS_ETIMER;
+       bfa_cb_queue(bfa, &iocfc->stats_hcb_qe, bfa_iocfc_stats_cb, bfa);
+}
+
+static void
+bfa_iocfc_stats_query(struct bfa_s *bfa)
+{
+       struct bfa_iocfc_s      *iocfc = &bfa->iocfc;
+       struct bfi_iocfc_stats_req_s stats_req;
+
+       bfa_timer_start(bfa, &iocfc->stats_timer,
+                           bfa_iocfc_stats_timeout, bfa, BFA_IOCFC_TOV);
+
+       bfi_h2i_set(stats_req.mh, BFI_MC_IOCFC, BFI_IOCFC_H2I_GET_STATS_REQ,
+                       bfa_lpuid(bfa));
+       bfa_ioc_mbox_send(&bfa->ioc, &stats_req,
+               sizeof(struct bfi_iocfc_stats_req_s));
+}
+
+void
+bfa_iocfc_reset_queues(struct bfa_s *bfa)
+{
+       int             q;
+
+       for (q = 0; q < BFI_IOC_MAX_CQS; q++) {
+               bfa_reqq_ci(bfa, q) = 0;
+               bfa_reqq_pi(bfa, q) = 0;
+               bfa_rspq_ci(bfa, q) = 0;
+               bfa_rspq_pi(bfa, q) = 0;
+       }
+}
+
+/**
+ * IOC enable request is complete
+ */
+static void
+bfa_iocfc_enable_cbfn(void *bfa_arg, enum bfa_status status)
+{
+       struct bfa_s    *bfa = bfa_arg;
+
+       if (status != BFA_STATUS_OK) {
+               bfa_isr_disable(bfa);
+               if (bfa->iocfc.action == BFA_IOCFC_ACT_INIT)
+                       bfa_cb_queue(bfa, &bfa->iocfc.init_hcb_qe,
+                                    bfa_iocfc_init_cb, bfa);
+               return;
+       }
+
+       bfa_iocfc_initdone_submod(bfa);
+       bfa_iocfc_send_cfg(bfa);
+}
+
+/**
+ * IOC disable request is complete
+ */
+static void
+bfa_iocfc_disable_cbfn(void *bfa_arg)
+{
+       struct bfa_s    *bfa = bfa_arg;
+
+       bfa_isr_disable(bfa);
+       bfa_iocfc_disable_submod(bfa);
+
+       if (bfa->iocfc.action == BFA_IOCFC_ACT_STOP)
+               bfa_cb_queue(bfa, &bfa->iocfc.stop_hcb_qe, bfa_iocfc_stop_cb,
+                            bfa);
+       else {
+               bfa_assert(bfa->iocfc.action == BFA_IOCFC_ACT_DISABLE);
+               bfa_cb_queue(bfa, &bfa->iocfc.dis_hcb_qe, bfa_iocfc_disable_cb,
+                            bfa);
+       }
+}
+
+/**
+ * Notify sub-modules of hardware failure.
+ */
+static void
+bfa_iocfc_hbfail_cbfn(void *bfa_arg)
+{
+       struct bfa_s    *bfa = bfa_arg;
+
+       bfa->rme_process = BFA_FALSE;
+
+       bfa_isr_disable(bfa);
+       bfa_iocfc_disable_submod(bfa);
+
+       if (bfa->iocfc.action == BFA_IOCFC_ACT_INIT)
+               bfa_cb_queue(bfa, &bfa->iocfc.init_hcb_qe, bfa_iocfc_init_cb,
+                            bfa);
+}
+
+/**
+ * Actions on chip-reset completion.
+ */
+static void
+bfa_iocfc_reset_cbfn(void *bfa_arg)
+{
+       struct bfa_s    *bfa = bfa_arg;
+
+       bfa_iocfc_reset_queues(bfa);
+       bfa_isr_enable(bfa);
+}
+
+
+
+/**
+ *  bfa_ioc_public
+ */
+
+/**
+ * Query IOC memory requirement information.
+ */
+void
+bfa_iocfc_meminfo(struct bfa_iocfc_cfg_s *cfg, u32 *km_len,
+               u32 *dm_len)
+{
+       /* dma memory for IOC */
+       *dm_len += bfa_ioc_meminfo();
+
+       bfa_iocfc_fw_cfg_sz(cfg, dm_len);
+       bfa_iocfc_cqs_sz(cfg, dm_len);
+       *km_len += bfa_ioc_debug_trcsz(bfa_auto_recover);
+}
+
+/**
+ * Query IOC memory requirement information.
+ */
+void
+bfa_iocfc_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
+                  struct bfa_meminfo_s *meminfo, struct bfa_pcidev_s *pcidev)
+{
+       int             i;
+
+       bfa_iocfc_cbfn.enable_cbfn = bfa_iocfc_enable_cbfn;
+       bfa_iocfc_cbfn.disable_cbfn = bfa_iocfc_disable_cbfn;
+       bfa_iocfc_cbfn.hbfail_cbfn = bfa_iocfc_hbfail_cbfn;
+       bfa_iocfc_cbfn.reset_cbfn = bfa_iocfc_reset_cbfn;
+
+       bfa_ioc_attach(&bfa->ioc, bfa, &bfa_iocfc_cbfn, &bfa->timer_mod,
+               bfa->trcmod, bfa->aen, bfa->logm);
+       bfa_ioc_pci_init(&bfa->ioc, pcidev, BFI_MC_IOCFC);
+       bfa_ioc_mbox_register(&bfa->ioc, bfa_mbox_isrs);
+
+       /**
+        * Choose FC (ssid: 0x1C) v/s FCoE (ssid: 0x14) mode.
+        */
+       if (0)
+               bfa_ioc_set_fcmode(&bfa->ioc);
+
+       bfa_iocfc_init_mem(bfa, bfad, cfg, pcidev);
+       bfa_iocfc_mem_claim(bfa, cfg, meminfo);
+       bfa_timer_init(&bfa->timer_mod);
+
+       INIT_LIST_HEAD(&bfa->comp_q);
+       for (i = 0; i < BFI_IOC_MAX_CQS; i++)
+               INIT_LIST_HEAD(&bfa->reqq_waitq[i]);
+}
+
+/**
+ * Query IOC memory requirement information.
+ */
+void
+bfa_iocfc_detach(struct bfa_s *bfa)
+{
+       bfa_ioc_detach(&bfa->ioc);
+}
+
+/**
+ * Query IOC memory requirement information.
+ */
+void
+bfa_iocfc_init(struct bfa_s *bfa)
+{
+       bfa->iocfc.action = BFA_IOCFC_ACT_INIT;
+       bfa_ioc_enable(&bfa->ioc);
+       bfa_msix_install(bfa);
+}
+
+/**
+ * IOC start called from bfa_start(). Called to start IOC operations
+ * at driver instantiation for this instance.
+ */
+void
+bfa_iocfc_start(struct bfa_s *bfa)
+{
+       if (bfa->iocfc.cfgdone)
+               bfa_iocfc_start_submod(bfa);
+}
+
+/**
+ * IOC stop called from bfa_stop(). Called only when driver is unloaded
+ * for this instance.
+ */
+void
+bfa_iocfc_stop(struct bfa_s *bfa)
+{
+       bfa->iocfc.action = BFA_IOCFC_ACT_STOP;
+
+       bfa->rme_process = BFA_FALSE;
+       bfa_ioc_disable(&bfa->ioc);
+}
+
+void
+bfa_iocfc_isr(void *bfaarg, struct bfi_mbmsg_s *m)
+{
+       struct bfa_s            *bfa = bfaarg;
+       struct bfa_iocfc_s      *iocfc = &bfa->iocfc;
+       union bfi_iocfc_i2h_msg_u       *msg;
+
+       msg = (union bfi_iocfc_i2h_msg_u *) m;
+       bfa_trc(bfa, msg->mh.msg_id);
+
+       switch (msg->mh.msg_id) {
+       case BFI_IOCFC_I2H_CFG_REPLY:
+               iocfc->cfg_reply = &msg->cfg_reply;
+               bfa_iocfc_cfgrsp(bfa);
+               break;
+
+       case BFI_IOCFC_I2H_GET_STATS_RSP:
+               if (iocfc->stats_busy == BFA_FALSE
+                   || iocfc->stats_status == BFA_STATUS_ETIMER)
+                       break;
+
+               bfa_timer_stop(&iocfc->stats_timer);
+               iocfc->stats_status = BFA_STATUS_OK;
+               bfa_cb_queue(bfa, &iocfc->stats_hcb_qe, bfa_iocfc_stats_cb,
+                             bfa);
+               break;
+       case BFI_IOCFC_I2H_CLEAR_STATS_RSP:
+               /*
+                * check for timer pop before processing the rsp
+                */
+               if (iocfc->stats_busy == BFA_FALSE
+                   || iocfc->stats_status == BFA_STATUS_ETIMER)
+                       break;
+
+               bfa_timer_stop(&iocfc->stats_timer);
+               iocfc->stats_status = BFA_STATUS_OK;
+               bfa_cb_queue(bfa, &iocfc->stats_hcb_qe,
+                             bfa_iocfc_stats_clr_cb, bfa);
+               break;
+       case BFI_IOCFC_I2H_UPDATEQ_RSP:
+               iocfc->updateq_cbfn(iocfc->updateq_cbarg, BFA_STATUS_OK);
+               break;
+       default:
+               bfa_assert(0);
+       }
+}
+
+#ifndef BFA_BIOS_BUILD
+void
+bfa_adapter_get_attr(struct bfa_s *bfa, struct bfa_adapter_attr_s *ad_attr)
+{
+       bfa_ioc_get_adapter_attr(&bfa->ioc, ad_attr);
+}
+
+u64
+bfa_adapter_get_id(struct bfa_s *bfa)
+{
+       return bfa_ioc_get_adid(&bfa->ioc);
+}
+
+void
+bfa_iocfc_get_attr(struct bfa_s *bfa, struct bfa_iocfc_attr_s *attr)
+{
+       struct bfa_iocfc_s      *iocfc = &bfa->iocfc;
+
+       attr->intr_attr = iocfc->cfginfo->intr_attr;
+       attr->config    = iocfc->cfg;
+}
+
+bfa_status_t
+bfa_iocfc_israttr_set(struct bfa_s *bfa, struct bfa_iocfc_intr_attr_s *attr)
+{
+       struct bfa_iocfc_s              *iocfc = &bfa->iocfc;
+       struct bfi_iocfc_set_intr_req_s *m;
+
+       iocfc->cfginfo->intr_attr = *attr;
+       if (!bfa_iocfc_is_operational(bfa))
+               return BFA_STATUS_OK;
+
+       m = bfa_reqq_next(bfa, BFA_REQQ_IOC);
+       if (!m)
+               return BFA_STATUS_DEVBUSY;
+
+       bfi_h2i_set(m->mh, BFI_MC_IOCFC, BFI_IOCFC_H2I_SET_INTR_REQ,
+                       bfa_lpuid(bfa));
+       m->coalesce = attr->coalesce;
+       m->delay    = bfa_os_htons(attr->delay);
+       m->latency  = bfa_os_htons(attr->latency);
+
+       bfa_trc(bfa, attr->delay);
+       bfa_trc(bfa, attr->latency);
+
+       bfa_reqq_produce(bfa, BFA_REQQ_IOC);
+       return BFA_STATUS_OK;
+}
+
+void
+bfa_iocfc_set_snsbase(struct bfa_s *bfa, u64 snsbase_pa)
+{
+       struct bfa_iocfc_s      *iocfc = &bfa->iocfc;
+
+       iocfc->cfginfo->sense_buf_len = (BFI_IOIM_SNSLEN - 1);
+       bfa_dma_be_addr_set(iocfc->cfginfo->ioim_snsbase, snsbase_pa);
+}
+
+bfa_status_t
+bfa_iocfc_get_stats(struct bfa_s *bfa, struct bfa_iocfc_stats_s *stats,
+                     bfa_cb_ioc_t cbfn, void *cbarg)
+{
+       struct bfa_iocfc_s      *iocfc = &bfa->iocfc;
+
+       if (iocfc->stats_busy) {
+               bfa_trc(bfa, iocfc->stats_busy);
+               return (BFA_STATUS_DEVBUSY);
+       }
+
+       iocfc->stats_busy = BFA_TRUE;
+       iocfc->stats_ret = stats;
+       iocfc->stats_cbfn = cbfn;
+       iocfc->stats_cbarg = cbarg;
+
+       bfa_iocfc_stats_query(bfa);
+
+       return (BFA_STATUS_OK);
+}
+
+bfa_status_t
+bfa_iocfc_clear_stats(struct bfa_s *bfa, bfa_cb_ioc_t cbfn, void *cbarg)
+{
+       struct bfa_iocfc_s      *iocfc = &bfa->iocfc;
+
+       if (iocfc->stats_busy) {
+               bfa_trc(bfa, iocfc->stats_busy);
+               return (BFA_STATUS_DEVBUSY);
+       }
+
+       iocfc->stats_busy = BFA_TRUE;
+       iocfc->stats_cbfn = cbfn;
+       iocfc->stats_cbarg = cbarg;
+
+       bfa_iocfc_stats_clear(bfa);
+       return (BFA_STATUS_OK);
+}
+
+/**
+ * Enable IOC after it is disabled.
+ */
+void
+bfa_iocfc_enable(struct bfa_s *bfa)
+{
+       bfa_plog_str(bfa->plog, BFA_PL_MID_HAL, BFA_PL_EID_MISC, 0,
+                    "IOC Enable");
+       bfa_ioc_enable(&bfa->ioc);
+}
+
+void
+bfa_iocfc_disable(struct bfa_s *bfa)
+{
+       bfa_plog_str(bfa->plog, BFA_PL_MID_HAL, BFA_PL_EID_MISC, 0,
+                    "IOC Disable");
+       bfa->iocfc.action = BFA_IOCFC_ACT_DISABLE;
+
+       bfa->rme_process = BFA_FALSE;
+       bfa_ioc_disable(&bfa->ioc);
+}
+
+
+bfa_boolean_t
+bfa_iocfc_is_operational(struct bfa_s *bfa)
+{
+       return bfa_ioc_is_operational(&bfa->ioc) && bfa->iocfc.cfgdone;
+}
+
+/**
+ * Return boot target port wwns -- read from boot information in flash.
+ */
+void
+bfa_iocfc_get_bootwwns(struct bfa_s *bfa, u8 *nwwns, wwn_t **wwns)
+{
+       struct bfa_iocfc_s              *iocfc   = &bfa->iocfc;
+       struct bfi_iocfc_cfgrsp_s       *cfgrsp  = iocfc->cfgrsp;
+
+       *nwwns = cfgrsp->bootwwns.nwwns;
+       *wwns = cfgrsp->bootwwns.wwn;
+}
+
+#endif
+
+
diff --git a/drivers/scsi/bfa/bfa_iocfc.h b/drivers/scsi/bfa/bfa_iocfc.h
new file mode 100644 (file)
index 0000000..7ad177e
--- /dev/null
@@ -0,0 +1,168 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ */
+
+#ifndef __BFA_IOCFC_H__
+#define __BFA_IOCFC_H__
+
+#include <bfa_ioc.h>
+#include <bfa.h>
+#include <bfi/bfi_iocfc.h>
+#include <bfa_callback_priv.h>
+
+#define BFA_REQQ_NELEMS_MIN    (4)
+#define BFA_RSPQ_NELEMS_MIN    (4)
+
+struct bfa_iocfc_regs_s {
+       bfa_os_addr_t   intr_status;
+       bfa_os_addr_t   intr_mask;
+       bfa_os_addr_t   cpe_q_pi[BFI_IOC_MAX_CQS];
+       bfa_os_addr_t   cpe_q_ci[BFI_IOC_MAX_CQS];
+       bfa_os_addr_t   cpe_q_depth[BFI_IOC_MAX_CQS];
+       bfa_os_addr_t   cpe_q_ctrl[BFI_IOC_MAX_CQS];
+       bfa_os_addr_t   rme_q_ci[BFI_IOC_MAX_CQS];
+       bfa_os_addr_t   rme_q_pi[BFI_IOC_MAX_CQS];
+       bfa_os_addr_t   rme_q_depth[BFI_IOC_MAX_CQS];
+       bfa_os_addr_t   rme_q_ctrl[BFI_IOC_MAX_CQS];
+};
+
+/**
+ * MSIX vector handlers
+ */
+#define BFA_MSIX_MAX_VECTORS   22
+typedef void (*bfa_msix_handler_t)(struct bfa_s *bfa, int vec);
+struct bfa_msix_s {
+       int     nvecs;
+       bfa_msix_handler_t handler[BFA_MSIX_MAX_VECTORS];
+};
+
+/**
+ * Chip specific interfaces
+ */
+struct bfa_hwif_s {
+       void (*hw_reginit)(struct bfa_s *bfa);
+       void (*hw_rspq_ack)(struct bfa_s *bfa, int rspq);
+       void (*hw_msix_init)(struct bfa_s *bfa, int nvecs);
+       void (*hw_msix_install)(struct bfa_s *bfa);
+       void (*hw_msix_uninstall)(struct bfa_s *bfa);
+       void (*hw_isr_mode_set)(struct bfa_s *bfa, bfa_boolean_t msix);
+       void (*hw_msix_getvecs)(struct bfa_s *bfa, u32 *vecmap,
+                       u32 *nvecs, u32 *maxvec);
+};
+typedef void (*bfa_cb_iocfc_t) (void *cbarg, enum bfa_status status);
+
+struct bfa_iocfc_s {
+       struct bfa_s            *bfa;
+       struct bfa_iocfc_cfg_s  cfg;
+       int                     action;
+
+       u32             req_cq_pi[BFI_IOC_MAX_CQS];
+       u32             rsp_cq_ci[BFI_IOC_MAX_CQS];
+
+       struct bfa_cb_qe_s      init_hcb_qe;
+       struct bfa_cb_qe_s      stop_hcb_qe;
+       struct bfa_cb_qe_s      dis_hcb_qe;
+       struct bfa_cb_qe_s      stats_hcb_qe;
+       bfa_boolean_t           cfgdone;
+
+       struct bfa_dma_s        cfg_info;
+       struct bfi_iocfc_cfg_s *cfginfo;
+       struct bfa_dma_s        cfgrsp_dma;
+       struct bfi_iocfc_cfgrsp_s *cfgrsp;
+       struct bfi_iocfc_cfg_reply_s *cfg_reply;
+
+       u8                      *stats_kva;
+       u64             stats_pa;
+       struct bfa_fw_stats_s   *fw_stats;
+       struct bfa_timer_s      stats_timer;    /*  timer */
+       struct bfa_iocfc_stats_s *stats_ret;    /*  driver stats location */
+       bfa_status_t            stats_status;   /*  stats/statsclr status */
+       bfa_boolean_t           stats_busy;     /*  outstanding stats */
+       bfa_cb_ioc_t            stats_cbfn;     /*  driver callback function */
+       void                    *stats_cbarg;   /*  user callback arg */
+
+       struct bfa_dma_s        req_cq_ba[BFI_IOC_MAX_CQS];
+       struct bfa_dma_s        req_cq_shadow_ci[BFI_IOC_MAX_CQS];
+       struct bfa_dma_s        rsp_cq_ba[BFI_IOC_MAX_CQS];
+       struct bfa_dma_s        rsp_cq_shadow_pi[BFI_IOC_MAX_CQS];
+       struct bfa_iocfc_regs_s bfa_regs;       /*  BFA device registers */
+       struct bfa_hwif_s       hwif;
+
+       bfa_cb_iocfc_t          updateq_cbfn; /*  bios callback function */
+       void                            *updateq_cbarg; /*  bios callback arg */
+};
+
+#define bfa_lpuid(__bfa)               bfa_ioc_portid(&(__bfa)->ioc)
+#define bfa_msix_init(__bfa, __nvecs)  \
+       (__bfa)->iocfc.hwif.hw_msix_init(__bfa, __nvecs)
+#define bfa_msix_install(__bfa)        \
+       (__bfa)->iocfc.hwif.hw_msix_install(__bfa)
+#define bfa_msix_uninstall(__bfa)      \
+       (__bfa)->iocfc.hwif.hw_msix_uninstall(__bfa)
+#define bfa_isr_mode_set(__bfa, __msix)        \
+       (__bfa)->iocfc.hwif.hw_isr_mode_set(__bfa, __msix)
+#define bfa_msix_getvecs(__bfa, __vecmap, __nvecs, __maxvec)   \
+       (__bfa)->iocfc.hwif.hw_msix_getvecs(__bfa, __vecmap, __nvecs, __maxvec)
+
+/*
+ * FC specific IOC functions.
+ */
+void bfa_iocfc_meminfo(struct bfa_iocfc_cfg_s *cfg, u32 *km_len,
+               u32 *dm_len);
+void bfa_iocfc_attach(struct bfa_s *bfa, void *bfad,
+               struct bfa_iocfc_cfg_s *cfg, struct bfa_meminfo_s *meminfo,
+               struct bfa_pcidev_s *pcidev);
+void bfa_iocfc_detach(struct bfa_s *bfa);
+void bfa_iocfc_init(struct bfa_s *bfa);
+void bfa_iocfc_start(struct bfa_s *bfa);
+void bfa_iocfc_stop(struct bfa_s *bfa);
+void bfa_iocfc_isr(void *bfa, struct bfi_mbmsg_s *msg);
+void bfa_iocfc_set_snsbase(struct bfa_s *bfa, u64 snsbase_pa);
+bfa_boolean_t bfa_iocfc_is_operational(struct bfa_s *bfa);
+void bfa_iocfc_reset_queues(struct bfa_s *bfa);
+void bfa_iocfc_updateq(struct bfa_s *bfa, u32 reqq_ba, u32 rspq_ba,
+                       u32 reqq_sci, u32 rspq_spi,
+                       bfa_cb_iocfc_t cbfn, void *cbarg);
+
+void bfa_msix_all(struct bfa_s *bfa, int vec);
+void bfa_msix_reqq(struct bfa_s *bfa, int vec);
+void bfa_msix_rspq(struct bfa_s *bfa, int vec);
+void bfa_msix_lpu_err(struct bfa_s *bfa, int vec);
+
+void bfa_hwcb_reginit(struct bfa_s *bfa);
+void bfa_hwcb_rspq_ack(struct bfa_s *bfa, int rspq);
+void bfa_hwcb_msix_init(struct bfa_s *bfa, int nvecs);
+void bfa_hwcb_msix_install(struct bfa_s *bfa);
+void bfa_hwcb_msix_uninstall(struct bfa_s *bfa);
+void bfa_hwcb_isr_mode_set(struct bfa_s *bfa, bfa_boolean_t msix);
+void bfa_hwcb_msix_getvecs(struct bfa_s *bfa, u32 *vecmap,
+                       u32 *nvecs, u32 *maxvec);
+void bfa_hwct_reginit(struct bfa_s *bfa);
+void bfa_hwct_rspq_ack(struct bfa_s *bfa, int rspq);
+void bfa_hwct_msix_init(struct bfa_s *bfa, int nvecs);
+void bfa_hwct_msix_install(struct bfa_s *bfa);
+void bfa_hwct_msix_uninstall(struct bfa_s *bfa);
+void bfa_hwct_isr_mode_set(struct bfa_s *bfa, bfa_boolean_t msix);
+void bfa_hwct_msix_getvecs(struct bfa_s *bfa, u32 *vecmap,
+                       u32 *nvecs, u32 *maxvec);
+
+void bfa_com_meminfo(bfa_boolean_t mincfg, u32 *dm_len);
+void bfa_com_attach(struct bfa_s *bfa, struct bfa_meminfo_s *mi,
+               bfa_boolean_t mincfg);
+void bfa_iocfc_get_bootwwns(struct bfa_s *bfa, u8 *nwwns, wwn_t **wwns);
+
+#endif /* __BFA_IOCFC_H__ */
+
diff --git a/drivers/scsi/bfa/bfa_iocfc_q.c b/drivers/scsi/bfa/bfa_iocfc_q.c
new file mode 100644 (file)
index 0000000..500a17d
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ */
+
+#include <bfa.h>
+#include "bfa_intr_priv.h"
+
+BFA_TRC_FILE(HAL, IOCFC_Q);
+
+void
+bfa_iocfc_updateq(struct bfa_s *bfa, u32 reqq_ba, u32 rspq_ba,
+                               u32 reqq_sci, u32 rspq_spi, bfa_cb_iocfc_t cbfn,
+                               void *cbarg)
+{
+       struct bfa_iocfc_s *iocfc = &bfa->iocfc;
+       struct bfi_iocfc_updateq_req_s updateq_req;
+
+       iocfc->updateq_cbfn = cbfn;
+       iocfc->updateq_cbarg = cbarg;
+
+       bfi_h2i_set(updateq_req.mh, BFI_MC_IOCFC, BFI_IOCFC_H2I_UPDATEQ_REQ,
+                       bfa_lpuid(bfa));
+
+       updateq_req.reqq_ba = bfa_os_htonl(reqq_ba);
+       updateq_req.rspq_ba = bfa_os_htonl(rspq_ba);
+       updateq_req.reqq_sci = bfa_os_htonl(reqq_sci);
+       updateq_req.rspq_spi = bfa_os_htonl(rspq_spi);
+
+       bfa_ioc_mbox_send(&bfa->ioc, &updateq_req,
+                       sizeof(struct bfi_iocfc_updateq_req_s));
+}
diff --git a/drivers/scsi/bfa/bfa_ioim.c b/drivers/scsi/bfa/bfa_ioim.c
new file mode 100644 (file)
index 0000000..7ae2552
--- /dev/null
@@ -0,0 +1,1311 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ */
+
+#include <bfa.h>
+#include <cs/bfa_debug.h>
+#include <bfa_cb_ioim_macros.h>
+
+BFA_TRC_FILE(HAL, IOIM);
+
+/*
+ * forward declarations.
+ */
+static bfa_boolean_t   bfa_ioim_send_ioreq(struct bfa_ioim_s *ioim);
+static bfa_boolean_t   bfa_ioim_sge_setup(struct bfa_ioim_s *ioim);
+static void            bfa_ioim_sgpg_setup(struct bfa_ioim_s *ioim);
+static bfa_boolean_t   bfa_ioim_send_abort(struct bfa_ioim_s *ioim);
+static void            bfa_ioim_notify_cleanup(struct bfa_ioim_s *ioim);
+static void __bfa_cb_ioim_good_comp(void *cbarg, bfa_boolean_t complete);
+static void __bfa_cb_ioim_comp(void *cbarg, bfa_boolean_t complete);
+static void __bfa_cb_ioim_abort(void *cbarg, bfa_boolean_t complete);
+static void __bfa_cb_ioim_failed(void *cbarg, bfa_boolean_t complete);
+static void __bfa_cb_ioim_pathtov(void *cbarg, bfa_boolean_t complete);
+
+/**
+ *  bfa_ioim_sm
+ */
+
+/**
+ * IO state machine events
+ */
+enum bfa_ioim_event {
+       BFA_IOIM_SM_START = 1,          /*  io start request from host */
+       BFA_IOIM_SM_COMP_GOOD = 2,      /*  io good comp, resource free */
+       BFA_IOIM_SM_COMP = 3,           /*  io comp, resource is free */
+       BFA_IOIM_SM_COMP_UTAG = 4,      /*  io comp, resource is free */
+       BFA_IOIM_SM_DONE = 5,           /*  io comp, resource not free */
+       BFA_IOIM_SM_FREE = 6,           /*  io resource is freed */
+       BFA_IOIM_SM_ABORT = 7,          /*  abort request from scsi stack */
+       BFA_IOIM_SM_ABORT_COMP = 8,     /*  abort from f/w */
+       BFA_IOIM_SM_ABORT_DONE = 9,     /*  abort completion from f/w */
+       BFA_IOIM_SM_QRESUME = 10,       /*  CQ space available to queue IO */
+       BFA_IOIM_SM_SGALLOCED = 11,     /*  SG page allocation successful */
+       BFA_IOIM_SM_SQRETRY = 12,       /*  sequence recovery retry */
+       BFA_IOIM_SM_HCB = 13,           /*  bfa callback complete */
+       BFA_IOIM_SM_CLEANUP = 14,       /*  IO cleanup from itnim */
+       BFA_IOIM_SM_TMSTART = 15,       /*  IO cleanup from tskim */
+       BFA_IOIM_SM_TMDONE = 16,        /*  IO cleanup from tskim */
+       BFA_IOIM_SM_HWFAIL = 17,        /*  IOC h/w failure event */
+       BFA_IOIM_SM_IOTOV = 18,         /*  ITN offline TOV       */
+};
+
+/*
+ * forward declaration of IO state machine
+ */
+static void     bfa_ioim_sm_uninit(struct bfa_ioim_s *ioim,
+                                      enum bfa_ioim_event event);
+static void     bfa_ioim_sm_sgalloc(struct bfa_ioim_s *ioim,
+                                       enum bfa_ioim_event event);
+static void     bfa_ioim_sm_active(struct bfa_ioim_s *ioim,
+                                      enum bfa_ioim_event event);
+static void     bfa_ioim_sm_abort(struct bfa_ioim_s *ioim,
+                                     enum bfa_ioim_event event);
+static void     bfa_ioim_sm_cleanup(struct bfa_ioim_s *ioim,
+                                       enum bfa_ioim_event event);
+static void     bfa_ioim_sm_qfull(struct bfa_ioim_s *ioim,
+                                     enum bfa_ioim_event event);
+static void     bfa_ioim_sm_abort_qfull(struct bfa_ioim_s *ioim,
+                                           enum bfa_ioim_event event);
+static void     bfa_ioim_sm_cleanup_qfull(struct bfa_ioim_s *ioim,
+                                             enum bfa_ioim_event event);
+static void     bfa_ioim_sm_hcb(struct bfa_ioim_s *ioim,
+                                   enum bfa_ioim_event event);
+static void     bfa_ioim_sm_hcb_free(struct bfa_ioim_s *ioim,
+                                        enum bfa_ioim_event event);
+static void     bfa_ioim_sm_resfree(struct bfa_ioim_s *ioim,
+                                       enum bfa_ioim_event event);
+
+/**
+ *             IO is not started (unallocated).
+ */
+static void
+bfa_ioim_sm_uninit(struct bfa_ioim_s *ioim, enum bfa_ioim_event event)
+{
+       bfa_trc_fp(ioim->bfa, ioim->iotag);
+       bfa_trc_fp(ioim->bfa, event);
+
+       switch (event) {
+       case BFA_IOIM_SM_START:
+               if (!bfa_itnim_is_online(ioim->itnim)) {
+                       if (!bfa_itnim_hold_io(ioim->itnim)) {
+                               bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
+                               list_del(&ioim->qe);
+                               list_add_tail(&ioim->qe,
+                                       &ioim->fcpim->ioim_comp_q);
+                               bfa_cb_queue(ioim->bfa, &ioim->hcb_qe,
+                                               __bfa_cb_ioim_pathtov, ioim);
+                       } else {
+                               list_del(&ioim->qe);
+                               list_add_tail(&ioim->qe,
+                                       &ioim->itnim->pending_q);
+                       }
+                       break;
+               }
+
+               if (ioim->nsges > BFI_SGE_INLINE) {
+                       if (!bfa_ioim_sge_setup(ioim)) {
+                               bfa_sm_set_state(ioim, bfa_ioim_sm_sgalloc);
+                               return;
+                       }
+               }
+
+               if (!bfa_ioim_send_ioreq(ioim)) {
+                       bfa_sm_set_state(ioim, bfa_ioim_sm_qfull);
+                       break;
+               }
+
+               bfa_sm_set_state(ioim, bfa_ioim_sm_active);
+               break;
+
+       case BFA_IOIM_SM_IOTOV:
+               bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
+               bfa_cb_queue(ioim->bfa, &ioim->hcb_qe,
+                               __bfa_cb_ioim_pathtov, ioim);
+               break;
+
+       case BFA_IOIM_SM_ABORT:
+               /**
+                * IO in pending queue can get abort requests. Complete abort
+                * requests immediately.
+                */
+               bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
+               bfa_assert(bfa_q_is_on_q(&ioim->itnim->pending_q, ioim));
+               bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, __bfa_cb_ioim_abort,
+                               ioim);
+               break;
+
+       default:
+               bfa_assert(0);
+       }
+}
+
+/**
+ *             IO is waiting for SG pages.
+ */
+static void
+bfa_ioim_sm_sgalloc(struct bfa_ioim_s *ioim, enum bfa_ioim_event event)
+{
+       bfa_trc(ioim->bfa, ioim->iotag);
+       bfa_trc(ioim->bfa, event);
+
+       switch (event) {
+       case BFA_IOIM_SM_SGALLOCED:
+               if (!bfa_ioim_send_ioreq(ioim)) {
+                       bfa_sm_set_state(ioim, bfa_ioim_sm_qfull);
+                       break;
+               }
+               bfa_sm_set_state(ioim, bfa_ioim_sm_active);
+               break;
+
+       case BFA_IOIM_SM_CLEANUP:
+               bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
+               bfa_sgpg_wcancel(ioim->bfa, &ioim->iosp->sgpg_wqe);
+               bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, __bfa_cb_ioim_failed,
+                             ioim);
+               bfa_ioim_notify_cleanup(ioim);
+               break;
+
+       case BFA_IOIM_SM_ABORT:
+               bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
+               bfa_sgpg_wcancel(ioim->bfa, &ioim->iosp->sgpg_wqe);
+               bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, __bfa_cb_ioim_abort,
+                             ioim);
+               break;
+
+       case BFA_IOIM_SM_HWFAIL:
+               bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
+               bfa_sgpg_wcancel(ioim->bfa, &ioim->iosp->sgpg_wqe);
+               bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, __bfa_cb_ioim_failed,
+                             ioim);
+               break;
+
+       default:
+               bfa_assert(0);
+       }
+}
+
+/**
+ *             IO is active.
+ */
+static void
+bfa_ioim_sm_active(struct bfa_ioim_s *ioim, enum bfa_ioim_event event)
+{
+       bfa_trc_fp(ioim->bfa, ioim->iotag);
+       bfa_trc_fp(ioim->bfa, event);
+
+       switch (event) {
+       case BFA_IOIM_SM_COMP_GOOD:
+               bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
+               bfa_cb_queue(ioim->bfa, &ioim->hcb_qe,
+                             __bfa_cb_ioim_good_comp, ioim);
+               break;
+
+       case BFA_IOIM_SM_COMP:
+               bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
+               bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, __bfa_cb_ioim_comp,
+                             ioim);
+               break;
+
+       case BFA_IOIM_SM_DONE:
+               bfa_sm_set_state(ioim, bfa_ioim_sm_hcb_free);
+               bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, __bfa_cb_ioim_comp,
+                             ioim);
+               break;
+
+       case BFA_IOIM_SM_ABORT:
+               ioim->iosp->abort_explicit = BFA_TRUE;
+               ioim->io_cbfn = __bfa_cb_ioim_abort;
+
+               if (bfa_ioim_send_abort(ioim))
+                       bfa_sm_set_state(ioim, bfa_ioim_sm_abort);
+               else {
+                       bfa_sm_set_state(ioim, bfa_ioim_sm_abort_qfull);
+                       bfa_reqq_wait(ioim->bfa, ioim->itnim->reqq,
+                                         &ioim->iosp->reqq_wait);
+               }
+               break;
+
+       case BFA_IOIM_SM_CLEANUP:
+               ioim->iosp->abort_explicit = BFA_FALSE;
+               ioim->io_cbfn = __bfa_cb_ioim_failed;
+
+               if (bfa_ioim_send_abort(ioim))
+                       bfa_sm_set_state(ioim, bfa_ioim_sm_cleanup);
+               else {
+                       bfa_sm_set_state(ioim, bfa_ioim_sm_cleanup_qfull);
+                       bfa_reqq_wait(ioim->bfa, ioim->itnim->reqq,
+                                         &ioim->iosp->reqq_wait);
+               }
+               break;
+
+       case BFA_IOIM_SM_HWFAIL:
+               bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
+               bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, __bfa_cb_ioim_failed,
+                             ioim);
+               break;
+
+       default:
+               bfa_assert(0);
+       }
+}
+
+/**
+ *             IO is being aborted, waiting for completion from firmware.
+ */
+static void
+bfa_ioim_sm_abort(struct bfa_ioim_s *ioim, enum bfa_ioim_event event)
+{
+       bfa_trc(ioim->bfa, ioim->iotag);
+       bfa_trc(ioim->bfa, event);
+
+       switch (event) {
+       case BFA_IOIM_SM_COMP_GOOD:
+       case BFA_IOIM_SM_COMP:
+       case BFA_IOIM_SM_DONE:
+       case BFA_IOIM_SM_FREE:
+               break;
+
+       case BFA_IOIM_SM_ABORT_DONE:
+               bfa_sm_set_state(ioim, bfa_ioim_sm_hcb_free);
+               bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, __bfa_cb_ioim_abort,
+                             ioim);
+               break;
+
+       case BFA_IOIM_SM_ABORT_COMP:
+               bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
+               bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, __bfa_cb_ioim_abort,
+                             ioim);
+               break;
+
+       case BFA_IOIM_SM_COMP_UTAG:
+               bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
+               bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, __bfa_cb_ioim_abort,
+                             ioim);
+               break;
+
+       case BFA_IOIM_SM_CLEANUP:
+               bfa_assert(ioim->iosp->abort_explicit == BFA_TRUE);
+               ioim->iosp->abort_explicit = BFA_FALSE;
+
+               if (bfa_ioim_send_abort(ioim))
+                       bfa_sm_set_state(ioim, bfa_ioim_sm_cleanup);
+               else {
+                       bfa_sm_set_state(ioim, bfa_ioim_sm_cleanup_qfull);
+                       bfa_reqq_wait(ioim->bfa, ioim->itnim->reqq,
+                                         &ioim->iosp->reqq_wait);
+               }
+               break;
+
+       case BFA_IOIM_SM_HWFAIL:
+               bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
+               bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, __bfa_cb_ioim_failed,
+                             ioim);
+               break;
+
+       default:
+               bfa_assert(0);
+       }
+}
+
+/**
+ * IO is being cleaned up (implicit abort), waiting for completion from
+ * firmware.
+ */
+static void
+bfa_ioim_sm_cleanup(struct bfa_ioim_s *ioim, enum bfa_ioim_event event)
+{
+       bfa_trc(ioim->bfa, ioim->iotag);
+       bfa_trc(ioim->bfa, event);
+
+       switch (event) {
+       case BFA_IOIM_SM_COMP_GOOD:
+       case BFA_IOIM_SM_COMP:
+       case BFA_IOIM_SM_DONE:
+       case BFA_IOIM_SM_FREE:
+               break;
+
+       case BFA_IOIM_SM_ABORT:
+               /**
+                * IO is already being aborted implicitly
+                */
+               ioim->io_cbfn = __bfa_cb_ioim_abort;
+               break;
+
+       case BFA_IOIM_SM_ABORT_DONE:
+               bfa_sm_set_state(ioim, bfa_ioim_sm_hcb_free);
+               bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, ioim->io_cbfn, ioim);
+               bfa_ioim_notify_cleanup(ioim);
+               break;
+
+       case BFA_IOIM_SM_ABORT_COMP:
+               bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
+               bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, ioim->io_cbfn, ioim);
+               bfa_ioim_notify_cleanup(ioim);
+               break;
+
+       case BFA_IOIM_SM_COMP_UTAG:
+               bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
+               bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, ioim->io_cbfn, ioim);
+               bfa_ioim_notify_cleanup(ioim);
+               break;
+
+       case BFA_IOIM_SM_HWFAIL:
+               bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
+               bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, __bfa_cb_ioim_failed,
+                             ioim);
+               break;
+
+       case BFA_IOIM_SM_CLEANUP:
+               /**
+                * IO can be in cleanup state already due to TM command. 2nd cleanup
+                * request comes from ITN offline event.
+                */
+               break;
+
+       default:
+               bfa_assert(0);
+       }
+}
+
+/**
+ *             IO is waiting for room in request CQ
+ */
+static void
+bfa_ioim_sm_qfull(struct bfa_ioim_s *ioim, enum bfa_ioim_event event)
+{
+       bfa_trc(ioim->bfa, ioim->iotag);
+       bfa_trc(ioim->bfa, event);
+
+       switch (event) {
+       case BFA_IOIM_SM_QRESUME:
+               bfa_sm_set_state(ioim, bfa_ioim_sm_active);
+               bfa_ioim_send_ioreq(ioim);
+               break;
+
+       case BFA_IOIM_SM_ABORT:
+               bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
+               bfa_reqq_wcancel(&ioim->iosp->reqq_wait);
+               bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, __bfa_cb_ioim_abort,
+                             ioim);
+               break;
+
+       case BFA_IOIM_SM_CLEANUP:
+               bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
+               bfa_reqq_wcancel(&ioim->iosp->reqq_wait);
+               bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, __bfa_cb_ioim_failed,
+                             ioim);
+               bfa_ioim_notify_cleanup(ioim);
+               break;
+
+       case BFA_IOIM_SM_HWFAIL:
+               bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
+               bfa_reqq_wcancel(&ioim->iosp->reqq_wait);
+               bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, __bfa_cb_ioim_failed,
+                             ioim);
+               break;
+
+       default:
+               bfa_assert(0);
+       }
+}
+
+/**
+ *             Active IO is being aborted, waiting for room in request CQ.
+ */
+static void
+bfa_ioim_sm_abort_qfull(struct bfa_ioim_s *ioim, enum bfa_ioim_event event)
+{
+       bfa_trc(ioim->bfa, ioim->iotag);
+       bfa_trc(ioim->bfa, event);
+
+       switch (event) {
+       case BFA_IOIM_SM_QRESUME:
+               bfa_sm_set_state(ioim, bfa_ioim_sm_abort);
+               bfa_ioim_send_abort(ioim);
+               break;
+
+       case BFA_IOIM_SM_CLEANUP:
+               bfa_assert(ioim->iosp->abort_explicit == BFA_TRUE);
+               ioim->iosp->abort_explicit = BFA_FALSE;
+               bfa_sm_set_state(ioim, bfa_ioim_sm_cleanup_qfull);
+               break;
+
+       case BFA_IOIM_SM_COMP_GOOD:
+       case BFA_IOIM_SM_COMP:
+               bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
+               bfa_reqq_wcancel(&ioim->iosp->reqq_wait);
+               bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, __bfa_cb_ioim_abort,
+                             ioim);
+               break;
+
+       case BFA_IOIM_SM_DONE:
+               bfa_sm_set_state(ioim, bfa_ioim_sm_hcb_free);
+               bfa_reqq_wcancel(&ioim->iosp->reqq_wait);
+               bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, __bfa_cb_ioim_abort,
+                             ioim);
+               break;
+
+       case BFA_IOIM_SM_HWFAIL:
+               bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
+               bfa_reqq_wcancel(&ioim->iosp->reqq_wait);
+               bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, __bfa_cb_ioim_failed,
+                             ioim);
+               break;
+
+       default:
+               bfa_assert(0);
+       }
+}
+
+/**
+ *             Active IO is being cleaned up, waiting for room in request CQ.
+ */
+static void
+bfa_ioim_sm_cleanup_qfull(struct bfa_ioim_s *ioim, enum bfa_ioim_event event)
+{
+       bfa_trc(ioim->bfa, ioim->iotag);
+       bfa_trc(ioim->bfa, event);
+
+       switch (event) {
+       case BFA_IOIM_SM_QRESUME:
+               bfa_sm_set_state(ioim, bfa_ioim_sm_cleanup);
+               bfa_ioim_send_abort(ioim);
+               break;
+
+       case BFA_IOIM_SM_ABORT:
+               /**
+                * IO is alraedy being cleaned up implicitly
+                */
+               ioim->io_cbfn = __bfa_cb_ioim_abort;
+               break;
+
+       case BFA_IOIM_SM_COMP_GOOD:
+       case BFA_IOIM_SM_COMP:
+               bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
+               bfa_reqq_wcancel(&ioim->iosp->reqq_wait);
+               bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, ioim->io_cbfn, ioim);
+               bfa_ioim_notify_cleanup(ioim);
+               break;
+
+       case BFA_IOIM_SM_DONE:
+               bfa_sm_set_state(ioim, bfa_ioim_sm_hcb_free);
+               bfa_reqq_wcancel(&ioim->iosp->reqq_wait);
+               bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, ioim->io_cbfn, ioim);
+               bfa_ioim_notify_cleanup(ioim);
+               break;
+
+       case BFA_IOIM_SM_HWFAIL:
+               bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
+               bfa_reqq_wcancel(&ioim->iosp->reqq_wait);
+               bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, __bfa_cb_ioim_failed,
+                             ioim);
+               break;
+
+       default:
+               bfa_assert(0);
+       }
+}
+
+/**
+ * IO bfa callback is pending.
+ */
+static void
+bfa_ioim_sm_hcb(struct bfa_ioim_s *ioim, enum bfa_ioim_event event)
+{
+       bfa_trc_fp(ioim->bfa, ioim->iotag);
+       bfa_trc_fp(ioim->bfa, event);
+
+       switch (event) {
+       case BFA_IOIM_SM_HCB:
+               bfa_sm_set_state(ioim, bfa_ioim_sm_uninit);
+               bfa_ioim_free(ioim);
+               bfa_cb_ioim_resfree(ioim->bfa->bfad);
+               break;
+
+       case BFA_IOIM_SM_CLEANUP:
+               bfa_ioim_notify_cleanup(ioim);
+               break;
+
+       case BFA_IOIM_SM_HWFAIL:
+               break;
+
+       default:
+               bfa_assert(0);
+       }
+}
+
+/**
+ * IO bfa callback is pending. IO resource cannot be freed.
+ */
+static void
+bfa_ioim_sm_hcb_free(struct bfa_ioim_s *ioim, enum bfa_ioim_event event)
+{
+       bfa_trc(ioim->bfa, ioim->iotag);
+       bfa_trc(ioim->bfa, event);
+
+       switch (event) {
+       case BFA_IOIM_SM_HCB:
+               bfa_sm_set_state(ioim, bfa_ioim_sm_resfree);
+               list_del(&ioim->qe);
+               list_add_tail(&ioim->qe, &ioim->fcpim->ioim_resfree_q);
+               break;
+
+       case BFA_IOIM_SM_FREE:
+               bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
+               break;
+
+       case BFA_IOIM_SM_CLEANUP:
+               bfa_ioim_notify_cleanup(ioim);
+               break;
+
+       case BFA_IOIM_SM_HWFAIL:
+               bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
+               break;
+
+       default:
+               bfa_assert(0);
+       }
+}
+
+/**
+ * IO is completed, waiting resource free from firmware.
+ */
+static void
+bfa_ioim_sm_resfree(struct bfa_ioim_s *ioim, enum bfa_ioim_event event)
+{
+       bfa_trc(ioim->bfa, ioim->iotag);
+       bfa_trc(ioim->bfa, event);
+
+       switch (event) {
+       case BFA_IOIM_SM_FREE:
+               bfa_sm_set_state(ioim, bfa_ioim_sm_uninit);
+               bfa_ioim_free(ioim);
+               bfa_cb_ioim_resfree(ioim->bfa->bfad);
+               break;
+
+       case BFA_IOIM_SM_CLEANUP:
+               bfa_ioim_notify_cleanup(ioim);
+               break;
+
+       case BFA_IOIM_SM_HWFAIL:
+               break;
+
+       default:
+               bfa_assert(0);
+       }
+}
+
+
+
+/**
+ *  bfa_ioim_private
+ */
+
+static void
+__bfa_cb_ioim_good_comp(void *cbarg, bfa_boolean_t complete)
+{
+       struct bfa_ioim_s *ioim = cbarg;
+
+       if (!complete) {
+               bfa_sm_send_event(ioim, BFA_IOIM_SM_HCB);
+               return;
+       }
+
+       bfa_cb_ioim_good_comp(ioim->bfa->bfad, ioim->dio);
+}
+
+static void
+__bfa_cb_ioim_comp(void *cbarg, bfa_boolean_t complete)
+{
+       struct bfa_ioim_s       *ioim = cbarg;
+       struct bfi_ioim_rsp_s *m;
+       u8              *snsinfo = NULL;
+       u8         sns_len = 0;
+       s32         residue = 0;
+
+       if (!complete) {
+               bfa_sm_send_event(ioim, BFA_IOIM_SM_HCB);
+               return;
+       }
+
+       m = (struct bfi_ioim_rsp_s *) &ioim->iosp->comp_rspmsg;
+       if (m->io_status == BFI_IOIM_STS_OK) {
+               /**
+                * setup sense information, if present
+                */
+               if (m->scsi_status == SCSI_STATUS_CHECK_CONDITION
+                                       && m->sns_len) {
+                       sns_len = m->sns_len;
+                       snsinfo = ioim->iosp->snsinfo;
+               }
+
+               /**
+                * setup residue value correctly for normal completions
+                */
+               if (m->resid_flags == FCP_RESID_UNDER)
+                       residue = bfa_os_ntohl(m->residue);
+               if (m->resid_flags == FCP_RESID_OVER) {
+                       residue = bfa_os_ntohl(m->residue);
+                       residue = -residue;
+               }
+       }
+
+       bfa_cb_ioim_done(ioim->bfa->bfad, ioim->dio, m->io_status,
+                         m->scsi_status, sns_len, snsinfo, residue);
+}
+
+static void
+__bfa_cb_ioim_failed(void *cbarg, bfa_boolean_t complete)
+{
+       struct bfa_ioim_s *ioim = cbarg;
+
+       if (!complete) {
+               bfa_sm_send_event(ioim, BFA_IOIM_SM_HCB);
+               return;
+       }
+
+       bfa_cb_ioim_done(ioim->bfa->bfad, ioim->dio, BFI_IOIM_STS_ABORTED,
+                         0, 0, NULL, 0);
+}
+
+static void
+__bfa_cb_ioim_pathtov(void *cbarg, bfa_boolean_t complete)
+{
+       struct bfa_ioim_s *ioim = cbarg;
+
+       if (!complete) {
+               bfa_sm_send_event(ioim, BFA_IOIM_SM_HCB);
+               return;
+       }
+
+       bfa_cb_ioim_done(ioim->bfa->bfad, ioim->dio, BFI_IOIM_STS_PATHTOV,
+                         0, 0, NULL, 0);
+}
+
+static void
+__bfa_cb_ioim_abort(void *cbarg, bfa_boolean_t complete)
+{
+       struct bfa_ioim_s *ioim = cbarg;
+
+       if (!complete) {
+               bfa_sm_send_event(ioim, BFA_IOIM_SM_HCB);
+               return;
+       }
+
+       bfa_cb_ioim_abort(ioim->bfa->bfad, ioim->dio);
+}
+
+static void
+bfa_ioim_sgpg_alloced(void *cbarg)
+{
+       struct bfa_ioim_s *ioim = cbarg;
+
+       ioim->nsgpgs = BFA_SGPG_NPAGE(ioim->nsges);
+       list_splice_tail_init(&ioim->iosp->sgpg_wqe.sgpg_q, &ioim->sgpg_q);
+       bfa_ioim_sgpg_setup(ioim);
+       bfa_sm_send_event(ioim, BFA_IOIM_SM_SGALLOCED);
+}
+
+/**
+ * Send I/O request to firmware.
+ */
+static          bfa_boolean_t
+bfa_ioim_send_ioreq(struct bfa_ioim_s *ioim)
+{
+       struct bfa_itnim_s *itnim = ioim->itnim;
+       struct bfi_ioim_req_s *m;
+       static struct fcp_cmnd_s cmnd_z0 = { 0 };
+       struct bfi_sge_s      *sge;
+       u32        pgdlen = 0;
+
+       /**
+        * check for room in queue to send request now
+        */
+       m = bfa_reqq_next(ioim->bfa, itnim->reqq);
+       if (!m) {
+               bfa_reqq_wait(ioim->bfa, ioim->itnim->reqq,
+                                 &ioim->iosp->reqq_wait);
+               return BFA_FALSE;
+       }
+
+       /**
+        * build i/o request message next
+        */
+       m->io_tag = bfa_os_htons(ioim->iotag);
+       m->rport_hdl = ioim->itnim->rport->fw_handle;
+       m->io_timeout = bfa_cb_ioim_get_timeout(ioim->dio);
+
+       /**
+        * build inline IO SG element here
+        */
+       sge = &m->sges[0];
+       if (ioim->nsges) {
+               sge->sga = bfa_cb_ioim_get_sgaddr(ioim->dio, 0);
+               pgdlen = bfa_cb_ioim_get_sglen(ioim->dio, 0);
+               sge->sg_len = pgdlen;
+               sge->flags = (ioim->nsges > BFI_SGE_INLINE) ?
+                                       BFI_SGE_DATA_CPL : BFI_SGE_DATA_LAST;
+               bfa_sge_to_be(sge);
+               sge++;
+       }
+
+       if (ioim->nsges > BFI_SGE_INLINE) {
+               sge->sga = ioim->sgpg->sgpg_pa;
+       } else {
+               sge->sga.a32.addr_lo = 0;
+               sge->sga.a32.addr_hi = 0;
+       }
+       sge->sg_len = pgdlen;
+       sge->flags = BFI_SGE_PGDLEN;
+       bfa_sge_to_be(sge);
+
+       /**
+        * set up I/O command parameters
+        */
+       bfa_os_assign(m->cmnd, cmnd_z0);
+       m->cmnd.lun = bfa_cb_ioim_get_lun(ioim->dio);
+       m->cmnd.iodir = bfa_cb_ioim_get_iodir(ioim->dio);
+       bfa_os_assign(m->cmnd.cdb,
+                       *(struct scsi_cdb_s *)bfa_cb_ioim_get_cdb(ioim->dio));
+       m->cmnd.fcp_dl = bfa_os_htonl(bfa_cb_ioim_get_size(ioim->dio));
+
+       /**
+        * set up I/O message header
+        */
+       switch (m->cmnd.iodir) {
+       case FCP_IODIR_READ:
+               bfi_h2i_set(m->mh, BFI_MC_IOIM_READ, 0, bfa_lpuid(ioim->bfa));
+               bfa_stats(itnim, input_reqs);
+               break;
+       case FCP_IODIR_WRITE:
+               bfi_h2i_set(m->mh, BFI_MC_IOIM_WRITE, 0, bfa_lpuid(ioim->bfa));
+               bfa_stats(itnim, output_reqs);
+               break;
+       case FCP_IODIR_RW:
+               bfa_stats(itnim, input_reqs);
+               bfa_stats(itnim, output_reqs);
+       default:
+               bfi_h2i_set(m->mh, BFI_MC_IOIM_IO, 0, bfa_lpuid(ioim->bfa));
+       }
+       if (itnim->seq_rec ||
+           (bfa_cb_ioim_get_size(ioim->dio) & (sizeof(u32) - 1)))
+               bfi_h2i_set(m->mh, BFI_MC_IOIM_IO, 0, bfa_lpuid(ioim->bfa));
+
+#ifdef IOIM_ADVANCED
+       m->cmnd.crn = bfa_cb_ioim_get_crn(ioim->dio);
+       m->cmnd.priority = bfa_cb_ioim_get_priority(ioim->dio);
+       m->cmnd.taskattr = bfa_cb_ioim_get_taskattr(ioim->dio);
+
+       /**
+        * Handle large CDB (>16 bytes).
+        */
+       m->cmnd.addl_cdb_len = (bfa_cb_ioim_get_cdblen(ioim->dio) -
+                                       FCP_CMND_CDB_LEN) / sizeof(u32);
+       if (m->cmnd.addl_cdb_len) {
+               bfa_os_memcpy(&m->cmnd.cdb + 1, (struct scsi_cdb_s *)
+                               bfa_cb_ioim_get_cdb(ioim->dio) + 1,
+                               m->cmnd.addl_cdb_len * sizeof(u32));
+               fcp_cmnd_fcpdl(&m->cmnd) =
+                               bfa_os_htonl(bfa_cb_ioim_get_size(ioim->dio));
+       }
+#endif
+
+       /**
+        * queue I/O message to firmware
+        */
+       bfa_reqq_produce(ioim->bfa, itnim->reqq);
+       return BFA_TRUE;
+}
+
+/**
+ * Setup any additional SG pages needed.Inline SG element is setup
+ * at queuing time.
+ */
+static bfa_boolean_t
+bfa_ioim_sge_setup(struct bfa_ioim_s *ioim)
+{
+       u16        nsgpgs;
+
+       bfa_assert(ioim->nsges > BFI_SGE_INLINE);
+
+       /**
+        * allocate SG pages needed
+        */
+       nsgpgs = BFA_SGPG_NPAGE(ioim->nsges);
+       if (!nsgpgs)
+               return BFA_TRUE;
+
+       if (bfa_sgpg_malloc(ioim->bfa, &ioim->sgpg_q, nsgpgs)
+           != BFA_STATUS_OK) {
+               bfa_sgpg_wait(ioim->bfa, &ioim->iosp->sgpg_wqe, nsgpgs);
+               return BFA_FALSE;
+       }
+
+       ioim->nsgpgs = nsgpgs;
+       bfa_ioim_sgpg_setup(ioim);
+
+       return BFA_TRUE;
+}
+
+static void
+bfa_ioim_sgpg_setup(struct bfa_ioim_s *ioim)
+{
+       int             sgeid, nsges, i;
+       struct bfi_sge_s      *sge;
+       struct bfa_sgpg_s *sgpg;
+       u32        pgcumsz;
+
+       sgeid = BFI_SGE_INLINE;
+       ioim->sgpg = sgpg = bfa_q_first(&ioim->sgpg_q);
+
+       do {
+               sge = sgpg->sgpg->sges;
+               nsges = ioim->nsges - sgeid;
+               if (nsges > BFI_SGPG_DATA_SGES)
+                       nsges = BFI_SGPG_DATA_SGES;
+
+               pgcumsz = 0;
+               for (i = 0; i < nsges; i++, sge++, sgeid++) {
+                       sge->sga = bfa_cb_ioim_get_sgaddr(ioim->dio, sgeid);
+                       sge->sg_len = bfa_cb_ioim_get_sglen(ioim->dio, sgeid);
+                       pgcumsz += sge->sg_len;
+
+                       /**
+                        * set flags
+                        */
+                       if (i < (nsges - 1))
+                               sge->flags = BFI_SGE_DATA;
+                       else if (sgeid < (ioim->nsges - 1))
+                               sge->flags = BFI_SGE_DATA_CPL;
+                       else
+                               sge->flags = BFI_SGE_DATA_LAST;
+               }
+
+               sgpg = (struct bfa_sgpg_s *) bfa_q_next(sgpg);
+
+               /**
+                * set the link element of each page
+                */
+               if (sgeid == ioim->nsges) {
+                       sge->flags = BFI_SGE_PGDLEN;
+                       sge->sga.a32.addr_lo = 0;
+                       sge->sga.a32.addr_hi = 0;
+               } else {
+                       sge->flags = BFI_SGE_LINK;
+                       sge->sga = sgpg->sgpg_pa;
+               }
+               sge->sg_len = pgcumsz;
+       } while (sgeid < ioim->nsges);
+}
+
+/**
+ * Send I/O abort request to firmware.
+ */
+static          bfa_boolean_t
+bfa_ioim_send_abort(struct bfa_ioim_s *ioim)
+{
+       struct bfa_itnim_s          *itnim = ioim->itnim;
+       struct bfi_ioim_abort_req_s *m;
+       enum bfi_ioim_h2i       msgop;
+
+       /**
+        * check for room in queue to send request now
+        */
+       m = bfa_reqq_next(ioim->bfa, itnim->reqq);
+       if (!m)
+               return BFA_FALSE;
+
+       /**
+        * build i/o request message next
+        */
+       if (ioim->iosp->abort_explicit)
+               msgop = BFI_IOIM_H2I_IOABORT_REQ;
+       else
+               msgop = BFI_IOIM_H2I_IOCLEANUP_REQ;
+
+       bfi_h2i_set(m->mh, BFI_MC_IOIM, msgop, bfa_lpuid(ioim->bfa));
+       m->io_tag    = bfa_os_htons(ioim->iotag);
+       m->abort_tag = ++ioim->abort_tag;
+
+       /**
+        * queue I/O message to firmware
+        */
+       bfa_reqq_produce(ioim->bfa, itnim->reqq);
+       return BFA_TRUE;
+}
+
+/**
+ * Call to resume any I/O requests waiting for room in request queue.
+ */
+static void
+bfa_ioim_qresume(void *cbarg)
+{
+       struct bfa_ioim_s *ioim = cbarg;
+
+       bfa_fcpim_stats(ioim->fcpim, qresumes);
+       bfa_sm_send_event(ioim, BFA_IOIM_SM_QRESUME);
+}
+
+
+static void
+bfa_ioim_notify_cleanup(struct bfa_ioim_s *ioim)
+{
+       /**
+        * Move IO from itnim queue to fcpim global queue since itnim will be
+        * freed.
+        */
+       list_del(&ioim->qe);
+       list_add_tail(&ioim->qe, &ioim->fcpim->ioim_comp_q);
+
+       if (!ioim->iosp->tskim) {
+               if (ioim->fcpim->delay_comp && ioim->itnim->iotov_active) {
+                       bfa_cb_dequeue(&ioim->hcb_qe);
+                       list_del(&ioim->qe);
+                       list_add_tail(&ioim->qe, &ioim->itnim->delay_comp_q);
+               }
+               bfa_itnim_iodone(ioim->itnim);
+       } else
+               bfa_tskim_iodone(ioim->iosp->tskim);
+}
+
+/**
+ *               or after the link comes back.
+ */
+void
+bfa_ioim_delayed_comp(struct bfa_ioim_s *ioim, bfa_boolean_t iotov)
+{
+       /**
+        * If path tov timer expired, failback with PATHTOV status - these
+        * IO requests are not normally retried by IO stack.
+        *
+        * Otherwise device cameback online and fail it with normal failed
+        * status so that IO stack retries these failed IO requests.
+        */
+       if (iotov)
+               ioim->io_cbfn = __bfa_cb_ioim_pathtov;
+       else
+               ioim->io_cbfn = __bfa_cb_ioim_failed;
+
+       bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, ioim->io_cbfn, ioim);
+
+    /**
+     * Move IO to fcpim global queue since itnim will be
+     * freed.
+     */
+    list_del(&ioim->qe);
+    list_add_tail(&ioim->qe, &ioim->fcpim->ioim_comp_q);
+}
+
+
+
+/**
+ *  bfa_ioim_friend
+ */
+
+/**
+ * Memory allocation and initialization.
+ */
+void
+bfa_ioim_attach(struct bfa_fcpim_mod_s *fcpim, struct bfa_meminfo_s *minfo)
+{
+       struct bfa_ioim_s               *ioim;
+       struct bfa_ioim_sp_s    *iosp;
+       u16             i;
+       u8                      *snsinfo;
+       u32             snsbufsz;
+
+       /**
+        * claim memory first
+        */
+       ioim = (struct bfa_ioim_s *) bfa_meminfo_kva(minfo);
+       fcpim->ioim_arr = ioim;
+       bfa_meminfo_kva(minfo) = (u8 *) (ioim + fcpim->num_ioim_reqs);
+
+       iosp = (struct bfa_ioim_sp_s *) bfa_meminfo_kva(minfo);
+       fcpim->ioim_sp_arr = iosp;
+       bfa_meminfo_kva(minfo) = (u8 *) (iosp + fcpim->num_ioim_reqs);
+
+       /**
+        * Claim DMA memory for per IO sense data.
+        */
+       snsbufsz = fcpim->num_ioim_reqs * BFI_IOIM_SNSLEN;
+       fcpim->snsbase.pa  = bfa_meminfo_dma_phys(minfo);
+       bfa_meminfo_dma_phys(minfo) += snsbufsz;
+
+       fcpim->snsbase.kva = bfa_meminfo_dma_virt(minfo);
+       bfa_meminfo_dma_virt(minfo) += snsbufsz;
+       snsinfo = fcpim->snsbase.kva;
+       bfa_iocfc_set_snsbase(fcpim->bfa, fcpim->snsbase.pa);
+
+       /**
+        * Initialize ioim free queues
+        */
+       INIT_LIST_HEAD(&fcpim->ioim_free_q);
+       INIT_LIST_HEAD(&fcpim->ioim_resfree_q);
+       INIT_LIST_HEAD(&fcpim->ioim_comp_q);
+
+       for (i = 0; i < fcpim->num_ioim_reqs;
+            i++, ioim++, iosp++, snsinfo += BFI_IOIM_SNSLEN) {
+               /*
+                * initialize IOIM
+                */
+               bfa_os_memset(ioim, 0, sizeof(struct bfa_ioim_s));
+               ioim->iotag   = i;
+               ioim->bfa     = fcpim->bfa;
+               ioim->fcpim   = fcpim;
+               ioim->iosp    = iosp;
+               iosp->snsinfo = snsinfo;
+               INIT_LIST_HEAD(&ioim->sgpg_q);
+               bfa_reqq_winit(&ioim->iosp->reqq_wait,
+                                  bfa_ioim_qresume, ioim);
+               bfa_sgpg_winit(&ioim->iosp->sgpg_wqe,
+                                  bfa_ioim_sgpg_alloced, ioim);
+               bfa_sm_set_state(ioim, bfa_ioim_sm_uninit);
+
+               list_add_tail(&ioim->qe, &fcpim->ioim_free_q);
+       }
+}
+
+/**
+ * Driver detach time call.
+ */
+void
+bfa_ioim_detach(struct bfa_fcpim_mod_s *fcpim)
+{
+}
+
+void
+bfa_ioim_isr(struct bfa_s *bfa, struct bfi_msg_s *m)
+{
+       struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(bfa);
+       struct bfi_ioim_rsp_s *rsp = (struct bfi_ioim_rsp_s *) m;
+       struct bfa_ioim_s *ioim;
+       u16        iotag;
+       enum bfa_ioim_event evt = BFA_IOIM_SM_COMP;
+
+       iotag = bfa_os_ntohs(rsp->io_tag);
+
+       ioim = BFA_IOIM_FROM_TAG(fcpim, iotag);
+       bfa_assert(ioim->iotag == iotag);
+
+       bfa_trc(ioim->bfa, ioim->iotag);
+       bfa_trc(ioim->bfa, rsp->io_status);
+       bfa_trc(ioim->bfa, rsp->reuse_io_tag);
+
+       if (bfa_sm_cmp_state(ioim, bfa_ioim_sm_active))
+               bfa_os_assign(ioim->iosp->comp_rspmsg, *m);
+
+       switch (rsp->io_status) {
+       case BFI_IOIM_STS_OK:
+               bfa_fcpim_stats(fcpim, iocomp_ok);
+               if (rsp->reuse_io_tag == 0)
+                       evt = BFA_IOIM_SM_DONE;
+               else
+                       evt = BFA_IOIM_SM_COMP;
+               break;
+
+       case BFI_IOIM_STS_TIMEDOUT:
+       case BFI_IOIM_STS_ABORTED:
+               rsp->io_status = BFI_IOIM_STS_ABORTED;
+               bfa_fcpim_stats(fcpim, iocomp_aborted);
+               if (rsp->reuse_io_tag == 0)
+                       evt = BFA_IOIM_SM_DONE;
+               else
+                       evt = BFA_IOIM_SM_COMP;
+               break;
+
+       case BFI_IOIM_STS_PROTO_ERR:
+               bfa_fcpim_stats(fcpim, iocom_proto_err);
+               bfa_assert(rsp->reuse_io_tag);
+               evt = BFA_IOIM_SM_COMP;
+               break;
+
+       case BFI_IOIM_STS_SQER_NEEDED:
+               bfa_fcpim_stats(fcpim, iocom_sqer_needed);
+               bfa_assert(rsp->reuse_io_tag == 0);
+               evt = BFA_IOIM_SM_SQRETRY;
+               break;
+
+       case BFI_IOIM_STS_RES_FREE:
+               bfa_fcpim_stats(fcpim, iocom_res_free);
+               evt = BFA_IOIM_SM_FREE;
+               break;
+
+       case BFI_IOIM_STS_HOST_ABORTED:
+               bfa_fcpim_stats(fcpim, iocom_hostabrts);
+               if (rsp->abort_tag != ioim->abort_tag) {
+                       bfa_trc(ioim->bfa, rsp->abort_tag);
+                       bfa_trc(ioim->bfa, ioim->abort_tag);
+                       return;
+               }
+
+               if (rsp->reuse_io_tag)
+                       evt = BFA_IOIM_SM_ABORT_COMP;
+               else
+                       evt = BFA_IOIM_SM_ABORT_DONE;
+               break;
+
+       case BFI_IOIM_STS_UTAG:
+               bfa_fcpim_stats(fcpim, iocom_utags);
+               evt = BFA_IOIM_SM_COMP_UTAG;
+               break;
+
+       default:
+               bfa_assert(0);
+       }
+
+       bfa_sm_send_event(ioim, evt);
+}
+
+void
+bfa_ioim_good_comp_isr(struct bfa_s *bfa, struct bfi_msg_s *m)
+{
+       struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(bfa);
+       struct bfi_ioim_rsp_s *rsp = (struct bfi_ioim_rsp_s *) m;
+       struct bfa_ioim_s *ioim;
+       u16        iotag;
+
+       iotag = bfa_os_ntohs(rsp->io_tag);
+
+       ioim = BFA_IOIM_FROM_TAG(fcpim, iotag);
+       bfa_assert(ioim->iotag == iotag);
+
+       bfa_trc_fp(ioim->bfa, ioim->iotag);
+       bfa_sm_send_event(ioim, BFA_IOIM_SM_COMP_GOOD);
+}
+
+/**
+ * Called by itnim to clean up IO while going offline.
+ */
+void
+bfa_ioim_cleanup(struct bfa_ioim_s *ioim)
+{
+       bfa_trc(ioim->bfa, ioim->iotag);
+       bfa_fcpim_stats(ioim->fcpim, io_cleanups);
+
+       ioim->iosp->tskim = NULL;
+       bfa_sm_send_event(ioim, BFA_IOIM_SM_CLEANUP);
+}
+
+void
+bfa_ioim_cleanup_tm(struct bfa_ioim_s *ioim, struct bfa_tskim_s *tskim)
+{
+       bfa_trc(ioim->bfa, ioim->iotag);
+       bfa_fcpim_stats(ioim->fcpim, io_tmaborts);
+
+       ioim->iosp->tskim = tskim;
+       bfa_sm_send_event(ioim, BFA_IOIM_SM_CLEANUP);
+}
+
+/**
+ * IOC failure handling.
+ */
+void
+bfa_ioim_iocdisable(struct bfa_ioim_s *ioim)
+{
+       bfa_sm_send_event(ioim, BFA_IOIM_SM_HWFAIL);
+}
+
+/**
+ * IO offline TOV popped. Fail the pending IO.
+ */
+void
+bfa_ioim_tov(struct bfa_ioim_s *ioim)
+{
+       bfa_sm_send_event(ioim, BFA_IOIM_SM_IOTOV);
+}
+
+
+
+/**
+ *  bfa_ioim_api
+ */
+
+/**
+ * Allocate IOIM resource for initiator mode I/O request.
+ */
+struct bfa_ioim_s *
+bfa_ioim_alloc(struct bfa_s *bfa, struct bfad_ioim_s *dio,
+               struct bfa_itnim_s *itnim, u16 nsges)
+{
+       struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(bfa);
+       struct bfa_ioim_s *ioim;
+
+       /**
+        * alocate IOIM resource
+        */
+       bfa_q_deq(&fcpim->ioim_free_q, &ioim);
+       if (!ioim) {
+               bfa_fcpim_stats(fcpim, no_iotags);
+               return NULL;
+       }
+
+       ioim->dio = dio;
+       ioim->itnim = itnim;
+       ioim->nsges = nsges;
+       ioim->nsgpgs = 0;
+
+       bfa_stats(fcpim, total_ios);
+       bfa_stats(itnim, ios);
+       fcpim->ios_active++;
+
+       list_add_tail(&ioim->qe, &itnim->io_q);
+       bfa_trc_fp(ioim->bfa, ioim->iotag);
+
+       return ioim;
+}
+
+void
+bfa_ioim_free(struct bfa_ioim_s *ioim)
+{
+       struct bfa_fcpim_mod_s *fcpim = ioim->fcpim;
+
+       bfa_trc_fp(ioim->bfa, ioim->iotag);
+       bfa_assert_fp(bfa_sm_cmp_state(ioim, bfa_ioim_sm_uninit));
+
+       bfa_assert_fp(list_empty(&ioim->sgpg_q)
+                  || (ioim->nsges > BFI_SGE_INLINE));
+
+       if (ioim->nsgpgs > 0)
+               bfa_sgpg_mfree(ioim->bfa, &ioim->sgpg_q, ioim->nsgpgs);
+
+       bfa_stats(ioim->itnim, io_comps);
+       fcpim->ios_active--;
+
+       list_del(&ioim->qe);
+       list_add_tail(&ioim->qe, &fcpim->ioim_free_q);
+}
+
+void
+bfa_ioim_start(struct bfa_ioim_s *ioim)
+{
+       bfa_trc_fp(ioim->bfa, ioim->iotag);
+       bfa_sm_send_event(ioim, BFA_IOIM_SM_START);
+}
+
+/**
+ * Driver I/O abort request.
+ */
+void
+bfa_ioim_abort(struct bfa_ioim_s *ioim)
+{
+       bfa_trc(ioim->bfa, ioim->iotag);
+       bfa_fcpim_stats(ioim->fcpim, io_aborts);
+       bfa_sm_send_event(ioim, BFA_IOIM_SM_ABORT);
+}
+
+
diff --git a/drivers/scsi/bfa/bfa_itnim.c b/drivers/scsi/bfa/bfa_itnim.c
new file mode 100644 (file)
index 0000000..4d5c61a
--- /dev/null
@@ -0,0 +1,1088 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ */
+
+#include <bfa.h>
+#include <bfa_fcpim.h>
+#include "bfa_fcpim_priv.h"
+
+BFA_TRC_FILE(HAL, ITNIM);
+
+#define BFA_ITNIM_FROM_TAG(_fcpim, _tag)                               \
+       ((_fcpim)->itnim_arr + ((_tag) & ((_fcpim)->num_itnims - 1)))
+
+#define bfa_fcpim_additn(__itnim)                                      \
+       list_add_tail(&(__itnim)->qe, &(__itnim)->fcpim->itnim_q)
+#define bfa_fcpim_delitn(__itnim)      do {                            \
+       bfa_assert(bfa_q_is_on_q(&(__itnim)->fcpim->itnim_q, __itnim));      \
+       list_del(&(__itnim)->qe);      \
+       bfa_assert(list_empty(&(__itnim)->io_q));      \
+       bfa_assert(list_empty(&(__itnim)->io_cleanup_q));      \
+       bfa_assert(list_empty(&(__itnim)->pending_q));      \
+} while (0)
+
+#define bfa_itnim_online_cb(__itnim) do {                              \
+       if ((__itnim)->bfa->fcs)                                        \
+               bfa_cb_itnim_online((__itnim)->ditn);      \
+       else {                                                          \
+               bfa_cb_queue((__itnim)->bfa, &(__itnim)->hcb_qe,        \
+               __bfa_cb_itnim_online, (__itnim));      \
+       }                                                               \
+} while (0)
+
+#define bfa_itnim_offline_cb(__itnim) do {                             \
+       if ((__itnim)->bfa->fcs)                                        \
+               bfa_cb_itnim_offline((__itnim)->ditn);      \
+       else {                                                          \
+               bfa_cb_queue((__itnim)->bfa, &(__itnim)->hcb_qe,        \
+               __bfa_cb_itnim_offline, (__itnim));      \
+       }                                                               \
+} while (0)
+
+#define bfa_itnim_sler_cb(__itnim) do {                                        \
+       if ((__itnim)->bfa->fcs)                                        \
+               bfa_cb_itnim_sler((__itnim)->ditn);      \
+       else {                                                          \
+               bfa_cb_queue((__itnim)->bfa, &(__itnim)->hcb_qe,        \
+               __bfa_cb_itnim_sler, (__itnim));      \
+       }                                                               \
+} while (0)
+
+/*
+ * forward declarations
+ */
+static void     bfa_itnim_iocdisable_cleanup(struct bfa_itnim_s *itnim);
+static bfa_boolean_t bfa_itnim_send_fwcreate(struct bfa_itnim_s *itnim);
+static bfa_boolean_t bfa_itnim_send_fwdelete(struct bfa_itnim_s *itnim);
+static void     bfa_itnim_cleanp_comp(void *itnim_cbarg);
+static void     bfa_itnim_cleanup(struct bfa_itnim_s *itnim);
+static void     __bfa_cb_itnim_online(void *cbarg, bfa_boolean_t complete);
+static void     __bfa_cb_itnim_offline(void *cbarg, bfa_boolean_t complete);
+static void     __bfa_cb_itnim_sler(void *cbarg, bfa_boolean_t complete);
+static void     bfa_itnim_iotov_online(struct bfa_itnim_s *itnim);
+static void     bfa_itnim_iotov_cleanup(struct bfa_itnim_s *itnim);
+static void     bfa_itnim_iotov(void *itnim_arg);
+static void     bfa_itnim_iotov_start(struct bfa_itnim_s *itnim);
+static void     bfa_itnim_iotov_stop(struct bfa_itnim_s *itnim);
+static void     bfa_itnim_iotov_delete(struct bfa_itnim_s *itnim);
+
+/**
+ *  bfa_itnim_sm BFA itnim state machine
+ */
+
+
+enum bfa_itnim_event {
+       BFA_ITNIM_SM_CREATE = 1,        /*  itnim is created */
+       BFA_ITNIM_SM_ONLINE = 2,        /*  itnim is online */
+       BFA_ITNIM_SM_OFFLINE = 3,       /*  itnim is offline */
+       BFA_ITNIM_SM_FWRSP = 4,         /*  firmware response */
+       BFA_ITNIM_SM_DELETE = 5,        /*  deleting an existing itnim */
+       BFA_ITNIM_SM_CLEANUP = 6,       /*  IO cleanup completion */
+       BFA_ITNIM_SM_SLER = 7,          /*  second level error recovery */
+       BFA_ITNIM_SM_HWFAIL = 8,        /*  IOC h/w failure event */
+       BFA_ITNIM_SM_QRESUME = 9,       /*  queue space available */
+};
+
+static void     bfa_itnim_sm_uninit(struct bfa_itnim_s *itnim,
+                                       enum bfa_itnim_event event);
+static void     bfa_itnim_sm_created(struct bfa_itnim_s *itnim,
+                                        enum bfa_itnim_event event);
+static void     bfa_itnim_sm_fwcreate(struct bfa_itnim_s *itnim,
+                                         enum bfa_itnim_event event);
+static void    bfa_itnim_sm_delete_pending(struct bfa_itnim_s *itnim,
+                               enum bfa_itnim_event event);
+static void     bfa_itnim_sm_online(struct bfa_itnim_s *itnim,
+                                       enum bfa_itnim_event event);
+static void     bfa_itnim_sm_sler(struct bfa_itnim_s *itnim,
+                                     enum bfa_itnim_event event);
+static void     bfa_itnim_sm_cleanup_offline(struct bfa_itnim_s *itnim,
+                                                enum bfa_itnim_event event);
+static void     bfa_itnim_sm_cleanup_delete(struct bfa_itnim_s *itnim,
+                                               enum bfa_itnim_event event);
+static void     bfa_itnim_sm_fwdelete(struct bfa_itnim_s *itnim,
+                                         enum bfa_itnim_event event);
+static void     bfa_itnim_sm_offline(struct bfa_itnim_s *itnim,
+                                        enum bfa_itnim_event event);
+static void     bfa_itnim_sm_iocdisable(struct bfa_itnim_s *itnim,
+                                           enum bfa_itnim_event event);
+static void     bfa_itnim_sm_deleting(struct bfa_itnim_s *itnim,
+                                         enum bfa_itnim_event event);
+static void     bfa_itnim_sm_fwcreate_qfull(struct bfa_itnim_s *itnim,
+                                         enum bfa_itnim_event event);
+static void     bfa_itnim_sm_fwdelete_qfull(struct bfa_itnim_s *itnim,
+                                         enum bfa_itnim_event event);
+static void     bfa_itnim_sm_deleting_qfull(struct bfa_itnim_s *itnim,
+                                         enum bfa_itnim_event event);
+
+/**
+ *             Beginning/unallocated state - no events expected.
+ */
+static void
+bfa_itnim_sm_uninit(struct bfa_itnim_s *itnim, enum bfa_itnim_event event)
+{
+       bfa_trc(itnim->bfa, itnim->rport->rport_tag);
+       bfa_trc(itnim->bfa, event);
+
+       switch (event) {
+       case BFA_ITNIM_SM_CREATE:
+               bfa_sm_set_state(itnim, bfa_itnim_sm_created);
+               itnim->is_online = BFA_FALSE;
+               bfa_fcpim_additn(itnim);
+               break;
+
+       default:
+               bfa_assert(0);
+       }
+}
+
+/**
+ *             Beginning state, only online event expected.
+ */
+static void
+bfa_itnim_sm_created(struct bfa_itnim_s *itnim, enum bfa_itnim_event event)
+{
+       bfa_trc(itnim->bfa, itnim->rport->rport_tag);
+       bfa_trc(itnim->bfa, event);
+
+       switch (event) {
+       case BFA_ITNIM_SM_ONLINE:
+               if (bfa_itnim_send_fwcreate(itnim))
+                       bfa_sm_set_state(itnim, bfa_itnim_sm_fwcreate);
+               else
+                       bfa_sm_set_state(itnim, bfa_itnim_sm_fwcreate_qfull);
+               break;
+
+       case BFA_ITNIM_SM_DELETE:
+               bfa_sm_set_state(itnim, bfa_itnim_sm_uninit);
+               bfa_fcpim_delitn(itnim);
+               break;
+
+       case BFA_ITNIM_SM_HWFAIL:
+               bfa_sm_set_state(itnim, bfa_itnim_sm_iocdisable);
+               break;
+
+       default:
+               bfa_assert(0);
+       }
+}
+
+/**
+ *             Waiting for itnim create response from firmware.
+ */
+static void
+bfa_itnim_sm_fwcreate(struct bfa_itnim_s *itnim, enum bfa_itnim_event event)
+{
+       bfa_trc(itnim->bfa, itnim->rport->rport_tag);
+       bfa_trc(itnim->bfa, event);
+
+       switch (event) {
+       case BFA_ITNIM_SM_FWRSP:
+               bfa_sm_set_state(itnim, bfa_itnim_sm_online);
+               itnim->is_online = BFA_TRUE;
+               bfa_itnim_iotov_online(itnim);
+               bfa_itnim_online_cb(itnim);
+               break;
+
+       case BFA_ITNIM_SM_DELETE:
+               bfa_sm_set_state(itnim, bfa_itnim_sm_delete_pending);
+               break;
+
+       case BFA_ITNIM_SM_OFFLINE:
+               if (bfa_itnim_send_fwdelete(itnim))
+                       bfa_sm_set_state(itnim, bfa_itnim_sm_fwdelete);
+               else
+                       bfa_sm_set_state(itnim, bfa_itnim_sm_fwdelete_qfull);
+               break;
+
+       case BFA_ITNIM_SM_HWFAIL:
+               bfa_sm_set_state(itnim, bfa_itnim_sm_iocdisable);
+               break;
+
+       default:
+               bfa_assert(0);
+       }
+}
+
+static void
+bfa_itnim_sm_fwcreate_qfull(struct bfa_itnim_s *itnim,
+                       enum bfa_itnim_event event)
+{
+       bfa_trc(itnim->bfa, itnim->rport->rport_tag);
+       bfa_trc(itnim->bfa, event);
+
+       switch (event) {
+       case BFA_ITNIM_SM_QRESUME:
+               bfa_sm_set_state(itnim, bfa_itnim_sm_fwcreate);
+               bfa_itnim_send_fwcreate(itnim);
+               break;
+
+       case BFA_ITNIM_SM_DELETE:
+               bfa_sm_set_state(itnim, bfa_itnim_sm_uninit);
+               bfa_reqq_wcancel(&itnim->reqq_wait);
+               bfa_fcpim_delitn(itnim);
+               break;
+
+       case BFA_ITNIM_SM_OFFLINE:
+               bfa_sm_set_state(itnim, bfa_itnim_sm_offline);
+               bfa_reqq_wcancel(&itnim->reqq_wait);
+               bfa_itnim_offline_cb(itnim);
+               break;
+
+       case BFA_ITNIM_SM_HWFAIL:
+               bfa_sm_set_state(itnim, bfa_itnim_sm_iocdisable);
+               bfa_reqq_wcancel(&itnim->reqq_wait);
+               break;
+
+       default:
+               bfa_assert(0);
+       }
+}
+
+/**
+ *     Waiting for itnim create response from firmware, a delete is pending.
+ */
+static void
+bfa_itnim_sm_delete_pending(struct bfa_itnim_s *itnim,
+                               enum bfa_itnim_event event)
+{
+       bfa_trc(itnim->bfa, itnim->rport->rport_tag);
+       bfa_trc(itnim->bfa, event);
+
+       switch (event) {
+       case BFA_ITNIM_SM_FWRSP:
+               if (bfa_itnim_send_fwdelete(itnim))
+                       bfa_sm_set_state(itnim, bfa_itnim_sm_deleting);
+               else
+                       bfa_sm_set_state(itnim, bfa_itnim_sm_deleting_qfull);
+               break;
+
+       case BFA_ITNIM_SM_HWFAIL:
+               bfa_sm_set_state(itnim, bfa_itnim_sm_uninit);
+               bfa_fcpim_delitn(itnim);
+               break;
+
+       default:
+               bfa_assert(0);
+       }
+}
+
+/**
+ *             Online state - normal parking state.
+ */
+static void
+bfa_itnim_sm_online(struct bfa_itnim_s *itnim, enum bfa_itnim_event event)
+{
+       bfa_trc(itnim->bfa, itnim->rport->rport_tag);
+       bfa_trc(itnim->bfa, event);
+
+       switch (event) {
+       case BFA_ITNIM_SM_OFFLINE:
+               bfa_sm_set_state(itnim, bfa_itnim_sm_cleanup_offline);
+               itnim->is_online = BFA_FALSE;
+               bfa_itnim_iotov_start(itnim);
+               bfa_itnim_cleanup(itnim);
+               break;
+
+       case BFA_ITNIM_SM_DELETE:
+               bfa_sm_set_state(itnim, bfa_itnim_sm_cleanup_delete);
+               itnim->is_online = BFA_FALSE;
+               bfa_itnim_cleanup(itnim);
+               break;
+
+       case BFA_ITNIM_SM_SLER:
+               bfa_sm_set_state(itnim, bfa_itnim_sm_sler);
+               itnim->is_online = BFA_FALSE;
+               bfa_itnim_iotov_start(itnim);
+               bfa_itnim_sler_cb(itnim);
+               break;
+
+       case BFA_ITNIM_SM_HWFAIL:
+               bfa_sm_set_state(itnim, bfa_itnim_sm_iocdisable);
+               itnim->is_online = BFA_FALSE;
+               bfa_itnim_iotov_start(itnim);
+               bfa_itnim_iocdisable_cleanup(itnim);
+               break;
+
+       default:
+               bfa_assert(0);
+       }
+}
+
+/**
+ *             Second level error recovery need.
+ */
+static void
+bfa_itnim_sm_sler(struct bfa_itnim_s *itnim, enum bfa_itnim_event event)
+{
+       bfa_trc(itnim->bfa, itnim->rport->rport_tag);
+       bfa_trc(itnim->bfa, event);
+
+       switch (event) {
+       case BFA_ITNIM_SM_OFFLINE:
+               bfa_sm_set_state(itnim, bfa_itnim_sm_cleanup_offline);
+               bfa_itnim_cleanup(itnim);
+               break;
+
+       case BFA_ITNIM_SM_DELETE:
+               bfa_sm_set_state(itnim, bfa_itnim_sm_cleanup_delete);
+               bfa_itnim_cleanup(itnim);
+               bfa_itnim_iotov_delete(itnim);
+               break;
+
+       case BFA_ITNIM_SM_HWFAIL:
+               bfa_sm_set_state(itnim, bfa_itnim_sm_iocdisable);
+               bfa_itnim_iocdisable_cleanup(itnim);
+               break;
+
+       default:
+               bfa_assert(0);
+       }
+}
+
+/**
+ *             Going offline. Waiting for active IO cleanup.
+ */
+static void
+bfa_itnim_sm_cleanup_offline(struct bfa_itnim_s *itnim,
+                                enum bfa_itnim_event event)
+{
+       bfa_trc(itnim->bfa, itnim->rport->rport_tag);
+       bfa_trc(itnim->bfa, event);
+
+       switch (event) {
+       case BFA_ITNIM_SM_CLEANUP:
+               if (bfa_itnim_send_fwdelete(itnim))
+                       bfa_sm_set_state(itnim, bfa_itnim_sm_fwdelete);
+               else
+                       bfa_sm_set_state(itnim, bfa_itnim_sm_fwdelete_qfull);
+               break;
+
+       case BFA_ITNIM_SM_DELETE:
+               bfa_sm_set_state(itnim, bfa_itnim_sm_cleanup_delete);
+               bfa_itnim_iotov_delete(itnim);
+               break;
+
+       case BFA_ITNIM_SM_HWFAIL:
+               bfa_sm_set_state(itnim, bfa_itnim_sm_iocdisable);
+               bfa_itnim_iocdisable_cleanup(itnim);
+               bfa_itnim_offline_cb(itnim);
+               break;
+
+       case BFA_ITNIM_SM_SLER:
+               break;
+
+       default:
+               bfa_assert(0);
+       }
+}
+
+/**
+ *             Deleting itnim. Waiting for active IO cleanup.
+ */
+static void
+bfa_itnim_sm_cleanup_delete(struct bfa_itnim_s *itnim,
+                               enum bfa_itnim_event event)
+{
+       bfa_trc(itnim->bfa, itnim->rport->rport_tag);
+       bfa_trc(itnim->bfa, event);
+
+       switch (event) {
+       case BFA_ITNIM_SM_CLEANUP:
+               if (bfa_itnim_send_fwdelete(itnim))
+                       bfa_sm_set_state(itnim, bfa_itnim_sm_deleting);
+               else
+                       bfa_sm_set_state(itnim, bfa_itnim_sm_deleting_qfull);
+               break;
+
+       case BFA_ITNIM_SM_HWFAIL:
+               bfa_sm_set_state(itnim, bfa_itnim_sm_iocdisable);
+               bfa_itnim_iocdisable_cleanup(itnim);
+               break;
+
+       default:
+               bfa_assert(0);
+       }
+}
+
+/**
+ * Rport offline. Fimrware itnim is being deleted - awaiting f/w response.
+ */
+static void
+bfa_itnim_sm_fwdelete(struct bfa_itnim_s *itnim, enum bfa_itnim_event event)
+{
+       bfa_trc(itnim->bfa, itnim->rport->rport_tag);
+       bfa_trc(itnim->bfa, event);
+
+       switch (event) {
+       case BFA_ITNIM_SM_FWRSP:
+               bfa_sm_set_state(itnim, bfa_itnim_sm_offline);
+               bfa_itnim_offline_cb(itnim);
+               break;
+
+       case BFA_ITNIM_SM_DELETE:
+               bfa_sm_set_state(itnim, bfa_itnim_sm_deleting);
+               break;
+
+       case BFA_ITNIM_SM_HWFAIL:
+               bfa_sm_set_state(itnim, bfa_itnim_sm_iocdisable);
+               bfa_itnim_offline_cb(itnim);
+               break;
+
+       default:
+               bfa_assert(0);
+       }
+}
+
+static void
+bfa_itnim_sm_fwdelete_qfull(struct bfa_itnim_s *itnim,
+                       enum bfa_itnim_event event)
+{
+       bfa_trc(itnim->bfa, itnim->rport->rport_tag);
+       bfa_trc(itnim->bfa, event);
+
+       switch (event) {
+       case BFA_ITNIM_SM_QRESUME:
+               bfa_sm_set_state(itnim, bfa_itnim_sm_fwdelete);
+               bfa_itnim_send_fwdelete(itnim);
+               break;
+
+       case BFA_ITNIM_SM_DELETE:
+               bfa_sm_set_state(itnim, bfa_itnim_sm_deleting_qfull);
+               break;
+
+       case BFA_ITNIM_SM_HWFAIL:
+               bfa_sm_set_state(itnim, bfa_itnim_sm_iocdisable);
+               bfa_reqq_wcancel(&itnim->reqq_wait);
+               bfa_itnim_offline_cb(itnim);
+               break;
+
+       default:
+               bfa_assert(0);
+       }
+}
+
+/**
+ *             Offline state.
+ */
+static void
+bfa_itnim_sm_offline(struct bfa_itnim_s *itnim, enum bfa_itnim_event event)
+{
+       bfa_trc(itnim->bfa, itnim->rport->rport_tag);
+       bfa_trc(itnim->bfa, event);
+
+       switch (event) {
+       case BFA_ITNIM_SM_DELETE:
+               bfa_sm_set_state(itnim, bfa_itnim_sm_uninit);
+               bfa_itnim_iotov_delete(itnim);
+               bfa_fcpim_delitn(itnim);
+               break;
+
+       case BFA_ITNIM_SM_ONLINE:
+               if (bfa_itnim_send_fwcreate(itnim))
+                       bfa_sm_set_state(itnim, bfa_itnim_sm_fwcreate);
+               else
+                       bfa_sm_set_state(itnim, bfa_itnim_sm_fwcreate_qfull);
+               break;
+
+       case BFA_ITNIM_SM_HWFAIL:
+               bfa_sm_set_state(itnim, bfa_itnim_sm_iocdisable);
+               break;
+
+       default:
+               bfa_assert(0);
+       }
+}
+
+/**
+ *             IOC h/w failed state.
+ */
+static void
+bfa_itnim_sm_iocdisable(struct bfa_itnim_s *itnim,
+                           enum bfa_itnim_event event)
+{
+       bfa_trc(itnim->bfa, itnim->rport->rport_tag);
+       bfa_trc(itnim->bfa, event);
+
+       switch (event) {
+       case BFA_ITNIM_SM_DELETE:
+               bfa_sm_set_state(itnim, bfa_itnim_sm_uninit);
+               bfa_itnim_iotov_delete(itnim);
+               bfa_fcpim_delitn(itnim);
+               break;
+
+       case BFA_ITNIM_SM_OFFLINE:
+               bfa_itnim_offline_cb(itnim);
+               break;
+
+       case BFA_ITNIM_SM_ONLINE:
+               if (bfa_itnim_send_fwcreate(itnim))
+                       bfa_sm_set_state(itnim, bfa_itnim_sm_fwcreate);
+               else
+                       bfa_sm_set_state(itnim, bfa_itnim_sm_fwcreate_qfull);
+               break;
+
+       case BFA_ITNIM_SM_HWFAIL:
+               break;
+
+       default:
+               bfa_assert(0);
+       }
+}
+
+/**
+ *             Itnim is deleted, waiting for firmware response to delete.
+ */
+static void
+bfa_itnim_sm_deleting(struct bfa_itnim_s *itnim, enum bfa_itnim_event event)
+{
+       bfa_trc(itnim->bfa, itnim->rport->rport_tag);
+       bfa_trc(itnim->bfa, event);
+
+       switch (event) {
+       case BFA_ITNIM_SM_FWRSP:
+       case BFA_ITNIM_SM_HWFAIL:
+               bfa_sm_set_state(itnim, bfa_itnim_sm_uninit);
+               bfa_fcpim_delitn(itnim);
+               break;
+
+       default:
+               bfa_assert(0);
+       }
+}
+
+static void
+bfa_itnim_sm_deleting_qfull(struct bfa_itnim_s *itnim,
+                       enum bfa_itnim_event event)
+{
+       bfa_trc(itnim->bfa, itnim->rport->rport_tag);
+       bfa_trc(itnim->bfa, event);
+
+       switch (event) {
+       case BFA_ITNIM_SM_QRESUME:
+               bfa_sm_set_state(itnim, bfa_itnim_sm_deleting);
+               bfa_itnim_send_fwdelete(itnim);
+               break;
+
+       case BFA_ITNIM_SM_HWFAIL:
+               bfa_sm_set_state(itnim, bfa_itnim_sm_uninit);
+               bfa_reqq_wcancel(&itnim->reqq_wait);
+               bfa_fcpim_delitn(itnim);
+               break;
+
+       default:
+               bfa_assert(0);
+       }
+}
+
+
+
+/**
+ *  bfa_itnim_private
+ */
+
+/**
+ *             Initiate cleanup of all IOs on an IOC failure.
+ */
+static void
+bfa_itnim_iocdisable_cleanup(struct bfa_itnim_s *itnim)
+{
+       struct bfa_tskim_s *tskim;
+       struct bfa_ioim_s *ioim;
+       struct list_head        *qe, *qen;
+
+       list_for_each_safe(qe, qen, &itnim->tsk_q) {
+               tskim = (struct bfa_tskim_s *) qe;
+               bfa_tskim_iocdisable(tskim);
+       }
+
+       list_for_each_safe(qe, qen, &itnim->io_q) {
+               ioim = (struct bfa_ioim_s *) qe;
+               bfa_ioim_iocdisable(ioim);
+       }
+
+       /**
+        * For IO request in pending queue, we pretend an early timeout.
+        */
+       list_for_each_safe(qe, qen, &itnim->pending_q) {
+               ioim = (struct bfa_ioim_s *) qe;
+               bfa_ioim_tov(ioim);
+       }
+
+       list_for_each_safe(qe, qen, &itnim->io_cleanup_q) {
+               ioim = (struct bfa_ioim_s *) qe;
+               bfa_ioim_iocdisable(ioim);
+       }
+}
+
+/**
+ *             IO cleanup completion
+ */
+static void
+bfa_itnim_cleanp_comp(void *itnim_cbarg)
+{
+       struct bfa_itnim_s *itnim = itnim_cbarg;
+
+       bfa_stats(itnim, cleanup_comps);
+       bfa_sm_send_event(itnim, BFA_ITNIM_SM_CLEANUP);
+}
+
+/**
+ *             Initiate cleanup of all IOs.
+ */
+static void
+bfa_itnim_cleanup(struct bfa_itnim_s *itnim)
+{
+       struct bfa_ioim_s  *ioim;
+       struct bfa_tskim_s *tskim;
+       struct list_head         *qe, *qen;
+
+       bfa_wc_init(&itnim->wc, bfa_itnim_cleanp_comp, itnim);
+
+       list_for_each_safe(qe, qen, &itnim->io_q) {
+               ioim = (struct bfa_ioim_s *) qe;
+
+               /**
+                * Move IO to a cleanup queue from active queue so that a later
+                * TM will not pickup this IO.
+                */
+               list_del(&ioim->qe);
+               list_add_tail(&ioim->qe, &itnim->io_cleanup_q);
+
+               bfa_wc_up(&itnim->wc);
+               bfa_ioim_cleanup(ioim);
+       }
+
+       list_for_each_safe(qe, qen, &itnim->tsk_q) {
+               tskim = (struct bfa_tskim_s *) qe;
+               bfa_wc_up(&itnim->wc);
+               bfa_tskim_cleanup(tskim);
+       }
+
+       bfa_wc_wait(&itnim->wc);
+}
+
+static void
+__bfa_cb_itnim_online(void *cbarg, bfa_boolean_t complete)
+{
+       struct bfa_itnim_s *itnim = cbarg;
+
+       if (complete)
+               bfa_cb_itnim_online(itnim->ditn);
+}
+
+static void
+__bfa_cb_itnim_offline(void *cbarg, bfa_boolean_t complete)
+{
+       struct bfa_itnim_s *itnim = cbarg;
+
+       if (complete)
+               bfa_cb_itnim_offline(itnim->ditn);
+}
+
+static void
+__bfa_cb_itnim_sler(void *cbarg, bfa_boolean_t complete)
+{
+       struct bfa_itnim_s *itnim = cbarg;
+
+       if (complete)
+               bfa_cb_itnim_sler(itnim->ditn);
+}
+
+/**
+ * Call to resume any I/O requests waiting for room in request queue.
+ */
+static void
+bfa_itnim_qresume(void *cbarg)
+{
+       struct bfa_itnim_s *itnim = cbarg;
+
+       bfa_sm_send_event(itnim, BFA_ITNIM_SM_QRESUME);
+}
+
+
+
+
+/**
+ *  bfa_itnim_public
+ */
+
+void
+bfa_itnim_iodone(struct bfa_itnim_s *itnim)
+{
+       bfa_wc_down(&itnim->wc);
+}
+
+void
+bfa_itnim_tskdone(struct bfa_itnim_s *itnim)
+{
+       bfa_wc_down(&itnim->wc);
+}
+
+void
+bfa_itnim_meminfo(struct bfa_iocfc_cfg_s *cfg, u32 *km_len,
+               u32 *dm_len)
+{
+       /**
+        * ITN memory
+        */
+       *km_len += cfg->fwcfg.num_rports * sizeof(struct bfa_itnim_s);
+}
+
+void
+bfa_itnim_attach(struct bfa_fcpim_mod_s *fcpim, struct bfa_meminfo_s *minfo)
+{
+       struct bfa_s      *bfa = fcpim->bfa;
+       struct bfa_itnim_s *itnim;
+       int             i;
+
+       INIT_LIST_HEAD(&fcpim->itnim_q);
+
+       itnim = (struct bfa_itnim_s *) bfa_meminfo_kva(minfo);
+       fcpim->itnim_arr = itnim;
+
+       for (i = 0; i < fcpim->num_itnims; i++, itnim++) {
+               bfa_os_memset(itnim, 0, sizeof(struct bfa_itnim_s));
+               itnim->bfa = bfa;
+               itnim->fcpim = fcpim;
+               itnim->reqq = BFA_REQQ_QOS_LO;
+               itnim->rport = BFA_RPORT_FROM_TAG(bfa, i);
+               itnim->iotov_active = BFA_FALSE;
+               bfa_reqq_winit(&itnim->reqq_wait, bfa_itnim_qresume, itnim);
+
+               INIT_LIST_HEAD(&itnim->io_q);
+               INIT_LIST_HEAD(&itnim->io_cleanup_q);
+               INIT_LIST_HEAD(&itnim->pending_q);
+               INIT_LIST_HEAD(&itnim->tsk_q);
+               INIT_LIST_HEAD(&itnim->delay_comp_q);
+               bfa_sm_set_state(itnim, bfa_itnim_sm_uninit);
+       }
+
+       bfa_meminfo_kva(minfo) = (u8 *) itnim;
+}
+
+void
+bfa_itnim_iocdisable(struct bfa_itnim_s *itnim)
+{
+       bfa_stats(itnim, ioc_disabled);
+       bfa_sm_send_event(itnim, BFA_ITNIM_SM_HWFAIL);
+}
+
+static bfa_boolean_t
+bfa_itnim_send_fwcreate(struct bfa_itnim_s *itnim)
+{
+       struct bfi_itnim_create_req_s *m;
+
+       itnim->msg_no++;
+
+       /**
+        * check for room in queue to send request now
+        */
+       m = bfa_reqq_next(itnim->bfa, itnim->reqq);
+       if (!m) {
+               bfa_reqq_wait(itnim->bfa, itnim->reqq, &itnim->reqq_wait);
+               return BFA_FALSE;
+       }
+
+       bfi_h2i_set(m->mh, BFI_MC_ITNIM, BFI_ITNIM_H2I_CREATE_REQ,
+                       bfa_lpuid(itnim->bfa));
+       m->fw_handle = itnim->rport->fw_handle;
+       m->class = FC_CLASS_3;
+       m->seq_rec = itnim->seq_rec;
+       m->msg_no = itnim->msg_no;
+
+       /**
+        * queue I/O message to firmware
+        */
+       bfa_reqq_produce(itnim->bfa, itnim->reqq);
+       return BFA_TRUE;
+}
+
+static bfa_boolean_t
+bfa_itnim_send_fwdelete(struct bfa_itnim_s *itnim)
+{
+       struct bfi_itnim_delete_req_s *m;
+
+       /**
+        * check for room in queue to send request now
+        */
+       m = bfa_reqq_next(itnim->bfa, itnim->reqq);
+       if (!m) {
+               bfa_reqq_wait(itnim->bfa, itnim->reqq, &itnim->reqq_wait);
+               return BFA_FALSE;
+       }
+
+       bfi_h2i_set(m->mh, BFI_MC_ITNIM, BFI_ITNIM_H2I_DELETE_REQ,
+                       bfa_lpuid(itnim->bfa));
+       m->fw_handle = itnim->rport->fw_handle;
+
+       /**
+        * queue I/O message to firmware
+        */
+       bfa_reqq_produce(itnim->bfa, itnim->reqq);
+       return BFA_TRUE;
+}
+
+/**
+ * Cleanup all pending failed inflight requests.
+ */
+static void
+bfa_itnim_delayed_comp(struct bfa_itnim_s *itnim, bfa_boolean_t iotov)
+{
+       struct bfa_ioim_s *ioim;
+       struct list_head *qe, *qen;
+
+       list_for_each_safe(qe, qen, &itnim->delay_comp_q) {
+               ioim = (struct bfa_ioim_s *)qe;
+               bfa_ioim_delayed_comp(ioim, iotov);
+       }
+}
+
+/**
+ * Start all pending IO requests.
+ */
+static void
+bfa_itnim_iotov_online(struct bfa_itnim_s *itnim)
+{
+       struct bfa_ioim_s *ioim;
+
+       bfa_itnim_iotov_stop(itnim);
+
+       /**
+        * Abort all inflight IO requests in the queue
+        */
+       bfa_itnim_delayed_comp(itnim, BFA_FALSE);
+
+       /**
+        * Start all pending IO requests.
+        */
+       while (!list_empty(&itnim->pending_q)) {
+               bfa_q_deq(&itnim->pending_q, &ioim);
+               list_add_tail(&ioim->qe, &itnim->io_q);
+               bfa_ioim_start(ioim);
+       }
+}
+
+/**
+ * Fail all pending IO requests
+ */
+static void
+bfa_itnim_iotov_cleanup(struct bfa_itnim_s *itnim)
+{
+       struct bfa_ioim_s *ioim;
+
+       /**
+        * Fail all inflight IO requests in the queue
+        */
+       bfa_itnim_delayed_comp(itnim, BFA_TRUE);
+
+       /**
+        * Fail any pending IO requests.
+        */
+       while (!list_empty(&itnim->pending_q)) {
+               bfa_q_deq(&itnim->pending_q, &ioim);
+               list_add_tail(&ioim->qe, &ioim->fcpim->ioim_comp_q);
+               bfa_ioim_tov(ioim);
+       }
+}
+
+/**
+ * IO TOV timer callback. Fail any pending IO requests.
+ */
+static void
+bfa_itnim_iotov(void *itnim_arg)
+{
+       struct bfa_itnim_s *itnim = itnim_arg;
+
+       itnim->iotov_active = BFA_FALSE;
+
+       bfa_cb_itnim_tov_begin(itnim->ditn);
+       bfa_itnim_iotov_cleanup(itnim);
+       bfa_cb_itnim_tov(itnim->ditn);
+}
+
+/**
+ * Start IO TOV timer for failing back pending IO requests in offline state.
+ */
+static void
+bfa_itnim_iotov_start(struct bfa_itnim_s *itnim)
+{
+       if (itnim->fcpim->path_tov > 0) {
+
+               itnim->iotov_active = BFA_TRUE;
+               bfa_assert(bfa_itnim_hold_io(itnim));
+               bfa_timer_start(itnim->bfa, &itnim->timer,
+                       bfa_itnim_iotov, itnim, itnim->fcpim->path_tov);
+       }
+}
+
+/**
+ * Stop IO TOV timer.
+ */
+static void
+bfa_itnim_iotov_stop(struct bfa_itnim_s *itnim)
+{
+       if (itnim->iotov_active) {
+               itnim->iotov_active = BFA_FALSE;
+               bfa_timer_stop(&itnim->timer);
+       }
+}
+
+/**
+ * Stop IO TOV timer.
+ */
+static void
+bfa_itnim_iotov_delete(struct bfa_itnim_s *itnim)
+{
+    bfa_boolean_t pathtov_active = BFA_FALSE;
+
+    if (itnim->iotov_active)
+               pathtov_active = BFA_TRUE;
+
+       bfa_itnim_iotov_stop(itnim);
+       if (pathtov_active)
+               bfa_cb_itnim_tov_begin(itnim->ditn);
+       bfa_itnim_iotov_cleanup(itnim);
+       if (pathtov_active)
+               bfa_cb_itnim_tov(itnim->ditn);
+}
+
+
+
+/**
+ *  bfa_itnim_public
+ */
+
+/**
+ *             Itnim interrupt processing.
+ */
+void
+bfa_itnim_isr(struct bfa_s *bfa, struct bfi_msg_s *m)
+{
+       struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(bfa);
+       union bfi_itnim_i2h_msg_u msg;
+       struct bfa_itnim_s *itnim;
+
+       bfa_trc(bfa, m->mhdr.msg_id);
+
+       msg.msg = m;
+
+       switch (m->mhdr.msg_id) {
+       case BFI_ITNIM_I2H_CREATE_RSP:
+               itnim = BFA_ITNIM_FROM_TAG(fcpim,
+                                              msg.create_rsp->bfa_handle);
+               bfa_assert(msg.create_rsp->status == BFA_STATUS_OK);
+               bfa_stats(itnim, create_comps);
+               bfa_sm_send_event(itnim, BFA_ITNIM_SM_FWRSP);
+               break;
+
+       case BFI_ITNIM_I2H_DELETE_RSP:
+               itnim = BFA_ITNIM_FROM_TAG(fcpim,
+                                              msg.delete_rsp->bfa_handle);
+               bfa_assert(msg.delete_rsp->status == BFA_STATUS_OK);
+               bfa_stats(itnim, delete_comps);
+               bfa_sm_send_event(itnim, BFA_ITNIM_SM_FWRSP);
+               break;
+
+       case BFI_ITNIM_I2H_SLER_EVENT:
+               itnim = BFA_ITNIM_FROM_TAG(fcpim,
+                                              msg.sler_event->bfa_handle);
+               bfa_stats(itnim, sler_events);
+               bfa_sm_send_event(itnim, BFA_ITNIM_SM_SLER);
+               break;
+
+       default:
+               bfa_trc(bfa, m->mhdr.msg_id);
+               bfa_assert(0);
+       }
+}
+
+
+
+/**
+ *  bfa_itnim_api
+ */
+
+struct bfa_itnim_s *
+bfa_itnim_create(struct bfa_s *bfa, struct bfa_rport_s *rport, void *ditn)
+{
+       struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(bfa);
+       struct bfa_itnim_s *itnim;
+
+       itnim = BFA_ITNIM_FROM_TAG(fcpim, rport->rport_tag);
+       bfa_assert(itnim->rport == rport);
+
+       itnim->ditn = ditn;
+
+       bfa_stats(itnim, creates);
+       bfa_sm_send_event(itnim, BFA_ITNIM_SM_CREATE);
+
+       return (itnim);
+}
+
+void
+bfa_itnim_delete(struct bfa_itnim_s *itnim)
+{
+       bfa_stats(itnim, deletes);
+       bfa_sm_send_event(itnim, BFA_ITNIM_SM_DELETE);
+}
+
+void
+bfa_itnim_online(struct bfa_itnim_s *itnim, bfa_boolean_t seq_rec)
+{
+       itnim->seq_rec = seq_rec;
+       bfa_stats(itnim, onlines);
+       bfa_sm_send_event(itnim, BFA_ITNIM_SM_ONLINE);
+}
+
+void
+bfa_itnim_offline(struct bfa_itnim_s *itnim)
+{
+       bfa_stats(itnim, offlines);
+       bfa_sm_send_event(itnim, BFA_ITNIM_SM_OFFLINE);
+}
+
+/**
+ * Return true if itnim is considered offline for holding off IO request.
+ * IO is not held if itnim is being deleted.
+ */
+bfa_boolean_t
+bfa_itnim_hold_io(struct bfa_itnim_s *itnim)
+{
+       return (
+               itnim->fcpim->path_tov && itnim->iotov_active &&
+               (bfa_sm_cmp_state(itnim, bfa_itnim_sm_fwcreate) ||
+                bfa_sm_cmp_state(itnim, bfa_itnim_sm_sler) ||
+                bfa_sm_cmp_state(itnim, bfa_itnim_sm_cleanup_offline) ||
+                bfa_sm_cmp_state(itnim, bfa_itnim_sm_fwdelete) ||
+                bfa_sm_cmp_state(itnim, bfa_itnim_sm_offline) ||
+                bfa_sm_cmp_state(itnim, bfa_itnim_sm_iocdisable))
+);
+}
+
+void
+bfa_itnim_get_stats(struct bfa_itnim_s *itnim,
+       struct bfa_itnim_hal_stats_s *stats)
+{
+       *stats = itnim->stats;
+}
+
+void
+bfa_itnim_clear_stats(struct bfa_itnim_s *itnim)
+{
+       bfa_os_memset(&itnim->stats, 0, sizeof(itnim->stats));
+}
+
+
diff --git a/drivers/scsi/bfa/bfa_log.c b/drivers/scsi/bfa/bfa_log.c
new file mode 100644 (file)
index 0000000..c2735e5
--- /dev/null
@@ -0,0 +1,346 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) 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.
+ */
+
+/**
+ *  bfa_log.c BFA log library
+ */
+
+#include <bfa_os_inc.h>
+#include <cs/bfa_log.h>
+
+/*
+ * global log info structure
+ */
+struct bfa_log_info_s {
+       u32        start_idx;   /*  start index for a module */
+       u32        total_count; /*  total count for a module */
+       enum bfa_log_severity level;    /*  global log level */
+       bfa_log_cb_t    cbfn;           /*  callback function */
+};
+
+static struct bfa_log_info_s bfa_log_info[BFA_LOG_MODULE_ID_MAX + 1];
+static u32 bfa_log_msg_total_count;
+static int      bfa_log_initialized;
+
+static char    *bfa_log_severity[] =
+       { "[none]", "[critical]", "[error]", "[warn]", "[info]", "" };
+
+/**
+ * BFA log library initialization
+ *
+ * The log library initialization includes the following,
+ *    - set log instance name and callback function
+ *    - read the message array generated from xml files
+ *    - calculate start index for each module
+ *    - calculate message count for each module
+ *    - perform error checking
+ *
+ * @param[in] log_mod - log module info
+ * @param[in] instance_name - instance name
+ * @param[in] cbfn - callback function
+ *
+ * It return 0 on success, or -1 on failure
+ */
+int
+bfa_log_init(struct bfa_log_mod_s *log_mod, char *instance_name,
+                       bfa_log_cb_t cbfn)
+{
+       struct bfa_log_msgdef_s *msg;
+       u32        pre_mod_id = 0;
+       u32        cur_mod_id = 0;
+       u32        i, pre_idx, idx, msg_id;
+
+       /*
+        * set instance name
+        */
+       if (log_mod) {
+               strncpy(log_mod->instance_info, instance_name,
+                       sizeof(log_mod->instance_info));
+               log_mod->cbfn = cbfn;
+               for (i = 0; i <= BFA_LOG_MODULE_ID_MAX; i++)
+                       log_mod->log_level[i] = BFA_LOG_WARNING;
+       }
+
+       if (bfa_log_initialized)
+               return 0;
+
+       for (i = 0; i <= BFA_LOG_MODULE_ID_MAX; i++) {
+               bfa_log_info[i].start_idx = 0;
+               bfa_log_info[i].total_count = 0;
+               bfa_log_info[i].level = BFA_LOG_WARNING;
+               bfa_log_info[i].cbfn = cbfn;
+       }
+
+       pre_idx = 0;
+       idx = 0;
+       msg = bfa_log_msg_array;
+       msg_id = BFA_LOG_GET_MSG_ID(msg);
+       pre_mod_id = BFA_LOG_GET_MOD_ID(msg_id);
+       while (msg_id != 0) {
+               cur_mod_id = BFA_LOG_GET_MOD_ID(msg_id);
+
+               if (cur_mod_id > BFA_LOG_MODULE_ID_MAX) {
+                       cbfn(log_mod, msg_id,
+                               "%s%s log: module id %u out of range\n",
+                               BFA_LOG_CAT_NAME,
+                               bfa_log_severity[BFA_LOG_ERROR],
+                               cur_mod_id);
+                       return -1;
+               }
+
+               if (pre_mod_id > BFA_LOG_MODULE_ID_MAX) {
+                       cbfn(log_mod, msg_id,
+                               "%s%s log: module id %u out of range\n",
+                               BFA_LOG_CAT_NAME,
+                               bfa_log_severity[BFA_LOG_ERROR],
+                               pre_mod_id);
+                       return -1;
+               }
+
+               if (cur_mod_id != pre_mod_id) {
+                       bfa_log_info[pre_mod_id].start_idx = pre_idx;
+                       bfa_log_info[pre_mod_id].total_count = idx - pre_idx;
+                       pre_mod_id = cur_mod_id;
+                       pre_idx = idx;
+               }
+
+               idx++;
+               msg++;
+               msg_id = BFA_LOG_GET_MSG_ID(msg);
+       }
+
+       bfa_log_info[cur_mod_id].start_idx = pre_idx;
+       bfa_log_info[cur_mod_id].total_count = idx - pre_idx;
+       bfa_log_msg_total_count = idx;
+
+       cbfn(log_mod, msg_id, "%s%s log: init OK, msg total count %u\n",
+               BFA_LOG_CAT_NAME,
+               bfa_log_severity[BFA_LOG_INFO], bfa_log_msg_total_count);
+
+       bfa_log_initialized = 1;
+
+       return 0;
+}
+
+/**
+ * BFA log set log level for a module
+ *
+ * @param[in] log_mod - log module info
+ * @param[in] mod_id - module id
+ * @param[in] log_level - log severity level
+ *
+ * It return BFA_STATUS_OK on success, or > 0 on failure
+ */
+bfa_status_t
+bfa_log_set_level(struct bfa_log_mod_s *log_mod, int mod_id,
+                 enum bfa_log_severity log_level)
+{
+       if (mod_id <= BFA_LOG_UNUSED_ID || mod_id > BFA_LOG_MODULE_ID_MAX)
+               return BFA_STATUS_EINVAL;
+
+       if (log_level <= BFA_LOG_INVALID || log_level > BFA_LOG_LEVEL_MAX)
+               return BFA_STATUS_EINVAL;
+
+       if (log_mod)
+               log_mod->log_level[mod_id] = log_level;
+       else
+               bfa_log_info[mod_id].level = log_level;
+
+       return BFA_STATUS_OK;
+}
+
+/**
+ * BFA log set log level for all modules
+ *
+ * @param[in] log_mod - log module info
+ * @param[in] log_level - log severity level
+ *
+ * It return BFA_STATUS_OK on success, or > 0 on failure
+ */
+bfa_status_t
+bfa_log_set_level_all(struct bfa_log_mod_s *log_mod,
+                 enum bfa_log_severity log_level)
+{
+       int mod_id = BFA_LOG_UNUSED_ID + 1;
+
+       if (log_level <= BFA_LOG_INVALID || log_level > BFA_LOG_LEVEL_MAX)
+               return BFA_STATUS_EINVAL;
+
+       if (log_mod) {
+               for (; mod_id <= BFA_LOG_MODULE_ID_MAX; mod_id++)
+                       log_mod->log_level[mod_id] = log_level;
+       } else {
+               for (; mod_id <= BFA_LOG_MODULE_ID_MAX; mod_id++)
+                       bfa_log_info[mod_id].level = log_level;
+       }
+
+       return BFA_STATUS_OK;
+}
+
+/**
+ * BFA log set log level for all aen sub-modules
+ *
+ * @param[in] log_mod - log module info
+ * @param[in] log_level - log severity level
+ *
+ * It return BFA_STATUS_OK on success, or > 0 on failure
+ */
+bfa_status_t
+bfa_log_set_level_aen(struct bfa_log_mod_s *log_mod,
+                 enum bfa_log_severity log_level)
+{
+       int mod_id = BFA_LOG_AEN_MIN + 1;
+
+       if (log_mod) {
+               for (; mod_id <= BFA_LOG_AEN_MAX; mod_id++)
+                       log_mod->log_level[mod_id] = log_level;
+       } else {
+               for (; mod_id <= BFA_LOG_AEN_MAX; mod_id++)
+                       bfa_log_info[mod_id].level = log_level;
+       }
+
+       return BFA_STATUS_OK;
+}
+
+/**
+ * BFA log get log level for a module
+ *
+ * @param[in] log_mod - log module info
+ * @param[in] mod_id - module id
+ *
+ * It returns log level or -1 on error
+ */
+enum bfa_log_severity
+bfa_log_get_level(struct bfa_log_mod_s *log_mod, int mod_id)
+{
+       if (mod_id <= BFA_LOG_UNUSED_ID || mod_id > BFA_LOG_MODULE_ID_MAX)
+               return BFA_LOG_INVALID;
+
+       if (log_mod)
+               return (log_mod->log_level[mod_id]);
+       else
+               return (bfa_log_info[mod_id].level);
+}
+
+enum bfa_log_severity
+bfa_log_get_msg_level(struct bfa_log_mod_s *log_mod, u32 msg_id)
+{
+       struct bfa_log_msgdef_s *msg;
+       u32        mod = BFA_LOG_GET_MOD_ID(msg_id);
+       u32        idx = BFA_LOG_GET_MSG_IDX(msg_id) - 1;
+
+       if (!bfa_log_initialized)
+               return BFA_LOG_INVALID;
+
+       if (mod > BFA_LOG_MODULE_ID_MAX)
+               return BFA_LOG_INVALID;
+
+       if (idx >= bfa_log_info[mod].total_count) {
+               bfa_log_info[mod].cbfn(log_mod, msg_id,
+                       "%s%s log: inconsistent idx %u vs. total count %u\n",
+                       BFA_LOG_CAT_NAME, bfa_log_severity[BFA_LOG_ERROR], idx,
+                       bfa_log_info[mod].total_count);
+               return BFA_LOG_INVALID;
+       }
+
+       msg = bfa_log_msg_array + bfa_log_info[mod].start_idx + idx;
+       if (msg_id != BFA_LOG_GET_MSG_ID(msg)) {
+               bfa_log_info[mod].cbfn(log_mod, msg_id,
+                       "%s%s log: inconsistent msg id %u array msg id %u\n",
+                       BFA_LOG_CAT_NAME, bfa_log_severity[BFA_LOG_ERROR],
+                       msg_id, BFA_LOG_GET_MSG_ID(msg));
+               return BFA_LOG_INVALID;
+       }
+
+       return BFA_LOG_GET_SEVERITY(msg);
+}
+
+/**
+ * BFA log message handling
+ *
+ * BFA log message handling finds the message based on message id and prints
+ * out the message based on its format and arguments. It also does prefix
+ * the severity etc.
+ *
+ * @param[in] log_mod - log module info
+ * @param[in] msg_id - message id
+ * @param[in] ... - message arguments
+ *
+ * It return 0 on success, or -1 on errors
+ */
+int
+bfa_log(struct bfa_log_mod_s *log_mod, u32 msg_id, ...)
+{
+       va_list         ap;
+       char            buf[256];
+       struct bfa_log_msgdef_s *msg;
+       int             log_level;
+       u32        mod = BFA_LOG_GET_MOD_ID(msg_id);
+       u32        idx = BFA_LOG_GET_MSG_IDX(msg_id) - 1;
+
+       if (!bfa_log_initialized)
+               return -1;
+
+       if (mod > BFA_LOG_MODULE_ID_MAX)
+               return -1;
+
+       if (idx >= bfa_log_info[mod].total_count) {
+               bfa_log_info[mod].
+                       cbfn
+                       (log_mod, msg_id,
+                       "%s%s log: inconsistent idx %u vs. total count %u\n",
+                       BFA_LOG_CAT_NAME, bfa_log_severity[BFA_LOG_ERROR], idx,
+                       bfa_log_info[mod].total_count);
+               return -1;
+       }
+
+       msg = bfa_log_msg_array + bfa_log_info[mod].start_idx + idx;
+       if (msg_id != BFA_LOG_GET_MSG_ID(msg)) {
+               bfa_log_info[mod].
+                       cbfn
+                       (log_mod, msg_id,
+                       "%s%s log: inconsistent msg id %u array msg id %u\n",
+                       BFA_LOG_CAT_NAME, bfa_log_severity[BFA_LOG_ERROR],
+                       msg_id, BFA_LOG_GET_MSG_ID(msg));
+               return -1;
+       }
+
+       log_level = log_mod ? log_mod->log_level[mod] : bfa_log_info[mod].level;
+       if ((BFA_LOG_GET_SEVERITY(msg) > log_level) &&
+                       (msg->attributes != BFA_LOG_ATTR_NONE))
+               return 0;
+
+       va_start(ap, msg_id);
+       bfa_os_vsprintf(buf, BFA_LOG_GET_MSG_FMT_STRING(msg), ap);
+       va_end(ap);
+
+       if (log_mod)
+               log_mod->cbfn(log_mod, msg_id, "%s[%s]%s%s %s: %s\n",
+                               BFA_LOG_CAT_NAME, log_mod->instance_info,
+                               bfa_log_severity[BFA_LOG_GET_SEVERITY(msg)],
+                               (msg->attributes & BFA_LOG_ATTR_AUDIT)
+                               ? " (audit) " : "", msg->msg_value, buf);
+       else
+               bfa_log_info[mod].cbfn(log_mod, msg_id, "%s%s%s %s: %s\n",
+                               BFA_LOG_CAT_NAME,
+                               bfa_log_severity[BFA_LOG_GET_SEVERITY(msg)],
+                               (msg->attributes & BFA_LOG_ATTR_AUDIT) ?
+                               " (audit) " : "", msg->msg_value, buf);
+
+       return 0;
+}
+
diff --git a/drivers/scsi/bfa/bfa_log_module.c b/drivers/scsi/bfa/bfa_log_module.c
new file mode 100644 (file)
index 0000000..5c154d3
--- /dev/null
@@ -0,0 +1,451 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ */
+
+#include <cs/bfa_log.h>
+#include <aen/bfa_aen_adapter.h>
+#include <aen/bfa_aen_audit.h>
+#include <aen/bfa_aen_ethport.h>
+#include <aen/bfa_aen_ioc.h>
+#include <aen/bfa_aen_itnim.h>
+#include <aen/bfa_aen_lport.h>
+#include <aen/bfa_aen_port.h>
+#include <aen/bfa_aen_rport.h>
+#include <log/bfa_log_fcs.h>
+#include <log/bfa_log_hal.h>
+#include <log/bfa_log_linux.h>
+#include <log/bfa_log_wdrv.h>
+
+struct bfa_log_msgdef_s bfa_log_msg_array[] = {
+
+
+/* messages define for BFA_AEN_CAT_ADAPTER Module */
+{BFA_AEN_ADAPTER_ADD, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, BFA_LOG_INFO,
+ "BFA_AEN_ADAPTER_ADD",
+ "New adapter found: SN = %s, base port WWN = %s.",
+ ((BFA_LOG_S << BFA_LOG_ARG0) | (BFA_LOG_S << BFA_LOG_ARG1) | 0), 2},
+
+{BFA_AEN_ADAPTER_REMOVE, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG,
+ BFA_LOG_WARNING, "BFA_AEN_ADAPTER_REMOVE",
+ "Adapter removed: SN = %s.",
+ ((BFA_LOG_S << BFA_LOG_ARG0) | 0), 1},
+
+
+
+
+/* messages define for BFA_AEN_CAT_AUDIT Module */
+{BFA_AEN_AUDIT_AUTH_ENABLE, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG,
+ BFA_LOG_INFO, "BFA_AEN_AUDIT_AUTH_ENABLE",
+ "Authentication enabled for base port: WWN = %s.",
+ ((BFA_LOG_S << BFA_LOG_ARG0) | 0), 1},
+
+{BFA_AEN_AUDIT_AUTH_DISABLE, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG,
+ BFA_LOG_INFO, "BFA_AEN_AUDIT_AUTH_DISABLE",
+ "Authentication disabled for base port: WWN = %s.",
+ ((BFA_LOG_S << BFA_LOG_ARG0) | 0), 1},
+
+
+
+
+/* messages define for BFA_AEN_CAT_ETHPORT Module */
+{BFA_AEN_ETHPORT_LINKUP, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, BFA_LOG_INFO,
+ "BFA_AEN_ETHPORT_LINKUP",
+ "Base port ethernet linkup: mac = %s.",
+ ((BFA_LOG_S << BFA_LOG_ARG0) | 0), 1},
+
+{BFA_AEN_ETHPORT_LINKDOWN, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, BFA_LOG_INFO,
+ "BFA_AEN_ETHPORT_LINKDOWN",
+ "Base port ethernet linkdown: mac = %s.",
+ ((BFA_LOG_S << BFA_LOG_ARG0) | 0), 1},
+
+{BFA_AEN_ETHPORT_ENABLE, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, BFA_LOG_INFO,
+ "BFA_AEN_ETHPORT_ENABLE",
+ "Base port ethernet interface enabled: mac = %s.",
+ ((BFA_LOG_S << BFA_LOG_ARG0) | 0), 1},
+
+{BFA_AEN_ETHPORT_DISABLE, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, BFA_LOG_INFO,
+ "BFA_AEN_ETHPORT_DISABLE",
+ "Base port ethernet interface disabled: mac = %s.",
+ ((BFA_LOG_S << BFA_LOG_ARG0) | 0), 1},
+
+
+
+
+/* messages define for BFA_AEN_CAT_IOC Module */
+{BFA_AEN_IOC_HBGOOD, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, BFA_LOG_INFO,
+ "BFA_AEN_IOC_HBGOOD",
+ "Heart Beat of IOC %d is good.",
+ ((BFA_LOG_D << BFA_LOG_ARG0) | 0), 1},
+
+{BFA_AEN_IOC_HBFAIL, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, BFA_LOG_CRITICAL,
+ "BFA_AEN_IOC_HBFAIL",
+ "Heart Beat of IOC %d has failed.",
+ ((BFA_LOG_D << BFA_LOG_ARG0) | 0), 1},
+
+{BFA_AEN_IOC_ENABLE, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, BFA_LOG_INFO,
+ "BFA_AEN_IOC_ENABLE",
+ "IOC %d is enabled.",
+ ((BFA_LOG_D << BFA_LOG_ARG0) | 0), 1},
+
+{BFA_AEN_IOC_DISABLE, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, BFA_LOG_INFO,
+ "BFA_AEN_IOC_DISABLE",
+ "IOC %d is disabled.",
+ ((BFA_LOG_D << BFA_LOG_ARG0) | 0), 1},
+
+{BFA_AEN_IOC_FWMISMATCH, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG,
+ BFA_LOG_CRITICAL, "BFA_AEN_IOC_FWMISMATCH",
+ "Running firmware version is incompatible with the driver version.",
+ (0), 0},
+
+
+
+
+/* messages define for BFA_AEN_CAT_ITNIM Module */
+{BFA_AEN_ITNIM_ONLINE, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, BFA_LOG_INFO,
+ "BFA_AEN_ITNIM_ONLINE",
+ "Target (WWN = %s) is online for initiator (WWN = %s).",
+ ((BFA_LOG_S << BFA_LOG_ARG0) | (BFA_LOG_S << BFA_LOG_ARG1) | 0), 2},
+
+{BFA_AEN_ITNIM_OFFLINE, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, BFA_LOG_INFO,
+ "BFA_AEN_ITNIM_OFFLINE",
+ "Target (WWN = %s) offlined by initiator (WWN = %s).",
+ ((BFA_LOG_S << BFA_LOG_ARG0) | (BFA_LOG_S << BFA_LOG_ARG1) | 0), 2},
+
+{BFA_AEN_ITNIM_DISCONNECT, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG,
+ BFA_LOG_ERROR, "BFA_AEN_ITNIM_DISCONNECT",
+ "Target (WWN = %s) connectivity lost for initiator (WWN = %s).",
+ ((BFA_LOG_S << BFA_LOG_ARG0) | (BFA_LOG_S << BFA_LOG_ARG1) | 0), 2},
+
+
+
+
+/* messages define for BFA_AEN_CAT_LPORT Module */
+{BFA_AEN_LPORT_NEW, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, BFA_LOG_INFO,
+ "BFA_AEN_LPORT_NEW",
+ "New logical port created: WWN = %s, Role = %s.",
+ ((BFA_LOG_S << BFA_LOG_ARG0) | (BFA_LOG_S << BFA_LOG_ARG1) | 0), 2},
+
+{BFA_AEN_LPORT_DELETE, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, BFA_LOG_INFO,
+ "BFA_AEN_LPORT_DELETE",
+ "Logical port deleted: WWN = %s, Role = %s.",
+ ((BFA_LOG_S << BFA_LOG_ARG0) | (BFA_LOG_S << BFA_LOG_ARG1) | 0), 2},
+
+{BFA_AEN_LPORT_ONLINE, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, BFA_LOG_INFO,
+ "BFA_AEN_LPORT_ONLINE",
+ "Logical port online: WWN = %s, Role = %s.",
+ ((BFA_LOG_S << BFA_LOG_ARG0) | (BFA_LOG_S << BFA_LOG_ARG1) | 0), 2},
+
+{BFA_AEN_LPORT_OFFLINE, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, BFA_LOG_INFO,
+ "BFA_AEN_LPORT_OFFLINE",
+ "Logical port taken offline: WWN = %s, Role = %s.",
+ ((BFA_LOG_S << BFA_LOG_ARG0) | (BFA_LOG_S << BFA_LOG_ARG1) | 0), 2},
+
+{BFA_AEN_LPORT_DISCONNECT, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG,
+ BFA_LOG_ERROR, "BFA_AEN_LPORT_DISCONNECT",
+ "Logical port lost fabric connectivity: WWN = %s, Role = %s.",
+ ((BFA_LOG_S << BFA_LOG_ARG0) | (BFA_LOG_S << BFA_LOG_ARG1) | 0), 2},
+
+{BFA_AEN_LPORT_NEW_PROP, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, BFA_LOG_INFO,
+ "BFA_AEN_LPORT_NEW_PROP",
+ "New virtual port created using proprietary interface: WWN = %s, Role = %s.",
+ ((BFA_LOG_S << BFA_LOG_ARG0) | (BFA_LOG_S << BFA_LOG_ARG1) | 0), 2},
+
+{BFA_AEN_LPORT_DELETE_PROP, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG,
+ BFA_LOG_INFO, "BFA_AEN_LPORT_DELETE_PROP",
+ "Virtual port deleted using proprietary interface: WWN = %s, Role = %s.",
+ ((BFA_LOG_S << BFA_LOG_ARG0) | (BFA_LOG_S << BFA_LOG_ARG1) | 0), 2},
+
+{BFA_AEN_LPORT_NEW_STANDARD, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG,
+ BFA_LOG_INFO, "BFA_AEN_LPORT_NEW_STANDARD",
+ "New virtual port created using standard interface: WWN = %s, Role = %s.",
+ ((BFA_LOG_S << BFA_LOG_ARG0) | (BFA_LOG_S << BFA_LOG_ARG1) | 0), 2},
+
+{BFA_AEN_LPORT_DELETE_STANDARD, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG,
+ BFA_LOG_INFO, "BFA_AEN_LPORT_DELETE_STANDARD",
+ "Virtual port deleted using standard interface: WWN = %s, Role = %s.",
+ ((BFA_LOG_S << BFA_LOG_ARG0) | (BFA_LOG_S << BFA_LOG_ARG1) | 0), 2},
+
+{BFA_AEN_LPORT_NPIV_DUP_WWN, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG,
+ BFA_LOG_WARNING, "BFA_AEN_LPORT_NPIV_DUP_WWN",
+ "Virtual port login failed. Duplicate WWN = %s reported by fabric.",
+ ((BFA_LOG_S << BFA_LOG_ARG0) | 0), 1},
+
+{BFA_AEN_LPORT_NPIV_FABRIC_MAX, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG,
+ BFA_LOG_WARNING, "BFA_AEN_LPORT_NPIV_FABRIC_MAX",
+ "Virtual port (WWN = %s) login failed. Max NPIV ports already exist in"
+ " fabric/fport.",
+ ((BFA_LOG_S << BFA_LOG_ARG0) | 0), 1},
+
+{BFA_AEN_LPORT_NPIV_UNKNOWN, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG,
+ BFA_LOG_WARNING, "BFA_AEN_LPORT_NPIV_UNKNOWN",
+ "Virtual port (WWN = %s) login failed.",
+ ((BFA_LOG_S << BFA_LOG_ARG0) | 0), 1},
+
+
+
+
+/* messages define for BFA_AEN_CAT_PORT Module */
+{BFA_AEN_PORT_ONLINE, BFA_LOG_ATTR_NONE, BFA_LOG_INFO, "BFA_AEN_PORT_ONLINE",
+ "Base port online: WWN = %s.",
+ ((BFA_LOG_S << BFA_LOG_ARG0) | 0), 1},
+
+{BFA_AEN_PORT_OFFLINE, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, BFA_LOG_WARNING,
+ "BFA_AEN_PORT_OFFLINE",
+ "Base port offline: WWN = %s.",
+ ((BFA_LOG_S << BFA_LOG_ARG0) | 0), 1},
+
+{BFA_AEN_PORT_RLIR, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, BFA_LOG_INFO,
+ "BFA_AEN_PORT_RLIR",
+ "RLIR event not supported.",
+ (0), 0},
+
+{BFA_AEN_PORT_SFP_INSERT, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, BFA_LOG_INFO,
+ "BFA_AEN_PORT_SFP_INSERT",
+ "New SFP found: WWN/MAC = %s.",
+ ((BFA_LOG_S << BFA_LOG_ARG0) | 0), 1},
+
+{BFA_AEN_PORT_SFP_REMOVE, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG,
+ BFA_LOG_WARNING, "BFA_AEN_PORT_SFP_REMOVE",
+ "SFP removed: WWN/MAC = %s.",
+ ((BFA_LOG_S << BFA_LOG_ARG0) | 0), 1},
+
+{BFA_AEN_PORT_SFP_POM, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, BFA_LOG_WARNING,
+ "BFA_AEN_PORT_SFP_POM",
+ "SFP POM level to %s: WWN/MAC = %s.",
+ ((BFA_LOG_S << BFA_LOG_ARG0) | (BFA_LOG_S << BFA_LOG_ARG1) | 0), 2},
+
+{BFA_AEN_PORT_ENABLE, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, BFA_LOG_INFO,
+ "BFA_AEN_PORT_ENABLE",
+ "Base port enabled: WWN = %s.",
+ ((BFA_LOG_S << BFA_LOG_ARG0) | 0), 1},
+
+{BFA_AEN_PORT_DISABLE, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, BFA_LOG_INFO,
+ "BFA_AEN_PORT_DISABLE",
+ "Base port disabled: WWN = %s.",
+ ((BFA_LOG_S << BFA_LOG_ARG0) | 0), 1},
+
+{BFA_AEN_PORT_AUTH_ON, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, BFA_LOG_INFO,
+ "BFA_AEN_PORT_AUTH_ON",
+ "Authentication successful for base port: WWN = %s.",
+ ((BFA_LOG_S << BFA_LOG_ARG0) | 0), 1},
+
+{BFA_AEN_PORT_AUTH_OFF, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, BFA_LOG_ERROR,
+ "BFA_AEN_PORT_AUTH_OFF",
+ "Authentication unsuccessful for base port: WWN = %s.",
+ ((BFA_LOG_S << BFA_LOG_ARG0) | 0), 1},
+
+{BFA_AEN_PORT_DISCONNECT, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, BFA_LOG_ERROR,
+ "BFA_AEN_PORT_DISCONNECT",
+ "Base port (WWN = %s) lost fabric connectivity.",
+ ((BFA_LOG_S << BFA_LOG_ARG0) | 0), 1},
+
+{BFA_AEN_PORT_QOS_NEG, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, BFA_LOG_WARNING,
+ "BFA_AEN_PORT_QOS_NEG",
+ "QOS negotiation failed for base port: WWN = %s.",
+ ((BFA_LOG_S << BFA_LOG_ARG0) | 0), 1},
+
+{BFA_AEN_PORT_FABRIC_NAME_CHANGE, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG,
+ BFA_LOG_WARNING, "BFA_AEN_PORT_FABRIC_NAME_CHANGE",
+ "Base port WWN = %s, Fabric WWN = %s.",
+ ((BFA_LOG_S << BFA_LOG_ARG0) | (BFA_LOG_S << BFA_LOG_ARG1) | 0), 2},
+
+{BFA_AEN_PORT_SFP_ACCESS_ERROR, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG,
+ BFA_LOG_WARNING, "BFA_AEN_PORT_SFP_ACCESS_ERROR",
+ "SFP access error: WWN/MAC = %s.",
+ ((BFA_LOG_S << BFA_LOG_ARG0) | 0), 1},
+
+{BFA_AEN_PORT_SFP_UNSUPPORT, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG,
+ BFA_LOG_WARNING, "BFA_AEN_PORT_SFP_UNSUPPORT",
+ "Unsupported SFP found: WWN/MAC = %s.",
+ ((BFA_LOG_S << BFA_LOG_ARG0) | 0), 1},
+
+
+
+
+/* messages define for BFA_AEN_CAT_RPORT Module */
+{BFA_AEN_RPORT_ONLINE, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, BFA_LOG_INFO,
+ "BFA_AEN_RPORT_ONLINE",
+ "Remote port (WWN = %s) online for logical port (WWN = %s).",
+ ((BFA_LOG_S << BFA_LOG_ARG0) | (BFA_LOG_S << BFA_LOG_ARG1) | 0), 2},
+
+{BFA_AEN_RPORT_OFFLINE, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, BFA_LOG_INFO,
+ "BFA_AEN_RPORT_OFFLINE",
+ "Remote port (WWN = %s) offlined by logical port (WWN = %s).",
+ ((BFA_LOG_S << BFA_LOG_ARG0) | (BFA_LOG_S << BFA_LOG_ARG1) | 0), 2},
+
+{BFA_AEN_RPORT_DISCONNECT, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG,
+ BFA_LOG_ERROR, "BFA_AEN_RPORT_DISCONNECT",
+ "Remote port (WWN = %s) connectivity lost for logical port (WWN = %s).",
+ ((BFA_LOG_S << BFA_LOG_ARG0) | (BFA_LOG_S << BFA_LOG_ARG1) | 0), 2},
+
+{BFA_AEN_RPORT_QOS_PRIO, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, BFA_LOG_INFO,
+ "BFA_AEN_RPORT_QOS_PRIO",
+ "QOS priority changed to %s: RPWWN = %s and LPWWN = %s.",
+ ((BFA_LOG_S << BFA_LOG_ARG0) | (BFA_LOG_S << BFA_LOG_ARG1) |
+  (BFA_LOG_S << BFA_LOG_ARG2) | 0), 3},
+
+{BFA_AEN_RPORT_QOS_FLOWID, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, BFA_LOG_INFO,
+ "BFA_AEN_RPORT_QOS_FLOWID",
+ "QOS flow ID changed to %d: RPWWN = %s and LPWWN = %s.",
+ ((BFA_LOG_D << BFA_LOG_ARG0) | (BFA_LOG_S << BFA_LOG_ARG1) |
+  (BFA_LOG_S << BFA_LOG_ARG2) | 0), 3},
+
+
+
+
+/* messages define for FCS Module */
+{BFA_LOG_FCS_FABRIC_NOSWITCH, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG,
+ BFA_LOG_INFO, "FCS_FABRIC_NOSWITCH",
+ "No switched fabric presence is detected.",
+ (0), 0},
+
+{BFA_LOG_FCS_FABRIC_ISOLATED, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG,
+ BFA_LOG_INFO, "FCS_FABRIC_ISOLATED",
+ "Port is isolated due to VF_ID mismatch. PWWN: %s, Port VF_ID: %04x and"
+ " switch port VF_ID: %04x.",
+ ((BFA_LOG_S << BFA_LOG_ARG0) | (BFA_LOG_X << BFA_LOG_ARG1) |
+  (BFA_LOG_X << BFA_LOG_ARG2) | 0), 3},
+
+
+
+
+/* messages define for HAL Module */
+{BFA_LOG_HAL_ASSERT, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, BFA_LOG_ERROR,
+ "HAL_ASSERT",
+ "Assertion failure: %s:%d: %s",
+ ((BFA_LOG_S << BFA_LOG_ARG0) | (BFA_LOG_D << BFA_LOG_ARG1) |
+  (BFA_LOG_S << BFA_LOG_ARG2) | 0), 3},
+
+{BFA_LOG_HAL_HEARTBEAT_FAILURE, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG,
+ BFA_LOG_CRITICAL, "HAL_HEARTBEAT_FAILURE",
+ "Firmware heartbeat failure at %d",
+ ((BFA_LOG_D << BFA_LOG_ARG0) | 0), 1},
+
+{BFA_LOG_HAL_FCPIM_PARM_INVALID, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG,
+ BFA_LOG_INFO, "HAL_FCPIM_PARM_INVALID",
+ "Driver configuration %s value %d is invalid. Value should be within"
+ " %d and %d.",
+ ((BFA_LOG_S << BFA_LOG_ARG0) | (BFA_LOG_D << BFA_LOG_ARG1) |
+  (BFA_LOG_D << BFA_LOG_ARG2) | (BFA_LOG_D << BFA_LOG_ARG3) | 0), 4},
+
+{BFA_LOG_HAL_SM_ASSERT, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, BFA_LOG_ERROR,
+ "HAL_SM_ASSERT",
+ "SM Assertion failure: %s:%d: event = %d",
+ ((BFA_LOG_S << BFA_LOG_ARG0) | (BFA_LOG_D << BFA_LOG_ARG1) |
+  (BFA_LOG_D << BFA_LOG_ARG2) | 0), 3},
+
+
+
+
+/* messages define for LINUX Module */
+{BFA_LOG_LINUX_DEVICE_CLAIMED, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG,
+ BFA_LOG_INFO, "LINUX_DEVICE_CLAIMED",
+ "bfa device at %s claimed.",
+ ((BFA_LOG_S << BFA_LOG_ARG0) | 0), 1},
+
+{BFA_LOG_LINUX_HASH_INIT_FAILED, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG,
+ BFA_LOG_INFO, "LINUX_HASH_INIT_FAILED",
+ "Hash table initialization failure for the port %s.",
+ ((BFA_LOG_S << BFA_LOG_ARG0) | 0), 1},
+
+{BFA_LOG_LINUX_SYSFS_FAILED, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG,
+ BFA_LOG_INFO, "LINUX_SYSFS_FAILED",
+ "sysfs file creation failure for the port %s.",
+ ((BFA_LOG_S << BFA_LOG_ARG0) | 0), 1},
+
+{BFA_LOG_LINUX_MEM_ALLOC_FAILED, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG,
+ BFA_LOG_INFO, "LINUX_MEM_ALLOC_FAILED",
+ "Memory allocation failed: %s.  ",
+ ((BFA_LOG_S << BFA_LOG_ARG0) | 0), 1},
+
+{BFA_LOG_LINUX_DRIVER_REGISTRATION_FAILED,
+ BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, BFA_LOG_INFO,
+ "LINUX_DRIVER_REGISTRATION_FAILED",
+ "%s.  ",
+ ((BFA_LOG_S << BFA_LOG_ARG0) | 0), 1},
+
+{BFA_LOG_LINUX_ITNIM_FREE, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, BFA_LOG_INFO,
+ "LINUX_ITNIM_FREE",
+ "scsi%d: FCID: %s WWPN: %s",
+ ((BFA_LOG_D << BFA_LOG_ARG0) | (BFA_LOG_S << BFA_LOG_ARG1) |
+  (BFA_LOG_S << BFA_LOG_ARG2) | 0), 3},
+
+{BFA_LOG_LINUX_ITNIM_ONLINE, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG,
+ BFA_LOG_INFO, "LINUX_ITNIM_ONLINE",
+ "Target: %d:0:%d FCID: %s WWPN: %s",
+ ((BFA_LOG_D << BFA_LOG_ARG0) | (BFA_LOG_D << BFA_LOG_ARG1) |
+  (BFA_LOG_S << BFA_LOG_ARG2) | (BFA_LOG_S << BFA_LOG_ARG3) | 0), 4},
+
+{BFA_LOG_LINUX_ITNIM_OFFLINE, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG,
+ BFA_LOG_INFO, "LINUX_ITNIM_OFFLINE",
+ "Target: %d:0:%d FCID: %s WWPN: %s",
+ ((BFA_LOG_D << BFA_LOG_ARG0) | (BFA_LOG_D << BFA_LOG_ARG1) |
+  (BFA_LOG_S << BFA_LOG_ARG2) | (BFA_LOG_S << BFA_LOG_ARG3) | 0), 4},
+
+{BFA_LOG_LINUX_SCSI_HOST_FREE, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG,
+ BFA_LOG_INFO, "LINUX_SCSI_HOST_FREE",
+ "Free scsi%d",
+ ((BFA_LOG_D << BFA_LOG_ARG0) | 0), 1},
+
+{BFA_LOG_LINUX_SCSI_ABORT, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, BFA_LOG_INFO,
+ "LINUX_SCSI_ABORT",
+ "scsi%d: abort cmnd %p, iotag %x",
+ ((BFA_LOG_D << BFA_LOG_ARG0) | (BFA_LOG_P << BFA_LOG_ARG1) |
+  (BFA_LOG_X << BFA_LOG_ARG2) | 0), 3},
+
+{BFA_LOG_LINUX_SCSI_ABORT_COMP, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG,
+ BFA_LOG_INFO, "LINUX_SCSI_ABORT_COMP",
+ "scsi%d: complete abort 0x%p, iotag 0x%x",
+ ((BFA_LOG_D << BFA_LOG_ARG0) | (BFA_LOG_P << BFA_LOG_ARG1) |
+  (BFA_LOG_X << BFA_LOG_ARG2) | 0), 3},
+
+
+
+
+/* messages define for WDRV Module */
+{BFA_LOG_WDRV_IOC_INIT_ERROR, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG,
+ BFA_LOG_INFO, "WDRV_IOC_INIT_ERROR",
+ "IOC initialization has failed.",
+ (0), 0},
+
+{BFA_LOG_WDRV_IOC_INTERNAL_ERROR, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG,
+ BFA_LOG_INFO, "WDRV_IOC_INTERNAL_ERROR",
+ "IOC internal error.  ",
+ (0), 0},
+
+{BFA_LOG_WDRV_IOC_START_ERROR, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG,
+ BFA_LOG_INFO, "WDRV_IOC_START_ERROR",
+ "IOC could not be started.  ",
+ (0), 0},
+
+{BFA_LOG_WDRV_IOC_STOP_ERROR, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG,
+ BFA_LOG_INFO, "WDRV_IOC_STOP_ERROR",
+ "IOC could not be stopped.  ",
+ (0), 0},
+
+{BFA_LOG_WDRV_INSUFFICIENT_RESOURCES, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG,
+ BFA_LOG_INFO, "WDRV_INSUFFICIENT_RESOURCES",
+ "Insufficient memory.  ",
+ (0), 0},
+
+{BFA_LOG_WDRV_BASE_ADDRESS_MAP_ERROR, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG,
+ BFA_LOG_INFO, "WDRV_BASE_ADDRESS_MAP_ERROR",
+ "Unable to map the IOC onto the system address space.  ",
+ (0), 0},
+
+
+{0, 0, 0, "", "", 0, 0},
+};
diff --git a/drivers/scsi/bfa/bfa_lps.c b/drivers/scsi/bfa/bfa_lps.c
new file mode 100644 (file)
index 0000000..9844b45
--- /dev/null
@@ -0,0 +1,782 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ */
+
+#include <bfa.h>
+#include <bfi/bfi_lps.h>
+#include <cs/bfa_debug.h>
+
+BFA_TRC_FILE(HAL, LPS);
+BFA_MODULE(lps);
+
+#define BFA_LPS_MIN_LPORTS     (1)
+#define BFA_LPS_MAX_LPORTS     (256)
+
+/**
+ * forward declarations
+ */
+static void bfa_lps_meminfo(struct bfa_iocfc_cfg_s *cfg, u32 *ndm_len,
+                           u32 *dm_len);
+static void bfa_lps_attach(struct bfa_s *bfa, void *bfad,
+                          struct bfa_iocfc_cfg_s *cfg,
+                          struct bfa_meminfo_s *meminfo,
+                          struct bfa_pcidev_s *pcidev);
+static void bfa_lps_initdone(struct bfa_s *bfa);
+static void bfa_lps_detach(struct bfa_s *bfa);
+static void bfa_lps_start(struct bfa_s *bfa);
+static void bfa_lps_stop(struct bfa_s *bfa);
+static void bfa_lps_iocdisable(struct bfa_s *bfa);
+static void bfa_lps_login_rsp(struct bfa_s *bfa,
+                             struct bfi_lps_login_rsp_s *rsp);
+static void bfa_lps_logout_rsp(struct bfa_s *bfa,
+                              struct bfi_lps_logout_rsp_s *rsp);
+static void bfa_lps_reqq_resume(void *lps_arg);
+static void bfa_lps_free(struct bfa_lps_s *lps);
+static void bfa_lps_send_login(struct bfa_lps_s *lps);
+static void bfa_lps_send_logout(struct bfa_lps_s *lps);
+static void bfa_lps_login_comp(struct bfa_lps_s *lps);
+static void bfa_lps_logout_comp(struct bfa_lps_s *lps);
+
+
+/**
+ *  lps_pvt BFA LPS private functions
+ */
+
+enum bfa_lps_event {
+       BFA_LPS_SM_LOGIN        = 1,    /* login request from user      */
+       BFA_LPS_SM_LOGOUT       = 2,    /* logout request from user     */
+       BFA_LPS_SM_FWRSP        = 3,    /* f/w response to login/logout */
+       BFA_LPS_SM_RESUME       = 4,    /* space present in reqq queue  */
+       BFA_LPS_SM_DELETE       = 5,    /* lps delete from user         */
+       BFA_LPS_SM_OFFLINE      = 6,    /* Link is offline              */
+};
+
+static void bfa_lps_sm_init(struct bfa_lps_s *lps, enum bfa_lps_event event);
+static void bfa_lps_sm_login(struct bfa_lps_s *lps, enum bfa_lps_event event);
+static void bfa_lps_sm_loginwait(struct bfa_lps_s *lps,
+                       enum bfa_lps_event event);
+static void bfa_lps_sm_online(struct bfa_lps_s *lps, enum bfa_lps_event event);
+static void bfa_lps_sm_logout(struct bfa_lps_s *lps, enum bfa_lps_event event);
+static void bfa_lps_sm_logowait(struct bfa_lps_s *lps,
+                       enum bfa_lps_event event);
+
+/**
+ * Init state -- no login
+ */
+static void
+bfa_lps_sm_init(struct bfa_lps_s *lps, enum bfa_lps_event event)
+{
+       bfa_trc(lps->bfa, lps->lp_tag);
+       bfa_trc(lps->bfa, event);
+
+       switch (event) {
+       case BFA_LPS_SM_LOGIN:
+               if (bfa_reqq_full(lps->bfa, lps->reqq)) {
+                       bfa_sm_set_state(lps, bfa_lps_sm_loginwait);
+                       bfa_reqq_wait(lps->bfa, lps->reqq, &lps->wqe);
+               } else {
+                       bfa_sm_set_state(lps, bfa_lps_sm_login);
+                       bfa_lps_send_login(lps);
+               }
+               break;
+
+       case BFA_LPS_SM_LOGOUT:
+               bfa_lps_logout_comp(lps);
+               break;
+
+       case BFA_LPS_SM_DELETE:
+               bfa_lps_free(lps);
+               break;
+
+       case BFA_LPS_SM_OFFLINE:
+               break;
+
+       case BFA_LPS_SM_FWRSP:
+               /* Could happen when fabric detects loopback and discards
+                * the lps request. Fw will eventually sent out the timeout
+                * Just ignore
+                */
+               break;
+
+       default:
+               bfa_assert(0);
+       }
+}
+
+/**
+ * login is in progress -- awaiting response from firmware
+ */
+static void
+bfa_lps_sm_login(struct bfa_lps_s *lps, enum bfa_lps_event event)
+{
+       bfa_trc(lps->bfa, lps->lp_tag);
+       bfa_trc(lps->bfa, event);
+
+       switch (event) {
+       case BFA_LPS_SM_FWRSP:
+               if (lps->status == BFA_STATUS_OK)
+                       bfa_sm_set_state(lps, bfa_lps_sm_online);
+               else
+                       bfa_sm_set_state(lps, bfa_lps_sm_init);
+               bfa_lps_login_comp(lps);
+               break;
+
+       case BFA_LPS_SM_OFFLINE:
+               bfa_sm_set_state(lps, bfa_lps_sm_init);
+               break;
+
+       default:
+               bfa_assert(0);
+       }
+}
+
+/**
+ * login pending - awaiting space in request queue
+ */
+static void
+bfa_lps_sm_loginwait(struct bfa_lps_s *lps, enum bfa_lps_event event)
+{
+       bfa_trc(lps->bfa, lps->lp_tag);
+       bfa_trc(lps->bfa, event);
+
+       switch (event) {
+       case BFA_LPS_SM_RESUME:
+               bfa_sm_set_state(lps, bfa_lps_sm_login);
+               break;
+
+       case BFA_LPS_SM_OFFLINE:
+               bfa_sm_set_state(lps, bfa_lps_sm_init);
+               bfa_reqq_wcancel(&lps->wqe);
+               break;
+
+       default:
+               bfa_assert(0);
+       }
+}
+
+/**
+ * login complete
+ */
+static void
+bfa_lps_sm_online(struct bfa_lps_s *lps, enum bfa_lps_event event)
+{
+       bfa_trc(lps->bfa, lps->lp_tag);
+       bfa_trc(lps->bfa, event);
+
+       switch (event) {
+       case BFA_LPS_SM_LOGOUT:
+               if (bfa_reqq_full(lps->bfa, lps->reqq)) {
+                       bfa_sm_set_state(lps, bfa_lps_sm_logowait);
+                       bfa_reqq_wait(lps->bfa, lps->reqq, &lps->wqe);
+               } else {
+                       bfa_sm_set_state(lps, bfa_lps_sm_logout);
+                       bfa_lps_send_logout(lps);
+               }
+               break;
+
+       case BFA_LPS_SM_OFFLINE:
+       case BFA_LPS_SM_DELETE:
+               bfa_sm_set_state(lps, bfa_lps_sm_init);
+               break;
+
+       default:
+               bfa_assert(0);
+       }
+}
+
+/**
+ * logout in progress - awaiting firmware response
+ */
+static void
+bfa_lps_sm_logout(struct bfa_lps_s *lps, enum bfa_lps_event event)
+{
+       bfa_trc(lps->bfa, lps->lp_tag);
+       bfa_trc(lps->bfa, event);
+
+       switch (event) {
+       case BFA_LPS_SM_FWRSP:
+               bfa_sm_set_state(lps, bfa_lps_sm_init);
+               bfa_lps_logout_comp(lps);
+               break;
+
+       case BFA_LPS_SM_OFFLINE:
+               bfa_sm_set_state(lps, bfa_lps_sm_init);
+               break;
+
+       default:
+               bfa_assert(0);
+       }
+}
+
+/**
+ * logout pending -- awaiting space in request queue
+ */
+static void
+bfa_lps_sm_logowait(struct bfa_lps_s *lps, enum bfa_lps_event event)
+{
+       bfa_trc(lps->bfa, lps->lp_tag);
+       bfa_trc(lps->bfa, event);
+
+       switch (event) {
+       case BFA_LPS_SM_RESUME:
+               bfa_sm_set_state(lps, bfa_lps_sm_logout);
+               bfa_lps_send_logout(lps);
+               break;
+
+       case BFA_LPS_SM_OFFLINE:
+               bfa_sm_set_state(lps, bfa_lps_sm_init);
+               bfa_reqq_wcancel(&lps->wqe);
+               break;
+
+       default:
+               bfa_assert(0);
+       }
+}
+
+
+
+/**
+ *  lps_pvt BFA LPS private functions
+ */
+
+/**
+ * return memory requirement
+ */
+static void
+bfa_lps_meminfo(struct bfa_iocfc_cfg_s *cfg, u32 *ndm_len, u32 *dm_len)
+{
+       if (cfg->drvcfg.min_cfg)
+               *ndm_len += sizeof(struct bfa_lps_s) * BFA_LPS_MIN_LPORTS;
+       else
+               *ndm_len += sizeof(struct bfa_lps_s) * BFA_LPS_MAX_LPORTS;
+}
+
+/**
+ * bfa module attach at initialization time
+ */
+static void
+bfa_lps_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
+               struct bfa_meminfo_s *meminfo, struct bfa_pcidev_s *pcidev)
+{
+       struct bfa_lps_mod_s    *mod = BFA_LPS_MOD(bfa);
+       struct bfa_lps_s        *lps;
+       int                     i;
+
+       bfa_os_memset(mod, 0, sizeof(struct bfa_lps_mod_s));
+       mod->num_lps = BFA_LPS_MAX_LPORTS;
+       if (cfg->drvcfg.min_cfg)
+               mod->num_lps = BFA_LPS_MIN_LPORTS;
+       else
+               mod->num_lps = BFA_LPS_MAX_LPORTS;
+       mod->lps_arr = lps = (struct bfa_lps_s *) bfa_meminfo_kva(meminfo);
+
+       bfa_meminfo_kva(meminfo) += mod->num_lps * sizeof(struct bfa_lps_s);
+
+       INIT_LIST_HEAD(&mod->lps_free_q);
+       INIT_LIST_HEAD(&mod->lps_active_q);
+
+       for (i = 0; i < mod->num_lps; i++, lps++) {
+               lps->bfa        = bfa;
+               lps->lp_tag     = (u8) i;
+               lps->reqq       = BFA_REQQ_LPS;
+               bfa_reqq_winit(&lps->wqe, bfa_lps_reqq_resume, lps);
+               list_add_tail(&lps->qe, &mod->lps_free_q);
+       }
+}
+
+static void
+bfa_lps_initdone(struct bfa_s *bfa)
+{
+}
+
+static void
+bfa_lps_detach(struct bfa_s *bfa)
+{
+}
+
+static void
+bfa_lps_start(struct bfa_s *bfa)
+{
+}
+
+static void
+bfa_lps_stop(struct bfa_s *bfa)
+{
+}
+
+/**
+ * IOC in disabled state -- consider all lps offline
+ */
+static void
+bfa_lps_iocdisable(struct bfa_s *bfa)
+{
+       struct bfa_lps_mod_s    *mod = BFA_LPS_MOD(bfa);
+       struct bfa_lps_s        *lps;
+       struct list_head                *qe, *qen;
+
+       list_for_each_safe(qe, qen, &mod->lps_active_q) {
+               lps = (struct bfa_lps_s *) qe;
+               bfa_sm_send_event(lps, BFA_LPS_SM_OFFLINE);
+       }
+}
+
+/**
+ * Firmware login response
+ */
+static void
+bfa_lps_login_rsp(struct bfa_s *bfa, struct bfi_lps_login_rsp_s *rsp)
+{
+       struct bfa_lps_mod_s    *mod = BFA_LPS_MOD(bfa);
+       struct bfa_lps_s        *lps;
+
+       bfa_assert(rsp->lp_tag < mod->num_lps);
+       lps = BFA_LPS_FROM_TAG(mod, rsp->lp_tag);
+
+       lps->status = rsp->status;
+       switch (rsp->status) {
+       case BFA_STATUS_OK:
+               lps->fport      = rsp->f_port;
+               lps->npiv_en    = rsp->npiv_en;
+               lps->lp_pid     = rsp->lp_pid;
+               lps->pr_bbcred  = bfa_os_ntohs(rsp->bb_credit);
+               lps->pr_pwwn    = rsp->port_name;
+               lps->pr_nwwn    = rsp->node_name;
+               lps->auth_req   = rsp->auth_req;
+               lps->lp_mac     = rsp->lp_mac;
+               lps->brcd_switch = rsp->brcd_switch;
+               lps->fcf_mac    = rsp->fcf_mac;
+
+               break;
+
+       case BFA_STATUS_FABRIC_RJT:
+               lps->lsrjt_rsn = rsp->lsrjt_rsn;
+               lps->lsrjt_expl = rsp->lsrjt_expl;
+
+               break;
+
+       case BFA_STATUS_EPROTOCOL:
+               lps->ext_status = rsp->ext_status;
+
+               break;
+
+       default:
+               /* Nothing to do with other status */
+               break;
+       }
+
+       bfa_sm_send_event(lps, BFA_LPS_SM_FWRSP);
+}
+
+/**
+ * Firmware logout response
+ */
+static void
+bfa_lps_logout_rsp(struct bfa_s *bfa, struct bfi_lps_logout_rsp_s *rsp)
+{
+       struct bfa_lps_mod_s    *mod = BFA_LPS_MOD(bfa);
+       struct bfa_lps_s        *lps;
+
+       bfa_assert(rsp->lp_tag < mod->num_lps);
+       lps = BFA_LPS_FROM_TAG(mod, rsp->lp_tag);
+
+       bfa_sm_send_event(lps, BFA_LPS_SM_FWRSP);
+}
+
+/**
+ * Space is available in request queue, resume queueing request to firmware.
+ */
+static void
+bfa_lps_reqq_resume(void *lps_arg)
+{
+       struct bfa_lps_s        *lps = lps_arg;
+
+       bfa_sm_send_event(lps, BFA_LPS_SM_RESUME);
+}
+
+/**
+ * lps is freed -- triggered by vport delete
+ */
+static void
+bfa_lps_free(struct bfa_lps_s *lps)
+{
+       struct bfa_lps_mod_s    *mod = BFA_LPS_MOD(lps->bfa);
+
+       list_del(&lps->qe);
+       list_add_tail(&lps->qe, &mod->lps_free_q);
+}
+
+/**
+ * send login request to firmware
+ */
+static void
+bfa_lps_send_login(struct bfa_lps_s *lps)
+{
+       struct bfi_lps_login_req_s      *m;
+
+       m = bfa_reqq_next(lps->bfa, lps->reqq);
+       bfa_assert(m);
+
+       bfi_h2i_set(m->mh, BFI_MC_LPS, BFI_LPS_H2I_LOGIN_REQ,
+                       bfa_lpuid(lps->bfa));
+
+       m->lp_tag       = lps->lp_tag;
+       m->alpa         = lps->alpa;
+       m->pdu_size     = bfa_os_htons(lps->pdusz);
+       m->pwwn         = lps->pwwn;
+       m->nwwn         = lps->nwwn;
+       m->fdisc        = lps->fdisc;
+       m->auth_en      = lps->auth_en;
+
+       bfa_reqq_produce(lps->bfa, lps->reqq);
+}
+
+/**
+ * send logout request to firmware
+ */
+static void
+bfa_lps_send_logout(struct bfa_lps_s *lps)
+{
+       struct bfi_lps_logout_req_s *m;
+
+       m = bfa_reqq_next(lps->bfa, lps->reqq);
+       bfa_assert(m);
+
+       bfi_h2i_set(m->mh, BFI_MC_LPS, BFI_LPS_H2I_LOGOUT_REQ,
+                       bfa_lpuid(lps->bfa));
+
+       m->lp_tag    = lps->lp_tag;
+       m->port_name = lps->pwwn;
+       bfa_reqq_produce(lps->bfa, lps->reqq);
+}
+
+/**
+ * Indirect login completion handler for non-fcs
+ */
+static void
+bfa_lps_login_comp_cb(void *arg, bfa_boolean_t complete)
+{
+       struct bfa_lps_s *lps   = arg;
+
+       if (!complete)
+               return;
+
+       if (lps->fdisc)
+               bfa_cb_lps_fdisc_comp(lps->bfa->bfad, lps->uarg, lps->status);
+       else
+               bfa_cb_lps_flogi_comp(lps->bfa->bfad, lps->uarg, lps->status);
+}
+
+/**
+ * Login completion handler -- direct call for fcs, queue for others
+ */
+static void
+bfa_lps_login_comp(struct bfa_lps_s *lps)
+{
+       if (!lps->bfa->fcs) {
+               bfa_cb_queue(lps->bfa, &lps->hcb_qe,
+                               bfa_lps_login_comp_cb, lps);
+               return;
+       }
+
+       if (lps->fdisc)
+               bfa_cb_lps_fdisc_comp(lps->bfa->bfad, lps->uarg, lps->status);
+       else
+               bfa_cb_lps_flogi_comp(lps->bfa->bfad, lps->uarg, lps->status);
+}
+
+/**
+ * Indirect logout completion handler for non-fcs
+ */
+static void
+bfa_lps_logout_comp_cb(void *arg, bfa_boolean_t complete)
+{
+       struct bfa_lps_s *lps   = arg;
+
+       if (!complete)
+               return;
+
+       if (lps->fdisc)
+               bfa_cb_lps_fdisclogo_comp(lps->bfa->bfad, lps->uarg);
+       else
+               bfa_cb_lps_flogo_comp(lps->bfa->bfad, lps->uarg);
+}
+
+/**
+ * Logout completion handler -- direct call for fcs, queue for others
+ */
+static void
+bfa_lps_logout_comp(struct bfa_lps_s *lps)
+{
+       if (!lps->bfa->fcs) {
+               bfa_cb_queue(lps->bfa, &lps->hcb_qe,
+                               bfa_lps_logout_comp_cb, lps);
+               return;
+       }
+       if (lps->fdisc)
+               bfa_cb_lps_fdisclogo_comp(lps->bfa->bfad, lps->uarg);
+       else
+               bfa_cb_lps_flogo_comp(lps->bfa->bfad, lps->uarg);
+}
+
+
+
+/**
+ *  lps_public BFA LPS public functions
+ */
+
+/**
+ * Allocate a lport srvice tag.
+ */
+struct bfa_lps_s  *
+bfa_lps_alloc(struct bfa_s *bfa)
+{
+       struct bfa_lps_mod_s    *mod = BFA_LPS_MOD(bfa);
+       struct bfa_lps_s        *lps = NULL;
+
+       bfa_q_deq(&mod->lps_free_q, &lps);
+
+       if (lps == NULL)
+               return NULL;
+
+       list_add_tail(&lps->qe, &mod->lps_active_q);
+
+       bfa_sm_set_state(lps, bfa_lps_sm_init);
+       return lps;
+}
+
+/**
+ * Free lport service tag. This can be called anytime after an alloc.
+ * No need to wait for any pending login/logout completions.
+ */
+void
+bfa_lps_delete(struct bfa_lps_s *lps)
+{
+       bfa_sm_send_event(lps, BFA_LPS_SM_DELETE);
+}
+
+/**
+ * Initiate a lport login.
+ */
+void
+bfa_lps_flogi(struct bfa_lps_s *lps, void *uarg, u8 alpa, u16 pdusz,
+       wwn_t pwwn, wwn_t nwwn, bfa_boolean_t auth_en)
+{
+       lps->uarg       = uarg;
+       lps->alpa       = alpa;
+       lps->pdusz      = pdusz;
+       lps->pwwn       = pwwn;
+       lps->nwwn       = nwwn;
+       lps->fdisc      = BFA_FALSE;
+       lps->auth_en    = auth_en;
+       bfa_sm_send_event(lps, BFA_LPS_SM_LOGIN);
+}
+
+/**
+ * Initiate a lport fdisc login.
+ */
+void
+bfa_lps_fdisc(struct bfa_lps_s *lps, void *uarg, u16 pdusz, wwn_t pwwn,
+       wwn_t nwwn)
+{
+       lps->uarg       = uarg;
+       lps->alpa       = 0;
+       lps->pdusz      = pdusz;
+       lps->pwwn       = pwwn;
+       lps->nwwn       = nwwn;
+       lps->fdisc      = BFA_TRUE;
+       lps->auth_en    = BFA_FALSE;
+       bfa_sm_send_event(lps, BFA_LPS_SM_LOGIN);
+}
+
+/**
+ * Initiate a lport logout (flogi).
+ */
+void
+bfa_lps_flogo(struct bfa_lps_s *lps)
+{
+       bfa_sm_send_event(lps, BFA_LPS_SM_LOGOUT);
+}
+
+/**
+ * Initiate a lport FDSIC logout.
+ */
+void
+bfa_lps_fdisclogo(struct bfa_lps_s *lps)
+{
+       bfa_sm_send_event(lps, BFA_LPS_SM_LOGOUT);
+}
+
+/**
+ * Discard a pending login request -- should be called only for
+ * link down handling.
+ */
+void
+bfa_lps_discard(struct bfa_lps_s *lps)
+{
+       bfa_sm_send_event(lps, BFA_LPS_SM_OFFLINE);
+}
+
+/**
+ * Return lport services tag
+ */
+u8
+bfa_lps_get_tag(struct bfa_lps_s *lps)
+{
+       return lps->lp_tag;
+}
+
+/**
+ * Return lport services tag given the pid
+ */
+u8
+bfa_lps_get_tag_from_pid(struct bfa_s *bfa, u32 pid)
+{
+       struct bfa_lps_mod_s    *mod = BFA_LPS_MOD(bfa);
+       struct bfa_lps_s        *lps;
+       int                     i;
+
+       for (i = 0, lps = mod->lps_arr; i < mod->num_lps; i++, lps++) {
+               if (lps->lp_pid == pid)
+                       return lps->lp_tag;
+       }
+
+       /* Return base port tag anyway */
+       return 0;
+}
+
+/**
+ * return if fabric login indicates support for NPIV
+ */
+bfa_boolean_t
+bfa_lps_is_npiv_en(struct bfa_lps_s *lps)
+{
+       return lps->npiv_en;
+}
+
+/**
+ * Return TRUE if attached to F-Port, else return FALSE
+ */
+bfa_boolean_t
+bfa_lps_is_fport(struct bfa_lps_s *lps)
+{
+       return lps->fport;
+}
+
+/**
+ * Return TRUE if attached to a Brocade Fabric
+ */
+bfa_boolean_t
+bfa_lps_is_brcd_fabric(struct bfa_lps_s *lps)
+{
+       return lps->brcd_switch;
+}
+/**
+ * return TRUE if authentication is required
+ */
+bfa_boolean_t
+bfa_lps_is_authreq(struct bfa_lps_s *lps)
+{
+       return lps->auth_req;
+}
+
+bfa_eproto_status_t
+bfa_lps_get_extstatus(struct bfa_lps_s *lps)
+{
+       return lps->ext_status;
+}
+
+/**
+ * return port id assigned to the lport
+ */
+u32
+bfa_lps_get_pid(struct bfa_lps_s *lps)
+{
+       return lps->lp_pid;
+}
+
+/**
+ * Return bb_credit assigned in FLOGI response
+ */
+u16
+bfa_lps_get_peer_bbcredit(struct bfa_lps_s *lps)
+{
+       return lps->pr_bbcred;
+}
+
+/**
+ * Return peer port name
+ */
+wwn_t
+bfa_lps_get_peer_pwwn(struct bfa_lps_s *lps)
+{
+       return lps->pr_pwwn;
+}
+
+/**
+ * Return peer node name
+ */
+wwn_t
+bfa_lps_get_peer_nwwn(struct bfa_lps_s *lps)
+{
+       return lps->pr_nwwn;
+}
+
+/**
+ * return reason code if login request is rejected
+ */
+u8
+bfa_lps_get_lsrjt_rsn(struct bfa_lps_s *lps)
+{
+       return lps->lsrjt_rsn;
+}
+
+/**
+ * return explanation code if login request is rejected
+ */
+u8
+bfa_lps_get_lsrjt_expl(struct bfa_lps_s *lps)
+{
+       return lps->lsrjt_expl;
+}
+
+
+/**
+ * LPS firmware message class handler.
+ */
+void
+bfa_lps_isr(struct bfa_s *bfa, struct bfi_msg_s *m)
+{
+       union bfi_lps_i2h_msg_u msg;
+
+       bfa_trc(bfa, m->mhdr.msg_id);
+       msg.msg = m;
+
+       switch (m->mhdr.msg_id) {
+       case BFI_LPS_H2I_LOGIN_RSP:
+               bfa_lps_login_rsp(bfa, msg.login_rsp);
+               break;
+
+       case BFI_LPS_H2I_LOGOUT_RSP:
+               bfa_lps_logout_rsp(bfa, msg.logout_rsp);
+               break;
+
+       default:
+               bfa_trc(bfa, m->mhdr.msg_id);
+               bfa_assert(0);
+       }
+}
+
+
diff --git a/drivers/scsi/bfa/bfa_lps_priv.h b/drivers/scsi/bfa/bfa_lps_priv.h
new file mode 100644 (file)
index 0000000..d16c6ce
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ */
+
+#ifndef __BFA_LPS_PRIV_H__
+#define __BFA_LPS_PRIV_H__
+
+#include <bfa_svc.h>
+
+struct bfa_lps_mod_s {
+       struct list_head                lps_free_q;
+       struct list_head                lps_active_q;
+       struct bfa_lps_s        *lps_arr;
+       int                     num_lps;
+};
+
+#define BFA_LPS_MOD(__bfa)             (&(__bfa)->modules.lps_mod)
+#define BFA_LPS_FROM_TAG(__mod, __tag) (&(__mod)->lps_arr[__tag])
+
+/*
+ * external functions
+ */
+void   bfa_lps_isr(struct bfa_s *bfa, struct bfi_msg_s *msg);
+
+#endif /* __BFA_LPS_PRIV_H__ */
diff --git a/drivers/scsi/bfa/bfa_module.c b/drivers/scsi/bfa/bfa_module.c
new file mode 100644 (file)
index 0000000..32eda8e
--- /dev/null
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ */
+#include <bfa.h>
+#include <defs/bfa_defs_pci.h>
+#include <cs/bfa_debug.h>
+#include <bfa_iocfc.h>
+
+/**
+ * BFA module list terminated by NULL
+ */
+struct bfa_module_s *hal_mods[] = {
+       &hal_mod_sgpg,
+       &hal_mod_pport,
+       &hal_mod_fcxp,
+       &hal_mod_lps,
+       &hal_mod_uf,
+       &hal_mod_rport,
+       &hal_mod_fcpim,
+#ifdef BFA_CFG_PBIND
+       &hal_mod_pbind,
+#endif
+       NULL
+};
+
+/**
+ * Message handlers for various modules.
+ */
+bfa_isr_func_t  bfa_isrs[BFI_MC_MAX] = {
+       bfa_isr_unhandled,      /* NONE */
+       bfa_isr_unhandled,      /* BFI_MC_IOC */
+       bfa_isr_unhandled,      /* BFI_MC_DIAG */
+       bfa_isr_unhandled,      /* BFI_MC_FLASH */
+       bfa_isr_unhandled,      /* BFI_MC_CEE */
+       bfa_pport_isr,          /* BFI_MC_PORT */
+       bfa_isr_unhandled,      /* BFI_MC_IOCFC */
+       bfa_isr_unhandled,      /* BFI_MC_LL */
+       bfa_uf_isr,             /* BFI_MC_UF */
+       bfa_fcxp_isr,           /* BFI_MC_FCXP */
+       bfa_lps_isr,            /* BFI_MC_LPS */
+       bfa_rport_isr,          /* BFI_MC_RPORT */
+       bfa_itnim_isr,          /* BFI_MC_ITNIM */
+       bfa_isr_unhandled,      /* BFI_MC_IOIM_READ */
+       bfa_isr_unhandled,      /* BFI_MC_IOIM_WRITE */
+       bfa_isr_unhandled,      /* BFI_MC_IOIM_IO */
+       bfa_ioim_isr,           /* BFI_MC_IOIM */
+       bfa_ioim_good_comp_isr, /* BFI_MC_IOIM_IOCOM */
+       bfa_tskim_isr,          /* BFI_MC_TSKIM */
+       bfa_isr_unhandled,      /* BFI_MC_SBOOT */
+       bfa_isr_unhandled,      /* BFI_MC_IPFC */
+       bfa_isr_unhandled,      /* BFI_MC_PORT */
+       bfa_isr_unhandled,      /* --------- */
+       bfa_isr_unhandled,      /* --------- */
+       bfa_isr_unhandled,      /* --------- */
+       bfa_isr_unhandled,      /* --------- */
+       bfa_isr_unhandled,      /* --------- */
+       bfa_isr_unhandled,      /* --------- */
+       bfa_isr_unhandled,      /* --------- */
+       bfa_isr_unhandled,      /* --------- */
+       bfa_isr_unhandled,      /* --------- */
+       bfa_isr_unhandled,      /* --------- */
+};
+
+/**
+ * Message handlers for mailbox command classes
+ */
+bfa_ioc_mbox_mcfunc_t  bfa_mbox_isrs[BFI_MC_MAX] = {
+       NULL,
+       NULL,                   /* BFI_MC_IOC   */
+       NULL,                   /* BFI_MC_DIAG  */
+       NULL,           /* BFI_MC_FLASH */
+       NULL,                   /* BFI_MC_CEE   */
+       NULL,                   /* BFI_MC_PORT  */
+       bfa_iocfc_isr,          /* BFI_MC_IOCFC */
+       NULL,
+};
+
diff --git a/drivers/scsi/bfa/bfa_modules_priv.h b/drivers/scsi/bfa/bfa_modules_priv.h
new file mode 100644 (file)
index 0000000..96f7053
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ */
+
+#ifndef __BFA_MODULES_PRIV_H__
+#define __BFA_MODULES_PRIV_H__
+
+#include "bfa_uf_priv.h"
+#include "bfa_port_priv.h"
+#include "bfa_rport_priv.h"
+#include "bfa_fcxp_priv.h"
+#include "bfa_lps_priv.h"
+#include "bfa_fcpim_priv.h"
+#include <cee/bfa_cee.h>
+#include <port/bfa_port.h>
+
+
+struct bfa_modules_s {
+       struct bfa_pport_s      pport;  /*  physical port module        */
+       struct bfa_fcxp_mod_s fcxp_mod; /*  fcxp module         */
+       struct bfa_lps_mod_s lps_mod;   /*  fcxp module         */
+       struct bfa_uf_mod_s uf_mod;     /*  unsolicited frame module    */
+       struct bfa_rport_mod_s rport_mod; /*  remote port module        */
+       struct bfa_fcpim_mod_s fcpim_mod; /*  FCP initiator module      */
+       struct bfa_sgpg_mod_s sgpg_mod; /*  SG page module              */
+       struct bfa_cee_s cee;           /*  CEE Module                 */
+       struct bfa_port_s port;         /*  Physical port module        */
+};
+
+#endif /* __BFA_MODULES_PRIV_H__ */
diff --git a/drivers/scsi/bfa/bfa_os_inc.h b/drivers/scsi/bfa/bfa_os_inc.h
new file mode 100644 (file)
index 0000000..10a89f7
--- /dev/null
@@ -0,0 +1,222 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) 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.
+ */
+
+/**
+ * Contains declarations all OS Specific files needed for BFA layer
+ */
+
+#ifndef __BFA_OS_INC_H__
+#define __BFA_OS_INC_H__
+
+#ifndef __KERNEL__
+#include <stdint.h>
+#else
+#include <linux/types.h>
+
+#include <linux/version.h>
+#include <linux/pci.h>
+
+#include <linux/dma-mapping.h>
+#define SET_MODULE_VERSION(VER)
+
+#include <linux/idr.h>
+
+#include <linux/interrupt.h>
+#include <linux/cdev.h>
+#include <linux/fs.h>
+#include <linux/delay.h>
+#include <linux/vmalloc.h>
+
+#include <linux/workqueue.h>
+
+#include <scsi/scsi.h>
+#include <scsi/scsi_host.h>
+
+#include <scsi/scsi_tcq.h>
+#include <scsi/scsi_transport_fc.h>
+#include <scsi/scsi_transport.h>
+
+#define BFA_ERR                        KERN_ERR
+#define BFA_WARNING            KERN_WARNING
+#define BFA_NOTICE             KERN_NOTICE
+#define BFA_INFO               KERN_INFO
+#define BFA_DEBUG              KERN_DEBUG
+
+#define LOG_BFAD_INIT          0x00000001
+#define LOG_FCP_IO             0x00000002
+
+#ifdef DEBUG
+#define BFA_LOG_TRACE(bfad, level, mask, fmt, arg...)                  \
+               BFA_LOG(bfad, level, mask, fmt, ## arg)
+#define BFA_DEV_TRACE(bfad, level, fmt, arg...)                                \
+               BFA_DEV_PRINTF(bfad, level, fmt, ## arg)
+#define BFA_TRACE(level, fmt, arg...)                                  \
+               BFA_PRINTF(level, fmt, ## arg)
+#else
+#define BFA_LOG_TRACE(bfad, level, mask, fmt, arg...)
+#define BFA_DEV_TRACE(bfad, level, fmt, arg...)
+#define BFA_TRACE(level, fmt, arg...)
+#endif
+
+#define BFA_ASSERT(p) do {                                             \
+       if (!(p)) {      \
+               printk(KERN_ERR "assert(%s) failed at %s:%d\n",         \
+               #p, __FILE__, __LINE__);      \
+               BUG();      \
+       }                                                               \
+} while (0)
+
+
+#define BFA_LOG(bfad, level, mask, fmt, arg...)                                \
+do {                                                                   \
+       if (((mask) & (((struct bfad_s *)(bfad))->                      \
+               cfg_data[cfg_log_mask])) || (level[1] <= '3'))          \
+               dev_printk(level, &(((struct bfad_s *)                  \
+                       (bfad))->pcidev->dev), fmt, ##arg);      \
+} while (0)
+
+#ifndef BFA_DEV_PRINTF
+#define BFA_DEV_PRINTF(bfad, level, fmt, arg...)                       \
+               dev_printk(level, &(((struct bfad_s *)                  \
+                       (bfad))->pcidev->dev), fmt, ##arg);
+#endif
+
+#define BFA_PRINTF(level, fmt, arg...)                                 \
+               printk(level fmt, ##arg);
+
+int bfa_os_MWB(void *);
+
+#define bfa_os_mmiowb()                mmiowb()
+
+#define bfa_swap_3b(_x)                                \
+       ((((_x) & 0xff) << 16) |                \
+       ((_x) & 0x00ff00) |                     \
+       (((_x) & 0xff0000) >> 16))
+
+#define bfa_swap_8b(_x)                                \
+     ((((_x) & 0xff00000000000000ull) >> 56)           \
+      | (((_x) & 0x00ff000000000000ull) >> 40)         \
+      | (((_x) & 0x0000ff0000000000ull) >> 24)         \
+      | (((_x) & 0x000000ff00000000ull) >> 8)          \
+      | (((_x) & 0x00000000ff000000ull) << 8)          \
+      | (((_x) & 0x0000000000ff0000ull) << 24)         \
+      | (((_x) & 0x000000000000ff00ull) << 40)         \
+      | (((_x) & 0x00000000000000ffull) << 56))
+
+#define bfa_os_swap32(_x)                      \
+       ((((_x) & 0xff) << 24)          |       \
+       (((_x) & 0x0000ff00) << 8)      |       \
+       (((_x) & 0x00ff0000) >> 8)      |       \
+       (((_x) & 0xff000000) >> 24))
+
+
+#ifndef __BIGENDIAN
+#define bfa_os_htons(_x) ((u16)((((_x) & 0xff00) >> 8) | \
+                                (((_x) & 0x00ff) << 8)))
+
+#define bfa_os_htonl(_x)       bfa_os_swap32(_x)
+#define bfa_os_htonll(_x)      bfa_swap_8b(_x)
+#define bfa_os_hton3b(_x)      bfa_swap_3b(_x)
+
+#define bfa_os_wtole(_x)   (_x)
+
+#else
+
+#define bfa_os_htons(_x)   (_x)
+#define bfa_os_htonl(_x)   (_x)
+#define bfa_os_hton3b(_x)  (_x)
+#define bfa_os_htonll(_x)  (_x)
+#define bfa_os_wtole(_x)   bfa_os_swap32(_x)
+
+#endif
+
+#define bfa_os_ntohs(_x)   bfa_os_htons(_x)
+#define bfa_os_ntohl(_x)   bfa_os_htonl(_x)
+#define bfa_os_ntohll(_x)  bfa_os_htonll(_x)
+#define bfa_os_ntoh3b(_x)  bfa_os_hton3b(_x)
+
+#define bfa_os_u32(__pa64) ((__pa64) >> 32)
+
+#define bfa_os_memset  memset
+#define bfa_os_memcpy  memcpy
+#define bfa_os_udelay  udelay
+#define bfa_os_vsprintf vsprintf
+
+#define bfa_os_assign(__t, __s) __t = __s
+
+#define bfa_os_addr_t char __iomem *
+#define bfa_os_panic()
+
+#define bfa_os_reg_read(_raddr) bfa_os_wtole(readl(_raddr))
+#define bfa_os_reg_write(_raddr, _val) writel(bfa_os_wtole((_val)), (_raddr))
+#define bfa_os_mem_read(_raddr, _off)                                   \
+       bfa_os_ntohl(readl(((_raddr) + (_off))))
+#define bfa_os_mem_write(_raddr, _off, _val)                            \
+       writel(bfa_os_htonl((_val)), ((_raddr) + (_off)))
+
+#define BFA_TRC_TS(_trcm)                                              \
+                       ({                                              \
+                               struct timeval tv;                      \
+                                                                       \
+                               do_gettimeofday(&tv);      \
+                               (tv.tv_sec*1000000+tv.tv_usec);      \
+                        })
+
+struct bfa_log_mod_s;
+void bfa_os_printf(struct bfa_log_mod_s *log_mod, u32 msg_id,
+                       const char *fmt, ...);
+#endif
+
+#define boolean_t int
+
+/**
+ * For current time stamp, OS API will fill-in
+ */
+struct bfa_timeval_s {
+       u32     tv_sec;         /*  seconds        */
+       u32     tv_usec;        /*  microseconds   */
+};
+
+void bfa_os_gettimeofday(struct bfa_timeval_s *tv);
+
+static inline void
+wwn2str(char *wwn_str, u64 wwn)
+{
+       union {
+               u64 wwn;
+               u8 byte[8];
+       } w;
+
+       w.wwn = wwn;
+       sprintf(wwn_str, "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x", w.byte[0],
+               w.byte[1], w.byte[2], w.byte[3], w.byte[4], w.byte[5],
+               w.byte[6], w.byte[7]);
+}
+
+static inline void
+fcid2str(char *fcid_str, u32 fcid)
+{
+       union {
+               u32 fcid;
+               u8 byte[4];
+       } f;
+
+       f.fcid = fcid;
+       sprintf(fcid_str, "%02x:%02x:%02x", f.byte[1], f.byte[2], f.byte[3]);
+}
+
+#endif /* __BFA_OS_INC_H__ */
diff --git a/drivers/scsi/bfa/bfa_port.c b/drivers/scsi/bfa/bfa_port.c
new file mode 100644 (file)
index 0000000..cab1902
--- /dev/null
@@ -0,0 +1,460 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ */
+
+#include <defs/bfa_defs_port.h>
+#include <cs/bfa_trc.h>
+#include <cs/bfa_log.h>
+#include <cs/bfa_debug.h>
+#include <port/bfa_port.h>
+#include <bfi/bfi.h>
+#include <bfi/bfi_port.h>
+#include <bfa_ioc.h>
+#include <cna/bfa_cna_trcmod.h>
+
+BFA_TRC_FILE(CNA, PORT);
+
+#define bfa_ioc_portid(__ioc) ((__ioc)->port_id)
+#define bfa_lpuid(__arg) bfa_ioc_portid(&(__arg)->ioc)
+
+static void
+bfa_port_stats_swap(struct bfa_port_s *port, union bfa_pport_stats_u *stats)
+{
+       u32       *dip = (u32 *) stats;
+       u32        t0, t1;
+       int             i;
+
+       for (i = 0; i < sizeof(union bfa_pport_stats_u) / sizeof(u32);
+            i += 2) {
+               t0 = dip[i];
+               t1 = dip[i + 1];
+#ifdef __BIGENDIAN
+               dip[i] = bfa_os_ntohl(t0);
+               dip[i + 1] = bfa_os_ntohl(t1);
+#else
+               dip[i] = bfa_os_ntohl(t1);
+               dip[i + 1] = bfa_os_ntohl(t0);
+#endif
+       }
+
+    /** todo
+     * QoS stats r also swapped as 64bit; that structure also
+     * has to use 64 bit counters
+     */
+}
+
+/**
+ * bfa_port_enable_isr()
+ *
+ *
+ * @param[in] port - Pointer to the port module
+ *            status - Return status from the f/w
+ *
+ * @return void
+ */
+static void
+bfa_port_enable_isr(struct bfa_port_s *port, bfa_status_t status)
+{
+       bfa_assert(0);
+}
+
+/**
+ * bfa_port_disable_isr()
+ *
+ *
+ * @param[in] port - Pointer to the port module
+ *            status - Return status from the f/w
+ *
+ * @return void
+ */
+static void
+bfa_port_disable_isr(struct bfa_port_s *port, bfa_status_t status)
+{
+       bfa_assert(0);
+}
+
+/**
+ * bfa_port_get_stats_isr()
+ *
+ *
+ * @param[in] port - Pointer to the Port module
+ *            status - Return status from the f/w
+ *
+ * @return void
+ */
+static void
+bfa_port_get_stats_isr(struct bfa_port_s *port, bfa_status_t status)
+{
+       port->stats_status = status;
+       port->stats_busy = BFA_FALSE;
+
+       if (status == BFA_STATUS_OK) {
+               memcpy(port->stats, port->stats_dma.kva,
+                      sizeof(union bfa_pport_stats_u));
+               bfa_port_stats_swap(port, port->stats);
+       }
+
+       if (port->stats_cbfn) {
+               port->stats_cbfn(port->stats_cbarg, status);
+               port->stats_cbfn = NULL;
+       }
+}
+
+/**
+ * bfa_port_clear_stats_isr()
+ *
+ *
+ * @param[in] port - Pointer to the Port module
+ *            status - Return status from the f/w
+ *
+ * @return void
+ */
+static void
+bfa_port_clear_stats_isr(struct bfa_port_s *port, bfa_status_t status)
+{
+       port->stats_status = status;
+       port->stats_busy = BFA_FALSE;
+
+       if (port->stats_cbfn) {
+               port->stats_cbfn(port->stats_cbarg, status);
+               port->stats_cbfn = NULL;
+       }
+}
+
+/**
+ * bfa_port_isr()
+ *
+ *
+ * @param[in] Pointer to the Port module data structure.
+ *
+ * @return void
+ */
+static void
+bfa_port_isr(void *cbarg, struct bfi_mbmsg_s *m)
+{
+       struct bfa_port_s *port = (struct bfa_port_s *)cbarg;
+       union bfi_port_i2h_msg_u *i2hmsg;
+
+       i2hmsg = (union bfi_port_i2h_msg_u *)m;
+       bfa_trc(port, m->mh.msg_id);
+
+       switch (m->mh.msg_id) {
+       case BFI_PORT_I2H_ENABLE_RSP:
+               if (port->endis_pending == BFA_FALSE)
+                       break;
+               bfa_port_enable_isr(port, i2hmsg->enable_rsp.status);
+               break;
+
+       case BFI_PORT_I2H_DISABLE_RSP:
+               if (port->endis_pending == BFA_FALSE)
+                       break;
+               bfa_port_disable_isr(port, i2hmsg->disable_rsp.status);
+               break;
+
+       case BFI_PORT_I2H_GET_STATS_RSP:
+               /*
+                * Stats busy flag is still set? (may be cmd timed out)
+                */
+               if (port->stats_busy == BFA_FALSE)
+                       break;
+               bfa_port_get_stats_isr(port, i2hmsg->getstats_rsp.status);
+               break;
+
+       case BFI_PORT_I2H_CLEAR_STATS_RSP:
+               if (port->stats_busy == BFA_FALSE)
+                       break;
+               bfa_port_clear_stats_isr(port, i2hmsg->clearstats_rsp.status);
+               break;
+
+       default:
+               bfa_assert(0);
+       }
+}
+
+/**
+ * bfa_port_meminfo()
+ *
+ *
+ * @param[in] void
+ *
+ * @return Size of DMA region
+ */
+u32
+bfa_port_meminfo(void)
+{
+       return BFA_ROUNDUP(sizeof(union bfa_pport_stats_u), BFA_DMA_ALIGN_SZ);
+}
+
+/**
+ * bfa_port_mem_claim()
+ *
+ *
+ * @param[in] port Port module pointer
+ *           dma_kva Kernel Virtual Address of Port DMA Memory
+ *           dma_pa  Physical Address of Port DMA Memory
+ *
+ * @return void
+ */
+void
+bfa_port_mem_claim(struct bfa_port_s *port, u8 *dma_kva, u64 dma_pa)
+{
+       port->stats_dma.kva = dma_kva;
+       port->stats_dma.pa = dma_pa;
+}
+
+/**
+ * bfa_port_enable()
+ *
+ *   Send the Port enable request to the f/w
+ *
+ * @param[in] Pointer to the Port module data structure.
+ *
+ * @return Status
+ */
+bfa_status_t
+bfa_port_enable(struct bfa_port_s *port, bfa_port_endis_cbfn_t cbfn,
+               void *cbarg)
+{
+       struct bfi_port_generic_req_s *m;
+
+       /** todo Not implemented */
+       bfa_assert(0);
+
+       if (!bfa_ioc_is_operational(port->ioc)) {
+               bfa_trc(port, BFA_STATUS_IOC_FAILURE);
+               return BFA_STATUS_IOC_FAILURE;
+       }
+
+       if (port->endis_pending) {
+               bfa_trc(port, BFA_STATUS_DEVBUSY);
+               return BFA_STATUS_DEVBUSY;
+       }
+
+       m = (struct bfi_port_generic_req_s *)port->endis_mb.msg;
+
+       port->msgtag++;
+       port->endis_cbfn = cbfn;
+       port->endis_cbarg = cbarg;
+       port->endis_pending = BFA_TRUE;
+
+       bfi_h2i_set(m->mh, BFI_MC_PORT, BFI_PORT_H2I_ENABLE_REQ,
+                   bfa_ioc_portid(port->ioc));
+       bfa_ioc_mbox_queue(port->ioc, &port->endis_mb);
+
+       return BFA_STATUS_OK;
+}
+
+/**
+ * bfa_port_disable()
+ *
+ *   Send the Port disable request to the f/w
+ *
+ * @param[in] Pointer to the Port module data structure.
+ *
+ * @return Status
+ */
+bfa_status_t
+bfa_port_disable(struct bfa_port_s *port, bfa_port_endis_cbfn_t cbfn,
+                void *cbarg)
+{
+       struct bfi_port_generic_req_s *m;
+
+       /** todo Not implemented */
+       bfa_assert(0);
+
+       if (!bfa_ioc_is_operational(port->ioc)) {
+               bfa_trc(port, BFA_STATUS_IOC_FAILURE);
+               return BFA_STATUS_IOC_FAILURE;
+       }
+
+       if (port->endis_pending) {
+               bfa_trc(port, BFA_STATUS_DEVBUSY);
+               return BFA_STATUS_DEVBUSY;
+       }
+
+       m = (struct bfi_port_generic_req_s *)port->endis_mb.msg;
+
+       port->msgtag++;
+       port->endis_cbfn = cbfn;
+       port->endis_cbarg = cbarg;
+       port->endis_pending = BFA_TRUE;
+
+       bfi_h2i_set(m->mh, BFI_MC_PORT, BFI_PORT_H2I_DISABLE_REQ,
+                   bfa_ioc_portid(port->ioc));
+       bfa_ioc_mbox_queue(port->ioc, &port->endis_mb);
+
+       return BFA_STATUS_OK;
+}
+
+/**
+ * bfa_port_get_stats()
+ *
+ *   Send the request to the f/w to fetch Port statistics.
+ *
+ * @param[in] Pointer to the Port module data structure.
+ *
+ * @return Status
+ */
+bfa_status_t
+bfa_port_get_stats(struct bfa_port_s *port, union bfa_pport_stats_u *stats,
+                  bfa_port_stats_cbfn_t cbfn, void *cbarg)
+{
+       struct bfi_port_get_stats_req_s *m;
+
+       if (!bfa_ioc_is_operational(port->ioc)) {
+               bfa_trc(port, BFA_STATUS_IOC_FAILURE);
+               return BFA_STATUS_IOC_FAILURE;
+       }
+
+       if (port->stats_busy) {
+               bfa_trc(port, BFA_STATUS_DEVBUSY);
+               return BFA_STATUS_DEVBUSY;
+       }
+
+       m = (struct bfi_port_get_stats_req_s *)port->stats_mb.msg;
+
+       port->stats = stats;
+       port->stats_cbfn = cbfn;
+       port->stats_cbarg = cbarg;
+       port->stats_busy = BFA_TRUE;
+       bfa_dma_be_addr_set(m->dma_addr, port->stats_dma.pa);
+
+       bfi_h2i_set(m->mh, BFI_MC_PORT, BFI_PORT_H2I_GET_STATS_REQ,
+                   bfa_ioc_portid(port->ioc));
+       bfa_ioc_mbox_queue(port->ioc, &port->stats_mb);
+
+       return BFA_STATUS_OK;
+}
+
+/**
+ * bfa_port_clear_stats()
+ *
+ *
+ * @param[in] Pointer to the Port module data structure.
+ *
+ * @return Status
+ */
+bfa_status_t
+bfa_port_clear_stats(struct bfa_port_s *port, bfa_port_stats_cbfn_t cbfn,
+                    void *cbarg)
+{
+       struct bfi_port_generic_req_s *m;
+
+       if (!bfa_ioc_is_operational(port->ioc)) {
+               bfa_trc(port, BFA_STATUS_IOC_FAILURE);
+               return BFA_STATUS_IOC_FAILURE;
+       }
+
+       if (port->stats_busy) {
+               bfa_trc(port, BFA_STATUS_DEVBUSY);
+               return BFA_STATUS_DEVBUSY;
+       }
+
+       m = (struct bfi_port_generic_req_s *)port->stats_mb.msg;
+
+       port->stats_cbfn = cbfn;
+       port->stats_cbarg = cbarg;
+       port->stats_busy = BFA_TRUE;
+
+       bfi_h2i_set(m->mh, BFI_MC_PORT, BFI_PORT_H2I_CLEAR_STATS_REQ,
+                   bfa_ioc_portid(port->ioc));
+       bfa_ioc_mbox_queue(port->ioc, &port->stats_mb);
+
+       return BFA_STATUS_OK;
+}
+
+/**
+ * bfa_port_hbfail()
+ *
+ *
+ * @param[in] Pointer to the Port module data structure.
+ *
+ * @return void
+ */
+void
+bfa_port_hbfail(void *arg)
+{
+       struct bfa_port_s *port = (struct bfa_port_s *)arg;
+
+       /*
+        * Fail any pending get_stats/clear_stats requests
+        */
+       if (port->stats_busy) {
+               if (port->stats_cbfn)
+                       port->stats_cbfn(port->dev, BFA_STATUS_FAILED);
+               port->stats_cbfn = NULL;
+               port->stats_busy = BFA_FALSE;
+       }
+
+       /*
+        * Clear any enable/disable is pending
+        */
+       if (port->endis_pending) {
+               if (port->endis_cbfn)
+                       port->endis_cbfn(port->dev, BFA_STATUS_FAILED);
+               port->endis_cbfn = NULL;
+               port->endis_pending = BFA_FALSE;
+       }
+}
+
+/**
+ * bfa_port_attach()
+ *
+ *
+ * @param[in] port - Pointer to the Port module data structure
+ *            ioc  - Pointer to the ioc module data structure
+ *            dev  - Pointer to the device driver module data structure
+ *                   The device driver specific mbox ISR functions have
+ *                   this pointer as one of the parameters.
+ *            trcmod -
+ *            logmod -
+ *
+ * @return void
+ */
+void
+bfa_port_attach(struct bfa_port_s *port, struct bfa_ioc_s *ioc, void *dev,
+               struct bfa_trc_mod_s *trcmod, struct bfa_log_mod_s *logmod)
+{
+       bfa_assert(port);
+
+       port->dev = dev;
+       port->ioc = ioc;
+       port->trcmod = trcmod;
+       port->logmod = logmod;
+
+       port->stats_busy = port->endis_pending = BFA_FALSE;
+       port->stats_cbfn = port->endis_cbfn = NULL;
+
+       bfa_ioc_mbox_regisr(port->ioc, BFI_MC_PORT, bfa_port_isr, port);
+       bfa_ioc_hbfail_init(&port->hbfail, bfa_port_hbfail, port);
+       bfa_ioc_hbfail_register(port->ioc, &port->hbfail);
+
+       bfa_trc(port, 0);
+}
+
+/**
+ * bfa_port_detach()
+ *
+ *
+ * @param[in] port - Pointer to the Port module data structure
+ *
+ * @return void
+ */
+void
+bfa_port_detach(struct bfa_port_s *port)
+{
+       bfa_trc(port, 0);
+}
diff --git a/drivers/scsi/bfa/bfa_port_priv.h b/drivers/scsi/bfa/bfa_port_priv.h
new file mode 100644 (file)
index 0000000..4b97e27
--- /dev/null
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ */
+
+#ifndef __BFA_PORT_PRIV_H__
+#define __BFA_PORT_PRIV_H__
+
+#include <defs/bfa_defs_pport.h>
+#include <bfi/bfi_pport.h>
+#include "bfa_intr_priv.h"
+
+/**
+ * BFA physical port data structure
+ */
+struct bfa_pport_s {
+       struct bfa_s            *bfa;   /*  parent BFA instance */
+       bfa_sm_t                sm;     /*  port state machine */
+       wwn_t                   nwwn;   /*  node wwn of physical port */
+       wwn_t                   pwwn;   /*  port wwn of physical oprt */
+       enum bfa_pport_speed speed_sup;
+                                       /*  supported speeds */
+       enum bfa_pport_speed speed;     /*  current speed */
+       enum bfa_pport_topology topology;       /*  current topology */
+       u8                      myalpa; /*  my ALPA in LOOP topology */
+       u8                      rsvd[3];
+       struct bfa_pport_cfg_s  cfg;    /*  current port configuration */
+       struct bfa_qos_attr_s  qos_attr;   /* QoS Attributes */
+       struct bfa_qos_vc_attr_s qos_vc_attr;  /*  VC info from ELP */
+       struct bfa_reqq_wait_s  reqq_wait;
+                                       /*  to wait for room in reqq */
+       struct bfa_reqq_wait_s  svcreq_wait;
+                                       /*  to wait for room in reqq */
+       struct bfa_reqq_wait_s  stats_reqq_wait;
+                                       /*  to wait for room in reqq (stats) */
+       void                    *event_cbarg;
+       void                    (*event_cbfn) (void *cbarg,
+                                               bfa_pport_event_t event);
+       union {
+               union bfi_pport_i2h_msg_u i2hmsg;
+       } event_arg;
+       void                    *bfad;  /*  BFA driver handle */
+       struct bfa_cb_qe_s              hcb_qe; /*  BFA callback queue elem */
+       enum bfa_pport_linkstate        hcb_event;
+                                       /*  link event for callback */
+       u32             msgtag; /*  fimrware msg tag for reply */
+       u8                      *stats_kva;
+       u64             stats_pa;
+       union bfa_pport_stats_u *stats; /*  pport stats */
+       u32             mypid : 24;
+       u32             rsvd_b : 8;
+       struct bfa_timer_s      timer;  /*  timer */
+       union bfa_pport_stats_u         *stats_ret;
+                                       /*  driver stats location */
+       bfa_status_t            stats_status;
+                                       /*  stats/statsclr status */
+       bfa_boolean_t           stats_busy;
+                                       /*  outstanding stats/statsclr */
+       bfa_boolean_t           stats_qfull;
+       bfa_boolean_t           diag_busy;
+                                       /*  diag busy status */
+       bfa_boolean_t           beacon;
+                                       /*  port beacon status */
+       bfa_boolean_t           link_e2e_beacon;
+                                       /*  link beacon status */
+       bfa_cb_pport_t          stats_cbfn;
+                                       /*  driver callback function */
+       void                    *stats_cbarg;
+                                       /* *!< user callback arg */
+};
+
+#define BFA_PORT_MOD(__bfa)    (&(__bfa)->modules.pport)
+
+/*
+ * public functions
+ */
+void   bfa_pport_isr(struct bfa_s *bfa, struct bfi_msg_s *msg);
+#endif /* __BFA_PORT_PRIV_H__ */
diff --git a/drivers/scsi/bfa/bfa_priv.h b/drivers/scsi/bfa/bfa_priv.h
new file mode 100644 (file)
index 0000000..0747a6b
--- /dev/null
@@ -0,0 +1,113 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ */
+
+#ifndef __BFA_PRIV_H__
+#define __BFA_PRIV_H__
+
+#include "bfa_iocfc.h"
+#include "bfa_intr_priv.h"
+#include "bfa_trcmod_priv.h"
+#include "bfa_modules_priv.h"
+#include "bfa_fwimg_priv.h"
+#include <cs/bfa_log.h>
+#include <bfa_timer.h>
+
+/**
+ * Macro to define a new BFA module
+ */
+#define BFA_MODULE(__mod)                                              \
+       static void bfa_ ## __mod ## _meminfo(                          \
+                       struct bfa_iocfc_cfg_s *cfg, u32 *ndm_len,      \
+                       u32 *dm_len);      \
+       static void bfa_ ## __mod ## _attach(struct bfa_s *bfa,         \
+                       void *bfad, struct bfa_iocfc_cfg_s *cfg,        \
+                       struct bfa_meminfo_s *meminfo,                  \
+                       struct bfa_pcidev_s *pcidev);      \
+       static void bfa_ ## __mod ## _initdone(struct bfa_s *bfa);      \
+       static void bfa_ ## __mod ## _detach(struct bfa_s *bfa);      \
+       static void bfa_ ## __mod ## _start(struct bfa_s *bfa);      \
+       static void bfa_ ## __mod ## _stop(struct bfa_s *bfa);      \
+       static void bfa_ ## __mod ## _iocdisable(struct bfa_s *bfa);      \
+                                                                       \
+       extern struct bfa_module_s hal_mod_ ## __mod;                   \
+       struct bfa_module_s hal_mod_ ## __mod = {                       \
+               bfa_ ## __mod ## _meminfo,                              \
+               bfa_ ## __mod ## _attach,                               \
+               bfa_ ## __mod ## _initdone,                             \
+               bfa_ ## __mod ## _detach,                               \
+               bfa_ ## __mod ## _start,                                \
+               bfa_ ## __mod ## _stop,                                 \
+               bfa_ ## __mod ## _iocdisable,                           \
+       }
+
+#define BFA_CACHELINE_SZ       (256)
+
+/**
+ * Structure used to interact between different BFA sub modules
+ *
+ * Each sub module needs to implement only the entry points relevant to it (and
+ * can leave entry points as NULL)
+ */
+struct bfa_module_s {
+       void (*meminfo) (struct bfa_iocfc_cfg_s *cfg, u32 *km_len,
+                       u32 *dm_len);
+       void (*attach) (struct bfa_s *bfa, void *bfad,
+                       struct bfa_iocfc_cfg_s *cfg,
+                       struct bfa_meminfo_s *meminfo,
+                       struct bfa_pcidev_s *pcidev);
+       void (*initdone) (struct bfa_s *bfa);
+       void (*detach) (struct bfa_s *bfa);
+       void (*start) (struct bfa_s *bfa);
+       void (*stop) (struct bfa_s *bfa);
+       void (*iocdisable) (struct bfa_s *bfa);
+};
+
+extern struct bfa_module_s *hal_mods[];
+
+struct bfa_s {
+       void                    *bfad;          /*  BFA driver instance    */
+       struct bfa_aen_s        *aen;           /*  AEN module              */
+       struct bfa_plog_s       *plog;          /*  portlog buffer          */
+       struct bfa_log_mod_s    *logm;          /*  driver logging modulen */
+       struct bfa_trc_mod_s    *trcmod;        /*  driver tracing          */
+       struct bfa_ioc_s        ioc;            /*  IOC module              */
+       struct bfa_iocfc_s      iocfc;          /*  IOCFC module            */
+       struct bfa_timer_mod_s  timer_mod;      /*  timer module            */
+       struct bfa_modules_s    modules;        /*  BFA modules     */
+       struct list_head        comp_q;         /*  pending completions    */
+       bfa_boolean_t           rme_process;    /*  RME processing enabled */
+       struct list_head                reqq_waitq[BFI_IOC_MAX_CQS];
+       bfa_boolean_t           fcs;            /*  FCS is attached to BFA */
+       struct bfa_msix_s       msix;
+};
+
+extern bfa_isr_func_t bfa_isrs[BFI_MC_MAX];
+extern bfa_ioc_mbox_mcfunc_t  bfa_mbox_isrs[];
+extern bfa_boolean_t bfa_auto_recover;
+extern struct bfa_module_s hal_mod_flash;
+extern struct bfa_module_s hal_mod_fcdiag;
+extern struct bfa_module_s hal_mod_sgpg;
+extern struct bfa_module_s hal_mod_pport;
+extern struct bfa_module_s hal_mod_fcxp;
+extern struct bfa_module_s hal_mod_lps;
+extern struct bfa_module_s hal_mod_uf;
+extern struct bfa_module_s hal_mod_rport;
+extern struct bfa_module_s hal_mod_fcpim;
+extern struct bfa_module_s hal_mod_pbind;
+
+#endif /* __BFA_PRIV_H__ */
+
diff --git a/drivers/scsi/bfa/bfa_rport.c b/drivers/scsi/bfa/bfa_rport.c
new file mode 100644 (file)
index 0000000..16da77a
--- /dev/null
@@ -0,0 +1,911 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ */
+
+#include <bfa.h>
+#include <bfa_svc.h>
+#include <cs/bfa_debug.h>
+#include <bfi/bfi_rport.h>
+#include "bfa_intr_priv.h"
+
+BFA_TRC_FILE(HAL, RPORT);
+BFA_MODULE(rport);
+
+#define bfa_rport_offline_cb(__rp) do {                                \
+       if ((__rp)->bfa->fcs)                                           \
+               bfa_cb_rport_offline((__rp)->rport_drv);      \
+       else {                                                          \
+               bfa_cb_queue((__rp)->bfa, &(__rp)->hcb_qe,              \
+                               __bfa_cb_rport_offline, (__rp));      \
+       }                                                               \
+} while (0)
+
+#define bfa_rport_online_cb(__rp) do {                         \
+       if ((__rp)->bfa->fcs)                                           \
+               bfa_cb_rport_online((__rp)->rport_drv);      \
+       else {                                                          \
+               bfa_cb_queue((__rp)->bfa, &(__rp)->hcb_qe,              \
+                                 __bfa_cb_rport_online, (__rp));      \
+               }                                                       \
+} while (0)
+
+/*
+ * forward declarations
+ */
+static struct bfa_rport_s *bfa_rport_alloc(struct bfa_rport_mod_s *rp_mod);
+static void bfa_rport_free(struct bfa_rport_s *rport);
+static bfa_boolean_t bfa_rport_send_fwcreate(struct bfa_rport_s *rp);
+static bfa_boolean_t bfa_rport_send_fwdelete(struct bfa_rport_s *rp);
+static bfa_boolean_t bfa_rport_send_fwspeed(struct bfa_rport_s *rp);
+static void __bfa_cb_rport_online(void *cbarg, bfa_boolean_t complete);
+static void __bfa_cb_rport_offline(void *cbarg, bfa_boolean_t complete);
+
+/**
+ *  bfa_rport_sm BFA rport state machine
+ */
+
+
+enum bfa_rport_event {
+       BFA_RPORT_SM_CREATE     = 1,    /*  rport create event          */
+       BFA_RPORT_SM_DELETE     = 2,    /*  deleting an existing rport */
+       BFA_RPORT_SM_ONLINE     = 3,    /*  rport is online             */
+       BFA_RPORT_SM_OFFLINE    = 4,    /*  rport is offline            */
+       BFA_RPORT_SM_FWRSP      = 5,    /*  firmware response           */
+       BFA_RPORT_SM_HWFAIL     = 6,    /*  IOC h/w failure             */
+       BFA_RPORT_SM_QOS_SCN    = 7,    /*  QoS SCN from firmware       */
+       BFA_RPORT_SM_SET_SPEED  = 8,    /*  Set Rport Speed             */
+       BFA_RPORT_SM_QRESUME    = 9,    /*  space in requeue queue      */
+};
+
+static void    bfa_rport_sm_uninit(struct bfa_rport_s *rp,
+                                       enum bfa_rport_event event);
+static void    bfa_rport_sm_created(struct bfa_rport_s *rp,
+                                        enum bfa_rport_event event);
+static void    bfa_rport_sm_fwcreate(struct bfa_rport_s *rp,
+                                         enum bfa_rport_event event);
+static void    bfa_rport_sm_online(struct bfa_rport_s *rp,
+                                       enum bfa_rport_event event);
+static void    bfa_rport_sm_fwdelete(struct bfa_rport_s *rp,
+                                         enum bfa_rport_event event);
+static void    bfa_rport_sm_offline(struct bfa_rport_s *rp,
+                                        enum bfa_rport_event event);
+static void    bfa_rport_sm_deleting(struct bfa_rport_s *rp,
+                                         enum bfa_rport_event event);
+static void    bfa_rport_sm_offline_pending(struct bfa_rport_s *rp,
+                                         enum bfa_rport_event event);
+static void    bfa_rport_sm_delete_pending(struct bfa_rport_s *rp,
+                                         enum bfa_rport_event event);
+static void    bfa_rport_sm_iocdisable(struct bfa_rport_s *rp,
+                                           enum bfa_rport_event event);
+static void    bfa_rport_sm_fwcreate_qfull(struct bfa_rport_s *rp,
+                                         enum bfa_rport_event event);
+static void    bfa_rport_sm_fwdelete_qfull(struct bfa_rport_s *rp,
+                                         enum bfa_rport_event event);
+static void    bfa_rport_sm_deleting_qfull(struct bfa_rport_s *rp,
+                                         enum bfa_rport_event event);
+
+/**
+ * Beginning state, only online event expected.
+ */
+static void
+bfa_rport_sm_uninit(struct bfa_rport_s *rp, enum bfa_rport_event event)
+{
+       bfa_trc(rp->bfa, rp->rport_tag);
+       bfa_trc(rp->bfa, event);
+
+       switch (event) {
+       case BFA_RPORT_SM_CREATE:
+               bfa_stats(rp, sm_un_cr);
+               bfa_sm_set_state(rp, bfa_rport_sm_created);
+               break;
+
+       default:
+               bfa_stats(rp, sm_un_unexp);
+               bfa_assert(0);
+       }
+}
+
+static void
+bfa_rport_sm_created(struct bfa_rport_s *rp, enum bfa_rport_event event)
+{
+       bfa_trc(rp->bfa, rp->rport_tag);
+       bfa_trc(rp->bfa, event);
+
+       switch (event) {
+       case BFA_RPORT_SM_ONLINE:
+               bfa_stats(rp, sm_cr_on);
+               if (bfa_rport_send_fwcreate(rp))
+                       bfa_sm_set_state(rp, bfa_rport_sm_fwcreate);
+               else
+                       bfa_sm_set_state(rp, bfa_rport_sm_fwcreate_qfull);
+               break;
+
+       case BFA_RPORT_SM_DELETE:
+               bfa_stats(rp, sm_cr_del);
+               bfa_sm_set_state(rp, bfa_rport_sm_uninit);
+               bfa_rport_free(rp);
+               break;
+
+       case BFA_RPORT_SM_HWFAIL:
+               bfa_stats(rp, sm_cr_hwf);
+               bfa_sm_set_state(rp, bfa_rport_sm_iocdisable);
+               break;
+
+       default:
+               bfa_stats(rp, sm_cr_unexp);
+               bfa_assert(0);
+       }
+}
+
+/**
+ * Waiting for rport create response from firmware.
+ */
+static void
+bfa_rport_sm_fwcreate(struct bfa_rport_s *rp, enum bfa_rport_event event)
+{
+       bfa_trc(rp->bfa, rp->rport_tag);
+       bfa_trc(rp->bfa, event);
+
+       switch (event) {
+       case BFA_RPORT_SM_FWRSP:
+               bfa_stats(rp, sm_fwc_rsp);
+               bfa_sm_set_state(rp, bfa_rport_sm_online);
+               bfa_rport_online_cb(rp);
+               break;
+
+       case BFA_RPORT_SM_DELETE:
+               bfa_stats(rp, sm_fwc_del);
+               bfa_sm_set_state(rp, bfa_rport_sm_delete_pending);
+               break;
+
+       case BFA_RPORT_SM_OFFLINE:
+               bfa_stats(rp, sm_fwc_off);
+               bfa_sm_set_state(rp, bfa_rport_sm_offline_pending);
+               break;
+
+       case BFA_RPORT_SM_HWFAIL:
+               bfa_stats(rp, sm_fwc_hwf);
+               bfa_sm_set_state(rp, bfa_rport_sm_iocdisable);
+               break;
+
+       default:
+               bfa_stats(rp, sm_fwc_unexp);
+               bfa_assert(0);
+       }
+}
+
+/**
+ * Request queue is full, awaiting queue resume to send create request.
+ */
+static void
+bfa_rport_sm_fwcreate_qfull(struct bfa_rport_s *rp, enum bfa_rport_event event)
+{
+       bfa_trc(rp->bfa, rp->rport_tag);
+       bfa_trc(rp->bfa, event);
+
+       switch (event) {
+       case BFA_RPORT_SM_QRESUME:
+               bfa_sm_set_state(rp, bfa_rport_sm_fwcreate);
+               bfa_rport_send_fwcreate(rp);
+               break;
+
+       case BFA_RPORT_SM_DELETE:
+               bfa_stats(rp, sm_fwc_del);
+               bfa_sm_set_state(rp, bfa_rport_sm_uninit);
+               bfa_reqq_wcancel(&rp->reqq_wait);
+               bfa_rport_free(rp);
+               break;
+
+       case BFA_RPORT_SM_OFFLINE:
+               bfa_stats(rp, sm_fwc_off);
+               bfa_sm_set_state(rp, bfa_rport_sm_offline);
+               bfa_reqq_wcancel(&rp->reqq_wait);
+               bfa_rport_offline_cb(rp);
+               break;
+
+       case BFA_RPORT_SM_HWFAIL:
+               bfa_stats(rp, sm_fwc_hwf);
+               bfa_sm_set_state(rp, bfa_rport_sm_iocdisable);
+               bfa_reqq_wcancel(&rp->reqq_wait);
+               break;
+
+       default:
+               bfa_stats(rp, sm_fwc_unexp);
+               bfa_assert(0);
+       }
+}
+
+/**
+ * Online state - normal parking state.
+ */
+static void
+bfa_rport_sm_online(struct bfa_rport_s *rp, enum bfa_rport_event event)
+{
+       struct bfi_rport_qos_scn_s *qos_scn;
+
+       bfa_trc(rp->bfa, rp->rport_tag);
+       bfa_trc(rp->bfa, event);
+
+       switch (event) {
+       case BFA_RPORT_SM_OFFLINE:
+               bfa_stats(rp, sm_on_off);
+               if (bfa_rport_send_fwdelete(rp))
+                       bfa_sm_set_state(rp, bfa_rport_sm_fwdelete);
+               else
+                       bfa_sm_set_state(rp, bfa_rport_sm_fwdelete_qfull);
+               break;
+
+       case BFA_RPORT_SM_DELETE:
+               bfa_stats(rp, sm_on_del);
+               if (bfa_rport_send_fwdelete(rp))
+                       bfa_sm_set_state(rp, bfa_rport_sm_deleting);
+               else
+                       bfa_sm_set_state(rp, bfa_rport_sm_deleting_qfull);
+               break;
+
+       case BFA_RPORT_SM_HWFAIL:
+               bfa_stats(rp, sm_on_hwf);
+               bfa_sm_set_state(rp, bfa_rport_sm_iocdisable);
+               break;
+
+       case BFA_RPORT_SM_SET_SPEED:
+               bfa_rport_send_fwspeed(rp);
+               break;
+
+       case BFA_RPORT_SM_QOS_SCN:
+               qos_scn = (struct bfi_rport_qos_scn_s *) rp->event_arg.fw_msg;
+               rp->qos_attr = qos_scn->new_qos_attr;
+               bfa_trc(rp->bfa, qos_scn->old_qos_attr.qos_flow_id);
+               bfa_trc(rp->bfa, qos_scn->new_qos_attr.qos_flow_id);
+               bfa_trc(rp->bfa, qos_scn->old_qos_attr.qos_priority);
+               bfa_trc(rp->bfa, qos_scn->new_qos_attr.qos_priority);
+
+               qos_scn->old_qos_attr.qos_flow_id  =
+                       bfa_os_ntohl(qos_scn->old_qos_attr.qos_flow_id);
+               qos_scn->new_qos_attr.qos_flow_id  =
+                       bfa_os_ntohl(qos_scn->new_qos_attr.qos_flow_id);
+               qos_scn->old_qos_attr.qos_priority =
+                       bfa_os_ntohl(qos_scn->old_qos_attr.qos_priority);
+               qos_scn->new_qos_attr.qos_priority =
+                       bfa_os_ntohl(qos_scn->new_qos_attr.qos_priority);
+
+               if (qos_scn->old_qos_attr.qos_flow_id !=
+                       qos_scn->new_qos_attr.qos_flow_id)
+                       bfa_cb_rport_qos_scn_flowid(rp->rport_drv,
+                                                   qos_scn->old_qos_attr,
+                                                   qos_scn->new_qos_attr);
+               if (qos_scn->old_qos_attr.qos_priority !=
+                       qos_scn->new_qos_attr.qos_priority)
+                       bfa_cb_rport_qos_scn_prio(rp->rport_drv,
+                                                 qos_scn->old_qos_attr,
+                                                 qos_scn->new_qos_attr);
+               break;
+
+       default:
+               bfa_stats(rp, sm_on_unexp);
+               bfa_assert(0);
+       }
+}
+
+/**
+ * Firmware rport is being deleted - awaiting f/w response.
+ */
+static void
+bfa_rport_sm_fwdelete(struct bfa_rport_s *rp, enum bfa_rport_event event)
+{
+       bfa_trc(rp->bfa, rp->rport_tag);
+       bfa_trc(rp->bfa, event);
+
+       switch (event) {
+       case BFA_RPORT_SM_FWRSP:
+               bfa_stats(rp, sm_fwd_rsp);
+               bfa_sm_set_state(rp, bfa_rport_sm_offline);
+               bfa_rport_offline_cb(rp);
+               break;
+
+       case BFA_RPORT_SM_DELETE:
+               bfa_stats(rp, sm_fwd_del);
+               bfa_sm_set_state(rp, bfa_rport_sm_deleting);
+               break;
+
+       case BFA_RPORT_SM_HWFAIL:
+               bfa_stats(rp, sm_fwd_hwf);
+               bfa_sm_set_state(rp, bfa_rport_sm_iocdisable);
+               bfa_rport_offline_cb(rp);
+               break;
+
+       default:
+               bfa_stats(rp, sm_fwd_unexp);
+               bfa_assert(0);
+       }
+}
+
+static void
+bfa_rport_sm_fwdelete_qfull(struct bfa_rport_s *rp, enum bfa_rport_event event)
+{
+       bfa_trc(rp->bfa, rp->rport_tag);
+       bfa_trc(rp->bfa, event);
+
+       switch (event) {
+       case BFA_RPORT_SM_QRESUME:
+               bfa_sm_set_state(rp, bfa_rport_sm_fwdelete);
+               bfa_rport_send_fwdelete(rp);
+               break;
+
+       case BFA_RPORT_SM_DELETE:
+               bfa_stats(rp, sm_fwd_del);
+               bfa_sm_set_state(rp, bfa_rport_sm_deleting_qfull);
+               break;
+
+       case BFA_RPORT_SM_HWFAIL:
+               bfa_stats(rp, sm_fwd_hwf);
+               bfa_sm_set_state(rp, bfa_rport_sm_iocdisable);
+               bfa_reqq_wcancel(&rp->reqq_wait);
+               bfa_rport_offline_cb(rp);
+               break;
+
+       default:
+               bfa_stats(rp, sm_fwd_unexp);
+               bfa_assert(0);
+       }
+}
+
+/**
+ * Offline state.
+ */
+static void
+bfa_rport_sm_offline(struct bfa_rport_s *rp, enum bfa_rport_event event)
+{
+       bfa_trc(rp->bfa, rp->rport_tag);
+       bfa_trc(rp->bfa, event);
+
+       switch (event) {
+       case BFA_RPORT_SM_DELETE:
+               bfa_stats(rp, sm_off_del);
+               bfa_sm_set_state(rp, bfa_rport_sm_uninit);
+               bfa_rport_free(rp);
+               break;
+
+       case BFA_RPORT_SM_ONLINE:
+               bfa_stats(rp, sm_off_on);
+               if (bfa_rport_send_fwcreate(rp))
+                       bfa_sm_set_state(rp, bfa_rport_sm_fwcreate);
+               else
+                       bfa_sm_set_state(rp, bfa_rport_sm_fwcreate_qfull);
+               break;
+
+       case BFA_RPORT_SM_HWFAIL:
+               bfa_stats(rp, sm_off_hwf);
+               bfa_sm_set_state(rp, bfa_rport_sm_iocdisable);
+               break;
+
+       default:
+               bfa_stats(rp, sm_off_unexp);
+               bfa_assert(0);
+       }
+}
+
+/**
+ * Rport is deleted, waiting for firmware response to delete.
+ */
+static void
+bfa_rport_sm_deleting(struct bfa_rport_s *rp, enum bfa_rport_event event)
+{
+       bfa_trc(rp->bfa, rp->rport_tag);
+       bfa_trc(rp->bfa, event);
+
+       switch (event) {
+       case BFA_RPORT_SM_FWRSP:
+               bfa_stats(rp, sm_del_fwrsp);
+               bfa_sm_set_state(rp, bfa_rport_sm_uninit);
+               bfa_rport_free(rp);
+               break;
+
+       case BFA_RPORT_SM_HWFAIL:
+               bfa_stats(rp, sm_del_hwf);
+               bfa_sm_set_state(rp, bfa_rport_sm_uninit);
+               bfa_rport_free(rp);
+               break;
+
+       default:
+               bfa_assert(0);
+       }
+}
+
+static void
+bfa_rport_sm_deleting_qfull(struct bfa_rport_s *rp, enum bfa_rport_event event)
+{
+       bfa_trc(rp->bfa, rp->rport_tag);
+       bfa_trc(rp->bfa, event);
+
+       switch (event) {
+       case BFA_RPORT_SM_QRESUME:
+               bfa_stats(rp, sm_del_fwrsp);
+               bfa_sm_set_state(rp, bfa_rport_sm_deleting);
+               bfa_rport_send_fwdelete(rp);
+               break;
+
+       case BFA_RPORT_SM_HWFAIL:
+               bfa_stats(rp, sm_del_hwf);
+               bfa_sm_set_state(rp, bfa_rport_sm_uninit);
+               bfa_reqq_wcancel(&rp->reqq_wait);
+               bfa_rport_free(rp);
+               break;
+
+       default:
+               bfa_assert(0);
+       }
+}
+
+/**
+ * Waiting for rport create response from firmware. A delete is pending.
+ */
+static void
+bfa_rport_sm_delete_pending(struct bfa_rport_s *rp,
+                               enum bfa_rport_event event)
+{
+       bfa_trc(rp->bfa, rp->rport_tag);
+       bfa_trc(rp->bfa, event);
+
+       switch (event) {
+       case BFA_RPORT_SM_FWRSP:
+               bfa_stats(rp, sm_delp_fwrsp);
+               if (bfa_rport_send_fwdelete(rp))
+                       bfa_sm_set_state(rp, bfa_rport_sm_deleting);
+               else
+                       bfa_sm_set_state(rp, bfa_rport_sm_deleting_qfull);
+               break;
+
+       case BFA_RPORT_SM_HWFAIL:
+               bfa_stats(rp, sm_delp_hwf);
+               bfa_sm_set_state(rp, bfa_rport_sm_uninit);
+               bfa_rport_free(rp);
+               break;
+
+       default:
+               bfa_stats(rp, sm_delp_unexp);
+               bfa_assert(0);
+       }
+}
+
+/**
+ * Waiting for rport create response from firmware. Rport offline is pending.
+ */
+static void
+bfa_rport_sm_offline_pending(struct bfa_rport_s *rp,
+                                enum bfa_rport_event event)
+{
+       bfa_trc(rp->bfa, rp->rport_tag);
+       bfa_trc(rp->bfa, event);
+
+       switch (event) {
+       case BFA_RPORT_SM_FWRSP:
+               bfa_stats(rp, sm_offp_fwrsp);
+               if (bfa_rport_send_fwdelete(rp))
+                       bfa_sm_set_state(rp, bfa_rport_sm_fwdelete);
+               else
+                       bfa_sm_set_state(rp, bfa_rport_sm_fwdelete_qfull);
+               break;
+
+       case BFA_RPORT_SM_DELETE:
+               bfa_stats(rp, sm_offp_del);
+               bfa_sm_set_state(rp, bfa_rport_sm_delete_pending);
+               break;
+
+       case BFA_RPORT_SM_HWFAIL:
+               bfa_stats(rp, sm_offp_hwf);
+               bfa_sm_set_state(rp, bfa_rport_sm_iocdisable);
+               break;
+
+       default:
+               bfa_stats(rp, sm_offp_unexp);
+               bfa_assert(0);
+       }
+}
+
+/**
+ * IOC h/w failed.
+ */
+static void
+bfa_rport_sm_iocdisable(struct bfa_rport_s *rp, enum bfa_rport_event event)
+{
+       bfa_trc(rp->bfa, rp->rport_tag);
+       bfa_trc(rp->bfa, event);
+
+       switch (event) {
+       case BFA_RPORT_SM_OFFLINE:
+               bfa_stats(rp, sm_iocd_off);
+               bfa_rport_offline_cb(rp);
+               break;
+
+       case BFA_RPORT_SM_DELETE:
+               bfa_stats(rp, sm_iocd_del);
+               bfa_sm_set_state(rp, bfa_rport_sm_uninit);
+               bfa_rport_free(rp);
+               break;
+
+       case BFA_RPORT_SM_ONLINE:
+               bfa_stats(rp, sm_iocd_on);
+               if (bfa_rport_send_fwcreate(rp))
+                       bfa_sm_set_state(rp, bfa_rport_sm_fwcreate);
+               else
+                       bfa_sm_set_state(rp, bfa_rport_sm_fwcreate_qfull);
+               break;
+
+       case BFA_RPORT_SM_HWFAIL:
+               break;
+
+       default:
+               bfa_stats(rp, sm_iocd_unexp);
+               bfa_assert(0);
+       }
+}
+
+
+
+/**
+ *  bfa_rport_private BFA rport private functions
+ */
+
+static void
+__bfa_cb_rport_online(void *cbarg, bfa_boolean_t complete)
+{
+       struct bfa_rport_s *rp = cbarg;
+
+       if (complete)
+               bfa_cb_rport_online(rp->rport_drv);
+}
+
+static void
+__bfa_cb_rport_offline(void *cbarg, bfa_boolean_t complete)
+{
+       struct bfa_rport_s *rp = cbarg;
+
+       if (complete)
+               bfa_cb_rport_offline(rp->rport_drv);
+}
+
+static void
+bfa_rport_qresume(void *cbarg)
+{
+       struct bfa_rport_s      *rp = cbarg;
+
+       bfa_sm_send_event(rp, BFA_RPORT_SM_QRESUME);
+}
+
+static void
+bfa_rport_meminfo(struct bfa_iocfc_cfg_s *cfg, u32 *km_len,
+               u32 *dm_len)
+{
+       if (cfg->fwcfg.num_rports < BFA_RPORT_MIN)
+               cfg->fwcfg.num_rports = BFA_RPORT_MIN;
+
+       *km_len += cfg->fwcfg.num_rports * sizeof(struct bfa_rport_s);
+}
+
+static void
+bfa_rport_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
+                    struct bfa_meminfo_s *meminfo, struct bfa_pcidev_s *pcidev)
+{
+       struct bfa_rport_mod_s *mod = BFA_RPORT_MOD(bfa);
+       struct bfa_rport_s *rp;
+       u16        i;
+
+       INIT_LIST_HEAD(&mod->rp_free_q);
+       INIT_LIST_HEAD(&mod->rp_active_q);
+
+       rp = (struct bfa_rport_s *) bfa_meminfo_kva(meminfo);
+       mod->rps_list = rp;
+       mod->num_rports = cfg->fwcfg.num_rports;
+
+       bfa_assert(mod->num_rports
+                  && !(mod->num_rports & (mod->num_rports - 1)));
+
+       for (i = 0; i < mod->num_rports; i++, rp++) {
+               bfa_os_memset(rp, 0, sizeof(struct bfa_rport_s));
+               rp->bfa = bfa;
+               rp->rport_tag = i;
+               bfa_sm_set_state(rp, bfa_rport_sm_uninit);
+
+               /**
+                *  - is unused
+                */
+               if (i)
+                       list_add_tail(&rp->qe, &mod->rp_free_q);
+
+               bfa_reqq_winit(&rp->reqq_wait, bfa_rport_qresume, rp);
+       }
+
+       /**
+        * consume memory
+        */
+       bfa_meminfo_kva(meminfo) = (u8 *) rp;
+}
+
+static void
+bfa_rport_initdone(struct bfa_s *bfa)
+{
+}
+
+static void
+bfa_rport_detach(struct bfa_s *bfa)
+{
+}
+
+static void
+bfa_rport_start(struct bfa_s *bfa)
+{
+}
+
+static void
+bfa_rport_stop(struct bfa_s *bfa)
+{
+}
+
+static void
+bfa_rport_iocdisable(struct bfa_s *bfa)
+{
+       struct bfa_rport_mod_s *mod = BFA_RPORT_MOD(bfa);
+       struct bfa_rport_s *rport;
+       struct list_head        *qe, *qen;
+
+       list_for_each_safe(qe, qen, &mod->rp_active_q) {
+               rport = (struct bfa_rport_s *) qe;
+               bfa_sm_send_event(rport, BFA_RPORT_SM_HWFAIL);
+       }
+}
+
+static struct bfa_rport_s *
+bfa_rport_alloc(struct bfa_rport_mod_s *mod)
+{
+       struct bfa_rport_s *rport;
+
+       bfa_q_deq(&mod->rp_free_q, &rport);
+       if (rport)
+               list_add_tail(&rport->qe, &mod->rp_active_q);
+
+       return (rport);
+}
+
+static void
+bfa_rport_free(struct bfa_rport_s *rport)
+{
+       struct bfa_rport_mod_s *mod = BFA_RPORT_MOD(rport->bfa);
+
+       bfa_assert(bfa_q_is_on_q(&mod->rp_active_q, rport));
+       list_del(&rport->qe);
+       list_add_tail(&rport->qe, &mod->rp_free_q);
+}
+
+static bfa_boolean_t
+bfa_rport_send_fwcreate(struct bfa_rport_s *rp)
+{
+       struct bfi_rport_create_req_s *m;
+
+       /**
+        * check for room in queue to send request now
+        */
+       m = bfa_reqq_next(rp->bfa, BFA_REQQ_RPORT);
+       if (!m) {
+               bfa_reqq_wait(rp->bfa, BFA_REQQ_RPORT, &rp->reqq_wait);
+               return BFA_FALSE;
+       }
+
+       bfi_h2i_set(m->mh, BFI_MC_RPORT, BFI_RPORT_H2I_CREATE_REQ,
+                       bfa_lpuid(rp->bfa));
+       m->bfa_handle = rp->rport_tag;
+       m->max_frmsz = bfa_os_htons(rp->rport_info.max_frmsz);
+       m->pid = rp->rport_info.pid;
+       m->lp_tag = rp->rport_info.lp_tag;
+       m->local_pid = rp->rport_info.local_pid;
+       m->fc_class = rp->rport_info.fc_class;
+       m->vf_en = rp->rport_info.vf_en;
+       m->vf_id = rp->rport_info.vf_id;
+       m->cisc = rp->rport_info.cisc;
+
+       /**
+        * queue I/O message to firmware
+        */
+       bfa_reqq_produce(rp->bfa, BFA_REQQ_RPORT);
+       return BFA_TRUE;
+}
+
+static bfa_boolean_t
+bfa_rport_send_fwdelete(struct bfa_rport_s *rp)
+{
+       struct bfi_rport_delete_req_s *m;
+
+       /**
+        * check for room in queue to send request now
+        */
+       m = bfa_reqq_next(rp->bfa, BFA_REQQ_RPORT);
+       if (!m) {
+               bfa_reqq_wait(rp->bfa, BFA_REQQ_RPORT, &rp->reqq_wait);
+               return BFA_FALSE;
+       }
+
+       bfi_h2i_set(m->mh, BFI_MC_RPORT, BFI_RPORT_H2I_DELETE_REQ,
+                       bfa_lpuid(rp->bfa));
+       m->fw_handle = rp->fw_handle;
+
+       /**
+        * queue I/O message to firmware
+        */
+       bfa_reqq_produce(rp->bfa, BFA_REQQ_RPORT);
+       return BFA_TRUE;
+}
+
+static bfa_boolean_t
+bfa_rport_send_fwspeed(struct bfa_rport_s *rp)
+{
+       struct bfa_rport_speed_req_s *m;
+
+       /**
+        * check for room in queue to send request now
+        */
+       m = bfa_reqq_next(rp->bfa, BFA_REQQ_RPORT);
+       if (!m) {
+               bfa_trc(rp->bfa, rp->rport_info.speed);
+               return BFA_FALSE;
+       }
+
+       bfi_h2i_set(m->mh, BFI_MC_RPORT, BFI_RPORT_H2I_SET_SPEED_REQ,
+                       bfa_lpuid(rp->bfa));
+       m->fw_handle = rp->fw_handle;
+       m->speed = (u8)rp->rport_info.speed;
+
+       /**
+        * queue I/O message to firmware
+        */
+       bfa_reqq_produce(rp->bfa, BFA_REQQ_RPORT);
+       return BFA_TRUE;
+}
+
+
+
+/**
+ *  bfa_rport_public
+ */
+
+/**
+ *             Rport interrupt processing.
+ */
+void
+bfa_rport_isr(struct bfa_s *bfa, struct bfi_msg_s *m)
+{
+       union bfi_rport_i2h_msg_u msg;
+       struct bfa_rport_s *rp;
+
+       bfa_trc(bfa, m->mhdr.msg_id);
+
+       msg.msg = m;
+
+       switch (m->mhdr.msg_id) {
+       case BFI_RPORT_I2H_CREATE_RSP:
+               rp = BFA_RPORT_FROM_TAG(bfa, msg.create_rsp->bfa_handle);
+               rp->fw_handle = msg.create_rsp->fw_handle;
+               rp->qos_attr = msg.create_rsp->qos_attr;
+               bfa_assert(msg.create_rsp->status == BFA_STATUS_OK);
+               bfa_sm_send_event(rp, BFA_RPORT_SM_FWRSP);
+               break;
+
+       case BFI_RPORT_I2H_DELETE_RSP:
+               rp = BFA_RPORT_FROM_TAG(bfa, msg.delete_rsp->bfa_handle);
+               bfa_assert(msg.delete_rsp->status == BFA_STATUS_OK);
+               bfa_sm_send_event(rp, BFA_RPORT_SM_FWRSP);
+               break;
+
+       case BFI_RPORT_I2H_QOS_SCN:
+               rp = BFA_RPORT_FROM_TAG(bfa, msg.qos_scn_evt->bfa_handle);
+               rp->event_arg.fw_msg = msg.qos_scn_evt;
+               bfa_sm_send_event(rp, BFA_RPORT_SM_QOS_SCN);
+               break;
+
+       default:
+               bfa_trc(bfa, m->mhdr.msg_id);
+               bfa_assert(0);
+       }
+}
+
+
+
+/**
+ *  bfa_rport_api
+ */
+
+struct bfa_rport_s *
+bfa_rport_create(struct bfa_s *bfa, void *rport_drv)
+{
+       struct bfa_rport_s *rp;
+
+       rp = bfa_rport_alloc(BFA_RPORT_MOD(bfa));
+
+       if (rp == NULL)
+               return (NULL);
+
+       rp->bfa = bfa;
+       rp->rport_drv = rport_drv;
+       bfa_rport_clear_stats(rp);
+
+       bfa_assert(bfa_sm_cmp_state(rp, bfa_rport_sm_uninit));
+       bfa_sm_send_event(rp, BFA_RPORT_SM_CREATE);
+
+       return (rp);
+}
+
+void
+bfa_rport_delete(struct bfa_rport_s *rport)
+{
+       bfa_sm_send_event(rport, BFA_RPORT_SM_DELETE);
+}
+
+void
+bfa_rport_online(struct bfa_rport_s *rport, struct bfa_rport_info_s *rport_info)
+{
+       bfa_assert(rport_info->max_frmsz != 0);
+
+       /**
+        * Some JBODs are seen to be not setting PDU size correctly in PLOGI
+        * responses. Default to minimum size.
+        */
+       if (rport_info->max_frmsz == 0) {
+               bfa_trc(rport->bfa, rport->rport_tag);
+               rport_info->max_frmsz = FC_MIN_PDUSZ;
+       }
+
+       bfa_os_assign(rport->rport_info, *rport_info);
+       bfa_sm_send_event(rport, BFA_RPORT_SM_ONLINE);
+}
+
+void
+bfa_rport_offline(struct bfa_rport_s *rport)
+{
+       bfa_sm_send_event(rport, BFA_RPORT_SM_OFFLINE);
+}
+
+void
+bfa_rport_speed(struct bfa_rport_s *rport, enum bfa_pport_speed speed)
+{
+       bfa_assert(speed != 0);
+       bfa_assert(speed != BFA_PPORT_SPEED_AUTO);
+
+       rport->rport_info.speed = speed;
+       bfa_sm_send_event(rport, BFA_RPORT_SM_SET_SPEED);
+}
+
+void
+bfa_rport_get_stats(struct bfa_rport_s *rport,
+       struct bfa_rport_hal_stats_s *stats)
+{
+       *stats = rport->stats;
+}
+
+void
+bfa_rport_get_qos_attr(struct bfa_rport_s *rport,
+                                       struct bfa_rport_qos_attr_s *qos_attr)
+{
+       qos_attr->qos_priority  = bfa_os_ntohl(rport->qos_attr.qos_priority);
+       qos_attr->qos_flow_id  = bfa_os_ntohl(rport->qos_attr.qos_flow_id);
+
+}
+
+void
+bfa_rport_clear_stats(struct bfa_rport_s *rport)
+{
+       bfa_os_memset(&rport->stats, 0, sizeof(rport->stats));
+}
+
+
diff --git a/drivers/scsi/bfa/bfa_rport_priv.h b/drivers/scsi/bfa/bfa_rport_priv.h
new file mode 100644 (file)
index 0000000..6490ce2
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ */
+
+#ifndef __BFA_RPORT_PRIV_H__
+#define __BFA_RPORT_PRIV_H__
+
+#include <bfa_svc.h>
+
+#define BFA_RPORT_MIN  4
+
+struct bfa_rport_mod_s {
+       struct bfa_rport_s *rps_list;   /*  list of rports      */
+       struct list_head        rp_free_q;      /*  free bfa_rports     */
+       struct list_head        rp_active_q;    /*  free bfa_rports     */
+       u16     num_rports;     /*  number of rports    */
+};
+
+#define BFA_RPORT_MOD(__bfa)   (&(__bfa)->modules.rport_mod)
+
+/**
+ * Convert rport tag to RPORT
+ */
+#define BFA_RPORT_FROM_TAG(__bfa, _tag)                                \
+       (BFA_RPORT_MOD(__bfa)->rps_list +                               \
+        ((_tag) & (BFA_RPORT_MOD(__bfa)->num_rports - 1)))
+
+/*
+ * external functions
+ */
+void   bfa_rport_isr(struct bfa_s *bfa, struct bfi_msg_s *msg);
+#endif /* __BFA_RPORT_PRIV_H__ */
diff --git a/drivers/scsi/bfa/bfa_sgpg.c b/drivers/scsi/bfa/bfa_sgpg.c
new file mode 100644 (file)
index 0000000..279d8f9
--- /dev/null
@@ -0,0 +1,231 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ */
+
+#include <bfa.h>
+
+BFA_TRC_FILE(HAL, SGPG);
+BFA_MODULE(sgpg);
+
+/**
+ *  bfa_sgpg_mod BFA SGPG Mode module
+ */
+
+/**
+ * Compute and return memory needed by FCP(im) module.
+ */
+static void
+bfa_sgpg_meminfo(struct bfa_iocfc_cfg_s *cfg, u32 *km_len,
+               u32 *dm_len)
+{
+       if (cfg->drvcfg.num_sgpgs < BFA_SGPG_MIN)
+               cfg->drvcfg.num_sgpgs = BFA_SGPG_MIN;
+
+       *km_len += (cfg->drvcfg.num_sgpgs + 1) * sizeof(struct bfa_sgpg_s);
+       *dm_len += (cfg->drvcfg.num_sgpgs + 1) * sizeof(struct bfi_sgpg_s);
+}
+
+
+static void
+bfa_sgpg_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
+                   struct bfa_meminfo_s *minfo, struct bfa_pcidev_s *pcidev)
+{
+       struct bfa_sgpg_mod_s   *mod = BFA_SGPG_MOD(bfa);
+       int                             i;
+       struct bfa_sgpg_s               *hsgpg;
+       struct bfi_sgpg_s       *sgpg;
+       u64             align_len;
+
+       union {
+               u64        pa;
+               union bfi_addr_u      addr;
+       } sgpg_pa;
+
+       INIT_LIST_HEAD(&mod->sgpg_q);
+       INIT_LIST_HEAD(&mod->sgpg_wait_q);
+
+       bfa_trc(bfa, cfg->drvcfg.num_sgpgs);
+
+       mod->num_sgpgs = cfg->drvcfg.num_sgpgs;
+       mod->sgpg_arr_pa = bfa_meminfo_dma_phys(minfo);
+       align_len = (BFA_SGPG_ROUNDUP(mod->sgpg_arr_pa) - mod->sgpg_arr_pa);
+       mod->sgpg_arr_pa += align_len;
+       mod->hsgpg_arr = (struct bfa_sgpg_s *) (bfa_meminfo_kva(minfo) +
+                                               align_len);
+       mod->sgpg_arr = (struct bfi_sgpg_s *) (bfa_meminfo_dma_virt(minfo) +
+                                               align_len);
+
+       hsgpg = mod->hsgpg_arr;
+       sgpg = mod->sgpg_arr;
+       sgpg_pa.pa = mod->sgpg_arr_pa;
+       mod->free_sgpgs = mod->num_sgpgs;
+
+       bfa_assert(!(sgpg_pa.pa & (sizeof(struct bfi_sgpg_s) - 1)));
+
+       for (i = 0; i < mod->num_sgpgs; i++) {
+               bfa_os_memset(hsgpg, 0, sizeof(*hsgpg));
+               bfa_os_memset(sgpg, 0, sizeof(*sgpg));
+
+               hsgpg->sgpg = sgpg;
+               hsgpg->sgpg_pa = sgpg_pa.addr;
+               list_add_tail(&hsgpg->qe, &mod->sgpg_q);
+
+               hsgpg++;
+               sgpg++;
+               sgpg_pa.pa += sizeof(struct bfi_sgpg_s);
+       }
+
+       bfa_meminfo_kva(minfo) = (u8 *) hsgpg;
+       bfa_meminfo_dma_virt(minfo) = (u8 *) sgpg;
+       bfa_meminfo_dma_phys(minfo) = sgpg_pa.pa;
+}
+
+static void
+bfa_sgpg_initdone(struct bfa_s *bfa)
+{
+}
+
+static void
+bfa_sgpg_detach(struct bfa_s *bfa)
+{
+}
+
+static void
+bfa_sgpg_start(struct bfa_s *bfa)
+{
+}
+
+static void
+bfa_sgpg_stop(struct bfa_s *bfa)
+{
+}
+
+static void
+bfa_sgpg_iocdisable(struct bfa_s *bfa)
+{
+}
+
+
+
+/**
+ *  bfa_sgpg_public BFA SGPG public functions
+ */
+
+bfa_status_t
+bfa_sgpg_malloc(struct bfa_s *bfa, struct list_head *sgpg_q, int nsgpgs)
+{
+       struct bfa_sgpg_mod_s *mod = BFA_SGPG_MOD(bfa);
+       struct bfa_sgpg_s *hsgpg;
+       int             i;
+
+       bfa_trc_fp(bfa, nsgpgs);
+
+       if (mod->free_sgpgs < nsgpgs)
+               return BFA_STATUS_ENOMEM;
+
+       for (i = 0; i < nsgpgs; i++) {
+               bfa_q_deq(&mod->sgpg_q, &hsgpg);
+               bfa_assert(hsgpg);
+               list_add_tail(&hsgpg->qe, sgpg_q);
+       }
+
+       mod->free_sgpgs -= nsgpgs;
+       return BFA_STATUS_OK;
+}
+
+void
+bfa_sgpg_mfree(struct bfa_s *bfa, struct list_head *sgpg_q, int nsgpg)
+{
+       struct bfa_sgpg_mod_s *mod = BFA_SGPG_MOD(bfa);
+       struct bfa_sgpg_wqe_s *wqe;
+
+       bfa_trc_fp(bfa, nsgpg);
+
+       mod->free_sgpgs += nsgpg;
+       bfa_assert(mod->free_sgpgs <= mod->num_sgpgs);
+
+       list_splice_tail_init(sgpg_q, &mod->sgpg_q);
+
+       if (list_empty(&mod->sgpg_wait_q))
+               return;
+
+       /**
+        * satisfy as many waiting requests as possible
+        */
+       do {
+               wqe = bfa_q_first(&mod->sgpg_wait_q);
+               if (mod->free_sgpgs < wqe->nsgpg)
+                       nsgpg = mod->free_sgpgs;
+               else
+                       nsgpg = wqe->nsgpg;
+               bfa_sgpg_malloc(bfa, &wqe->sgpg_q, nsgpg);
+               wqe->nsgpg -= nsgpg;
+               if (wqe->nsgpg == 0) {
+                       list_del(&wqe->qe);
+                       wqe->cbfn(wqe->cbarg);
+               }
+       } while (mod->free_sgpgs && !list_empty(&mod->sgpg_wait_q));
+}
+
+void
+bfa_sgpg_wait(struct bfa_s *bfa, struct bfa_sgpg_wqe_s *wqe, int nsgpg)
+{
+       struct bfa_sgpg_mod_s *mod = BFA_SGPG_MOD(bfa);
+
+       bfa_assert(nsgpg > 0);
+       bfa_assert(nsgpg > mod->free_sgpgs);
+
+       wqe->nsgpg_total = wqe->nsgpg = nsgpg;
+
+       /**
+        * allocate any left to this one first
+        */
+       if (mod->free_sgpgs) {
+               /**
+                * no one else is waiting for SGPG
+                */
+               bfa_assert(list_empty(&mod->sgpg_wait_q));
+               list_splice_tail_init(&mod->sgpg_q, &wqe->sgpg_q);
+               wqe->nsgpg -= mod->free_sgpgs;
+               mod->free_sgpgs = 0;
+       }
+
+       list_add_tail(&wqe->qe, &mod->sgpg_wait_q);
+}
+
+void
+bfa_sgpg_wcancel(struct bfa_s *bfa, struct bfa_sgpg_wqe_s *wqe)
+{
+       struct bfa_sgpg_mod_s *mod = BFA_SGPG_MOD(bfa);
+
+       bfa_assert(bfa_q_is_on_q(&mod->sgpg_wait_q, wqe));
+       list_del(&wqe->qe);
+
+       if (wqe->nsgpg_total != wqe->nsgpg)
+               bfa_sgpg_mfree(bfa, &wqe->sgpg_q,
+                                  wqe->nsgpg_total - wqe->nsgpg);
+}
+
+void
+bfa_sgpg_winit(struct bfa_sgpg_wqe_s *wqe, void (*cbfn) (void *cbarg),
+                  void *cbarg)
+{
+       INIT_LIST_HEAD(&wqe->sgpg_q);
+       wqe->cbfn = cbfn;
+       wqe->cbarg = cbarg;
+}
+
+
diff --git a/drivers/scsi/bfa/bfa_sgpg_priv.h b/drivers/scsi/bfa/bfa_sgpg_priv.h
new file mode 100644 (file)
index 0000000..9c2a8cb
--- /dev/null
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) 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.
+ */
+
+/**
+ *  hal_sgpg.h BFA SG page module
+ */
+
+#ifndef __BFA_SGPG_PRIV_H__
+#define __BFA_SGPG_PRIV_H__
+
+#include <cs/bfa_q.h>
+
+#define BFA_SGPG_MIN   (16)
+
+/**
+ * Alignment macro for SG page allocation
+ */
+#define BFA_SGPG_ROUNDUP(_l) (((_l) + (sizeof(struct bfi_sgpg_s) - 1)) \
+                       & ~(sizeof(struct bfi_sgpg_s) - 1))
+
+struct bfa_sgpg_wqe_s {
+       struct list_head qe;    /*  queue sg page element       */
+       int     nsgpg;          /*  pages to be allocated       */
+       int     nsgpg_total;    /*  total pages required        */
+       void    (*cbfn) (void *cbarg);
+                               /*  callback function           */
+       void    *cbarg;         /*  callback arg                */
+       struct list_head sgpg_q;        /*  queue of alloced sgpgs      */
+};
+
+struct bfa_sgpg_s {
+       struct list_head        qe;     /*  queue sg page element       */
+       struct bfi_sgpg_s *sgpg; /*  va of SG page              */
+       union bfi_addr_u sgpg_pa;/*  pa of SG page              */
+};
+
+/**
+ * Given number of SG elements, BFA_SGPG_NPAGE() returns the number of
+ * SG pages required.
+ */
+#define BFA_SGPG_NPAGE(_nsges)  (((_nsges) / BFI_SGPG_DATA_SGES) + 1)
+
+struct bfa_sgpg_mod_s {
+       struct bfa_s *bfa;
+       int             num_sgpgs;      /*  number of SG pages          */
+       int             free_sgpgs;     /*  number of free SG pages     */
+       struct bfa_sgpg_s *hsgpg_arr;   /*  BFA SG page array   */
+       struct bfi_sgpg_s *sgpg_arr;    /*  actual SG page array        */
+       u64     sgpg_arr_pa;    /*  SG page array DMA addr      */
+       struct list_head sgpg_q;        /*  queue of free SG pages      */
+       struct list_head sgpg_wait_q; /*  wait queue for SG pages       */
+};
+#define BFA_SGPG_MOD(__bfa)    (&(__bfa)->modules.sgpg_mod)
+
+bfa_status_t   bfa_sgpg_malloc(struct bfa_s *bfa, struct list_head *sgpg_q,
+                                                               int nsgpgs);
+void           bfa_sgpg_mfree(struct bfa_s *bfa, struct list_head *sgpg_q,
+                                                               int nsgpgs);
+void           bfa_sgpg_winit(struct bfa_sgpg_wqe_s *wqe,
+                                  void (*cbfn) (void *cbarg), void *cbarg);
+void           bfa_sgpg_wait(struct bfa_s *bfa, struct bfa_sgpg_wqe_s *wqe,
+                                                               int nsgpgs);
+void           bfa_sgpg_wcancel(struct bfa_s *bfa, struct bfa_sgpg_wqe_s *wqe);
+
+#endif /* __BFA_SGPG_PRIV_H__ */
diff --git a/drivers/scsi/bfa/bfa_sm.c b/drivers/scsi/bfa/bfa_sm.c
new file mode 100644 (file)
index 0000000..5420f4f
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) 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.
+ */
+
+/**
+ *  bfasm.c BFA State machine utility functions
+ */
+
+#include <cs/bfa_sm.h>
+
+/**
+ *  cs_sm_api
+ */
+
+int
+bfa_sm_to_state(struct bfa_sm_table_s *smt, bfa_sm_t sm)
+{
+       int             i = 0;
+
+       while (smt[i].sm && smt[i].sm != sm)
+               i++;
+       return smt[i].state;
+}
+
+
diff --git a/drivers/scsi/bfa/bfa_timer.c b/drivers/scsi/bfa/bfa_timer.c
new file mode 100644 (file)
index 0000000..cb76481
--- /dev/null
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ */
+
+#include <bfa_timer.h>
+#include <cs/bfa_debug.h>
+
+void
+bfa_timer_init(struct bfa_timer_mod_s *mod)
+{
+       INIT_LIST_HEAD(&mod->timer_q);
+}
+
+void
+bfa_timer_beat(struct bfa_timer_mod_s *mod)
+{
+       struct list_head        *qh = &mod->timer_q;
+       struct list_head        *qe, *qe_next;
+       struct bfa_timer_s *elem;
+       struct list_head         timedout_q;
+
+       INIT_LIST_HEAD(&timedout_q);
+
+       qe = bfa_q_next(qh);
+
+       while (qe != qh) {
+               qe_next = bfa_q_next(qe);
+
+               elem = (struct bfa_timer_s *) qe;
+               if (elem->timeout <= BFA_TIMER_FREQ) {
+                       elem->timeout = 0;
+                       list_del(&elem->qe);
+                       list_add_tail(&elem->qe, &timedout_q);
+               } else {
+                       elem->timeout -= BFA_TIMER_FREQ;
+               }
+
+               qe = qe_next;   /* go to next elem */
+       }
+
+       /*
+        * Pop all the timeout entries
+        */
+       while (!list_empty(&timedout_q)) {
+               bfa_q_deq(&timedout_q, &elem);
+               elem->timercb(elem->arg);
+       }
+}
+
+/**
+ * Should be called with lock protection
+ */
+void
+bfa_timer_begin(struct bfa_timer_mod_s *mod, struct bfa_timer_s *timer,
+                   void (*timercb) (void *), void *arg, unsigned int timeout)
+{
+
+       bfa_assert(timercb != NULL);
+       bfa_assert(!bfa_q_is_on_q(&mod->timer_q, timer));
+
+       timer->timeout = timeout;
+       timer->timercb = timercb;
+       timer->arg = arg;
+
+       list_add_tail(&timer->qe, &mod->timer_q);
+}
+
+/**
+ * Should be called with lock protection
+ */
+void
+bfa_timer_stop(struct bfa_timer_s *timer)
+{
+       bfa_assert(!list_empty(&timer->qe));
+
+       list_del(&timer->qe);
+}
diff --git a/drivers/scsi/bfa/bfa_trcmod_priv.h b/drivers/scsi/bfa/bfa_trcmod_priv.h
new file mode 100644 (file)
index 0000000..b3562dc
--- /dev/null
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) 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.
+ */
+
+/**
+ *  hal_trcmod.h BFA trace modules
+ */
+
+#ifndef __BFA_TRCMOD_PRIV_H__
+#define __BFA_TRCMOD_PRIV_H__
+
+#include <cs/bfa_trc.h>
+
+/*
+ * !!! Only append to the enums defined here to avoid any versioning
+ * !!! needed between trace utility and driver version
+ */
+enum {
+       BFA_TRC_HAL_IOC         = 1,
+       BFA_TRC_HAL_INTR        = 2,
+       BFA_TRC_HAL_FCXP        = 3,
+       BFA_TRC_HAL_UF          = 4,
+       BFA_TRC_HAL_DIAG        = 5,
+       BFA_TRC_HAL_RPORT       = 6,
+       BFA_TRC_HAL_FCPIM       = 7,
+       BFA_TRC_HAL_IOIM        = 8,
+       BFA_TRC_HAL_TSKIM       = 9,
+       BFA_TRC_HAL_ITNIM       = 10,
+       BFA_TRC_HAL_PPORT       = 11,
+       BFA_TRC_HAL_SGPG        = 12,
+       BFA_TRC_HAL_FLASH       = 13,
+       BFA_TRC_HAL_DEBUG       = 14,
+       BFA_TRC_HAL_WWN         = 15,
+       BFA_TRC_HAL_FLASH_RAW   = 16,
+       BFA_TRC_HAL_SBOOT       = 17,
+       BFA_TRC_HAL_SBOOT_IO    = 18,
+       BFA_TRC_HAL_SBOOT_INTR  = 19,
+       BFA_TRC_HAL_SBTEST      = 20,
+       BFA_TRC_HAL_IPFC        = 21,
+       BFA_TRC_HAL_IOCFC       = 22,
+       BFA_TRC_HAL_FCPTM       = 23,
+       BFA_TRC_HAL_IOTM        = 24,
+       BFA_TRC_HAL_TSKTM       = 25,
+       BFA_TRC_HAL_TIN         = 26,
+       BFA_TRC_HAL_LPS         = 27,
+       BFA_TRC_HAL_FCDIAG      = 28,
+       BFA_TRC_HAL_PBIND       = 29,
+       BFA_TRC_HAL_IOCFC_CT    = 30,
+       BFA_TRC_HAL_IOCFC_CB    = 31,
+       BFA_TRC_HAL_IOCFC_Q     = 32,
+};
+
+#endif /* __BFA_TRCMOD_PRIV_H__ */
diff --git a/drivers/scsi/bfa/bfa_tskim.c b/drivers/scsi/bfa/bfa_tskim.c
new file mode 100644 (file)
index 0000000..010d40d
--- /dev/null
@@ -0,0 +1,689 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ */
+
+#include <bfa.h>
+#include <bfa_cb_ioim_macros.h>
+
+BFA_TRC_FILE(HAL, TSKIM);
+
+/**
+ * task management completion handling
+ */
+#define bfa_tskim_qcomp(__tskim, __cbfn) do {                       \
+       bfa_cb_queue((__tskim)->bfa, &(__tskim)->hcb_qe, __cbfn, (__tskim)); \
+       bfa_tskim_notify_comp(__tskim);      \
+} while (0)
+
+#define bfa_tskim_notify_comp(__tskim) do {                                 \
+       if ((__tskim)->notify)                                               \
+               bfa_itnim_tskdone((__tskim)->itnim);      \
+} while (0)
+
+/*
+ * forward declarations
+ */
+static void     __bfa_cb_tskim_done(void *cbarg, bfa_boolean_t complete);
+static void     __bfa_cb_tskim_failed(void *cbarg, bfa_boolean_t complete);
+static bfa_boolean_t bfa_tskim_match_scope(struct bfa_tskim_s *tskim,
+                                              lun_t lun);
+static void     bfa_tskim_gather_ios(struct bfa_tskim_s *tskim);
+static void     bfa_tskim_cleanp_comp(void *tskim_cbarg);
+static void     bfa_tskim_cleanup_ios(struct bfa_tskim_s *tskim);
+static bfa_boolean_t bfa_tskim_send(struct bfa_tskim_s *tskim);
+static bfa_boolean_t bfa_tskim_send_abort(struct bfa_tskim_s *tskim);
+static void     bfa_tskim_iocdisable_ios(struct bfa_tskim_s *tskim);
+
+/**
+ *  bfa_tskim_sm
+ */
+
+enum bfa_tskim_event {
+       BFA_TSKIM_SM_START        = 1,  /*  TM command start            */
+       BFA_TSKIM_SM_DONE         = 2,  /*  TM completion               */
+       BFA_TSKIM_SM_QRESUME      = 3,  /*  resume after qfull          */
+       BFA_TSKIM_SM_HWFAIL       = 5,  /*  IOC h/w failure event       */
+       BFA_TSKIM_SM_HCB          = 6,  /*  BFA callback completion     */
+       BFA_TSKIM_SM_IOS_DONE     = 7,  /*  IO and sub TM completions   */
+       BFA_TSKIM_SM_CLEANUP      = 8,  /*  TM cleanup on ITN offline   */
+       BFA_TSKIM_SM_CLEANUP_DONE = 9,  /*  TM abort completion         */
+};
+
+static void     bfa_tskim_sm_uninit(struct bfa_tskim_s *tskim,
+                                       enum bfa_tskim_event event);
+static void     bfa_tskim_sm_active(struct bfa_tskim_s *tskim,
+                                       enum bfa_tskim_event event);
+static void     bfa_tskim_sm_cleanup(struct bfa_tskim_s *tskim,
+                                        enum bfa_tskim_event event);
+static void     bfa_tskim_sm_iocleanup(struct bfa_tskim_s *tskim,
+                                        enum bfa_tskim_event event);
+static void     bfa_tskim_sm_qfull(struct bfa_tskim_s *tskim,
+                                      enum bfa_tskim_event event);
+static void     bfa_tskim_sm_cleanup_qfull(struct bfa_tskim_s *tskim,
+                                      enum bfa_tskim_event event);
+static void     bfa_tskim_sm_hcb(struct bfa_tskim_s *tskim,
+                                    enum bfa_tskim_event event);
+
+/**
+ *      Task management command beginning state.
+ */
+static void
+bfa_tskim_sm_uninit(struct bfa_tskim_s *tskim, enum bfa_tskim_event event)
+{
+       bfa_trc(tskim->bfa, event);
+
+       switch (event) {
+       case BFA_TSKIM_SM_START:
+               bfa_sm_set_state(tskim, bfa_tskim_sm_active);
+               bfa_tskim_gather_ios(tskim);
+
+               /**
+                * If device is offline, do not send TM on wire. Just cleanup
+                * any pending IO requests and complete TM request.
+                */
+               if (!bfa_itnim_is_online(tskim->itnim)) {
+                       bfa_sm_set_state(tskim, bfa_tskim_sm_iocleanup);
+                       tskim->tsk_status = BFI_TSKIM_STS_OK;
+                       bfa_tskim_cleanup_ios(tskim);
+                       return;
+               }
+
+               if (!bfa_tskim_send(tskim)) {
+                       bfa_sm_set_state(tskim, bfa_tskim_sm_qfull);
+                       bfa_reqq_wait(tskim->bfa, tskim->itnim->reqq,
+                                         &tskim->reqq_wait);
+               }
+               break;
+
+       default:
+               bfa_assert(0);
+       }
+}
+
+/**
+ * brief
+ *     TM command is active, awaiting completion from firmware to
+ *     cleanup IO requests in TM scope.
+ */
+static void
+bfa_tskim_sm_active(struct bfa_tskim_s *tskim, enum bfa_tskim_event event)
+{
+       bfa_trc(tskim->bfa, event);
+
+       switch (event) {
+       case BFA_TSKIM_SM_DONE:
+               bfa_sm_set_state(tskim, bfa_tskim_sm_iocleanup);
+               bfa_tskim_cleanup_ios(tskim);
+               break;
+
+       case BFA_TSKIM_SM_CLEANUP:
+               bfa_sm_set_state(tskim, bfa_tskim_sm_cleanup);
+               if (!bfa_tskim_send_abort(tskim)) {
+                       bfa_sm_set_state(tskim, bfa_tskim_sm_cleanup_qfull);
+                       bfa_reqq_wait(tskim->bfa, tskim->itnim->reqq,
+                               &tskim->reqq_wait);
+               }
+               break;
+
+       case BFA_TSKIM_SM_HWFAIL:
+               bfa_sm_set_state(tskim, bfa_tskim_sm_hcb);
+               bfa_tskim_iocdisable_ios(tskim);
+               bfa_tskim_qcomp(tskim, __bfa_cb_tskim_failed);
+               break;
+
+       default:
+               bfa_assert(0);
+       }
+}
+
+/**
+ *     An active TM is being cleaned up since ITN is offline. Awaiting cleanup
+ *     completion event from firmware.
+ */
+static void
+bfa_tskim_sm_cleanup(struct bfa_tskim_s *tskim, enum bfa_tskim_event event)
+{
+       bfa_trc(tskim->bfa, event);
+
+       switch (event) {
+       case BFA_TSKIM_SM_DONE:
+               /**
+                * Ignore and wait for ABORT completion from firmware.
+                */
+               break;
+
+       case BFA_TSKIM_SM_CLEANUP_DONE:
+               bfa_sm_set_state(tskim, bfa_tskim_sm_iocleanup);
+               bfa_tskim_cleanup_ios(tskim);
+               break;
+
+       case BFA_TSKIM_SM_HWFAIL:
+               bfa_sm_set_state(tskim, bfa_tskim_sm_hcb);
+               bfa_tskim_iocdisable_ios(tskim);
+               bfa_tskim_qcomp(tskim, __bfa_cb_tskim_failed);
+               break;
+
+       default:
+               bfa_assert(0);
+       }
+}
+
+static void
+bfa_tskim_sm_iocleanup(struct bfa_tskim_s *tskim, enum bfa_tskim_event event)
+{
+       bfa_trc(tskim->bfa, event);
+
+       switch (event) {
+       case BFA_TSKIM_SM_IOS_DONE:
+               bfa_sm_set_state(tskim, bfa_tskim_sm_hcb);
+               bfa_tskim_qcomp(tskim, __bfa_cb_tskim_done);
+               break;
+
+       case BFA_TSKIM_SM_CLEANUP:
+               /**
+                * Ignore, TM command completed on wire.
+                * Notify TM conmpletion on IO cleanup completion.
+                */
+               break;
+
+       case BFA_TSKIM_SM_HWFAIL:
+               bfa_sm_set_state(tskim, bfa_tskim_sm_hcb);
+               bfa_tskim_iocdisable_ios(tskim);
+               bfa_tskim_qcomp(tskim, __bfa_cb_tskim_failed);
+               break;
+
+       default:
+               bfa_assert(0);
+       }
+}
+
+/**
+ *      Task management command is waiting for room in request CQ
+ */
+static void
+bfa_tskim_sm_qfull(struct bfa_tskim_s *tskim, enum bfa_tskim_event event)
+{
+       bfa_trc(tskim->bfa, event);
+
+       switch (event) {
+       case BFA_TSKIM_SM_QRESUME:
+               bfa_sm_set_state(tskim, bfa_tskim_sm_active);
+               bfa_tskim_send(tskim);
+               break;
+
+       case BFA_TSKIM_SM_CLEANUP:
+               /**
+                * No need to send TM on wire since ITN is offline.
+                */
+               bfa_sm_set_state(tskim, bfa_tskim_sm_iocleanup);
+               bfa_reqq_wcancel(&tskim->reqq_wait);
+               bfa_tskim_cleanup_ios(tskim);
+               break;
+
+       case BFA_TSKIM_SM_HWFAIL:
+               bfa_sm_set_state(tskim, bfa_tskim_sm_hcb);
+               bfa_reqq_wcancel(&tskim->reqq_wait);
+               bfa_tskim_iocdisable_ios(tskim);
+               bfa_tskim_qcomp(tskim, __bfa_cb_tskim_failed);
+               break;
+
+       default:
+               bfa_assert(0);
+       }
+}
+
+/**
+ *      Task management command is active, awaiting for room in request CQ
+ *     to send clean up request.
+ */
+static void
+bfa_tskim_sm_cleanup_qfull(struct bfa_tskim_s *tskim,
+               enum bfa_tskim_event event)
+{
+       bfa_trc(tskim->bfa, event);
+
+       switch (event) {
+       case BFA_TSKIM_SM_DONE:
+               bfa_reqq_wcancel(&tskim->reqq_wait);
+               /**
+                *
+                * Fall through !!!
+                */
+
+       case BFA_TSKIM_SM_QRESUME:
+               bfa_sm_set_state(tskim, bfa_tskim_sm_cleanup);
+               bfa_tskim_send_abort(tskim);
+               break;
+
+       case BFA_TSKIM_SM_HWFAIL:
+               bfa_sm_set_state(tskim, bfa_tskim_sm_hcb);
+               bfa_reqq_wcancel(&tskim->reqq_wait);
+               bfa_tskim_iocdisable_ios(tskim);
+               bfa_tskim_qcomp(tskim, __bfa_cb_tskim_failed);
+               break;
+
+       default:
+               bfa_assert(0);
+       }
+}
+
+/**
+ *      BFA callback is pending
+ */
+static void
+bfa_tskim_sm_hcb(struct bfa_tskim_s *tskim, enum bfa_tskim_event event)
+{
+       bfa_trc(tskim->bfa, event);
+
+       switch (event) {
+       case BFA_TSKIM_SM_HCB:
+               bfa_sm_set_state(tskim, bfa_tskim_sm_uninit);
+               bfa_tskim_free(tskim);
+               break;
+
+       case BFA_TSKIM_SM_CLEANUP:
+               bfa_tskim_notify_comp(tskim);
+               break;
+
+       case BFA_TSKIM_SM_HWFAIL:
+               break;
+
+       default:
+               bfa_assert(0);
+       }
+}
+
+
+
+/**
+ *  bfa_tskim_private
+ */
+
+static void
+__bfa_cb_tskim_done(void *cbarg, bfa_boolean_t complete)
+{
+       struct bfa_tskim_s *tskim = cbarg;
+
+       if (!complete) {
+               bfa_sm_send_event(tskim, BFA_TSKIM_SM_HCB);
+               return;
+       }
+
+       bfa_stats(tskim->itnim, tm_success);
+       bfa_cb_tskim_done(tskim->bfa->bfad, tskim->dtsk, tskim->tsk_status);
+}
+
+static void
+__bfa_cb_tskim_failed(void *cbarg, bfa_boolean_t complete)
+{
+       struct bfa_tskim_s *tskim = cbarg;
+
+       if (!complete) {
+               bfa_sm_send_event(tskim, BFA_TSKIM_SM_HCB);
+               return;
+       }
+
+       bfa_stats(tskim->itnim, tm_failures);
+       bfa_cb_tskim_done(tskim->bfa->bfad, tskim->dtsk,
+                          BFI_TSKIM_STS_FAILED);
+}
+
+static          bfa_boolean_t
+bfa_tskim_match_scope(struct bfa_tskim_s *tskim, lun_t lun)
+{
+       switch (tskim->tm_cmnd) {
+       case FCP_TM_TARGET_RESET:
+               return BFA_TRUE;
+
+       case FCP_TM_ABORT_TASK_SET:
+       case FCP_TM_CLEAR_TASK_SET:
+       case FCP_TM_LUN_RESET:
+       case FCP_TM_CLEAR_ACA:
+               return (tskim->lun == lun);
+
+       default:
+               bfa_assert(0);
+       }
+
+       return BFA_FALSE;
+}
+
+/**
+ *      Gather affected IO requests and task management commands.
+ */
+static void
+bfa_tskim_gather_ios(struct bfa_tskim_s *tskim)
+{
+       struct bfa_itnim_s *itnim = tskim->itnim;
+       struct bfa_ioim_s *ioim;
+       struct list_head        *qe, *qen;
+
+       INIT_LIST_HEAD(&tskim->io_q);
+
+       /**
+        * Gather any active IO requests first.
+        */
+       list_for_each_safe(qe, qen, &itnim->io_q) {
+               ioim = (struct bfa_ioim_s *) qe;
+               if (bfa_tskim_match_scope
+                   (tskim, bfa_cb_ioim_get_lun(ioim->dio))) {
+                       list_del(&ioim->qe);
+                       list_add_tail(&ioim->qe, &tskim->io_q);
+               }
+       }
+
+       /**
+        * Failback any pending IO requests immediately.
+        */
+       list_for_each_safe(qe, qen, &itnim->pending_q) {
+               ioim = (struct bfa_ioim_s *) qe;
+               if (bfa_tskim_match_scope
+                   (tskim, bfa_cb_ioim_get_lun(ioim->dio))) {
+                       list_del(&ioim->qe);
+                       list_add_tail(&ioim->qe, &ioim->fcpim->ioim_comp_q);
+                       bfa_ioim_tov(ioim);
+               }
+       }
+}
+
+/**
+ *             IO cleanup completion
+ */
+static void
+bfa_tskim_cleanp_comp(void *tskim_cbarg)
+{
+       struct bfa_tskim_s *tskim = tskim_cbarg;
+
+       bfa_stats(tskim->itnim, tm_io_comps);
+       bfa_sm_send_event(tskim, BFA_TSKIM_SM_IOS_DONE);
+}
+
+/**
+ *      Gather affected IO requests and task management commands.
+ */
+static void
+bfa_tskim_cleanup_ios(struct bfa_tskim_s *tskim)
+{
+       struct bfa_ioim_s *ioim;
+       struct list_head        *qe, *qen;
+
+       bfa_wc_init(&tskim->wc, bfa_tskim_cleanp_comp, tskim);
+
+       list_for_each_safe(qe, qen, &tskim->io_q) {
+               ioim = (struct bfa_ioim_s *) qe;
+               bfa_wc_up(&tskim->wc);
+               bfa_ioim_cleanup_tm(ioim, tskim);
+       }
+
+       bfa_wc_wait(&tskim->wc);
+}
+
+/**
+ *      Send task management request to firmware.
+ */
+static bfa_boolean_t
+bfa_tskim_send(struct bfa_tskim_s *tskim)
+{
+       struct bfa_itnim_s *itnim = tskim->itnim;
+       struct bfi_tskim_req_s *m;
+
+       /**
+        * check for room in queue to send request now
+        */
+       m = bfa_reqq_next(tskim->bfa, itnim->reqq);
+       if (!m)
+               return BFA_FALSE;
+
+       /**
+        * build i/o request message next
+        */
+       bfi_h2i_set(m->mh, BFI_MC_TSKIM, BFI_TSKIM_H2I_TM_REQ,
+                       bfa_lpuid(tskim->bfa));
+
+       m->tsk_tag = bfa_os_htons(tskim->tsk_tag);
+       m->itn_fhdl = tskim->itnim->rport->fw_handle;
+       m->t_secs = tskim->tsecs;
+       m->lun = tskim->lun;
+       m->tm_flags = tskim->tm_cmnd;
+
+       /**
+        * queue I/O message to firmware
+        */
+       bfa_reqq_produce(tskim->bfa, itnim->reqq);
+       return BFA_TRUE;
+}
+
+/**
+ *      Send abort request to cleanup an active TM to firmware.
+ */
+static bfa_boolean_t
+bfa_tskim_send_abort(struct bfa_tskim_s *tskim)
+{
+       struct bfa_itnim_s             *itnim = tskim->itnim;
+       struct bfi_tskim_abortreq_s    *m;
+
+       /**
+        * check for room in queue to send request now
+        */
+       m = bfa_reqq_next(tskim->bfa, itnim->reqq);
+       if (!m)
+               return BFA_FALSE;
+
+       /**
+        * build i/o request message next
+        */
+       bfi_h2i_set(m->mh, BFI_MC_TSKIM, BFI_TSKIM_H2I_ABORT_REQ,
+                       bfa_lpuid(tskim->bfa));
+
+       m->tsk_tag  = bfa_os_htons(tskim->tsk_tag);
+
+       /**
+        * queue I/O message to firmware
+        */
+       bfa_reqq_produce(tskim->bfa, itnim->reqq);
+       return BFA_TRUE;
+}
+
+/**
+ *      Call to resume task management cmnd waiting for room in request queue.
+ */
+static void
+bfa_tskim_qresume(void *cbarg)
+{
+       struct bfa_tskim_s *tskim = cbarg;
+
+       bfa_fcpim_stats(tskim->fcpim, qresumes);
+       bfa_stats(tskim->itnim, tm_qresumes);
+       bfa_sm_send_event(tskim, BFA_TSKIM_SM_QRESUME);
+}
+
+/**
+ * Cleanup IOs associated with a task mangement command on IOC failures.
+ */
+static void
+bfa_tskim_iocdisable_ios(struct bfa_tskim_s *tskim)
+{
+       struct bfa_ioim_s *ioim;
+       struct list_head        *qe, *qen;
+
+       list_for_each_safe(qe, qen, &tskim->io_q) {
+               ioim = (struct bfa_ioim_s *) qe;
+               bfa_ioim_iocdisable(ioim);
+       }
+}
+
+
+
+/**
+ *  bfa_tskim_friend
+ */
+
+/**
+ * Notification on completions from related ioim.
+ */
+void
+bfa_tskim_iodone(struct bfa_tskim_s *tskim)
+{
+       bfa_wc_down(&tskim->wc);
+}
+
+/**
+ * Handle IOC h/w failure notification from itnim.
+ */
+void
+bfa_tskim_iocdisable(struct bfa_tskim_s *tskim)
+{
+       tskim->notify = BFA_FALSE;
+       bfa_stats(tskim->itnim, tm_iocdowns);
+       bfa_sm_send_event(tskim, BFA_TSKIM_SM_HWFAIL);
+}
+
+/**
+ * Cleanup TM command and associated IOs as part of ITNIM offline.
+ */
+void
+bfa_tskim_cleanup(struct bfa_tskim_s *tskim)
+{
+       tskim->notify = BFA_TRUE;
+       bfa_stats(tskim->itnim, tm_cleanups);
+       bfa_sm_send_event(tskim, BFA_TSKIM_SM_CLEANUP);
+}
+
+/**
+ *      Memory allocation and initialization.
+ */
+void
+bfa_tskim_attach(struct bfa_fcpim_mod_s *fcpim, struct bfa_meminfo_s *minfo)
+{
+       struct bfa_tskim_s *tskim;
+       u16        i;
+
+       INIT_LIST_HEAD(&fcpim->tskim_free_q);
+
+       tskim = (struct bfa_tskim_s *) bfa_meminfo_kva(minfo);
+       fcpim->tskim_arr = tskim;
+
+       for (i = 0; i < fcpim->num_tskim_reqs; i++, tskim++) {
+               /*
+                * initialize TSKIM
+                */
+               bfa_os_memset(tskim, 0, sizeof(struct bfa_tskim_s));
+               tskim->tsk_tag = i;
+               tskim->bfa     = fcpim->bfa;
+               tskim->fcpim   = fcpim;
+               tskim->notify  = BFA_FALSE;
+               bfa_reqq_winit(&tskim->reqq_wait, bfa_tskim_qresume,
+                                  tskim);
+               bfa_sm_set_state(tskim, bfa_tskim_sm_uninit);
+
+               list_add_tail(&tskim->qe, &fcpim->tskim_free_q);
+       }
+
+       bfa_meminfo_kva(minfo) = (u8 *) tskim;
+}
+
+void
+bfa_tskim_detach(struct bfa_fcpim_mod_s *fcpim)
+{
+    /**
+     * @todo
+     */
+}
+
+void
+bfa_tskim_isr(struct bfa_s *bfa, struct bfi_msg_s *m)
+{
+       struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(bfa);
+       struct bfi_tskim_rsp_s *rsp = (struct bfi_tskim_rsp_s *) m;
+       struct bfa_tskim_s *tskim;
+       u16        tsk_tag = bfa_os_ntohs(rsp->tsk_tag);
+
+       tskim = BFA_TSKIM_FROM_TAG(fcpim, tsk_tag);
+       bfa_assert(tskim->tsk_tag == tsk_tag);
+
+       tskim->tsk_status = rsp->tsk_status;
+
+       /**
+        * Firmware sends BFI_TSKIM_STS_ABORTED status for abort
+        * requests. All other statuses are for normal completions.
+        */
+       if (rsp->tsk_status == BFI_TSKIM_STS_ABORTED) {
+               bfa_stats(tskim->itnim, tm_cleanup_comps);
+               bfa_sm_send_event(tskim, BFA_TSKIM_SM_CLEANUP_DONE);
+       } else {
+               bfa_stats(tskim->itnim, tm_fw_rsps);
+               bfa_sm_send_event(tskim, BFA_TSKIM_SM_DONE);
+       }
+}
+
+
+
+/**
+ *  bfa_tskim_api
+ */
+
+
+struct bfa_tskim_s *
+bfa_tskim_alloc(struct bfa_s *bfa, struct bfad_tskim_s *dtsk)
+{
+       struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(bfa);
+       struct bfa_tskim_s *tskim;
+
+       bfa_q_deq(&fcpim->tskim_free_q, &tskim);
+
+       if (!tskim)
+               bfa_fcpim_stats(fcpim, no_tskims);
+       else
+               tskim->dtsk = dtsk;
+
+       return tskim;
+}
+
+void
+bfa_tskim_free(struct bfa_tskim_s *tskim)
+{
+       bfa_assert(bfa_q_is_on_q_func(&tskim->itnim->tsk_q, &tskim->qe));
+       list_del(&tskim->qe);
+       list_add_tail(&tskim->qe, &tskim->fcpim->tskim_free_q);
+}
+
+/**
+ *      Start a task management command.
+ *
+ * @param[in]       tskim       BFA task management command instance
+ * @param[in]       itnim       i-t nexus for the task management command
+ * @param[in]       lun         lun, if applicable
+ * @param[in]       tm_cmnd     Task management command code.
+ * @param[in]       t_secs      Timeout in seconds
+ *
+ * @return None.
+ */
+void
+bfa_tskim_start(struct bfa_tskim_s *tskim, struct bfa_itnim_s *itnim, lun_t lun,
+                   enum fcp_tm_cmnd tm_cmnd, u8 tsecs)
+{
+       tskim->itnim   = itnim;
+       tskim->lun     = lun;
+       tskim->tm_cmnd = tm_cmnd;
+       tskim->tsecs   = tsecs;
+       tskim->notify  = BFA_FALSE;
+       bfa_stats(itnim, tm_cmnds);
+
+       list_add_tail(&tskim->qe, &itnim->tsk_q);
+       bfa_sm_send_event(tskim, BFA_TSKIM_SM_START);
+}
+
+
diff --git a/drivers/scsi/bfa/bfa_uf.c b/drivers/scsi/bfa/bfa_uf.c
new file mode 100644 (file)
index 0000000..ff5f9de
--- /dev/null
@@ -0,0 +1,345 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) 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.
+ */
+
+/**
+ *  bfa_uf.c BFA unsolicited frame receive implementation
+ */
+
+#include <bfa.h>
+#include <bfa_svc.h>
+#include <bfi/bfi_uf.h>
+#include <cs/bfa_debug.h>
+
+BFA_TRC_FILE(HAL, UF);
+BFA_MODULE(uf);
+
+/*
+ *****************************************************************************
+ * Internal functions
+ *****************************************************************************
+ */
+static void
+__bfa_cb_uf_recv(void *cbarg, bfa_boolean_t complete)
+{
+       struct bfa_uf_s   *uf = cbarg;
+       struct bfa_uf_mod_s *ufm = BFA_UF_MOD(uf->bfa);
+
+       if (complete)
+               ufm->ufrecv(ufm->cbarg, uf);
+}
+
+static void
+claim_uf_pbs(struct bfa_uf_mod_s *ufm, struct bfa_meminfo_s *mi)
+{
+       u32        uf_pb_tot_sz;
+
+       ufm->uf_pbs_kva = (struct bfa_uf_buf_s *) bfa_meminfo_dma_virt(mi);
+       ufm->uf_pbs_pa = bfa_meminfo_dma_phys(mi);
+       uf_pb_tot_sz = BFA_ROUNDUP((sizeof(struct bfa_uf_buf_s) * ufm->num_ufs),
+                                                       BFA_DMA_ALIGN_SZ);
+
+       bfa_meminfo_dma_virt(mi) += uf_pb_tot_sz;
+       bfa_meminfo_dma_phys(mi) += uf_pb_tot_sz;
+
+       bfa_os_memset((void *)ufm->uf_pbs_kva, 0, uf_pb_tot_sz);
+}
+
+static void
+claim_uf_post_msgs(struct bfa_uf_mod_s *ufm, struct bfa_meminfo_s *mi)
+{
+       struct bfi_uf_buf_post_s *uf_bp_msg;
+       struct bfi_sge_s      *sge;
+       union bfi_addr_u      sga_zero = { {0} };
+       u16        i;
+       u16        buf_len;
+
+       ufm->uf_buf_posts = (struct bfi_uf_buf_post_s *) bfa_meminfo_kva(mi);
+       uf_bp_msg = ufm->uf_buf_posts;
+
+       for (i = 0, uf_bp_msg = ufm->uf_buf_posts; i < ufm->num_ufs;
+            i++, uf_bp_msg++) {
+               bfa_os_memset(uf_bp_msg, 0, sizeof(struct bfi_uf_buf_post_s));
+
+               uf_bp_msg->buf_tag = i;
+               buf_len = sizeof(struct bfa_uf_buf_s);
+               uf_bp_msg->buf_len = bfa_os_htons(buf_len);
+               bfi_h2i_set(uf_bp_msg->mh, BFI_MC_UF, BFI_UF_H2I_BUF_POST,
+                           bfa_lpuid(ufm->bfa));
+
+               sge = uf_bp_msg->sge;
+               sge[0].sg_len = buf_len;
+               sge[0].flags = BFI_SGE_DATA_LAST;
+               bfa_dma_addr_set(sge[0].sga, ufm_pbs_pa(ufm, i));
+               bfa_sge_to_be(sge);
+
+               sge[1].sg_len = buf_len;
+               sge[1].flags = BFI_SGE_PGDLEN;
+               sge[1].sga = sga_zero;
+               bfa_sge_to_be(&sge[1]);
+       }
+
+       /**
+        * advance pointer beyond consumed memory
+        */
+       bfa_meminfo_kva(mi) = (u8 *) uf_bp_msg;
+}
+
+static void
+claim_ufs(struct bfa_uf_mod_s *ufm, struct bfa_meminfo_s *mi)
+{
+       u16        i;
+       struct bfa_uf_s   *uf;
+
+       /*
+        * Claim block of memory for UF list
+        */
+       ufm->uf_list = (struct bfa_uf_s *) bfa_meminfo_kva(mi);
+
+       /*
+        * Initialize UFs and queue it in UF free queue
+        */
+       for (i = 0, uf = ufm->uf_list; i < ufm->num_ufs; i++, uf++) {
+               bfa_os_memset(uf, 0, sizeof(struct bfa_uf_s));
+               uf->bfa = ufm->bfa;
+               uf->uf_tag = i;
+               uf->pb_len = sizeof(struct bfa_uf_buf_s);
+               uf->buf_kva = (void *)&ufm->uf_pbs_kva[i];
+               uf->buf_pa = ufm_pbs_pa(ufm, i);
+               list_add_tail(&uf->qe, &ufm->uf_free_q);
+       }
+
+       /**
+        * advance memory pointer
+        */
+       bfa_meminfo_kva(mi) = (u8 *) uf;
+}
+
+static void
+uf_mem_claim(struct bfa_uf_mod_s *ufm, struct bfa_meminfo_s *mi)
+{
+       claim_uf_pbs(ufm, mi);
+       claim_ufs(ufm, mi);
+       claim_uf_post_msgs(ufm, mi);
+}
+
+static void
+bfa_uf_meminfo(struct bfa_iocfc_cfg_s *cfg, u32 *ndm_len, u32 *dm_len)
+{
+       u32        num_ufs = cfg->fwcfg.num_uf_bufs;
+
+       /*
+        * dma-able memory for UF posted bufs
+        */
+       *dm_len += BFA_ROUNDUP((sizeof(struct bfa_uf_buf_s) * num_ufs),
+                                                       BFA_DMA_ALIGN_SZ);
+
+       /*
+        * kernel Virtual memory for UFs and UF buf post msg copies
+        */
+       *ndm_len += sizeof(struct bfa_uf_s) * num_ufs;
+       *ndm_len += sizeof(struct bfi_uf_buf_post_s) * num_ufs;
+}
+
+static void
+bfa_uf_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
+                 struct bfa_meminfo_s *meminfo, struct bfa_pcidev_s *pcidev)
+{
+       struct bfa_uf_mod_s *ufm = BFA_UF_MOD(bfa);
+
+       bfa_os_memset(ufm, 0, sizeof(struct bfa_uf_mod_s));
+       ufm->bfa = bfa;
+       ufm->num_ufs = cfg->fwcfg.num_uf_bufs;
+       INIT_LIST_HEAD(&ufm->uf_free_q);
+       INIT_LIST_HEAD(&ufm->uf_posted_q);
+
+       uf_mem_claim(ufm, meminfo);
+}
+
+static void
+bfa_uf_initdone(struct bfa_s *bfa)
+{
+}
+
+static void
+bfa_uf_detach(struct bfa_s *bfa)
+{
+}
+
+static struct bfa_uf_s *
+bfa_uf_get(struct bfa_uf_mod_s *uf_mod)
+{
+       struct bfa_uf_s   *uf;
+
+       bfa_q_deq(&uf_mod->uf_free_q, &uf);
+       return (uf);
+}
+
+static void
+bfa_uf_put(struct bfa_uf_mod_s *uf_mod, struct bfa_uf_s *uf)
+{
+       list_add_tail(&uf->qe, &uf_mod->uf_free_q);
+}
+
+static bfa_status_t
+bfa_uf_post(struct bfa_uf_mod_s *ufm, struct bfa_uf_s *uf)
+{
+       struct bfi_uf_buf_post_s *uf_post_msg;
+
+       uf_post_msg = bfa_reqq_next(ufm->bfa, BFA_REQQ_FCXP);
+       if (!uf_post_msg)
+               return BFA_STATUS_FAILED;
+
+       bfa_os_memcpy(uf_post_msg, &ufm->uf_buf_posts[uf->uf_tag],
+                     sizeof(struct bfi_uf_buf_post_s));
+       bfa_reqq_produce(ufm->bfa, BFA_REQQ_FCXP);
+
+       bfa_trc(ufm->bfa, uf->uf_tag);
+
+       list_add_tail(&uf->qe, &ufm->uf_posted_q);
+       return BFA_STATUS_OK;
+}
+
+static void
+bfa_uf_post_all(struct bfa_uf_mod_s *uf_mod)
+{
+       struct bfa_uf_s   *uf;
+
+       while ((uf = bfa_uf_get(uf_mod)) != NULL) {
+               if (bfa_uf_post(uf_mod, uf) != BFA_STATUS_OK)
+                       break;
+       }
+}
+
+static void
+uf_recv(struct bfa_s *bfa, struct bfi_uf_frm_rcvd_s *m)
+{
+       struct bfa_uf_mod_s *ufm = BFA_UF_MOD(bfa);
+       u16        uf_tag = m->buf_tag;
+       struct bfa_uf_buf_s *uf_buf = &ufm->uf_pbs_kva[uf_tag];
+       struct bfa_uf_s   *uf = &ufm->uf_list[uf_tag];
+       u8        *buf = &uf_buf->d[0];
+       struct fchs_s         *fchs;
+
+       m->frm_len = bfa_os_ntohs(m->frm_len);
+       m->xfr_len = bfa_os_ntohs(m->xfr_len);
+
+       fchs = (struct fchs_s *) uf_buf;
+
+       list_del(&uf->qe);      /* dequeue from posted queue */
+
+       uf->data_ptr = buf;
+       uf->data_len = m->xfr_len;
+
+       bfa_assert(uf->data_len >= sizeof(struct fchs_s));
+
+       if (uf->data_len == sizeof(struct fchs_s)) {
+               bfa_plog_fchdr(bfa->plog, BFA_PL_MID_HAL_UF, BFA_PL_EID_RX,
+                              uf->data_len, (struct fchs_s *) buf);
+       } else {
+               u32        pld_w0 = *((u32 *) (buf + sizeof(struct fchs_s)));
+               bfa_plog_fchdr_and_pl(bfa->plog, BFA_PL_MID_HAL_UF,
+                                     BFA_PL_EID_RX, uf->data_len,
+                                     (struct fchs_s *) buf, pld_w0);
+       }
+
+       bfa_cb_queue(bfa, &uf->hcb_qe, __bfa_cb_uf_recv, uf);
+}
+
+static void
+bfa_uf_stop(struct bfa_s *bfa)
+{
+}
+
+static void
+bfa_uf_iocdisable(struct bfa_s *bfa)
+{
+       struct bfa_uf_mod_s *ufm = BFA_UF_MOD(bfa);
+       struct bfa_uf_s   *uf;
+       struct list_head        *qe, *qen;
+
+       list_for_each_safe(qe, qen, &ufm->uf_posted_q) {
+               uf = (struct bfa_uf_s *) qe;
+               list_del(&uf->qe);
+               bfa_uf_put(ufm, uf);
+       }
+}
+
+static void
+bfa_uf_start(struct bfa_s *bfa)
+{
+       bfa_uf_post_all(BFA_UF_MOD(bfa));
+}
+
+
+
+/**
+ *  bfa_uf_api
+ */
+
+/**
+ *             Register handler for all unsolicted recieve frames.
+ *
+ * @param[in]  bfa             BFA instance
+ * @param[in]  ufrecv  receive handler function
+ * @param[in]  cbarg   receive handler arg
+ */
+void
+bfa_uf_recv_register(struct bfa_s *bfa, bfa_cb_uf_recv_t ufrecv, void *cbarg)
+{
+       struct bfa_uf_mod_s *ufm = BFA_UF_MOD(bfa);
+
+       ufm->ufrecv = ufrecv;
+       ufm->cbarg = cbarg;
+}
+
+/**
+ *             Free an unsolicited frame back to BFA.
+ *
+ * @param[in]          uf              unsolicited frame to be freed
+ *
+ * @return None
+ */
+void
+bfa_uf_free(struct bfa_uf_s *uf)
+{
+       bfa_uf_put(BFA_UF_MOD(uf->bfa), uf);
+       bfa_uf_post_all(BFA_UF_MOD(uf->bfa));
+}
+
+
+
+/**
+ *  uf_pub BFA uf module public functions
+ */
+
+void
+bfa_uf_isr(struct bfa_s *bfa, struct bfi_msg_s *msg)
+{
+       bfa_trc(bfa, msg->mhdr.msg_id);
+
+       switch (msg->mhdr.msg_id) {
+       case BFI_UF_I2H_FRM_RCVD:
+               uf_recv(bfa, (struct bfi_uf_frm_rcvd_s *) msg);
+               break;
+
+       default:
+               bfa_trc(bfa, msg->mhdr.msg_id);
+               bfa_assert(0);
+       }
+}
+
+
diff --git a/drivers/scsi/bfa/bfa_uf_priv.h b/drivers/scsi/bfa/bfa_uf_priv.h
new file mode 100644 (file)
index 0000000..bcb490f
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ */
+#ifndef __BFA_UF_PRIV_H__
+#define __BFA_UF_PRIV_H__
+
+#include <cs/bfa_sm.h>
+#include <bfa_svc.h>
+#include <bfi/bfi_uf.h>
+
+#define BFA_UF_MIN     (4)
+
+struct bfa_uf_mod_s {
+       struct bfa_s *bfa;              /*  back pointer to BFA */
+       struct bfa_uf_s *uf_list;       /*  array of UFs */
+       u16     num_ufs;        /*  num unsolicited rx frames */
+       struct list_head        uf_free_q;      /*  free UFs */
+       struct list_head        uf_posted_q;    /*  UFs posted to IOC */
+       struct bfa_uf_buf_s *uf_pbs_kva;        /*  list UF bufs request pld */
+       u64     uf_pbs_pa;      /*  phy addr for UF bufs */
+       struct bfi_uf_buf_post_s *uf_buf_posts;
+                                       /*  pre-built UF post msgs */
+       bfa_cb_uf_recv_t ufrecv;        /*  uf recv handler function */
+       void            *cbarg;         /*  uf receive handler arg */
+};
+
+#define BFA_UF_MOD(__bfa)      (&(__bfa)->modules.uf_mod)
+
+#define ufm_pbs_pa(_ufmod, _uftag)     \
+       ((_ufmod)->uf_pbs_pa + sizeof(struct bfa_uf_buf_s) * (_uftag))
+
+void   bfa_uf_isr(struct bfa_s *bfa, struct bfi_msg_s *msg);
+
+#endif /* __BFA_UF_PRIV_H__ */
diff --git a/drivers/scsi/bfa/bfad.c b/drivers/scsi/bfa/bfad.c
new file mode 100644 (file)
index 0000000..6f2be5a
--- /dev/null
@@ -0,0 +1,1182 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) 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.
+ */
+
+/**
+ *  bfad.c Linux driver PCI interface module.
+ */
+
+#include <linux/module.h>
+#include "bfad_drv.h"
+#include "bfad_im.h"
+#include "bfad_tm.h"
+#include "bfad_ipfc.h"
+#include "bfad_trcmod.h"
+#include <fcb/bfa_fcb_vf.h>
+#include <fcb/bfa_fcb_rport.h>
+#include <fcb/bfa_fcb_port.h>
+#include <fcb/bfa_fcb.h>
+
+BFA_TRC_FILE(LDRV, BFAD);
+static DEFINE_MUTEX(bfad_mutex);
+LIST_HEAD(bfad_list);
+static int      bfad_inst;
+int bfad_supported_fc4s;
+
+static char     *host_name;
+static char     *os_name;
+static char     *os_patch;
+static int      num_rports;
+static int      num_ios;
+static int      num_tms;
+static int      num_fcxps;
+static int      num_ufbufs;
+static int      reqq_size;
+static int      rspq_size;
+static int      num_sgpgs;
+static int      rport_del_timeout = BFA_FCS_RPORT_DEF_DEL_TIMEOUT;
+static int      bfa_io_max_sge = BFAD_IO_MAX_SGE;
+static int      log_level = BFA_LOG_WARNING;
+static int      ioc_auto_recover = BFA_TRUE;
+static int      ipfc_enable = BFA_FALSE;
+static int      ipfc_mtu = -1;
+int            bfa_lun_queue_depth = BFAD_LUN_QUEUE_DEPTH;
+int            bfa_linkup_delay = -1;
+
+module_param(os_name, charp, S_IRUGO | S_IWUSR);
+module_param(os_patch, charp, S_IRUGO | S_IWUSR);
+module_param(host_name, charp, S_IRUGO | S_IWUSR);
+module_param(num_rports, int, S_IRUGO | S_IWUSR);
+module_param(num_ios, int, S_IRUGO | S_IWUSR);
+module_param(num_tms, int, S_IRUGO | S_IWUSR);
+module_param(num_fcxps, int, S_IRUGO | S_IWUSR);
+module_param(num_ufbufs, int, S_IRUGO | S_IWUSR);
+module_param(reqq_size, int, S_IRUGO | S_IWUSR);
+module_param(rspq_size, int, S_IRUGO | S_IWUSR);
+module_param(num_sgpgs, int, S_IRUGO | S_IWUSR);
+module_param(rport_del_timeout, int, S_IRUGO | S_IWUSR);
+module_param(bfa_lun_queue_depth, int, S_IRUGO | S_IWUSR);
+module_param(bfa_io_max_sge, int, S_IRUGO | S_IWUSR);
+module_param(log_level, int, S_IRUGO | S_IWUSR);
+module_param(ioc_auto_recover, int, S_IRUGO | S_IWUSR);
+module_param(ipfc_enable, int, S_IRUGO | S_IWUSR);
+module_param(ipfc_mtu, int, S_IRUGO | S_IWUSR);
+module_param(bfa_linkup_delay, int, S_IRUGO | S_IWUSR);
+
+/*
+ * Stores the module parm num_sgpgs value;
+ * used to reset for bfad next instance.
+ */
+static int num_sgpgs_parm;
+
+static bfa_status_t
+bfad_fc4_probe(struct bfad_s *bfad)
+{
+       int             rc;
+
+       rc = bfad_im_probe(bfad);
+       if (rc != BFA_STATUS_OK)
+               goto ext;
+
+       bfad_tm_probe(bfad);
+
+       if (ipfc_enable)
+               bfad_ipfc_probe(bfad);
+ext:
+       return rc;
+}
+
+static void
+bfad_fc4_probe_undo(struct bfad_s *bfad)
+{
+       bfad_im_probe_undo(bfad);
+       bfad_tm_probe_undo(bfad);
+       if (ipfc_enable)
+               bfad_ipfc_probe_undo(bfad);
+}
+
+static void
+bfad_fc4_probe_post(struct bfad_s *bfad)
+{
+       if (bfad->im)
+               bfad_im_probe_post(bfad->im);
+
+       bfad_tm_probe_post(bfad);
+       if (ipfc_enable)
+               bfad_ipfc_probe_post(bfad);
+}
+
+static bfa_status_t
+bfad_fc4_port_new(struct bfad_s *bfad, struct bfad_port_s *port, int roles)
+{
+       int             rc = BFA_STATUS_FAILED;
+
+       if (roles & BFA_PORT_ROLE_FCP_IM)
+               rc = bfad_im_port_new(bfad, port);
+       if (rc != BFA_STATUS_OK)
+               goto ext;
+
+       if (roles & BFA_PORT_ROLE_FCP_TM)
+               rc = bfad_tm_port_new(bfad, port);
+       if (rc != BFA_STATUS_OK)
+               goto ext;
+
+       if ((roles & BFA_PORT_ROLE_FCP_IPFC) && ipfc_enable)
+               rc = bfad_ipfc_port_new(bfad, port, port->pvb_type);
+ext:
+       return rc;
+}
+
+static void
+bfad_fc4_port_delete(struct bfad_s *bfad, struct bfad_port_s *port, int roles)
+{
+       if (roles & BFA_PORT_ROLE_FCP_IM)
+               bfad_im_port_delete(bfad, port);
+
+       if (roles & BFA_PORT_ROLE_FCP_TM)
+               bfad_tm_port_delete(bfad, port);
+
+       if ((roles & BFA_PORT_ROLE_FCP_IPFC) && ipfc_enable)
+               bfad_ipfc_port_delete(bfad, port);
+}
+
+/**
+ *  BFA callbacks
+ */
+void
+bfad_hcb_comp(void *arg, bfa_status_t status)
+{
+       struct bfad_hal_comp *fcomp = (struct bfad_hal_comp *)arg;
+
+       fcomp->status = status;
+       complete(&fcomp->comp);
+}
+
+/**
+ * bfa_init callback
+ */
+void
+bfa_cb_init(void *drv, bfa_status_t init_status)
+{
+       struct bfad_s  *bfad = drv;
+
+       if (init_status == BFA_STATUS_OK)
+               bfad->bfad_flags |= BFAD_HAL_INIT_DONE;
+
+       complete(&bfad->comp);
+}
+
+
+
+/**
+ *  BFA_FCS callbacks
+ */
+static struct bfad_port_s *
+bfad_get_drv_port(struct bfad_s *bfad, struct bfad_vf_s *vf_drv,
+                 struct bfad_vport_s *vp_drv)
+{
+       return ((vp_drv) ? (&(vp_drv)->drv_port)
+               : ((vf_drv) ? (&(vf_drv)->base_port) : (&(bfad)->pport)));
+}
+
+struct bfad_port_s *
+bfa_fcb_port_new(struct bfad_s *bfad, struct bfa_fcs_port_s *port,
+                enum bfa_port_role roles, struct bfad_vf_s *vf_drv,
+                struct bfad_vport_s *vp_drv)
+{
+       bfa_status_t    rc;
+       struct bfad_port_s *port_drv;
+
+       if (!vp_drv && !vf_drv) {
+               port_drv = &bfad->pport;
+               port_drv->pvb_type = BFAD_PORT_PHYS_BASE;
+       } else if (!vp_drv && vf_drv) {
+               port_drv = &vf_drv->base_port;
+               port_drv->pvb_type = BFAD_PORT_VF_BASE;
+       } else if (vp_drv && !vf_drv) {
+               port_drv = &vp_drv->drv_port;
+               port_drv->pvb_type = BFAD_PORT_PHYS_VPORT;
+       } else {
+               port_drv = &vp_drv->drv_port;
+               port_drv->pvb_type = BFAD_PORT_VF_VPORT;
+       }
+
+       port_drv->fcs_port = port;
+       port_drv->roles = roles;
+       rc = bfad_fc4_port_new(bfad, port_drv, roles);
+       if (rc != BFA_STATUS_OK) {
+               bfad_fc4_port_delete(bfad, port_drv, roles);
+               port_drv = NULL;
+       }
+
+       return port_drv;
+}
+
+void
+bfa_fcb_port_delete(struct bfad_s *bfad, enum bfa_port_role roles,
+                   struct bfad_vf_s *vf_drv, struct bfad_vport_s *vp_drv)
+{
+       struct bfad_port_s *port_drv;
+
+       /*
+        * this will be only called from rmmod context
+        */
+       if (vp_drv && !vp_drv->comp_del) {
+               port_drv = bfad_get_drv_port(bfad, vf_drv, vp_drv);
+               bfa_trc(bfad, roles);
+               bfad_fc4_port_delete(bfad, port_drv, roles);
+       }
+}
+
+void
+bfa_fcb_port_online(struct bfad_s *bfad, enum bfa_port_role roles,
+                   struct bfad_vf_s *vf_drv, struct bfad_vport_s *vp_drv)
+{
+       struct bfad_port_s *port_drv = bfad_get_drv_port(bfad, vf_drv, vp_drv);
+
+       if (roles & BFA_PORT_ROLE_FCP_IM)
+               bfad_im_port_online(bfad, port_drv);
+
+       if (roles & BFA_PORT_ROLE_FCP_TM)
+               bfad_tm_port_online(bfad, port_drv);
+
+       if ((roles & BFA_PORT_ROLE_FCP_IPFC) && ipfc_enable)
+               bfad_ipfc_port_online(bfad, port_drv);
+
+       bfad->bfad_flags |= BFAD_PORT_ONLINE;
+}
+
+void
+bfa_fcb_port_offline(struct bfad_s *bfad, enum bfa_port_role roles,
+                    struct bfad_vf_s *vf_drv, struct bfad_vport_s *vp_drv)
+{
+       struct bfad_port_s *port_drv = bfad_get_drv_port(bfad, vf_drv, vp_drv);
+
+       if (roles & BFA_PORT_ROLE_FCP_IM)
+               bfad_im_port_offline(bfad, port_drv);
+
+       if (roles & BFA_PORT_ROLE_FCP_TM)
+               bfad_tm_port_offline(bfad, port_drv);
+
+       if ((roles & BFA_PORT_ROLE_FCP_IPFC) && ipfc_enable)
+               bfad_ipfc_port_offline(bfad, port_drv);
+}
+
+void
+bfa_fcb_vport_delete(struct bfad_vport_s *vport_drv)
+{
+       if (vport_drv->comp_del) {
+               complete(vport_drv->comp_del);
+               return;
+       }
+
+       kfree(vport_drv);
+}
+
+/**
+ * FCS RPORT alloc callback, after successful PLOGI by FCS
+ */
+bfa_status_t
+bfa_fcb_rport_alloc(struct bfad_s *bfad, struct bfa_fcs_rport_s **rport,
+                   struct bfad_rport_s **rport_drv)
+{
+       bfa_status_t    rc = BFA_STATUS_OK;
+
+       *rport_drv = kzalloc(sizeof(struct bfad_rport_s), GFP_ATOMIC);
+       if (*rport_drv == NULL) {
+               rc = BFA_STATUS_ENOMEM;
+               goto ext;
+       }
+
+       *rport = &(*rport_drv)->fcs_rport;
+
+ext:
+       return rc;
+}
+
+
+
+void
+bfad_hal_mem_release(struct bfad_s *bfad)
+{
+       int             i;
+       struct bfa_meminfo_s *hal_meminfo = &bfad->meminfo;
+       struct bfa_mem_elem_s *meminfo_elem;
+
+       for (i = 0; i < BFA_MEM_TYPE_MAX; i++) {
+               meminfo_elem = &hal_meminfo->meminfo[i];
+               if (meminfo_elem->kva != NULL) {
+                       switch (meminfo_elem->mem_type) {
+                       case BFA_MEM_TYPE_KVA:
+                               vfree(meminfo_elem->kva);
+                               break;
+                       case BFA_MEM_TYPE_DMA:
+                               dma_free_coherent(&bfad->pcidev->dev,
+                                               meminfo_elem->mem_len,
+                                               meminfo_elem->kva,
+                                               (dma_addr_t) meminfo_elem->dma);
+                               break;
+                       default:
+                               bfa_assert(0);
+                               break;
+                       }
+               }
+       }
+
+       memset(hal_meminfo, 0, sizeof(struct bfa_meminfo_s));
+}
+
+void
+bfad_update_hal_cfg(struct bfa_iocfc_cfg_s *bfa_cfg)
+{
+       if (num_rports > 0)
+               bfa_cfg->fwcfg.num_rports = num_rports;
+       if (num_ios > 0)
+               bfa_cfg->fwcfg.num_ioim_reqs = num_ios;
+       if (num_tms > 0)
+               bfa_cfg->fwcfg.num_tskim_reqs = num_tms;
+       if (num_fcxps > 0)
+               bfa_cfg->fwcfg.num_fcxp_reqs = num_fcxps;
+       if (num_ufbufs > 0)
+               bfa_cfg->fwcfg.num_uf_bufs = num_ufbufs;
+       if (reqq_size > 0)
+               bfa_cfg->drvcfg.num_reqq_elems = reqq_size;
+       if (rspq_size > 0)
+               bfa_cfg->drvcfg.num_rspq_elems = rspq_size;
+       if (num_sgpgs > 0)
+               bfa_cfg->drvcfg.num_sgpgs = num_sgpgs;
+
+       /*
+        * populate the hal values back to the driver for sysfs use.
+        * otherwise, the default values will be shown as 0 in sysfs
+        */
+       num_rports = bfa_cfg->fwcfg.num_rports;
+       num_ios    = bfa_cfg->fwcfg.num_ioim_reqs;
+       num_tms    = bfa_cfg->fwcfg.num_tskim_reqs;
+       num_fcxps  = bfa_cfg->fwcfg.num_fcxp_reqs;
+       num_ufbufs = bfa_cfg->fwcfg.num_uf_bufs;
+       reqq_size  = bfa_cfg->drvcfg.num_reqq_elems;
+       rspq_size  = bfa_cfg->drvcfg.num_rspq_elems;
+       num_sgpgs  = bfa_cfg->drvcfg.num_sgpgs;
+}
+
+bfa_status_t
+bfad_hal_mem_alloc(struct bfad_s *bfad)
+{
+       struct bfa_meminfo_s *hal_meminfo = &bfad->meminfo;
+       struct bfa_mem_elem_s *meminfo_elem;
+       bfa_status_t    rc = BFA_STATUS_OK;
+       dma_addr_t      phys_addr;
+       int             retry_count = 0;
+       int             reset_value = 1;
+       int             min_num_sgpgs = 512;
+       void           *kva;
+       int             i;
+
+       bfa_cfg_get_default(&bfad->ioc_cfg);
+
+retry:
+       bfad_update_hal_cfg(&bfad->ioc_cfg);
+       bfad->cfg_data.ioc_queue_depth = bfad->ioc_cfg.fwcfg.num_ioim_reqs;
+       bfa_cfg_get_meminfo(&bfad->ioc_cfg, hal_meminfo);
+
+       for (i = 0; i < BFA_MEM_TYPE_MAX; i++) {
+               meminfo_elem = &hal_meminfo->meminfo[i];
+               switch (meminfo_elem->mem_type) {
+               case BFA_MEM_TYPE_KVA:
+                       kva = vmalloc(meminfo_elem->mem_len);
+                       if (kva == NULL) {
+                               bfad_hal_mem_release(bfad);
+                               rc = BFA_STATUS_ENOMEM;
+                               goto ext;
+                       }
+                       memset(kva, 0, meminfo_elem->mem_len);
+                       meminfo_elem->kva = kva;
+                       break;
+               case BFA_MEM_TYPE_DMA:
+                       kva = dma_alloc_coherent(&bfad->pcidev->dev,
+                                       meminfo_elem->mem_len,
+                                       &phys_addr, GFP_KERNEL);
+                       if (kva == NULL) {
+                               bfad_hal_mem_release(bfad);
+                               /*
+                                * If we cannot allocate with default
+                                * num_sgpages try with half the value.
+                                */
+                               if (num_sgpgs > min_num_sgpgs) {
+                                       printk(KERN_INFO "bfad[%d]: memory"
+                                               " allocation failed with"
+                                               " num_sgpgs: %d\n",
+                                               bfad->inst_no, num_sgpgs);
+                                       nextLowerInt(&num_sgpgs);
+                                       printk(KERN_INFO "bfad[%d]: trying to"
+                                               " allocate memory with"
+                                               " num_sgpgs: %d\n",
+                                               bfad->inst_no, num_sgpgs);
+                                       retry_count++;
+                                       goto retry;
+                               } else {
+                                       if (num_sgpgs_parm > 0)
+                                               num_sgpgs = num_sgpgs_parm;
+                                       else {
+                                               reset_value =
+                                                       (1 << retry_count);
+                                               num_sgpgs *= reset_value;
+                                       }
+                                       rc = BFA_STATUS_ENOMEM;
+                                       goto ext;
+                               }
+                       }
+
+                       if (num_sgpgs_parm > 0)
+                               num_sgpgs = num_sgpgs_parm;
+                       else {
+                               reset_value = (1 << retry_count);
+                               num_sgpgs *= reset_value;
+                       }
+
+                       memset(kva, 0, meminfo_elem->mem_len);
+                       meminfo_elem->kva = kva;
+                       meminfo_elem->dma = phys_addr;
+                       break;
+               default:
+                       break;
+
+               }
+       }
+ext:
+       return rc;
+}
+
+/**
+ * Create a vport under a vf.
+ */
+bfa_status_t
+bfad_vport_create(struct bfad_s *bfad, u16 vf_id,
+                 struct bfa_port_cfg_s *port_cfg)
+{
+       struct bfad_vport_s *vport;
+       int             rc = BFA_STATUS_OK;
+       unsigned long   flags;
+       struct completion fcomp;
+
+       vport = kzalloc(sizeof(struct bfad_vport_s), GFP_KERNEL);
+       if (!vport) {
+               rc = BFA_STATUS_ENOMEM;
+               goto ext;
+       }
+
+       vport->drv_port.bfad = bfad;
+       spin_lock_irqsave(&bfad->bfad_lock, flags);
+       rc = bfa_fcs_vport_create(&vport->fcs_vport, &bfad->bfa_fcs, vf_id,
+                                 port_cfg, vport);
+       spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+
+       if (rc != BFA_STATUS_OK)
+               goto ext_free_vport;
+
+       if (port_cfg->roles & BFA_PORT_ROLE_FCP_IM) {
+               rc = bfad_im_scsi_host_alloc(bfad, vport->drv_port.im_port);
+               if (rc != BFA_STATUS_OK)
+                       goto ext_free_fcs_vport;
+       }
+
+       spin_lock_irqsave(&bfad->bfad_lock, flags);
+       bfa_fcs_vport_start(&vport->fcs_vport);
+       spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+
+       return BFA_STATUS_OK;
+
+ext_free_fcs_vport:
+       spin_lock_irqsave(&bfad->bfad_lock, flags);
+       vport->comp_del = &fcomp;
+       init_completion(vport->comp_del);
+       bfa_fcs_vport_delete(&vport->fcs_vport);
+       spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+       wait_for_completion(vport->comp_del);
+ext_free_vport:
+       kfree(vport);
+ext:
+       return rc;
+}
+
+/**
+ * Create a vf and its base vport implicitely.
+ */
+bfa_status_t
+bfad_vf_create(struct bfad_s *bfad, u16 vf_id,
+              struct bfa_port_cfg_s *port_cfg)
+{
+       struct bfad_vf_s *vf;
+       int             rc = BFA_STATUS_OK;
+
+       vf = kzalloc(sizeof(struct bfad_vf_s), GFP_KERNEL);
+       if (!vf) {
+               rc = BFA_STATUS_FAILED;
+               goto ext;
+       }
+
+       rc = bfa_fcs_vf_create(&vf->fcs_vf, &bfad->bfa_fcs, vf_id, port_cfg,
+                              vf);
+       if (rc != BFA_STATUS_OK)
+               kfree(vf);
+ext:
+       return rc;
+}
+
+void
+bfad_bfa_tmo(unsigned long data)
+{
+       struct bfad_s  *bfad = (struct bfad_s *)data;
+       unsigned long   flags;
+       struct list_head  doneq;
+
+       spin_lock_irqsave(&bfad->bfad_lock, flags);
+
+       bfa_timer_tick(&bfad->bfa);
+
+       bfa_comp_deq(&bfad->bfa, &doneq);
+       spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+
+       if (!list_empty(&doneq)) {
+               bfa_comp_process(&bfad->bfa, &doneq);
+               spin_lock_irqsave(&bfad->bfad_lock, flags);
+               bfa_comp_free(&bfad->bfa, &doneq);
+               spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+       }
+
+       mod_timer(&bfad->hal_tmo, jiffies + msecs_to_jiffies(BFA_TIMER_FREQ));
+}
+
+void
+bfad_init_timer(struct bfad_s *bfad)
+{
+       init_timer(&bfad->hal_tmo);
+       bfad->hal_tmo.function = bfad_bfa_tmo;
+       bfad->hal_tmo.data = (unsigned long)bfad;
+
+       mod_timer(&bfad->hal_tmo, jiffies + msecs_to_jiffies(BFA_TIMER_FREQ));
+}
+
+int
+bfad_pci_init(struct pci_dev *pdev, struct bfad_s *bfad)
+{
+       unsigned long   bar0_len;
+       int             rc = -ENODEV;
+
+       if (pci_enable_device(pdev)) {
+               BFA_PRINTF(BFA_ERR, "pci_enable_device fail %p\n", pdev);
+               goto out;
+       }
+
+       if (pci_request_regions(pdev, BFAD_DRIVER_NAME))
+               goto out_disable_device;
+
+       pci_set_master(pdev);
+
+
+       if (pci_set_dma_mask(pdev, DMA_BIT_MASK(64)) != 0)
+               if (pci_set_dma_mask(pdev, DMA_BIT_MASK(32)) != 0) {
+                       BFA_PRINTF(BFA_ERR, "pci_set_dma_mask fail %p\n", pdev);
+                       goto out_release_region;
+               }
+
+       bfad->pci_bar0_map = pci_resource_start(pdev, 0);
+       bar0_len = pci_resource_len(pdev, 0);
+       bfad->pci_bar0_kva = ioremap(bfad->pci_bar0_map, bar0_len);
+
+       if (bfad->pci_bar0_kva == NULL) {
+               BFA_PRINTF(BFA_ERR, "Fail to map bar0\n");
+               goto out_release_region;
+       }
+
+       bfad->hal_pcidev.pci_slot = PCI_SLOT(pdev->devfn);
+       bfad->hal_pcidev.pci_func = PCI_FUNC(pdev->devfn);
+       bfad->hal_pcidev.pci_bar_kva = bfad->pci_bar0_kva;
+       bfad->hal_pcidev.device_id = pdev->device;
+       bfad->pci_name = pci_name(pdev);
+
+       bfad->pci_attr.vendor_id = pdev->vendor;
+       bfad->pci_attr.device_id = pdev->device;
+       bfad->pci_attr.ssid = pdev->subsystem_device;
+       bfad->pci_attr.ssvid = pdev->subsystem_vendor;
+       bfad->pci_attr.pcifn = PCI_FUNC(pdev->devfn);
+
+       bfad->pcidev = pdev;
+       return 0;
+
+out_release_region:
+       pci_release_regions(pdev);
+out_disable_device:
+       pci_disable_device(pdev);
+out:
+       return rc;
+}
+
+void
+bfad_pci_uninit(struct pci_dev *pdev, struct bfad_s *bfad)
+{
+#if defined(__ia64__)
+       pci_iounmap(pdev, bfad->pci_bar0_kva);
+#else
+       iounmap(bfad->pci_bar0_kva);
+#endif
+       pci_release_regions(pdev);
+       pci_disable_device(pdev);
+       pci_set_drvdata(pdev, NULL);
+}
+
+void
+bfad_fcs_port_cfg(struct bfad_s *bfad)
+{
+       struct bfa_port_cfg_s port_cfg;
+       struct bfa_pport_attr_s attr;
+       char            symname[BFA_SYMNAME_MAXLEN];
+
+       sprintf(symname, "%s-%d", BFAD_DRIVER_NAME, bfad->inst_no);
+       memcpy(port_cfg.sym_name.symname, symname, strlen(symname));
+       bfa_pport_get_attr(&bfad->bfa, &attr);
+       port_cfg.nwwn = attr.nwwn;
+       port_cfg.pwwn = attr.pwwn;
+
+       bfa_fcs_cfg_base_port(&bfad->bfa_fcs, &port_cfg);
+}
+
+bfa_status_t
+bfad_drv_init(struct bfad_s *bfad)
+{
+       bfa_status_t    rc;
+       unsigned long   flags;
+       struct bfa_fcs_driver_info_s driver_info;
+       int             i;
+
+       bfad->cfg_data.rport_del_timeout = rport_del_timeout;
+       bfad->cfg_data.lun_queue_depth = bfa_lun_queue_depth;
+       bfad->cfg_data.io_max_sge = bfa_io_max_sge;
+       bfad->cfg_data.binding_method = FCP_PWWN_BINDING;
+
+       rc = bfad_hal_mem_alloc(bfad);
+       if (rc != BFA_STATUS_OK) {
+               printk(KERN_WARNING "bfad%d bfad_hal_mem_alloc failure\n",
+                      bfad->inst_no);
+               printk(KERN_WARNING
+                       "Not enough memory to attach all Brocade HBA ports,"
+                       " System may need more memory.\n");
+               goto out_hal_mem_alloc_failure;
+       }
+
+       bfa_init_log(&bfad->bfa, bfad->logmod);
+       bfa_init_trc(&bfad->bfa, bfad->trcmod);
+       bfa_init_aen(&bfad->bfa, bfad->aen);
+       INIT_LIST_HEAD(&bfad->file_q);
+       INIT_LIST_HEAD(&bfad->file_free_q);
+       for (i = 0; i < BFAD_AEN_MAX_APPS; i++) {
+               bfa_q_qe_init(&bfad->file_buf[i].qe);
+               list_add_tail(&bfad->file_buf[i].qe, &bfad->file_free_q);
+       }
+       bfa_init_plog(&bfad->bfa, &bfad->plog_buf);
+       bfa_plog_init(&bfad->plog_buf);
+       bfa_plog_str(&bfad->plog_buf, BFA_PL_MID_DRVR, BFA_PL_EID_DRIVER_START,
+                    0, "Driver Attach");
+
+       bfa_attach(&bfad->bfa, bfad, &bfad->ioc_cfg, &bfad->meminfo,
+                  &bfad->hal_pcidev);
+
+       init_completion(&bfad->comp);
+
+       /*
+        * Enable Interrupt and wait bfa_init completion
+        */
+       if (bfad_setup_intr(bfad)) {
+               printk(KERN_WARNING "bfad%d: bfad_setup_intr failed\n",
+                      bfad->inst_no);
+               goto out_setup_intr_failure;
+       }
+
+       spin_lock_irqsave(&bfad->bfad_lock, flags);
+       bfa_init(&bfad->bfa);
+       spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+
+       /*
+        * Set up interrupt handler for each vectors
+        */
+       if ((bfad->bfad_flags & BFAD_MSIX_ON)
+           && bfad_install_msix_handler(bfad)) {
+               printk(KERN_WARNING "%s: install_msix failed, bfad%d\n",
+                      __FUNCTION__, bfad->inst_no);
+       }
+
+       bfad_init_timer(bfad);
+
+       wait_for_completion(&bfad->comp);
+
+       memset(&driver_info, 0, sizeof(driver_info));
+       strncpy(driver_info.version, BFAD_DRIVER_VERSION,
+               sizeof(driver_info.version) - 1);
+       if (host_name)
+               strncpy(driver_info.host_machine_name, host_name,
+                       sizeof(driver_info.host_machine_name) - 1);
+       if (os_name)
+               strncpy(driver_info.host_os_name, os_name,
+                       sizeof(driver_info.host_os_name) - 1);
+       if (os_patch)
+               strncpy(driver_info.host_os_patch, os_patch,
+                       sizeof(driver_info.host_os_patch) - 1);
+
+       strncpy(driver_info.os_device_name, bfad->pci_name,
+               sizeof(driver_info.os_device_name - 1));
+
+       /*
+        * FCS INIT
+        */
+       spin_lock_irqsave(&bfad->bfad_lock, flags);
+       bfa_fcs_log_init(&bfad->bfa_fcs, bfad->logmod);
+       bfa_fcs_trc_init(&bfad->bfa_fcs, bfad->trcmod);
+       bfa_fcs_aen_init(&bfad->bfa_fcs, bfad->aen);
+       bfa_fcs_init(&bfad->bfa_fcs, &bfad->bfa, bfad, BFA_FALSE);
+       bfa_fcs_driver_info_init(&bfad->bfa_fcs, &driver_info);
+       spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+
+       bfad->bfad_flags |= BFAD_DRV_INIT_DONE;
+       return BFA_STATUS_OK;
+
+out_setup_intr_failure:
+       bfa_detach(&bfad->bfa);
+       bfad_hal_mem_release(bfad);
+out_hal_mem_alloc_failure:
+       return BFA_STATUS_FAILED;
+}
+
+void
+bfad_drv_uninit(struct bfad_s *bfad)
+{
+       del_timer_sync(&bfad->hal_tmo);
+       bfa_isr_disable(&bfad->bfa);
+       bfa_detach(&bfad->bfa);
+       bfad_remove_intr(bfad);
+       bfa_assert(list_empty(&bfad->file_q));
+       bfad_hal_mem_release(bfad);
+}
+
+void
+bfad_drv_start(struct bfad_s *bfad)
+{
+       unsigned long   flags;
+
+       spin_lock_irqsave(&bfad->bfad_lock, flags);
+       bfa_start(&bfad->bfa);
+       bfa_fcs_start(&bfad->bfa_fcs);
+       bfad->bfad_flags |= BFAD_HAL_START_DONE;
+       spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+
+       bfad_fc4_probe_post(bfad);
+}
+
+void
+bfad_drv_stop(struct bfad_s *bfad)
+{
+       unsigned long   flags;
+
+       spin_lock_irqsave(&bfad->bfad_lock, flags);
+       init_completion(&bfad->comp);
+       bfad->pport.flags |= BFAD_PORT_DELETE;
+       bfa_fcs_exit(&bfad->bfa_fcs);
+       spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+       wait_for_completion(&bfad->comp);
+
+       spin_lock_irqsave(&bfad->bfad_lock, flags);
+       init_completion(&bfad->comp);
+       bfa_stop(&bfad->bfa);
+       bfad->bfad_flags &= ~BFAD_HAL_START_DONE;
+       spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+       wait_for_completion(&bfad->comp);
+}
+
+bfa_status_t
+bfad_cfg_pport(struct bfad_s *bfad, enum bfa_port_role role)
+{
+       int             rc = BFA_STATUS_OK;
+
+       /*
+        * Allocate scsi_host for the physical port
+        */
+       if ((bfad_supported_fc4s & BFA_PORT_ROLE_FCP_IM)
+           && (role & BFA_PORT_ROLE_FCP_IM)) {
+               if (bfad->pport.im_port == NULL) {
+                       rc = BFA_STATUS_FAILED;
+                       goto out;
+               }
+
+               rc = bfad_im_scsi_host_alloc(bfad, bfad->pport.im_port);
+               if (rc != BFA_STATUS_OK)
+                       goto out;
+
+               bfad->pport.roles |= BFA_PORT_ROLE_FCP_IM;
+       }
+
+       bfad->bfad_flags |= BFAD_CFG_PPORT_DONE;
+
+out:
+       return rc;
+}
+
+void
+bfad_uncfg_pport(struct bfad_s *bfad)
+{
+       if ((bfad->pport.roles & BFA_PORT_ROLE_FCP_IPFC) && ipfc_enable) {
+               bfad_ipfc_port_delete(bfad, &bfad->pport);
+               bfad->pport.roles &= ~BFA_PORT_ROLE_FCP_IPFC;
+       }
+
+       if ((bfad_supported_fc4s & BFA_PORT_ROLE_FCP_IM)
+           && (bfad->pport.roles & BFA_PORT_ROLE_FCP_IM)) {
+               bfad_im_scsi_host_free(bfad, bfad->pport.im_port);
+               bfad_im_port_clean(bfad->pport.im_port);
+               kfree(bfad->pport.im_port);
+               bfad->pport.roles &= ~BFA_PORT_ROLE_FCP_IM;
+       }
+
+       bfad->bfad_flags &= ~BFAD_CFG_PPORT_DONE;
+}
+
+void
+bfad_drv_log_level_set(struct bfad_s *bfad)
+{
+       if (log_level > BFA_LOG_INVALID && log_level <= BFA_LOG_LEVEL_MAX)
+               bfa_log_set_level_all(&bfad->log_data, log_level);
+}
+
+ /*
+  *  PCI_entry PCI driver entries * {
+  */
+
+/**
+ * PCI probe entry.
+ */
+int
+bfad_pci_probe(struct pci_dev *pdev, const struct pci_device_id *pid)
+{
+       struct bfad_s  *bfad;
+       int             error = -ENODEV, retval;
+       char            buf[16];
+
+       /*
+        * For single port cards - only claim function 0
+        */
+       if ((pdev->device == BFA_PCI_DEVICE_ID_FC_8G1P)
+           && (PCI_FUNC(pdev->devfn) != 0))
+               return -ENODEV;
+
+       BFA_TRACE(BFA_INFO, "bfad_pci_probe entry");
+
+       bfad = kzalloc(sizeof(struct bfad_s), GFP_KERNEL);
+       if (!bfad) {
+               error = -ENOMEM;
+               goto out;
+       }
+
+       bfad->trcmod = kzalloc(sizeof(struct bfa_trc_mod_s), GFP_KERNEL);
+       if (!bfad->trcmod) {
+               printk(KERN_WARNING "Error alloc trace buffer!\n");
+               error = -ENOMEM;
+               goto out_alloc_trace_failure;
+       }
+
+       /*
+        * LOG/TRACE INIT
+        */
+       bfa_trc_init(bfad->trcmod);
+       bfa_trc(bfad, bfad_inst);
+
+       bfad->logmod = &bfad->log_data;
+       sprintf(buf, "%d", bfad_inst);
+       bfa_log_init(bfad->logmod, buf, bfa_os_printf);
+
+       bfad_drv_log_level_set(bfad);
+
+       bfad->aen = &bfad->aen_buf;
+
+       if (!(bfad_load_fwimg(pdev))) {
+               printk(KERN_WARNING "bfad_load_fwimg failure!\n");
+               kfree(bfad->trcmod);
+               goto out_alloc_trace_failure;
+       }
+
+       retval = bfad_pci_init(pdev, bfad);
+       if (retval) {
+               printk(KERN_WARNING "bfad_pci_init failure!\n");
+               error = retval;
+               goto out_pci_init_failure;
+       }
+
+       mutex_lock(&bfad_mutex);
+       bfad->inst_no = bfad_inst++;
+       list_add_tail(&bfad->list_entry, &bfad_list);
+       mutex_unlock(&bfad_mutex);
+
+       spin_lock_init(&bfad->bfad_lock);
+       pci_set_drvdata(pdev, bfad);
+
+       bfad->ref_count = 0;
+       bfad->pport.bfad = bfad;
+
+       retval = bfad_drv_init(bfad);
+       if (retval != BFA_STATUS_OK)
+               goto out_drv_init_failure;
+       if (!(bfad->bfad_flags & BFAD_HAL_INIT_DONE)) {
+               printk(KERN_WARNING "bfad%d: hal init failed\n", bfad->inst_no);
+               goto ok;
+       }
+
+       /*
+        * PPORT FCS config
+        */
+       bfad_fcs_port_cfg(bfad);
+
+       retval = bfad_cfg_pport(bfad, BFA_PORT_ROLE_FCP_IM);
+       if (retval != BFA_STATUS_OK)
+               goto out_cfg_pport_failure;
+
+       /*
+        * BFAD level FC4 (IM/TM/IPFC) specific resource allocation
+        */
+       retval = bfad_fc4_probe(bfad);
+       if (retval != BFA_STATUS_OK) {
+               printk(KERN_WARNING "bfad_fc4_probe failed\n");
+               goto out_fc4_probe_failure;
+       }
+
+       bfad_drv_start(bfad);
+
+       /*
+        * If bfa_linkup_delay is set to -1 default; try to retrive the
+        * value using the bfad_os_get_linkup_delay(); else use the
+        * passed in module param value as the bfa_linkup_delay.
+        */
+       if (bfa_linkup_delay < 0) {
+               bfa_linkup_delay = bfad_os_get_linkup_delay(bfad);
+               bfad_os_rport_online_wait(bfad);
+               bfa_linkup_delay = -1;
+       } else {
+               bfad_os_rport_online_wait(bfad);
+       }
+
+       bfa_log(bfad->logmod, BFA_LOG_LINUX_DEVICE_CLAIMED, bfad->pci_name);
+ok:
+       return 0;
+
+out_fc4_probe_failure:
+       bfad_fc4_probe_undo(bfad);
+       bfad_uncfg_pport(bfad);
+out_cfg_pport_failure:
+       bfad_drv_uninit(bfad);
+out_drv_init_failure:
+       mutex_lock(&bfad_mutex);
+       bfad_inst--;
+       list_del(&bfad->list_entry);
+       mutex_unlock(&bfad_mutex);
+       bfad_pci_uninit(pdev, bfad);
+out_pci_init_failure:
+       kfree(bfad->trcmod);
+out_alloc_trace_failure:
+       kfree(bfad);
+out:
+       return error;
+}
+
+/**
+ * PCI remove entry.
+ */
+void
+bfad_pci_remove(struct pci_dev *pdev)
+{
+       struct bfad_s  *bfad = pci_get_drvdata(pdev);
+       unsigned long   flags;
+
+       bfa_trc(bfad, bfad->inst_no);
+
+       if ((bfad->bfad_flags & BFAD_DRV_INIT_DONE)
+           && !(bfad->bfad_flags & BFAD_HAL_INIT_DONE)) {
+
+               spin_lock_irqsave(&bfad->bfad_lock, flags);
+               init_completion(&bfad->comp);
+               bfa_stop(&bfad->bfa);
+               spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+               wait_for_completion(&bfad->comp);
+
+               bfad_remove_intr(bfad);
+               del_timer_sync(&bfad->hal_tmo);
+               goto hal_detach;
+       } else if (!(bfad->bfad_flags & BFAD_DRV_INIT_DONE)) {
+               goto remove_sysfs;
+       }
+
+       if (bfad->bfad_flags & BFAD_HAL_START_DONE)
+               bfad_drv_stop(bfad);
+
+       bfad_remove_intr(bfad);
+
+       del_timer_sync(&bfad->hal_tmo);
+       bfad_fc4_probe_undo(bfad);
+
+       if (bfad->bfad_flags & BFAD_CFG_PPORT_DONE)
+               bfad_uncfg_pport(bfad);
+
+hal_detach:
+       spin_lock_irqsave(&bfad->bfad_lock, flags);
+       bfa_detach(&bfad->bfa);
+       spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+       bfad_hal_mem_release(bfad);
+remove_sysfs:
+
+       mutex_lock(&bfad_mutex);
+       bfad_inst--;
+       list_del(&bfad->list_entry);
+       mutex_unlock(&bfad_mutex);
+       bfad_pci_uninit(pdev, bfad);
+
+       kfree(bfad->trcmod);
+       kfree(bfad);
+}
+
+
+static struct pci_device_id bfad_id_table[] = {
+       {
+        .vendor = BFA_PCI_VENDOR_ID_BROCADE,
+        .device = BFA_PCI_DEVICE_ID_FC_8G2P,
+        .subvendor = PCI_ANY_ID,
+        .subdevice = PCI_ANY_ID,
+        },
+       {
+        .vendor = BFA_PCI_VENDOR_ID_BROCADE,
+        .device = BFA_PCI_DEVICE_ID_FC_8G1P,
+        .subvendor = PCI_ANY_ID,
+        .subdevice = PCI_ANY_ID,
+        },
+       {
+        .vendor = BFA_PCI_VENDOR_ID_BROCADE,
+        .device = BFA_PCI_DEVICE_ID_CT,
+        .subvendor = PCI_ANY_ID,
+        .subdevice = PCI_ANY_ID,
+        .class = (PCI_CLASS_SERIAL_FIBER << 8),
+        .class_mask = ~0,
+        },
+
+       {0, 0},
+};
+
+MODULE_DEVICE_TABLE(pci, bfad_id_table);
+
+static struct pci_driver bfad_pci_driver = {
+       .name = BFAD_DRIVER_NAME,
+       .id_table = bfad_id_table,
+       .probe = bfad_pci_probe,
+       .remove = __devexit_p(bfad_pci_remove),
+};
+
+/**
+ *  Linux driver module functions
+ */
+bfa_status_t
+bfad_fc4_module_init(void)
+{
+       int             rc;
+
+       rc = bfad_im_module_init();
+       if (rc != BFA_STATUS_OK)
+               goto ext;
+
+       bfad_tm_module_init();
+       if (ipfc_enable)
+               bfad_ipfc_module_init();
+ext:
+       return rc;
+}
+
+void
+bfad_fc4_module_exit(void)
+{
+       if (ipfc_enable)
+               bfad_ipfc_module_exit();
+       bfad_tm_module_exit();
+       bfad_im_module_exit();
+}
+
+/**
+ * Driver module init.
+ */
+static int      __init
+bfad_init(void)
+{
+       int             error = 0;
+
+       printk(KERN_INFO "Brocade BFA FC/FCOE SCSI driver - version: %s\n",
+              BFAD_DRIVER_VERSION);
+
+       if (num_sgpgs > 0)
+               num_sgpgs_parm = num_sgpgs;
+
+       error = bfad_fc4_module_init();
+       if (error) {
+               error = -ENOMEM;
+               printk(KERN_WARNING "bfad_fc4_module_init failure\n");
+               goto ext;
+       }
+
+       if (!strcmp(FCPI_NAME, " fcpim"))
+               bfad_supported_fc4s |= BFA_PORT_ROLE_FCP_IM;
+       if (!strcmp(FCPT_NAME, " fcptm"))
+               bfad_supported_fc4s |= BFA_PORT_ROLE_FCP_TM;
+       if (!strcmp(IPFC_NAME, " ipfc"))
+               bfad_supported_fc4s |= BFA_PORT_ROLE_FCP_IPFC;
+
+       bfa_ioc_auto_recover(ioc_auto_recover);
+       bfa_fcs_rport_set_del_timeout(rport_del_timeout);
+       error = pci_register_driver(&bfad_pci_driver);
+
+       if (error) {
+               printk(KERN_WARNING "bfad pci_register_driver failure\n");
+               goto ext;
+       }
+
+       return 0;
+
+ext:
+       bfad_fc4_module_exit();
+       return error;
+}
+
+/**
+ * Driver module exit.
+ */
+static void     __exit
+bfad_exit(void)
+{
+       pci_unregister_driver(&bfad_pci_driver);
+       bfad_fc4_module_exit();
+       bfad_free_fwimg();
+}
+
+#define BFAD_PROTO_NAME FCPI_NAME FCPT_NAME IPFC_NAME
+
+module_init(bfad_init);
+module_exit(bfad_exit);
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Brocade Fibre Channel HBA Driver" BFAD_PROTO_NAME);
+MODULE_AUTHOR("Brocade Communications Systems, Inc.");
+MODULE_VERSION(BFAD_DRIVER_VERSION);
+
+
diff --git a/drivers/scsi/bfa/bfad_attr.c b/drivers/scsi/bfa/bfad_attr.c
new file mode 100644 (file)
index 0000000..9129ae3
--- /dev/null
@@ -0,0 +1,649 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) 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.
+ */
+
+/**
+ *  bfa_attr.c Linux driver configuration interface module.
+ */
+
+#include "bfad_drv.h"
+#include "bfad_im.h"
+#include "bfad_trcmod.h"
+#include "bfad_attr.h"
+
+/**
+ *  FC_transport_template FC transport template
+ */
+
+/**
+ * FC transport template entry, get SCSI target port ID.
+ */
+void
+bfad_im_get_starget_port_id(struct scsi_target *starget)
+{
+       struct Scsi_Host *shost;
+       struct bfad_im_port_s *im_port;
+       struct bfad_s         *bfad;
+       struct bfad_itnim_s   *itnim = NULL;
+       u32        fc_id = -1;
+       unsigned long   flags;
+
+       shost = bfad_os_starget_to_shost(starget);
+       im_port = (struct bfad_im_port_s *) shost->hostdata[0];
+       bfad = im_port->bfad;
+       spin_lock_irqsave(&bfad->bfad_lock, flags);
+
+       itnim = bfad_os_get_itnim(im_port, starget->id);
+       if (itnim)
+               fc_id = bfa_fcs_itnim_get_fcid(&itnim->fcs_itnim);
+
+       fc_starget_port_id(starget) = fc_id;
+       spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+}
+
+/**
+ * FC transport template entry, get SCSI target nwwn.
+ */
+void
+bfad_im_get_starget_node_name(struct scsi_target *starget)
+{
+       struct Scsi_Host *shost;
+       struct bfad_im_port_s *im_port;
+       struct bfad_s         *bfad;
+       struct bfad_itnim_s   *itnim = NULL;
+       u64             node_name = 0;
+       unsigned long   flags;
+
+       shost = bfad_os_starget_to_shost(starget);
+       im_port = (struct bfad_im_port_s *) shost->hostdata[0];
+       bfad = im_port->bfad;
+       spin_lock_irqsave(&bfad->bfad_lock, flags);
+
+       itnim = bfad_os_get_itnim(im_port, starget->id);
+       if (itnim)
+               node_name = bfa_fcs_itnim_get_nwwn(&itnim->fcs_itnim);
+
+       fc_starget_node_name(starget) = bfa_os_htonll(node_name);
+       spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+}
+
+/**
+ * FC transport template entry, get SCSI target pwwn.
+ */
+void
+bfad_im_get_starget_port_name(struct scsi_target *starget)
+{
+       struct Scsi_Host *shost;
+       struct bfad_im_port_s *im_port;
+       struct bfad_s         *bfad;
+       struct bfad_itnim_s   *itnim = NULL;
+       u64             port_name = 0;
+       unsigned long   flags;
+
+       shost = bfad_os_starget_to_shost(starget);
+       im_port = (struct bfad_im_port_s *) shost->hostdata[0];
+       bfad = im_port->bfad;
+       spin_lock_irqsave(&bfad->bfad_lock, flags);
+
+       itnim = bfad_os_get_itnim(im_port, starget->id);
+       if (itnim)
+               port_name = bfa_fcs_itnim_get_pwwn(&itnim->fcs_itnim);
+
+       fc_starget_port_name(starget) = bfa_os_htonll(port_name);
+       spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+}
+
+/**
+ * FC transport template entry, get SCSI host port ID.
+ */
+void
+bfad_im_get_host_port_id(struct Scsi_Host *shost)
+{
+       struct bfad_im_port_s *im_port =
+                       (struct bfad_im_port_s *) shost->hostdata[0];
+       struct bfad_port_s    *port = im_port->port;
+
+       fc_host_port_id(shost) =
+                       bfa_os_hton3b(bfa_fcs_port_get_fcid(port->fcs_port));
+}
+
+
+
+
+
+struct Scsi_Host *
+bfad_os_starget_to_shost(struct scsi_target *starget)
+{
+       return dev_to_shost(starget->dev.parent);
+}
+
+/**
+ * FC transport template entry, get SCSI host port type.
+ */
+static void
+bfad_im_get_host_port_type(struct Scsi_Host *shost)
+{
+       struct bfad_im_port_s *im_port =
+                       (struct bfad_im_port_s *) shost->hostdata[0];
+       struct bfad_s         *bfad = im_port->bfad;
+       struct bfa_pport_attr_s attr;
+
+       bfa_pport_get_attr(&bfad->bfa, &attr);
+
+       switch (attr.port_type) {
+       case BFA_PPORT_TYPE_NPORT:
+               fc_host_port_type(shost) = FC_PORTTYPE_NPORT;
+               break;
+       case BFA_PPORT_TYPE_NLPORT:
+               fc_host_port_type(shost) = FC_PORTTYPE_NLPORT;
+               break;
+       case BFA_PPORT_TYPE_P2P:
+               fc_host_port_type(shost) = FC_PORTTYPE_PTP;
+               break;
+       case BFA_PPORT_TYPE_LPORT:
+               fc_host_port_type(shost) = FC_PORTTYPE_LPORT;
+               break;
+       default:
+               fc_host_port_type(shost) = FC_PORTTYPE_UNKNOWN;
+               break;
+       }
+}
+
+/**
+ * FC transport template entry, get SCSI host port state.
+ */
+static void
+bfad_im_get_host_port_state(struct Scsi_Host *shost)
+{
+       struct bfad_im_port_s *im_port =
+                       (struct bfad_im_port_s *) shost->hostdata[0];
+       struct bfad_s         *bfad = im_port->bfad;
+       struct bfa_pport_attr_s attr;
+
+       bfa_pport_get_attr(&bfad->bfa, &attr);
+
+       switch (attr.port_state) {
+       case BFA_PPORT_ST_LINKDOWN:
+               fc_host_port_state(shost) = FC_PORTSTATE_LINKDOWN;
+               break;
+       case BFA_PPORT_ST_LINKUP:
+               fc_host_port_state(shost) = FC_PORTSTATE_ONLINE;
+               break;
+       case BFA_PPORT_ST_UNINIT:
+       case BFA_PPORT_ST_ENABLING_QWAIT:
+       case BFA_PPORT_ST_ENABLING:
+       case BFA_PPORT_ST_DISABLING_QWAIT:
+       case BFA_PPORT_ST_DISABLING:
+       case BFA_PPORT_ST_DISABLED:
+       case BFA_PPORT_ST_STOPPED:
+       case BFA_PPORT_ST_IOCDOWN:
+       default:
+               fc_host_port_state(shost) = FC_PORTSTATE_UNKNOWN;
+               break;
+       }
+}
+
+/**
+ * FC transport template entry, get SCSI host active fc4s.
+ */
+static void
+bfad_im_get_host_active_fc4s(struct Scsi_Host *shost)
+{
+       struct bfad_im_port_s *im_port =
+                       (struct bfad_im_port_s *) shost->hostdata[0];
+       struct bfad_port_s    *port = im_port->port;
+
+       memset(fc_host_active_fc4s(shost), 0,
+              sizeof(fc_host_active_fc4s(shost)));
+
+       if (port->supported_fc4s &
+               (BFA_PORT_ROLE_FCP_IM | BFA_PORT_ROLE_FCP_TM))
+               fc_host_active_fc4s(shost)[2] = 1;
+
+       if (port->supported_fc4s & BFA_PORT_ROLE_FCP_IPFC)
+               fc_host_active_fc4s(shost)[3] = 0x20;
+
+       fc_host_active_fc4s(shost)[7] = 1;
+}
+
+/**
+ * FC transport template entry, get SCSI host link speed.
+ */
+static void
+bfad_im_get_host_speed(struct Scsi_Host *shost)
+{
+       struct bfad_im_port_s *im_port =
+                       (struct bfad_im_port_s *) shost->hostdata[0];
+       struct bfad_s         *bfad = im_port->bfad;
+       struct bfa_pport_attr_s attr;
+
+       bfa_pport_get_attr(&bfad->bfa, &attr);
+       switch (attr.speed) {
+       case BFA_PPORT_SPEED_8GBPS:
+               fc_host_speed(shost) = FC_PORTSPEED_8GBIT;
+               break;
+       case BFA_PPORT_SPEED_4GBPS:
+               fc_host_speed(shost) = FC_PORTSPEED_4GBIT;
+               break;
+       case BFA_PPORT_SPEED_2GBPS:
+               fc_host_speed(shost) = FC_PORTSPEED_2GBIT;
+               break;
+       case BFA_PPORT_SPEED_1GBPS:
+               fc_host_speed(shost) = FC_PORTSPEED_1GBIT;
+               break;
+       default:
+               fc_host_speed(shost) = FC_PORTSPEED_UNKNOWN;
+               break;
+       }
+}
+
+/**
+ * FC transport template entry, get SCSI host port type.
+ */
+static void
+bfad_im_get_host_fabric_name(struct Scsi_Host *shost)
+{
+       struct bfad_im_port_s *im_port =
+                       (struct bfad_im_port_s *) shost->hostdata[0];
+       struct bfad_port_s    *port = im_port->port;
+       wwn_t           fabric_nwwn = 0;
+
+       fabric_nwwn = bfa_fcs_port_get_fabric_name(port->fcs_port);
+
+       fc_host_fabric_name(shost) = bfa_os_htonll(fabric_nwwn);
+
+}
+
+/**
+ * FC transport template entry, get BFAD statistics.
+ */
+static struct fc_host_statistics *
+bfad_im_get_stats(struct Scsi_Host *shost)
+{
+       struct bfad_im_port_s *im_port =
+                       (struct bfad_im_port_s *) shost->hostdata[0];
+       struct bfad_s         *bfad = im_port->bfad;
+       struct bfad_hal_comp fcomp;
+       struct fc_host_statistics *hstats;
+       bfa_status_t    rc;
+       unsigned long   flags;
+
+       hstats = &bfad->link_stats;
+       init_completion(&fcomp.comp);
+       spin_lock_irqsave(&bfad->bfad_lock, flags);
+       memset(hstats, 0, sizeof(struct fc_host_statistics));
+       rc = bfa_pport_get_stats(&bfad->bfa,
+                                    (union bfa_pport_stats_u *) hstats,
+                                    bfad_hcb_comp, &fcomp);
+       spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+       if (rc != BFA_STATUS_OK)
+               return NULL;
+
+       wait_for_completion(&fcomp.comp);
+
+       return hstats;
+}
+
+/**
+ * FC transport template entry, reset BFAD statistics.
+ */
+static void
+bfad_im_reset_stats(struct Scsi_Host *shost)
+{
+       struct bfad_im_port_s *im_port =
+                       (struct bfad_im_port_s *) shost->hostdata[0];
+       struct bfad_s         *bfad = im_port->bfad;
+       struct bfad_hal_comp fcomp;
+       unsigned long   flags;
+       bfa_status_t    rc;
+
+       init_completion(&fcomp.comp);
+       spin_lock_irqsave(&bfad->bfad_lock, flags);
+       rc = bfa_pport_clear_stats(&bfad->bfa, bfad_hcb_comp, &fcomp);
+       spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+
+       if (rc != BFA_STATUS_OK)
+               return;
+
+       wait_for_completion(&fcomp.comp);
+
+       return;
+}
+
+/**
+ * FC transport template entry, get rport loss timeout.
+ */
+static void
+bfad_im_get_rport_loss_tmo(struct fc_rport *rport)
+{
+       struct bfad_itnim_data_s *itnim_data = rport->dd_data;
+       struct bfad_itnim_s   *itnim = itnim_data->itnim;
+       struct bfad_s         *bfad = itnim->im->bfad;
+       unsigned long   flags;
+
+       spin_lock_irqsave(&bfad->bfad_lock, flags);
+       rport->dev_loss_tmo = bfa_fcpim_path_tov_get(&bfad->bfa);
+       spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+}
+
+/**
+ * FC transport template entry, set rport loss timeout.
+ */
+static void
+bfad_im_set_rport_loss_tmo(struct fc_rport *rport, u32 timeout)
+{
+       struct bfad_itnim_data_s *itnim_data = rport->dd_data;
+       struct bfad_itnim_s   *itnim = itnim_data->itnim;
+       struct bfad_s         *bfad = itnim->im->bfad;
+       unsigned long   flags;
+
+       if (timeout > 0) {
+               spin_lock_irqsave(&bfad->bfad_lock, flags);
+               bfa_fcpim_path_tov_set(&bfad->bfa, timeout);
+               rport->dev_loss_tmo = bfa_fcpim_path_tov_get(&bfad->bfa);
+               spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+       }
+
+}
+
+struct fc_function_template bfad_im_fc_function_template = {
+
+       /* Target dynamic attributes */
+       .get_starget_port_id = bfad_im_get_starget_port_id,
+       .show_starget_port_id = 1,
+       .get_starget_node_name = bfad_im_get_starget_node_name,
+       .show_starget_node_name = 1,
+       .get_starget_port_name = bfad_im_get_starget_port_name,
+       .show_starget_port_name = 1,
+
+       /* Host dynamic attribute */
+       .get_host_port_id = bfad_im_get_host_port_id,
+       .show_host_port_id = 1,
+
+       /* Host fixed attributes */
+       .show_host_node_name = 1,
+       .show_host_port_name = 1,
+       .show_host_supported_classes = 1,
+       .show_host_supported_fc4s = 1,
+       .show_host_supported_speeds = 1,
+       .show_host_maxframe_size = 1,
+
+       /* More host dynamic attributes */
+       .show_host_port_type = 1,
+       .get_host_port_type = bfad_im_get_host_port_type,
+       .show_host_port_state = 1,
+       .get_host_port_state = bfad_im_get_host_port_state,
+       .show_host_active_fc4s = 1,
+       .get_host_active_fc4s = bfad_im_get_host_active_fc4s,
+       .show_host_speed = 1,
+       .get_host_speed = bfad_im_get_host_speed,
+       .show_host_fabric_name = 1,
+       .get_host_fabric_name = bfad_im_get_host_fabric_name,
+
+       .show_host_symbolic_name = 1,
+
+       /* Statistics */
+       .get_fc_host_stats = bfad_im_get_stats,
+       .reset_fc_host_stats = bfad_im_reset_stats,
+
+       /* Allocation length for host specific data */
+       .dd_fcrport_size = sizeof(struct bfad_itnim_data_s *),
+
+       /* Remote port fixed attributes */
+       .show_rport_maxframe_size = 1,
+       .show_rport_supported_classes = 1,
+       .show_rport_dev_loss_tmo = 1,
+       .get_rport_dev_loss_tmo = bfad_im_get_rport_loss_tmo,
+       .set_rport_dev_loss_tmo = bfad_im_set_rport_loss_tmo,
+};
+
+/**
+ *  Scsi_Host_attrs SCSI host attributes
+ */
+static ssize_t
+bfad_im_serial_num_show(struct device *dev, struct device_attribute *attr,
+                        char *buf)
+{
+       struct Scsi_Host *shost = class_to_shost(dev);
+       struct bfad_im_port_s *im_port =
+                       (struct bfad_im_port_s *) shost->hostdata[0];
+       struct bfad_s         *bfad = im_port->bfad;
+       struct bfa_ioc_attr_s  ioc_attr;
+
+       memset(&ioc_attr, 0, sizeof(ioc_attr));
+       bfa_get_attr(&bfad->bfa, &ioc_attr);
+       return snprintf(buf, PAGE_SIZE, "%s\n",
+                       ioc_attr.adapter_attr.serial_num);
+}
+
+static ssize_t
+bfad_im_model_show(struct device *dev, struct device_attribute *attr,
+                       char *buf)
+{
+       struct Scsi_Host *shost = class_to_shost(dev);
+       struct bfad_im_port_s *im_port =
+                       (struct bfad_im_port_s *) shost->hostdata[0];
+       struct bfad_s         *bfad = im_port->bfad;
+       struct bfa_ioc_attr_s  ioc_attr;
+
+       memset(&ioc_attr, 0, sizeof(ioc_attr));
+       bfa_get_attr(&bfad->bfa, &ioc_attr);
+       return snprintf(buf, PAGE_SIZE, "%s\n", ioc_attr.adapter_attr.model);
+}
+
+static ssize_t
+bfad_im_model_desc_show(struct device *dev, struct device_attribute *attr,
+                                char *buf)
+{
+       struct Scsi_Host *shost = class_to_shost(dev);
+       struct bfad_im_port_s *im_port =
+                       (struct bfad_im_port_s *) shost->hostdata[0];
+       struct bfad_s         *bfad = im_port->bfad;
+       struct bfa_ioc_attr_s  ioc_attr;
+
+       memset(&ioc_attr, 0, sizeof(ioc_attr));
+       bfa_get_attr(&bfad->bfa, &ioc_attr);
+       return snprintf(buf, PAGE_SIZE, "%s\n",
+                       ioc_attr.adapter_attr.model_descr);
+}
+
+static ssize_t
+bfad_im_node_name_show(struct device *dev, struct device_attribute *attr,
+                                char *buf)
+{
+       struct Scsi_Host *shost = class_to_shost(dev);
+       struct bfad_im_port_s *im_port =
+                       (struct bfad_im_port_s *) shost->hostdata[0];
+       struct bfad_port_s    *port = im_port->port;
+       u64        nwwn;
+
+       nwwn = bfa_fcs_port_get_nwwn(port->fcs_port);
+       return snprintf(buf, PAGE_SIZE, "0x%llx\n", bfa_os_htonll(nwwn));
+}
+
+static ssize_t
+bfad_im_symbolic_name_show(struct device *dev, struct device_attribute *attr,
+                                char *buf)
+{
+       struct Scsi_Host *shost = class_to_shost(dev);
+       struct bfad_im_port_s *im_port =
+                       (struct bfad_im_port_s *) shost->hostdata[0];
+       struct bfad_s         *bfad = im_port->bfad;
+       struct bfa_ioc_attr_s  ioc_attr;
+
+       memset(&ioc_attr, 0, sizeof(ioc_attr));
+       bfa_get_attr(&bfad->bfa, &ioc_attr);
+
+       return snprintf(buf, PAGE_SIZE, "Brocade %s FV%s DV%s\n",
+                       ioc_attr.adapter_attr.model,
+                       ioc_attr.adapter_attr.fw_ver, BFAD_DRIVER_VERSION);
+}
+
+static ssize_t
+bfad_im_hw_version_show(struct device *dev, struct device_attribute *attr,
+                               char *buf)
+{
+       struct Scsi_Host *shost = class_to_shost(dev);
+       struct bfad_im_port_s *im_port =
+                       (struct bfad_im_port_s *) shost->hostdata[0];
+       struct bfad_s         *bfad = im_port->bfad;
+       struct bfa_ioc_attr_s  ioc_attr;
+
+       memset(&ioc_attr, 0, sizeof(ioc_attr));
+       bfa_get_attr(&bfad->bfa, &ioc_attr);
+       return snprintf(buf, PAGE_SIZE, "%s\n", ioc_attr.adapter_attr.hw_ver);
+}
+
+static ssize_t
+bfad_im_drv_version_show(struct device *dev, struct device_attribute *attr,
+                               char *buf)
+{
+       return snprintf(buf, PAGE_SIZE, "%s\n", BFAD_DRIVER_VERSION);
+}
+
+static ssize_t
+bfad_im_optionrom_version_show(struct device *dev,
+                        struct device_attribute *attr, char *buf)
+{
+       struct Scsi_Host *shost = class_to_shost(dev);
+       struct bfad_im_port_s *im_port =
+                       (struct bfad_im_port_s *) shost->hostdata[0];
+       struct bfad_s         *bfad = im_port->bfad;
+       struct bfa_ioc_attr_s  ioc_attr;
+
+       memset(&ioc_attr, 0, sizeof(ioc_attr));
+       bfa_get_attr(&bfad->bfa, &ioc_attr);
+       return snprintf(buf, PAGE_SIZE, "%s\n",
+                       ioc_attr.adapter_attr.optrom_ver);
+}
+
+static ssize_t
+bfad_im_fw_version_show(struct device *dev, struct device_attribute *attr,
+                                char *buf)
+{
+       struct Scsi_Host *shost = class_to_shost(dev);
+       struct bfad_im_port_s *im_port =
+                       (struct bfad_im_port_s *) shost->hostdata[0];
+       struct bfad_s         *bfad = im_port->bfad;
+       struct bfa_ioc_attr_s  ioc_attr;
+
+       memset(&ioc_attr, 0, sizeof(ioc_attr));
+       bfa_get_attr(&bfad->bfa, &ioc_attr);
+       return snprintf(buf, PAGE_SIZE, "%s\n", ioc_attr.adapter_attr.fw_ver);
+}
+
+static ssize_t
+bfad_im_num_of_ports_show(struct device *dev, struct device_attribute *attr,
+                               char *buf)
+{
+       struct Scsi_Host *shost = class_to_shost(dev);
+       struct bfad_im_port_s *im_port =
+                       (struct bfad_im_port_s *) shost->hostdata[0];
+       struct bfad_s         *bfad = im_port->bfad;
+       struct bfa_ioc_attr_s  ioc_attr;
+
+       memset(&ioc_attr, 0, sizeof(ioc_attr));
+       bfa_get_attr(&bfad->bfa, &ioc_attr);
+       return snprintf(buf, PAGE_SIZE, "%d\n", ioc_attr.adapter_attr.nports);
+}
+
+static ssize_t
+bfad_im_drv_name_show(struct device *dev, struct device_attribute *attr,
+                               char *buf)
+{
+       return snprintf(buf, PAGE_SIZE, "%s\n", BFAD_DRIVER_NAME);
+}
+
+static ssize_t
+bfad_im_num_of_discovered_ports_show(struct device *dev,
+                       struct device_attribute *attr, char *buf)
+{
+       struct Scsi_Host *shost = class_to_shost(dev);
+       struct bfad_im_port_s *im_port =
+                       (struct bfad_im_port_s *) shost->hostdata[0];
+       struct bfad_port_s    *port = im_port->port;
+       struct bfad_s         *bfad = im_port->bfad;
+       int        nrports = 2048;
+       wwn_t          *rports = NULL;
+       unsigned long   flags;
+
+       rports = kzalloc(sizeof(wwn_t) * nrports , GFP_ATOMIC);
+       if (rports == NULL)
+               return -ENOMEM;
+
+       spin_lock_irqsave(&bfad->bfad_lock, flags);
+       bfa_fcs_port_get_rports(port->fcs_port, rports, &nrports);
+       spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+       kfree(rports);
+
+       return snprintf(buf, PAGE_SIZE, "%d\n", nrports);
+}
+
+static          DEVICE_ATTR(serial_number, S_IRUGO,
+                               bfad_im_serial_num_show, NULL);
+static          DEVICE_ATTR(model, S_IRUGO, bfad_im_model_show, NULL);
+static          DEVICE_ATTR(model_description, S_IRUGO,
+                               bfad_im_model_desc_show, NULL);
+static          DEVICE_ATTR(node_name, S_IRUGO, bfad_im_node_name_show, NULL);
+static          DEVICE_ATTR(symbolic_name, S_IRUGO,
+                               bfad_im_symbolic_name_show, NULL);
+static          DEVICE_ATTR(hardware_version, S_IRUGO,
+                               bfad_im_hw_version_show, NULL);
+static          DEVICE_ATTR(driver_version, S_IRUGO,
+                               bfad_im_drv_version_show, NULL);
+static          DEVICE_ATTR(option_rom_version, S_IRUGO,
+                               bfad_im_optionrom_version_show, NULL);
+static          DEVICE_ATTR(firmware_version, S_IRUGO,
+                               bfad_im_fw_version_show, NULL);
+static          DEVICE_ATTR(number_of_ports, S_IRUGO,
+                               bfad_im_num_of_ports_show, NULL);
+static          DEVICE_ATTR(driver_name, S_IRUGO, bfad_im_drv_name_show, NULL);
+static          DEVICE_ATTR(number_of_discovered_ports, S_IRUGO,
+                               bfad_im_num_of_discovered_ports_show, NULL);
+
+struct device_attribute *bfad_im_host_attrs[] = {
+       &dev_attr_serial_number,
+       &dev_attr_model,
+       &dev_attr_model_description,
+       &dev_attr_node_name,
+       &dev_attr_symbolic_name,
+       &dev_attr_hardware_version,
+       &dev_attr_driver_version,
+       &dev_attr_option_rom_version,
+       &dev_attr_firmware_version,
+       &dev_attr_number_of_ports,
+       &dev_attr_driver_name,
+       &dev_attr_number_of_discovered_ports,
+       NULL,
+};
+
+struct device_attribute *bfad_im_vport_attrs[] = {
+    &dev_attr_serial_number,
+    &dev_attr_model,
+    &dev_attr_model_description,
+    &dev_attr_node_name,
+    &dev_attr_symbolic_name,
+    &dev_attr_hardware_version,
+    &dev_attr_driver_version,
+    &dev_attr_option_rom_version,
+    &dev_attr_firmware_version,
+    &dev_attr_number_of_ports,
+    &dev_attr_driver_name,
+    &dev_attr_number_of_discovered_ports,
+    NULL,
+};
+
+
diff --git a/drivers/scsi/bfa/bfad_attr.h b/drivers/scsi/bfa/bfad_attr.h
new file mode 100644 (file)
index 0000000..4d3312d
--- /dev/null
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ */
+
+#ifndef __BFAD_ATTR_H__
+#define __BFAD_ATTR_H__
+/**
+ *  bfad_attr.h VMware driver configuration interface module.
+ */
+
+/**
+ *  FC_transport_template FC transport template
+ */
+
+struct Scsi_Host*
+bfad_os_dev_to_shost(struct scsi_target *starget);
+
+/**
+ * FC transport template entry, get SCSI target port ID.
+ */
+void
+bfad_im_get_starget_port_id(struct scsi_target *starget);
+
+/**
+ * FC transport template entry, get SCSI target nwwn.
+ */
+void
+bfad_im_get_starget_node_name(struct scsi_target *starget);
+
+/**
+ * FC transport template entry, get SCSI target pwwn.
+ */
+void
+bfad_im_get_starget_port_name(struct scsi_target *starget);
+
+/**
+ * FC transport template entry, get SCSI host port ID.
+ */
+void
+bfad_im_get_host_port_id(struct Scsi_Host *shost);
+
+/**
+ * FC transport template entry, issue a LIP.
+ */
+int
+bfad_im_issue_fc_host_lip(struct Scsi_Host *shost);
+
+struct Scsi_Host*
+bfad_os_starget_to_shost(struct scsi_target *starget);
+
+
+#endif /*  __BFAD_ATTR_H__ */
diff --git a/drivers/scsi/bfa/bfad_drv.h b/drivers/scsi/bfa/bfad_drv.h
new file mode 100644 (file)
index 0000000..172c81e
--- /dev/null
@@ -0,0 +1,295 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) 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.
+ */
+
+/**
+ * Contains base driver definitions.
+ */
+
+/**
+ *  bfa_drv.h Linux driver data structures.
+ */
+
+#ifndef __BFAD_DRV_H__
+#define __BFAD_DRV_H__
+
+#include "bfa_os_inc.h"
+
+#include <bfa.h>
+#include <bfa_svc.h>
+#include <fcs/bfa_fcs.h>
+#include <defs/bfa_defs_pci.h>
+#include <defs/bfa_defs_port.h>
+#include <defs/bfa_defs_rport.h>
+#include <fcs/bfa_fcs_rport.h>
+#include <defs/bfa_defs_vport.h>
+#include <fcs/bfa_fcs_vport.h>
+
+#include <cs/bfa_plog.h>
+#include "aen/bfa_aen.h"
+#include <log/bfa_log_linux.h>
+
+#define BFAD_DRIVER_NAME        "bfa"
+#ifdef BFA_DRIVER_VERSION
+#define BFAD_DRIVER_VERSION    BFA_DRIVER_VERSION
+#else
+#define BFAD_DRIVER_VERSION    "2.0.0.0"
+#endif
+
+
+#define BFAD_IRQ_FLAGS IRQF_SHARED
+
+/*
+ * BFAD flags
+ */
+#define BFAD_MSIX_ON                           0x00000001
+#define BFAD_HAL_INIT_DONE                     0x00000002
+#define BFAD_DRV_INIT_DONE                     0x00000004
+#define BFAD_CFG_PPORT_DONE                    0x00000008
+#define BFAD_HAL_START_DONE                    0x00000010
+#define BFAD_PORT_ONLINE                       0x00000020
+#define BFAD_RPORT_ONLINE                      0x00000040
+
+#define BFAD_PORT_DELETE                       0x00000001
+
+/*
+ * BFAD related definition
+ */
+#define SCSI_SCAN_DELAY                HZ
+#define BFAD_STOP_TIMEOUT      30
+#define BFAD_SUSPEND_TIMEOUT   BFAD_STOP_TIMEOUT
+
+/*
+ * BFAD configuration parameter default values
+ */
+#define BFAD_LUN_QUEUE_DEPTH           32
+#define BFAD_IO_MAX_SGE                SG_ALL
+
+#define bfad_isr_t irq_handler_t
+
+#define MAX_MSIX_ENTRY 22
+
+struct bfad_msix_s {
+       struct bfad_s *bfad;
+       struct msix_entry msix;
+};
+
+enum bfad_port_pvb_type {
+       BFAD_PORT_PHYS_BASE = 0,
+       BFAD_PORT_PHYS_VPORT = 1,
+       BFAD_PORT_VF_BASE = 2,
+       BFAD_PORT_VF_VPORT = 3,
+};
+
+/*
+ * PORT data structure
+ */
+struct bfad_port_s {
+       struct list_head list_entry;
+       struct bfad_s         *bfad;
+       struct bfa_fcs_port_s *fcs_port;
+       u32        roles;
+       s32         flags;
+       u32        supported_fc4s;
+       u8              ipfc_flags;
+       enum bfad_port_pvb_type pvb_type;
+       struct bfad_im_port_s *im_port; /* IM specific data */
+       struct bfad_tm_port_s *tm_port; /* TM specific data */
+       struct bfad_ipfc_port_s *ipfc_port;     /* IPFC specific data */
+};
+
+/*
+ * VPORT data structure
+ */
+struct bfad_vport_s {
+       struct bfad_port_s     drv_port;
+       struct bfa_fcs_vport_s fcs_vport;
+       struct completion *comp_del;
+};
+
+/*
+ * VF data structure
+ */
+struct bfad_vf_s {
+       bfa_fcs_vf_t    fcs_vf;
+       struct bfad_port_s    base_port;        /* base port for vf */
+       struct bfad_s   *bfad;
+};
+
+struct bfad_cfg_param_s {
+       u32        rport_del_timeout;
+       u32        ioc_queue_depth;
+       u32        lun_queue_depth;
+       u32        io_max_sge;
+       u32        binding_method;
+};
+
+#define BFAD_AEN_MAX_APPS 8
+struct bfad_aen_file_s {
+       struct list_head  qe;
+       struct bfad_s *bfad;
+       s32 ri;
+       s32 app_id;
+};
+
+/*
+ * BFAD (PCI function) data structure
+ */
+struct bfad_s {
+       struct list_head list_entry;
+       struct bfa_s       bfa;
+       struct bfa_fcs_s       bfa_fcs;
+       struct pci_dev *pcidev;
+       const char *pci_name;
+       struct bfa_pcidev_s hal_pcidev;
+       struct bfa_ioc_pci_attr_s pci_attr;
+       unsigned long   pci_bar0_map;
+       void __iomem   *pci_bar0_kva;
+       struct completion comp;
+       struct completion suspend;
+       struct completion disable_comp;
+       bfa_boolean_t   disable_active;
+       struct bfad_port_s     pport;   /* physical port of the BFAD */
+       struct bfa_meminfo_s meminfo;
+       struct bfa_iocfc_cfg_s   ioc_cfg;
+       u32        inst_no;     /* BFAD instance number */
+       u32        bfad_flags;
+       spinlock_t      bfad_lock;
+       struct bfad_cfg_param_s cfg_data;
+       struct bfad_msix_s msix_tab[MAX_MSIX_ENTRY];
+       int             nvec;
+       char            adapter_name[BFA_ADAPTER_SYM_NAME_LEN];
+       char            port_name[BFA_ADAPTER_SYM_NAME_LEN];
+       struct timer_list hal_tmo;
+       unsigned long   hs_start;
+       struct bfad_im_s *im;           /* IM specific data */
+       struct bfad_tm_s *tm;           /* TM specific data */
+       struct bfad_ipfc_s *ipfc;       /* IPFC specific data */
+       struct bfa_log_mod_s   log_data;
+       struct bfa_trc_mod_s  *trcmod;
+       struct bfa_log_mod_s  *logmod;
+       struct bfa_aen_s      *aen;
+       struct bfa_aen_s       aen_buf;
+       struct bfad_aen_file_s file_buf[BFAD_AEN_MAX_APPS];
+       struct list_head         file_q;
+       struct list_head         file_free_q;
+       struct bfa_plog_s      plog_buf;
+       int             ref_count;
+       bfa_boolean_t   ipfc_enabled;
+       struct fc_host_statistics link_stats;
+
+       struct kobject *bfa_kobj;
+       struct kobject *ioc_kobj;
+       struct kobject *pport_kobj;
+       struct kobject *lport_kobj;
+};
+
+/*
+ * RPORT data structure
+ */
+struct bfad_rport_s {
+       struct bfa_fcs_rport_s fcs_rport;
+};
+
+struct bfad_buf_info {
+       void           *virt;
+       dma_addr_t      phys;
+       u32        size;
+};
+
+struct bfad_fcxp {
+       struct bfad_port_s    *port;
+       struct bfa_rport_s *bfa_rport;
+       bfa_status_t    req_status;
+       u16        tag;
+       u16        rsp_len;
+       u16        rsp_maxlen;
+       u8         use_ireqbuf;
+       u8         use_irspbuf;
+       u32        num_req_sgles;
+       u32        num_rsp_sgles;
+       struct fchs_s          fchs;
+       void           *reqbuf_info;
+       void           *rspbuf_info;
+       struct bfa_sge_s  *req_sge;
+       struct bfa_sge_s  *rsp_sge;
+       fcxp_send_cb_t  send_cbfn;
+       void           *send_cbarg;
+       void           *bfa_fcxp;
+       struct completion comp;
+};
+
+struct bfad_hal_comp {
+       bfa_status_t    status;
+       struct completion comp;
+};
+
+/*
+ * Macro to obtain the immediate lower power
+ * of two for the integer.
+ */
+#define nextLowerInt(x)                                \
+do {                                                   \
+       int j;                                          \
+       (*x)--;                                         \
+       for (j = 1; j < (sizeof(int) * 8); j <<= 1)     \
+               (*x) = (*x) | (*x) >> j;                \
+       (*x)++;                                         \
+       (*x) = (*x) >> 1;                               \
+} while (0)
+
+
+bfa_status_t    bfad_vport_create(struct bfad_s *bfad, u16 vf_id,
+                                 struct bfa_port_cfg_s *port_cfg);
+bfa_status_t    bfad_vf_create(struct bfad_s *bfad, u16 vf_id,
+                              struct bfa_port_cfg_s *port_cfg);
+bfa_status_t    bfad_cfg_pport(struct bfad_s *bfad, enum bfa_port_role role);
+bfa_status_t    bfad_drv_init(struct bfad_s *bfad);
+void            bfad_drv_start(struct bfad_s *bfad);
+void            bfad_uncfg_pport(struct bfad_s *bfad);
+void            bfad_drv_stop(struct bfad_s *bfad);
+void            bfad_remove_intr(struct bfad_s *bfad);
+void            bfad_hal_mem_release(struct bfad_s *bfad);
+void            bfad_hcb_comp(void *arg, bfa_status_t status);
+
+int             bfad_setup_intr(struct bfad_s *bfad);
+void            bfad_remove_intr(struct bfad_s *bfad);
+
+void           bfad_update_hal_cfg(struct bfa_iocfc_cfg_s *bfa_cfg);
+bfa_status_t   bfad_hal_mem_alloc(struct bfad_s *bfad);
+void           bfad_bfa_tmo(unsigned long data);
+void           bfad_init_timer(struct bfad_s *bfad);
+int            bfad_pci_init(struct pci_dev *pdev, struct bfad_s *bfad);
+void           bfad_pci_uninit(struct pci_dev *pdev, struct bfad_s *bfad);
+void           bfad_fcs_port_cfg(struct bfad_s *bfad);
+void           bfad_drv_uninit(struct bfad_s *bfad);
+void           bfad_drv_log_level_set(struct bfad_s *bfad);
+bfa_status_t   bfad_fc4_module_init(void);
+void           bfad_fc4_module_exit(void);
+
+void bfad_pci_remove(struct pci_dev *pdev);
+int bfad_pci_probe(struct pci_dev *pdev, const struct pci_device_id *pid);
+void bfad_os_rport_online_wait(struct bfad_s *bfad);
+int bfad_os_get_linkup_delay(struct bfad_s *bfad);
+int bfad_install_msix_handler(struct bfad_s *bfad);
+
+extern struct idr bfad_im_port_index;
+extern struct list_head bfad_list;
+extern int bfa_lun_queue_depth;
+extern int bfad_supported_fc4s;
+extern int bfa_linkup_delay;
+
+#endif /* __BFAD_DRV_H__ */
diff --git a/drivers/scsi/bfa/bfad_fwimg.c b/drivers/scsi/bfa/bfad_fwimg.c
new file mode 100644 (file)
index 0000000..b2f6949
--- /dev/null
@@ -0,0 +1,95 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) 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.
+ */
+
+/**
+ *  bfad_fwimg.c Linux driver PCI interface module.
+ */
+#include <bfa_os_inc.h>
+#include <bfad_drv.h>
+#include <bfad_im_compat.h>
+#include <defs/bfa_defs_version.h>
+#include <linux/errno.h>
+#include <linux/sched.h>
+#include <linux/init.h>
+#include <linux/fs.h>
+#include <asm/uaccess.h>
+#include <asm/fcntl.h>
+#include <linux/pci.h>
+#include <linux/firmware.h>
+#include <bfa_fwimg_priv.h>
+#include <bfa.h>
+
+u32 bfi_image_ct_size;
+u32 bfi_image_cb_size;
+u32 *bfi_image_ct;
+u32 *bfi_image_cb;
+
+
+#define        BFAD_FW_FILE_CT "ctfw.bin"
+#define        BFAD_FW_FILE_CB "cbfw.bin"
+
+u32 *
+bfad_read_firmware(struct pci_dev *pdev, u32 **bfi_image,
+                       u32 *bfi_image_size, char *fw_name)
+{
+       const struct firmware *fw;
+
+       if (request_firmware(&fw, fw_name, &pdev->dev)) {
+               printk(KERN_ALERT "Can't locate firmware %s\n", fw_name);
+               goto error;
+       }
+
+       *bfi_image = vmalloc(fw->size);
+       if (NULL == *bfi_image) {
+               printk(KERN_ALERT "Fail to allocate buffer for fw image "
+                       "size=%x!\n", (u32) fw->size);
+               goto error;
+       }
+
+       memcpy(*bfi_image, fw->data, fw->size);
+       *bfi_image_size = fw->size/sizeof(u32);
+
+       return(*bfi_image);
+
+error:
+       return(NULL);
+}
+
+u32 *
+bfad_get_firmware_buf(struct pci_dev *pdev)
+{
+       if (pdev->device == BFA_PCI_DEVICE_ID_CT) {
+               if (bfi_image_ct_size == 0)
+                       bfad_read_firmware(pdev, &bfi_image_ct,
+                               &bfi_image_ct_size, BFAD_FW_FILE_CT);
+               return(bfi_image_ct);
+       } else {
+               if (bfi_image_cb_size == 0)
+                       bfad_read_firmware(pdev, &bfi_image_cb,
+                               &bfi_image_cb_size, BFAD_FW_FILE_CB);
+               return(bfi_image_cb);
+       }
+}
+
+u32 *
+bfi_image_ct_get_chunk(u32 off)
+{ return (u32 *)(bfi_image_ct + off); }
+
+u32 *
+bfi_image_cb_get_chunk(u32 off)
+{ return (u32 *)(bfi_image_cb + off); }
+
diff --git a/drivers/scsi/bfa/bfad_im.c b/drivers/scsi/bfa/bfad_im.c
new file mode 100644 (file)
index 0000000..158c992
--- /dev/null
@@ -0,0 +1,1230 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) 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.
+ */
+
+/**
+ *  bfad_im.c Linux driver IM module.
+ */
+
+#include "bfad_drv.h"
+#include "bfad_im.h"
+#include "bfad_trcmod.h"
+#include "bfa_cb_ioim_macros.h"
+#include <fcb/bfa_fcb_fcpim.h>
+
+BFA_TRC_FILE(LDRV, IM);
+
+DEFINE_IDR(bfad_im_port_index);
+struct scsi_transport_template *bfad_im_scsi_transport_template;
+static void bfad_im_itnim_work_handler(struct work_struct *work);
+static int bfad_im_queuecommand(struct scsi_cmnd *cmnd,
+               void (*done)(struct scsi_cmnd *));
+static int bfad_im_slave_alloc(struct scsi_device *sdev);
+
+void
+bfa_cb_ioim_done(void *drv, struct bfad_ioim_s *dio,
+                       enum bfi_ioim_status io_status, u8 scsi_status,
+                       int sns_len, u8 *sns_info, s32 residue)
+{
+       struct scsi_cmnd *cmnd = (struct scsi_cmnd *)dio;
+       struct bfad_s         *bfad = drv;
+       struct bfad_itnim_data_s *itnim_data;
+       struct bfad_itnim_s *itnim;
+
+       switch (io_status) {
+       case BFI_IOIM_STS_OK:
+               bfa_trc(bfad, scsi_status);
+               cmnd->result = ScsiResult(DID_OK, scsi_status);
+               scsi_set_resid(cmnd, 0);
+
+               if (sns_len > 0) {
+                       bfa_trc(bfad, sns_len);
+                       if (sns_len > SCSI_SENSE_BUFFERSIZE)
+                               sns_len = SCSI_SENSE_BUFFERSIZE;
+                       memcpy(cmnd->sense_buffer, sns_info, sns_len);
+               }
+               if (residue > 0)
+                       scsi_set_resid(cmnd, residue);
+               break;
+
+       case BFI_IOIM_STS_ABORTED:
+       case BFI_IOIM_STS_TIMEDOUT:
+       case BFI_IOIM_STS_PATHTOV:
+       default:
+               cmnd->result = ScsiResult(DID_ERROR, 0);
+       }
+
+       /* Unmap DMA, if host is NULL, it means a scsi passthru cmd */
+       if (cmnd->device->host != NULL)
+               scsi_dma_unmap(cmnd);
+
+       cmnd->host_scribble = NULL;
+       bfa_trc(bfad, cmnd->result);
+
+       itnim_data = cmnd->device->hostdata;
+       if (itnim_data) {
+               itnim = itnim_data->itnim;
+               if (!cmnd->result && itnim &&
+                        (bfa_lun_queue_depth > cmnd->device->queue_depth)) {
+                       /* Queue depth adjustment for good status completion */
+                       bfad_os_ramp_up_qdepth(itnim, cmnd->device);
+               } else if (cmnd->result == SAM_STAT_TASK_SET_FULL && itnim) {
+                       /* qfull handling */
+                       bfad_os_handle_qfull(itnim, cmnd->device);
+               }
+       }
+
+       cmnd->scsi_done(cmnd);
+}
+
+void
+bfa_cb_ioim_good_comp(void *drv, struct bfad_ioim_s *dio)
+{
+       struct scsi_cmnd *cmnd = (struct scsi_cmnd *)dio;
+       struct bfad_itnim_data_s *itnim_data;
+       struct bfad_itnim_s *itnim;
+
+       cmnd->result = ScsiResult(DID_OK, SCSI_STATUS_GOOD);
+
+       /* Unmap DMA, if host is NULL, it means a scsi passthru cmd */
+       if (cmnd->device->host != NULL)
+               scsi_dma_unmap(cmnd);
+
+       cmnd->host_scribble = NULL;
+
+       /* Queue depth adjustment */
+       if (bfa_lun_queue_depth > cmnd->device->queue_depth) {
+               itnim_data = cmnd->device->hostdata;
+               if (itnim_data) {
+                       itnim = itnim_data->itnim;
+                       if (itnim)
+                               bfad_os_ramp_up_qdepth(itnim, cmnd->device);
+               }
+       }
+
+       cmnd->scsi_done(cmnd);
+}
+
+void
+bfa_cb_ioim_abort(void *drv, struct bfad_ioim_s *dio)
+{
+       struct scsi_cmnd *cmnd = (struct scsi_cmnd *)dio;
+       struct bfad_s         *bfad = drv;
+
+       cmnd->result = ScsiResult(DID_ERROR, 0);
+
+       /* Unmap DMA, if host is NULL, it means a scsi passthru cmd */
+       if (cmnd->device->host != NULL)
+               scsi_dma_unmap(cmnd);
+
+       bfa_trc(bfad, cmnd->result);
+       cmnd->host_scribble = NULL;
+}
+
+void
+bfa_cb_tskim_done(void *bfad, struct bfad_tskim_s *dtsk,
+                  enum bfi_tskim_status tsk_status)
+{
+       struct scsi_cmnd *cmnd = (struct scsi_cmnd *)dtsk;
+       wait_queue_head_t *wq;
+
+       cmnd->SCp.Status |= tsk_status << 1;
+       set_bit(IO_DONE_BIT, (unsigned long *)&cmnd->SCp.Status);
+       wq = (wait_queue_head_t *) cmnd->SCp.ptr;
+       cmnd->SCp.ptr = NULL;
+
+       if (wq)
+               wake_up(wq);
+}
+
+void
+bfa_cb_ioim_resfree(void *drv)
+{
+}
+
+/**
+ *  Scsi_Host_template SCSI host template
+ */
+/**
+ * Scsi_Host template entry, returns BFAD PCI info.
+ */
+static const char *
+bfad_im_info(struct Scsi_Host *shost)
+{
+       static char     bfa_buf[256];
+       struct bfad_im_port_s *im_port =
+                       (struct bfad_im_port_s *) shost->hostdata[0];
+       struct bfa_ioc_attr_s  ioc_attr;
+       struct bfad_s         *bfad = im_port->bfad;
+
+       memset(&ioc_attr, 0, sizeof(ioc_attr));
+       bfa_get_attr(&bfad->bfa, &ioc_attr);
+
+       memset(bfa_buf, 0, sizeof(bfa_buf));
+       snprintf(bfa_buf, sizeof(bfa_buf),
+                "Brocade FC/FCOE Adapter, " "model: %s hwpath: %s driver: %s",
+                ioc_attr.adapter_attr.model, bfad->pci_name,
+                BFAD_DRIVER_VERSION);
+       return bfa_buf;
+}
+
+/**
+ * Scsi_Host template entry, aborts the specified SCSI command.
+ *
+ * Returns: SUCCESS or FAILED.
+ */
+static int
+bfad_im_abort_handler(struct scsi_cmnd *cmnd)
+{
+       struct Scsi_Host *shost = cmnd->device->host;
+       struct bfad_im_port_s *im_port =
+                       (struct bfad_im_port_s *) shost->hostdata[0];
+       struct bfad_s         *bfad = im_port->bfad;
+       struct bfa_ioim_s *hal_io;
+       unsigned long   flags;
+       u32        timeout;
+       int             rc = FAILED;
+
+       spin_lock_irqsave(&bfad->bfad_lock, flags);
+       hal_io = (struct bfa_ioim_s *) cmnd->host_scribble;
+       if (!hal_io) {
+               /* IO has been completed, retrun success */
+               rc = SUCCESS;
+               goto out;
+       }
+       if (hal_io->dio != (struct bfad_ioim_s *) cmnd) {
+               rc = FAILED;
+               goto out;
+       }
+
+       bfa_trc(bfad, hal_io->iotag);
+       bfa_log(bfad->logmod, BFA_LOG_LINUX_SCSI_ABORT,
+               im_port->shost->host_no, cmnd, hal_io->iotag);
+       bfa_ioim_abort(hal_io);
+       spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+
+       /* Need to wait until the command get aborted */
+       timeout = 10;
+       while ((struct bfa_ioim_s *) cmnd->host_scribble == hal_io) {
+               set_current_state(TASK_UNINTERRUPTIBLE);
+               schedule_timeout(timeout);
+               if (timeout < 4 * HZ)
+                       timeout *= 2;
+       }
+
+       cmnd->scsi_done(cmnd);
+       bfa_trc(bfad, hal_io->iotag);
+       bfa_log(bfad->logmod, BFA_LOG_LINUX_SCSI_ABORT_COMP,
+               im_port->shost->host_no, cmnd, hal_io->iotag);
+       return SUCCESS;
+out:
+       spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+       return rc;
+}
+
+static bfa_status_t
+bfad_im_target_reset_send(struct bfad_s *bfad, struct scsi_cmnd *cmnd,
+                    struct bfad_itnim_s *itnim)
+{
+       struct bfa_tskim_s *tskim;
+       struct bfa_itnim_s *bfa_itnim;
+       bfa_status_t    rc = BFA_STATUS_OK;
+
+       bfa_itnim = bfa_fcs_itnim_get_halitn(&itnim->fcs_itnim);
+       tskim = bfa_tskim_alloc(&bfad->bfa, (struct bfad_tskim_s *) cmnd);
+       if (!tskim) {
+               BFA_DEV_PRINTF(bfad, BFA_ERR,
+                              "target reset, fail to allocate tskim\n");
+               rc = BFA_STATUS_FAILED;
+               goto out;
+       }
+
+       /*
+        * Set host_scribble to NULL to avoid aborting a task command if
+        * happens.
+        */
+       cmnd->host_scribble = NULL;
+       cmnd->SCp.Status = 0;
+       bfa_itnim = bfa_fcs_itnim_get_halitn(&itnim->fcs_itnim);
+       bfa_tskim_start(tskim, bfa_itnim, (lun_t)0,
+                           FCP_TM_TARGET_RESET, BFAD_TARGET_RESET_TMO);
+out:
+       return rc;
+}
+
+/**
+ * Scsi_Host template entry, resets a LUN and abort its all commands.
+ *
+ * Returns: SUCCESS or FAILED.
+ *
+ */
+static int
+bfad_im_reset_lun_handler(struct scsi_cmnd *cmnd)
+{
+       struct Scsi_Host *shost = cmnd->device->host;
+       struct bfad_im_port_s *im_port =
+                       (struct bfad_im_port_s *) shost->hostdata[0];
+       struct bfad_itnim_data_s *itnim_data = cmnd->device->hostdata;
+       struct bfad_s         *bfad = im_port->bfad;
+       struct bfa_tskim_s *tskim;
+       struct bfad_itnim_s   *itnim;
+       struct bfa_itnim_s *bfa_itnim;
+       DECLARE_WAIT_QUEUE_HEAD(wq);
+       int             rc = SUCCESS;
+       unsigned long   flags;
+       enum bfi_tskim_status task_status;
+
+       spin_lock_irqsave(&bfad->bfad_lock, flags);
+       itnim = itnim_data->itnim;
+       if (!itnim) {
+               spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+               rc = FAILED;
+               goto out;
+       }
+
+       tskim = bfa_tskim_alloc(&bfad->bfa, (struct bfad_tskim_s *) cmnd);
+       if (!tskim) {
+               BFA_DEV_PRINTF(bfad, BFA_ERR,
+                               "LUN reset, fail to allocate tskim");
+               spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+               rc = FAILED;
+               goto out;
+       }
+
+       /**
+        * Set host_scribble to NULL to avoid aborting a task command
+        * if happens.
+        */
+       cmnd->host_scribble = NULL;
+       cmnd->SCp.ptr = (char *)&wq;
+       cmnd->SCp.Status = 0;
+       bfa_itnim = bfa_fcs_itnim_get_halitn(&itnim->fcs_itnim);
+       bfa_tskim_start(tskim, bfa_itnim,
+                           bfad_int_to_lun(cmnd->device->lun),
+                           FCP_TM_LUN_RESET, BFAD_LUN_RESET_TMO);
+       spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+
+       wait_event(wq, test_bit(IO_DONE_BIT,
+                       (unsigned long *)&cmnd->SCp.Status));
+
+       task_status = cmnd->SCp.Status >> 1;
+       if (task_status != BFI_TSKIM_STS_OK) {
+               BFA_DEV_PRINTF(bfad, BFA_ERR, "LUN reset failure, status: %d\n",
+                              task_status);
+               rc = FAILED;
+       }
+
+out:
+       return rc;
+}
+
+/**
+ * Scsi_Host template entry, resets the bus and abort all commands.
+ */
+static int
+bfad_im_reset_bus_handler(struct scsi_cmnd *cmnd)
+{
+       struct Scsi_Host *shost = cmnd->device->host;
+       struct bfad_im_port_s *im_port =
+                               (struct bfad_im_port_s *) shost->hostdata[0];
+       struct bfad_s         *bfad = im_port->bfad;
+       struct bfad_itnim_s   *itnim;
+       unsigned long   flags;
+       u32        i, rc, err_cnt = 0;
+       DECLARE_WAIT_QUEUE_HEAD(wq);
+       enum bfi_tskim_status task_status;
+
+       spin_lock_irqsave(&bfad->bfad_lock, flags);
+       for (i = 0; i < MAX_FCP_TARGET; i++) {
+               itnim = bfad_os_get_itnim(im_port, i);
+               if (itnim) {
+                       cmnd->SCp.ptr = (char *)&wq;
+                       rc = bfad_im_target_reset_send(bfad, cmnd, itnim);
+                       if (rc != BFA_STATUS_OK) {
+                               err_cnt++;
+                               continue;
+                       }
+
+                       /* wait target reset to complete */
+                       spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+                       wait_event(wq, test_bit(IO_DONE_BIT,
+                                       (unsigned long *)&cmnd->SCp.Status));
+                       spin_lock_irqsave(&bfad->bfad_lock, flags);
+
+                       task_status = cmnd->SCp.Status >> 1;
+                       if (task_status != BFI_TSKIM_STS_OK) {
+                               BFA_DEV_PRINTF(bfad, BFA_ERR,
+                                       "target reset failure,"
+                                       " status: %d\n", task_status);
+                               err_cnt++;
+                       }
+               }
+       }
+       spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+
+       if (err_cnt)
+               return FAILED;
+
+       return SUCCESS;
+}
+
+/**
+ * Scsi_Host template entry slave_destroy.
+ */
+static void
+bfad_im_slave_destroy(struct scsi_device *sdev)
+{
+       sdev->hostdata = NULL;
+       return;
+}
+
+/**
+ *  BFA FCS itnim callbacks
+ */
+
+/**
+ * BFA FCS itnim alloc callback, after successful PRLI
+ * Context: Interrupt
+ */
+void
+bfa_fcb_itnim_alloc(struct bfad_s *bfad, struct bfa_fcs_itnim_s **itnim,
+                   struct bfad_itnim_s **itnim_drv)
+{
+       *itnim_drv = kzalloc(sizeof(struct bfad_itnim_s), GFP_ATOMIC);
+       if (*itnim_drv == NULL)
+               return;
+
+       (*itnim_drv)->im = bfad->im;
+       *itnim = &(*itnim_drv)->fcs_itnim;
+       (*itnim_drv)->state = ITNIM_STATE_NONE;
+
+       /*
+        * Initiaze the itnim_work
+        */
+       INIT_WORK(&(*itnim_drv)->itnim_work, bfad_im_itnim_work_handler);
+       bfad->bfad_flags |= BFAD_RPORT_ONLINE;
+}
+
+/**
+ * BFA FCS itnim free callback.
+ * Context: Interrupt. bfad_lock is held
+ */
+void
+bfa_fcb_itnim_free(struct bfad_s *bfad, struct bfad_itnim_s *itnim_drv)
+{
+       struct bfad_port_s    *port;
+       wwn_t wwpn;
+       u32 fcid;
+       char wwpn_str[32], fcid_str[16];
+
+       /* online to free state transtion should not happen */
+       bfa_assert(itnim_drv->state != ITNIM_STATE_ONLINE);
+
+       itnim_drv->queue_work = 1;
+       /* offline request is not yet done, use the same request to free */
+       if (itnim_drv->state == ITNIM_STATE_OFFLINE_PENDING)
+               itnim_drv->queue_work = 0;
+
+       itnim_drv->state = ITNIM_STATE_FREE;
+       port = bfa_fcs_itnim_get_drvport(&itnim_drv->fcs_itnim);
+       itnim_drv->im_port = port->im_port;
+       wwpn = bfa_fcs_itnim_get_pwwn(&itnim_drv->fcs_itnim);
+       fcid = bfa_fcs_itnim_get_fcid(&itnim_drv->fcs_itnim);
+       wwn2str(wwpn_str, wwpn);
+       fcid2str(fcid_str, fcid);
+       bfa_log(bfad->logmod, BFA_LOG_LINUX_ITNIM_FREE,
+               port->im_port->shost->host_no,
+               fcid_str, wwpn_str);
+       bfad_os_itnim_process(itnim_drv);
+}
+
+/**
+ * BFA FCS itnim online callback.
+ * Context: Interrupt. bfad_lock is held
+ */
+void
+bfa_fcb_itnim_online(struct bfad_itnim_s *itnim_drv)
+{
+       struct bfad_port_s    *port;
+
+       itnim_drv->bfa_itnim = bfa_fcs_itnim_get_halitn(&itnim_drv->fcs_itnim);
+       port = bfa_fcs_itnim_get_drvport(&itnim_drv->fcs_itnim);
+       itnim_drv->state = ITNIM_STATE_ONLINE;
+       itnim_drv->queue_work = 1;
+       itnim_drv->im_port = port->im_port;
+       bfad_os_itnim_process(itnim_drv);
+}
+
+/**
+ * BFA FCS itnim offline callback.
+ * Context: Interrupt. bfad_lock is held
+ */
+void
+bfa_fcb_itnim_offline(struct bfad_itnim_s *itnim_drv)
+{
+       struct bfad_port_s    *port;
+       struct bfad_s *bfad;
+
+       port = bfa_fcs_itnim_get_drvport(&itnim_drv->fcs_itnim);
+       bfad = port->bfad;
+       if ((bfad->pport.flags & BFAD_PORT_DELETE) ||
+                (port->flags & BFAD_PORT_DELETE)) {
+               itnim_drv->state = ITNIM_STATE_OFFLINE;
+               return;
+       }
+       itnim_drv->im_port = port->im_port;
+       itnim_drv->state = ITNIM_STATE_OFFLINE_PENDING;
+       itnim_drv->queue_work = 1;
+       bfad_os_itnim_process(itnim_drv);
+}
+
+/**
+ * BFA FCS itnim timeout callback.
+ * Context: Interrupt. bfad_lock is held
+ */
+void bfa_fcb_itnim_tov(struct bfad_itnim_s *itnim)
+{
+       itnim->state = ITNIM_STATE_TIMEOUT;
+}
+
+/**
+ * Path TOV processing begin notification -- dummy for linux
+ */
+void
+bfa_fcb_itnim_tov_begin(struct bfad_itnim_s *itnim)
+{
+}
+
+
+
+/**
+ * Allocate a Scsi_Host for a port.
+ */
+int
+bfad_im_scsi_host_alloc(struct bfad_s *bfad, struct bfad_im_port_s *im_port)
+{
+       int error = 1;
+
+       if (!idr_pre_get(&bfad_im_port_index, GFP_KERNEL)) {
+               printk(KERN_WARNING "idr_pre_get failure\n");
+               goto out;
+       }
+
+       error = idr_get_new(&bfad_im_port_index, im_port,
+                                        &im_port->idr_id);
+       if (error) {
+               printk(KERN_WARNING "idr_get_new failure\n");
+               goto out;
+       }
+
+       im_port->shost = bfad_os_scsi_host_alloc(im_port, bfad);
+       if (!im_port->shost) {
+               error = 1;
+               goto out_free_idr;
+       }
+
+       im_port->shost->hostdata[0] = (unsigned long)im_port;
+       im_port->shost->unique_id = im_port->idr_id;
+       im_port->shost->this_id = -1;
+       im_port->shost->max_id = MAX_FCP_TARGET;
+       im_port->shost->max_lun = MAX_FCP_LUN;
+       im_port->shost->max_cmd_len = 16;
+       im_port->shost->can_queue = bfad->cfg_data.ioc_queue_depth;
+       im_port->shost->transportt = bfad_im_scsi_transport_template;
+
+       error = bfad_os_scsi_add_host(im_port->shost, im_port, bfad);
+       if (error) {
+               printk(KERN_WARNING "bfad_os_scsi_add_host failure %d\n",
+                                                       error);
+               goto out_fc_rel;
+       }
+
+       /* setup host fixed attribute if the lk supports */
+       bfad_os_fc_host_init(im_port);
+
+       return 0;
+
+out_fc_rel:
+       scsi_host_put(im_port->shost);
+out_free_idr:
+       idr_remove(&bfad_im_port_index, im_port->idr_id);
+out:
+       return error;
+}
+
+void
+bfad_im_scsi_host_free(struct bfad_s *bfad, struct bfad_im_port_s *im_port)
+{
+       unsigned long flags;
+
+       bfa_trc(bfad, bfad->inst_no);
+       bfa_log(bfad->logmod, BFA_LOG_LINUX_SCSI_HOST_FREE,
+                       im_port->shost->host_no);
+
+       fc_remove_host(im_port->shost);
+
+       scsi_remove_host(im_port->shost);
+       scsi_host_put(im_port->shost);
+
+       spin_lock_irqsave(&bfad->bfad_lock, flags);
+       idr_remove(&bfad_im_port_index, im_port->idr_id);
+       spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+}
+
+static void
+bfad_im_port_delete_handler(struct work_struct *work)
+{
+       struct bfad_im_port_s *im_port =
+               container_of(work, struct bfad_im_port_s, port_delete_work);
+
+       bfad_im_scsi_host_free(im_port->bfad, im_port);
+       bfad_im_port_clean(im_port);
+       kfree(im_port);
+}
+
+bfa_status_t
+bfad_im_port_new(struct bfad_s *bfad, struct bfad_port_s *port)
+{
+       int             rc = BFA_STATUS_OK;
+       struct bfad_im_port_s *im_port;
+
+       im_port = kzalloc(sizeof(struct bfad_im_port_s), GFP_ATOMIC);
+       if (im_port == NULL) {
+               rc = BFA_STATUS_ENOMEM;
+               goto ext;
+       }
+       port->im_port = im_port;
+       im_port->port = port;
+       im_port->bfad = bfad;
+
+       INIT_WORK(&im_port->port_delete_work, bfad_im_port_delete_handler);
+       INIT_LIST_HEAD(&im_port->itnim_mapped_list);
+       INIT_LIST_HEAD(&im_port->binding_list);
+
+ext:
+       return rc;
+}
+
+void
+bfad_im_port_delete(struct bfad_s *bfad, struct bfad_port_s *port)
+{
+       struct bfad_im_port_s *im_port = port->im_port;
+
+       queue_work(bfad->im->drv_workq,
+                               &im_port->port_delete_work);
+}
+
+void
+bfad_im_port_clean(struct bfad_im_port_s *im_port)
+{
+       struct bfad_fcp_binding *bp, *bp_new;
+       unsigned long flags;
+       struct bfad_s *bfad =  im_port->bfad;
+
+       spin_lock_irqsave(&bfad->bfad_lock, flags);
+       list_for_each_entry_safe(bp, bp_new, &im_port->binding_list,
+                                       list_entry) {
+               list_del(&bp->list_entry);
+               kfree(bp);
+       }
+
+       /* the itnim_mapped_list must be empty at this time */
+       bfa_assert(list_empty(&im_port->itnim_mapped_list));
+
+       spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+}
+
+void
+bfad_im_port_online(struct bfad_s *bfad, struct bfad_port_s *port)
+{
+}
+
+void
+bfad_im_port_offline(struct bfad_s *bfad, struct bfad_port_s *port)
+{
+}
+
+bfa_status_t
+bfad_im_probe(struct bfad_s *bfad)
+{
+       struct bfad_im_s      *im;
+       bfa_status_t    rc = BFA_STATUS_OK;
+
+       im = kzalloc(sizeof(struct bfad_im_s), GFP_KERNEL);
+       if (im == NULL) {
+               rc = BFA_STATUS_ENOMEM;
+               goto ext;
+       }
+
+       bfad->im = im;
+       im->bfad = bfad;
+
+       if (bfad_os_thread_workq(bfad) != BFA_STATUS_OK) {
+               kfree(im);
+               rc = BFA_STATUS_FAILED;
+       }
+
+ext:
+       return rc;
+}
+
+void
+bfad_im_probe_undo(struct bfad_s *bfad)
+{
+       if (bfad->im) {
+               bfad_os_destroy_workq(bfad->im);
+               kfree(bfad->im);
+               bfad->im = NULL;
+       }
+}
+
+
+
+
+int
+bfad_os_scsi_add_host(struct Scsi_Host *shost, struct bfad_im_port_s *im_port,
+                       struct bfad_s *bfad)
+{
+    struct device *dev;
+
+    if (im_port->port->pvb_type == BFAD_PORT_PHYS_BASE)
+               dev = &bfad->pcidev->dev;
+    else
+               dev = &bfad->pport.im_port->shost->shost_gendev;
+
+    return scsi_add_host(shost, dev);
+}
+
+struct Scsi_Host *
+bfad_os_scsi_host_alloc(struct bfad_im_port_s *im_port, struct bfad_s *bfad)
+{
+       struct scsi_host_template *sht;
+
+       if (im_port->port->pvb_type == BFAD_PORT_PHYS_BASE)
+               sht = &bfad_im_scsi_host_template;
+       else
+               sht = &bfad_im_vport_template;
+
+       sht->sg_tablesize = bfad->cfg_data.io_max_sge;
+
+       return scsi_host_alloc(sht, sizeof(unsigned long));
+}
+
+void
+bfad_os_scsi_host_free(struct bfad_s *bfad, struct bfad_im_port_s *im_port)
+{
+       flush_workqueue(bfad->im->drv_workq);
+       bfad_im_scsi_host_free(im_port->bfad, im_port);
+       bfad_im_port_clean(im_port);
+       kfree(im_port);
+}
+
+void
+bfad_os_destroy_workq(struct bfad_im_s *im)
+{
+       if (im && im->drv_workq) {
+               destroy_workqueue(im->drv_workq);
+               im->drv_workq = NULL;
+       }
+}
+
+bfa_status_t
+bfad_os_thread_workq(struct bfad_s *bfad)
+{
+       struct bfad_im_s      *im = bfad->im;
+
+       bfa_trc(bfad, 0);
+       snprintf(im->drv_workq_name, BFAD_KOBJ_NAME_LEN, "bfad_wq_%d",
+                bfad->inst_no);
+       im->drv_workq = create_singlethread_workqueue(im->drv_workq_name);
+       if (!im->drv_workq)
+               return BFA_STATUS_FAILED;
+
+       return BFA_STATUS_OK;
+}
+
+/**
+ * Scsi_Host template entry.
+ *
+ * Description:
+ * OS entry point to adjust the queue_depths on a per-device basis.
+ * Called once per device during the bus scan.
+ * Return non-zero if fails.
+ */
+static int
+bfad_im_slave_configure(struct scsi_device *sdev)
+{
+       if (sdev->tagged_supported)
+               scsi_activate_tcq(sdev, bfa_lun_queue_depth);
+       else
+               scsi_deactivate_tcq(sdev, bfa_lun_queue_depth);
+
+       return 0;
+}
+
+struct scsi_host_template bfad_im_scsi_host_template = {
+       .module = THIS_MODULE,
+       .name = BFAD_DRIVER_NAME,
+       .info = bfad_im_info,
+       .queuecommand = bfad_im_queuecommand,
+       .eh_abort_handler = bfad_im_abort_handler,
+       .eh_device_reset_handler = bfad_im_reset_lun_handler,
+       .eh_bus_reset_handler = bfad_im_reset_bus_handler,
+
+       .slave_alloc = bfad_im_slave_alloc,
+       .slave_configure = bfad_im_slave_configure,
+       .slave_destroy = bfad_im_slave_destroy,
+
+       .this_id = -1,
+       .sg_tablesize = BFAD_IO_MAX_SGE,
+       .cmd_per_lun = 3,
+       .use_clustering = ENABLE_CLUSTERING,
+       .shost_attrs = bfad_im_host_attrs,
+       .max_sectors = 0xFFFF,
+};
+
+struct scsi_host_template bfad_im_vport_template = {
+       .module = THIS_MODULE,
+       .name = BFAD_DRIVER_NAME,
+       .info = bfad_im_info,
+       .queuecommand = bfad_im_queuecommand,
+       .eh_abort_handler = bfad_im_abort_handler,
+       .eh_device_reset_handler = bfad_im_reset_lun_handler,
+       .eh_bus_reset_handler = bfad_im_reset_bus_handler,
+
+       .slave_alloc = bfad_im_slave_alloc,
+       .slave_configure = bfad_im_slave_configure,
+       .slave_destroy = bfad_im_slave_destroy,
+
+       .this_id = -1,
+       .sg_tablesize = BFAD_IO_MAX_SGE,
+       .cmd_per_lun = 3,
+       .use_clustering = ENABLE_CLUSTERING,
+       .shost_attrs = bfad_im_vport_attrs,
+       .max_sectors = 0xFFFF,
+};
+
+void
+bfad_im_probe_post(struct bfad_im_s *im)
+{
+       flush_workqueue(im->drv_workq);
+}
+
+bfa_status_t
+bfad_im_module_init(void)
+{
+       bfad_im_scsi_transport_template =
+               fc_attach_transport(&bfad_im_fc_function_template);
+       if (!bfad_im_scsi_transport_template)
+               return BFA_STATUS_ENOMEM;
+
+       return BFA_STATUS_OK;
+}
+
+void
+bfad_im_module_exit(void)
+{
+       if (bfad_im_scsi_transport_template)
+               fc_release_transport(bfad_im_scsi_transport_template);
+}
+
+void
+bfad_os_itnim_process(struct bfad_itnim_s *itnim_drv)
+{
+       struct bfad_im_s      *im = itnim_drv->im;
+
+       if (itnim_drv->queue_work)
+               queue_work(im->drv_workq, &itnim_drv->itnim_work);
+}
+
+void
+bfad_os_ramp_up_qdepth(struct bfad_itnim_s *itnim, struct scsi_device *sdev)
+{
+       struct scsi_device *tmp_sdev;
+
+       if (((jiffies - itnim->last_ramp_up_time) >
+               BFA_QUEUE_FULL_RAMP_UP_TIME * HZ) &&
+               ((jiffies - itnim->last_queue_full_time) >
+               BFA_QUEUE_FULL_RAMP_UP_TIME * HZ)) {
+               shost_for_each_device(tmp_sdev, sdev->host) {
+                       if (bfa_lun_queue_depth > tmp_sdev->queue_depth) {
+                               if (tmp_sdev->id != sdev->id)
+                                       continue;
+                               if (tmp_sdev->ordered_tags)
+                                       scsi_adjust_queue_depth(tmp_sdev,
+                                               MSG_ORDERED_TAG,
+                                               tmp_sdev->queue_depth + 1);
+                               else
+                                       scsi_adjust_queue_depth(tmp_sdev,
+                                               MSG_SIMPLE_TAG,
+                                               tmp_sdev->queue_depth + 1);
+
+                               itnim->last_ramp_up_time = jiffies;
+                       }
+               }
+       }
+}
+
+void
+bfad_os_handle_qfull(struct bfad_itnim_s *itnim, struct scsi_device *sdev)
+{
+       struct scsi_device *tmp_sdev;
+
+       itnim->last_queue_full_time = jiffies;
+
+       shost_for_each_device(tmp_sdev, sdev->host) {
+               if (tmp_sdev->id != sdev->id)
+                       continue;
+               scsi_track_queue_full(tmp_sdev, tmp_sdev->queue_depth - 1);
+       }
+}
+
+
+
+
+struct bfad_itnim_s *
+bfad_os_get_itnim(struct bfad_im_port_s *im_port, int id)
+{
+       struct bfad_itnim_s   *itnim = NULL;
+
+       /* Search the mapped list for this target ID */
+       list_for_each_entry(itnim, &im_port->itnim_mapped_list, list_entry) {
+               if (id == itnim->scsi_tgt_id)
+                       return itnim;
+       }
+
+       return NULL;
+}
+
+/**
+ * Scsi_Host template entry slave_alloc
+ */
+static int
+bfad_im_slave_alloc(struct scsi_device *sdev)
+{
+       struct fc_rport *rport = starget_to_rport(scsi_target(sdev));
+
+       if (!rport || fc_remote_port_chkready(rport))
+               return -ENXIO;
+
+       sdev->hostdata = rport->dd_data;
+
+       return 0;
+}
+
+void
+bfad_os_fc_host_init(struct bfad_im_port_s *im_port)
+{
+       struct Scsi_Host *host = im_port->shost;
+       struct bfad_s         *bfad = im_port->bfad;
+       struct bfad_port_s    *port = im_port->port;
+       union attr {
+               struct bfa_pport_attr_s pattr;
+               struct bfa_ioc_attr_s  ioc_attr;
+       } attr;
+
+       fc_host_node_name(host) =
+               bfa_os_htonll((bfa_fcs_port_get_nwwn(port->fcs_port)));
+       fc_host_port_name(host) =
+               bfa_os_htonll((bfa_fcs_port_get_pwwn(port->fcs_port)));
+
+       fc_host_supported_classes(host) = FC_COS_CLASS3;
+
+       memset(fc_host_supported_fc4s(host), 0,
+              sizeof(fc_host_supported_fc4s(host)));
+       if (bfad_supported_fc4s & (BFA_PORT_ROLE_FCP_IM | BFA_PORT_ROLE_FCP_TM))
+               /* For FCP type 0x08 */
+               fc_host_supported_fc4s(host)[2] = 1;
+       if (bfad_supported_fc4s | BFA_PORT_ROLE_FCP_IPFC)
+               /* For LLC/SNAP type 0x05 */
+               fc_host_supported_fc4s(host)[3] = 0x20;
+       /* For fibre channel services type 0x20 */
+       fc_host_supported_fc4s(host)[7] = 1;
+
+       memset(&attr.ioc_attr, 0, sizeof(attr.ioc_attr));
+       bfa_get_attr(&bfad->bfa, &attr.ioc_attr);
+       sprintf(fc_host_symbolic_name(host), "Brocade %s FV%s DV%s",
+               attr.ioc_attr.adapter_attr.model,
+               attr.ioc_attr.adapter_attr.fw_ver, BFAD_DRIVER_VERSION);
+
+       fc_host_supported_speeds(host) = 0;
+       fc_host_supported_speeds(host) |=
+               FC_PORTSPEED_8GBIT | FC_PORTSPEED_4GBIT | FC_PORTSPEED_2GBIT |
+               FC_PORTSPEED_1GBIT;
+
+       memset(&attr.pattr, 0, sizeof(attr.pattr));
+       bfa_pport_get_attr(&bfad->bfa, &attr.pattr);
+       fc_host_maxframe_size(host) = attr.pattr.pport_cfg.maxfrsize;
+}
+
+static void
+bfad_im_fc_rport_add(struct bfad_im_port_s *im_port, struct bfad_itnim_s *itnim)
+{
+       struct fc_rport_identifiers rport_ids;
+       struct fc_rport *fc_rport;
+       struct bfad_itnim_data_s *itnim_data;
+
+       rport_ids.node_name =
+               bfa_os_htonll(bfa_fcs_itnim_get_nwwn(&itnim->fcs_itnim));
+       rport_ids.port_name =
+               bfa_os_htonll(bfa_fcs_itnim_get_pwwn(&itnim->fcs_itnim));
+       rport_ids.port_id =
+               bfa_os_hton3b(bfa_fcs_itnim_get_fcid(&itnim->fcs_itnim));
+       rport_ids.roles = FC_RPORT_ROLE_UNKNOWN;
+
+       itnim->fc_rport = fc_rport =
+               fc_remote_port_add(im_port->shost, 0, &rport_ids);
+
+       if (!fc_rport)
+               return;
+
+       fc_rport->maxframe_size =
+               bfa_fcs_itnim_get_maxfrsize(&itnim->fcs_itnim);
+       fc_rport->supported_classes = bfa_fcs_itnim_get_cos(&itnim->fcs_itnim);
+
+       itnim_data = fc_rport->dd_data;
+       itnim_data->itnim = itnim;
+
+       rport_ids.roles |= FC_RPORT_ROLE_FCP_TARGET;
+
+       if (rport_ids.roles != FC_RPORT_ROLE_UNKNOWN)
+               fc_remote_port_rolechg(fc_rport, rport_ids.roles);
+
+       if ((fc_rport->scsi_target_id != -1)
+           && (fc_rport->scsi_target_id < MAX_FCP_TARGET))
+               itnim->scsi_tgt_id = fc_rport->scsi_target_id;
+
+       return;
+}
+
+/**
+ * Work queue handler using FC transport service
+* Context: kernel
+ */
+static void
+bfad_im_itnim_work_handler(struct work_struct *work)
+{
+       struct bfad_itnim_s   *itnim = container_of(work, struct bfad_itnim_s,
+                                                       itnim_work);
+       struct bfad_im_s      *im = itnim->im;
+       struct bfad_s         *bfad = im->bfad;
+       struct bfad_im_port_s *im_port;
+       unsigned long   flags;
+       struct fc_rport *fc_rport;
+       wwn_t wwpn;
+       u32 fcid;
+       char wwpn_str[32], fcid_str[16];
+
+       spin_lock_irqsave(&bfad->bfad_lock, flags);
+       im_port = itnim->im_port;
+       bfa_trc(bfad, itnim->state);
+       switch (itnim->state) {
+       case ITNIM_STATE_ONLINE:
+               if (!itnim->fc_rport) {
+                       spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+                       bfad_im_fc_rport_add(im_port, itnim);
+                       spin_lock_irqsave(&bfad->bfad_lock, flags);
+                       wwpn = bfa_fcs_itnim_get_pwwn(&itnim->fcs_itnim);
+                       fcid = bfa_fcs_itnim_get_fcid(&itnim->fcs_itnim);
+                       wwn2str(wwpn_str, wwpn);
+                       fcid2str(fcid_str, fcid);
+                       list_add_tail(&itnim->list_entry,
+                               &im_port->itnim_mapped_list);
+                       bfa_log(bfad->logmod, BFA_LOG_LINUX_ITNIM_ONLINE,
+                               im_port->shost->host_no,
+                               itnim->scsi_tgt_id,
+                               fcid_str, wwpn_str);
+               } else {
+                       printk(KERN_WARNING
+                               "%s: itnim %llx is already in online state\n",
+                               __FUNCTION__,
+                               bfa_fcs_itnim_get_pwwn(&itnim->fcs_itnim));
+               }
+
+               break;
+       case ITNIM_STATE_OFFLINE_PENDING:
+               itnim->state = ITNIM_STATE_OFFLINE;
+               if (itnim->fc_rport) {
+                       fc_rport = itnim->fc_rport;
+                       ((struct bfad_itnim_data_s *)
+                               fc_rport->dd_data)->itnim = NULL;
+                       itnim->fc_rport = NULL;
+                       if (!(im_port->port->flags & BFAD_PORT_DELETE)) {
+                               spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+                               fc_rport->dev_loss_tmo =
+                                       bfa_fcpim_path_tov_get(&bfad->bfa) + 1;
+                               fc_remote_port_delete(fc_rport);
+                               spin_lock_irqsave(&bfad->bfad_lock, flags);
+                       }
+                       wwpn = bfa_fcs_itnim_get_pwwn(&itnim->fcs_itnim);
+                       fcid = bfa_fcs_itnim_get_fcid(&itnim->fcs_itnim);
+                       wwn2str(wwpn_str, wwpn);
+                       fcid2str(fcid_str, fcid);
+                       list_del(&itnim->list_entry);
+                       bfa_log(bfad->logmod, BFA_LOG_LINUX_ITNIM_OFFLINE,
+                               im_port->shost->host_no,
+                               itnim->scsi_tgt_id,
+                               fcid_str, wwpn_str);
+               }
+               break;
+       case ITNIM_STATE_FREE:
+               if (itnim->fc_rport) {
+                       fc_rport = itnim->fc_rport;
+                       ((struct bfad_itnim_data_s *)
+                               fc_rport->dd_data)->itnim = NULL;
+                       itnim->fc_rport = NULL;
+                       if (!(im_port->port->flags & BFAD_PORT_DELETE)) {
+                               spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+                               fc_rport->dev_loss_tmo =
+                                       bfa_fcpim_path_tov_get(&bfad->bfa) + 1;
+                               fc_remote_port_delete(fc_rport);
+                               spin_lock_irqsave(&bfad->bfad_lock, flags);
+                       }
+                       list_del(&itnim->list_entry);
+               }
+
+               kfree(itnim);
+               break;
+       default:
+               bfa_assert(0);
+               break;
+       }
+
+       spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+}
+
+/**
+ * Scsi_Host template entry, queue a SCSI command to the BFAD.
+ */
+static int
+bfad_im_queuecommand(struct scsi_cmnd *cmnd, void (*done) (struct scsi_cmnd *))
+{
+       struct bfad_im_port_s *im_port =
+               (struct bfad_im_port_s *) cmnd->device->host->hostdata[0];
+       struct bfad_s         *bfad = im_port->bfad;
+       struct bfad_itnim_data_s *itnim_data = cmnd->device->hostdata;
+       struct bfad_itnim_s   *itnim;
+       struct bfa_ioim_s *hal_io;
+       unsigned long   flags;
+       int             rc;
+       s16        sg_cnt = 0;
+       struct fc_rport *rport = starget_to_rport(scsi_target(cmnd->device));
+
+       rc = fc_remote_port_chkready(rport);
+       if (rc) {
+               cmnd->result = rc;
+               done(cmnd);
+               return 0;
+       }
+
+       sg_cnt = scsi_dma_map(cmnd);
+
+       if (sg_cnt < 0)
+               return SCSI_MLQUEUE_HOST_BUSY;
+
+       cmnd->scsi_done = done;
+
+       spin_lock_irqsave(&bfad->bfad_lock, flags);
+       if (!(bfad->bfad_flags & BFAD_HAL_START_DONE)) {
+               printk(KERN_WARNING
+                       "bfad%d, queuecommand %p %x failed, BFA stopped\n",
+                      bfad->inst_no, cmnd, cmnd->cmnd[0]);
+               cmnd->result = ScsiResult(DID_NO_CONNECT, 0);
+               goto out_fail_cmd;
+       }
+
+       itnim = itnim_data->itnim;
+       if (!itnim) {
+               cmnd->result = ScsiResult(DID_IMM_RETRY, 0);
+               goto out_fail_cmd;
+       }
+
+       hal_io = bfa_ioim_alloc(&bfad->bfa, (struct bfad_ioim_s *) cmnd,
+                                   itnim->bfa_itnim, sg_cnt);
+       if (!hal_io) {
+               printk(KERN_WARNING "hal_io failure\n");
+               spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+               scsi_dma_unmap(cmnd);
+               return SCSI_MLQUEUE_HOST_BUSY;
+       }
+
+       cmnd->host_scribble = (char *)hal_io;
+       bfa_trc_fp(bfad, hal_io->iotag);
+       bfa_ioim_start(hal_io);
+       spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+
+       return 0;
+
+out_fail_cmd:
+       spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+       scsi_dma_unmap(cmnd);
+       if (done)
+               done(cmnd);
+
+       return 0;
+}
+
+void
+bfad_os_rport_online_wait(struct bfad_s *bfad)
+{
+       int i;
+       int rport_delay = 10;
+
+       for (i = 0; !(bfad->bfad_flags & BFAD_PORT_ONLINE)
+                && i < bfa_linkup_delay; i++)
+               schedule_timeout_uninterruptible(HZ);
+
+       if (bfad->bfad_flags & BFAD_PORT_ONLINE) {
+               rport_delay = rport_delay < bfa_linkup_delay ?
+                                rport_delay : bfa_linkup_delay;
+               for (i = 0; !(bfad->bfad_flags & BFAD_RPORT_ONLINE)
+                        && i < rport_delay; i++)
+                       schedule_timeout_uninterruptible(HZ);
+
+               if (rport_delay > 0 && (bfad->bfad_flags & BFAD_RPORT_ONLINE))
+                       schedule_timeout_uninterruptible(rport_delay * HZ);
+       }
+}
+
+int
+bfad_os_get_linkup_delay(struct bfad_s *bfad)
+{
+
+       u8         nwwns = 0;
+       wwn_t           *wwns;
+       int             ldelay;
+
+       /*
+        * Querying for the boot target port wwns
+        * -- read from boot information in flash.
+        * If nwwns > 0 => boot over SAN and set bfa_linkup_delay = 30
+        * else => local boot machine set bfa_linkup_delay = 10
+        */
+
+       bfa_iocfc_get_bootwwns(&bfad->bfa, &nwwns, &wwns);
+
+       if (nwwns > 0) {
+               /* If boot over SAN; linkup_delay = 30sec */
+               ldelay = 30;
+       } else {
+               /* If local boot; linkup_delay = 10sec */
+               ldelay = 0;
+       }
+
+       return ldelay;
+}
+
+
diff --git a/drivers/scsi/bfa/bfad_im.h b/drivers/scsi/bfa/bfad_im.h
new file mode 100644 (file)
index 0000000..189a5b2
--- /dev/null
@@ -0,0 +1,150 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ */
+
+#ifndef __BFAD_IM_H__
+#define __BFAD_IM_H__
+
+#include "fcs/bfa_fcs_fcpim.h"
+#include "bfad_im_compat.h"
+
+#define FCPI_NAME " fcpim"
+
+void bfad_flags_set(struct bfad_s *bfad, u32 flags);
+bfa_status_t bfad_im_module_init(void);
+void bfad_im_module_exit(void);
+bfa_status_t bfad_im_probe(struct bfad_s *bfad);
+void bfad_im_probe_undo(struct bfad_s *bfad);
+void bfad_im_probe_post(struct bfad_im_s *im);
+bfa_status_t bfad_im_port_new(struct bfad_s *bfad, struct bfad_port_s *port);
+void bfad_im_port_delete(struct bfad_s *bfad, struct bfad_port_s *port);
+void bfad_im_port_online(struct bfad_s *bfad, struct bfad_port_s *port);
+void bfad_im_port_offline(struct bfad_s *bfad, struct bfad_port_s *port);
+void bfad_im_port_clean(struct bfad_im_port_s *im_port);
+int  bfad_im_scsi_host_alloc(struct bfad_s *bfad,
+                               struct bfad_im_port_s *im_port);
+void bfad_im_scsi_host_free(struct bfad_s *bfad,
+                               struct bfad_im_port_s *im_port);
+
+#define MAX_FCP_TARGET 1024
+#define MAX_FCP_LUN 16384
+#define BFAD_TARGET_RESET_TMO 60
+#define BFAD_LUN_RESET_TMO 60
+#define ScsiResult(host_code, scsi_code) (((host_code) << 16) | scsi_code)
+#define BFA_QUEUE_FULL_RAMP_UP_TIME 120
+#define BFAD_KOBJ_NAME_LEN 20
+
+/*
+ * itnim flags
+ */
+#define ITNIM_MAPPED           0x00000001
+
+#define SCSI_TASK_MGMT         0x00000001
+#define IO_DONE_BIT                    0
+
+struct bfad_itnim_data_s {
+       struct bfad_itnim_s *itnim;
+};
+
+struct bfad_im_port_s {
+       struct bfad_s         *bfad;
+       struct bfad_port_s    *port;
+       struct work_struct port_delete_work;
+       int             idr_id;
+       u16        cur_scsi_id;
+       struct list_head binding_list;
+       struct Scsi_Host *shost;
+       struct list_head itnim_mapped_list;
+};
+
+enum bfad_itnim_state {
+       ITNIM_STATE_NONE,
+       ITNIM_STATE_ONLINE,
+       ITNIM_STATE_OFFLINE_PENDING,
+       ITNIM_STATE_OFFLINE,
+       ITNIM_STATE_TIMEOUT,
+       ITNIM_STATE_FREE,
+};
+
+/*
+ * Per itnim data structure
+ */
+struct bfad_itnim_s {
+       struct list_head list_entry;
+       struct bfa_fcs_itnim_s fcs_itnim;
+       struct work_struct itnim_work;
+       u32        flags;
+       enum bfad_itnim_state state;
+       struct bfad_im_s *im;
+       struct bfad_im_port_s *im_port;
+       struct bfad_rport_s *drv_rport;
+       struct fc_rport *fc_rport;
+       struct bfa_itnim_s *bfa_itnim;
+       u16        scsi_tgt_id;
+       u16        queue_work;
+       unsigned long   last_ramp_up_time;
+       unsigned long   last_queue_full_time;
+};
+
+enum bfad_binding_type {
+       FCP_PWWN_BINDING = 0x1,
+       FCP_NWWN_BINDING = 0x2,
+       FCP_FCID_BINDING = 0x3,
+};
+
+struct bfad_fcp_binding {
+       struct list_head list_entry;
+       enum bfad_binding_type binding_type;
+       u16        scsi_target_id;
+       u32        fc_id;
+       wwn_t           nwwn;
+       wwn_t           pwwn;
+};
+
+struct bfad_im_s {
+       struct bfad_s         *bfad;
+       struct workqueue_struct *drv_workq;
+       char   drv_workq_name[BFAD_KOBJ_NAME_LEN];
+};
+
+struct Scsi_Host *bfad_os_scsi_host_alloc(struct bfad_im_port_s *im_port,
+                               struct bfad_s *);
+bfa_status_t bfad_os_thread_workq(struct bfad_s *bfad);
+void bfad_os_destroy_workq(struct bfad_im_s *im);
+void bfad_os_itnim_process(struct bfad_itnim_s *itnim_drv);
+void bfad_os_fc_host_init(struct bfad_im_port_s *im_port);
+void bfad_os_init_work(struct bfad_im_port_s *im_port);
+void bfad_os_scsi_host_free(struct bfad_s *bfad,
+                                struct bfad_im_port_s *im_port);
+void bfad_os_ramp_up_qdepth(struct bfad_itnim_s *itnim,
+                                struct scsi_device *sdev);
+void bfad_os_handle_qfull(struct bfad_itnim_s *itnim, struct scsi_device *sdev);
+struct bfad_itnim_s *bfad_os_get_itnim(struct bfad_im_port_s *im_port, int id);
+int bfad_os_scsi_add_host(struct Scsi_Host *shost,
+               struct bfad_im_port_s *im_port, struct bfad_s *bfad);
+
+/*
+ * scsi_host_template entries
+ */
+void bfad_im_itnim_unmap(struct bfad_im_port_s  *im_port,
+                        struct bfad_itnim_s *itnim);
+
+extern struct scsi_host_template bfad_im_scsi_host_template;
+extern struct scsi_host_template bfad_im_vport_template;
+extern struct fc_function_template bfad_im_fc_function_template;
+extern struct scsi_transport_template *bfad_im_scsi_transport_template;
+
+#endif
diff --git a/drivers/scsi/bfa/bfad_im_compat.h b/drivers/scsi/bfa/bfad_im_compat.h
new file mode 100644 (file)
index 0000000..1d3e74e
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ */
+
+#ifndef __BFAD_IM_COMPAT_H__
+#define __BFAD_IM_COMPAT_H__
+
+extern u32 *bfi_image_buf;
+extern u32 bfi_image_size;
+
+extern struct device_attribute *bfad_im_host_attrs[];
+extern struct device_attribute *bfad_im_vport_attrs[];
+
+u32 *bfad_get_firmware_buf(struct pci_dev *pdev);
+u32 *bfad_read_firmware(struct pci_dev *pdev, u32 **bfi_image,
+                       u32 *bfi_image_size, char *fw_name);
+
+static inline u32 *
+bfad_load_fwimg(struct pci_dev *pdev)
+{
+       return(bfad_get_firmware_buf(pdev));
+}
+
+static inline void
+bfad_free_fwimg(void)
+{
+       if (bfi_image_ct_size && bfi_image_ct)
+               vfree(bfi_image_ct);
+       if (bfi_image_cb_size && bfi_image_cb)
+               vfree(bfi_image_cb);
+}
+
+#endif
diff --git a/drivers/scsi/bfa/bfad_intr.c b/drivers/scsi/bfa/bfad_intr.c
new file mode 100644 (file)
index 0000000..f104e02
--- /dev/null
@@ -0,0 +1,214 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ */
+
+#include "bfad_drv.h"
+#include "bfad_trcmod.h"
+
+BFA_TRC_FILE(LDRV, INTR);
+
+/**
+ *  bfa_isr BFA driver interrupt functions
+ */
+irqreturn_t bfad_intx(int irq, void *dev_id);
+static int msix_disable;
+module_param(msix_disable, int, S_IRUGO | S_IWUSR);
+/**
+ * Line based interrupt handler.
+ */
+irqreturn_t
+bfad_intx(int irq, void *dev_id)
+{
+       struct bfad_s         *bfad = dev_id;
+       struct list_head         doneq;
+       unsigned long   flags;
+       bfa_boolean_t rc;
+
+       spin_lock_irqsave(&bfad->bfad_lock, flags);
+       rc = bfa_intx(&bfad->bfa);
+       if (!rc) {
+               spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+               return IRQ_NONE;
+       }
+
+       bfa_comp_deq(&bfad->bfa, &doneq);
+       spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+
+       if (!list_empty(&doneq)) {
+               bfa_comp_process(&bfad->bfa, &doneq);
+
+               spin_lock_irqsave(&bfad->bfad_lock, flags);
+               bfa_comp_free(&bfad->bfa, &doneq);
+               spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+               bfa_trc_fp(bfad, irq);
+       }
+
+       return IRQ_HANDLED;
+
+}
+
+static irqreturn_t
+bfad_msix(int irq, void *dev_id)
+{
+       struct bfad_msix_s *vec = dev_id;
+       struct bfad_s *bfad = vec->bfad;
+       struct list_head doneq;
+       unsigned long   flags;
+
+       spin_lock_irqsave(&bfad->bfad_lock, flags);
+
+       bfa_msix(&bfad->bfa, vec->msix.entry);
+       bfa_comp_deq(&bfad->bfa, &doneq);
+       spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+
+       if (!list_empty(&doneq)) {
+               bfa_comp_process(&bfad->bfa, &doneq);
+
+               spin_lock_irqsave(&bfad->bfad_lock, flags);
+               bfa_comp_free(&bfad->bfa, &doneq);
+               spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+       }
+
+       return IRQ_HANDLED;
+}
+
+/**
+ * Initialize the MSIX entry table.
+ */
+static void
+bfad_init_msix_entry(struct bfad_s *bfad, struct msix_entry *msix_entries,
+                        int mask, int max_bit)
+{
+       int             i;
+       int             match = 0x00000001;
+
+       for (i = 0, bfad->nvec = 0; i < MAX_MSIX_ENTRY; i++) {
+               if (mask & match) {
+                       bfad->msix_tab[bfad->nvec].msix.entry = i;
+                       bfad->msix_tab[bfad->nvec].bfad = bfad;
+                       msix_entries[bfad->nvec].entry = i;
+                       bfad->nvec++;
+               }
+
+               match <<= 1;
+       }
+
+}
+
+int
+bfad_install_msix_handler(struct bfad_s *bfad)
+{
+       int             i, error = 0;
+
+       for (i = 0; i < bfad->nvec; i++) {
+               error = request_irq(bfad->msix_tab[i].msix.vector,
+                                   (irq_handler_t) bfad_msix, 0,
+                                   BFAD_DRIVER_NAME, &bfad->msix_tab[i]);
+               bfa_trc(bfad, i);
+               bfa_trc(bfad, bfad->msix_tab[i].msix.vector);
+               if (error) {
+                       int             j;
+
+                       for (j = 0; j < i; j++)
+                               free_irq(bfad->msix_tab[j].msix.vector,
+                                               &bfad->msix_tab[j]);
+
+                       return 1;
+               }
+       }
+
+       return 0;
+}
+
+/**
+ * Setup MSIX based interrupt.
+ */
+int
+bfad_setup_intr(struct bfad_s *bfad)
+{
+       int error = 0;
+       u32 mask = 0, i, num_bit = 0, max_bit = 0;
+       struct msix_entry msix_entries[MAX_MSIX_ENTRY];
+
+       /* Call BFA to get the msix map for this PCI function.  */
+       bfa_msix_getvecs(&bfad->bfa, &mask, &num_bit, &max_bit);
+
+       /* Set up the msix entry table */
+       bfad_init_msix_entry(bfad, msix_entries, mask, max_bit);
+
+       if (!msix_disable) {
+               error = pci_enable_msix(bfad->pcidev, msix_entries, bfad->nvec);
+               if (error) {
+                       /*
+                        * Only error number of vector is available.
+                        * We don't have a mechanism to map multiple
+                        * interrupts into one vector, so even if we
+                        * can try to request less vectors, we don't
+                        * know how to associate interrupt events to
+                        *  vectors. Linux doesn't dupicate vectors
+                        * in the MSIX table for this case.
+                        */
+
+                       printk(KERN_WARNING "bfad%d: "
+                               "pci_enable_msix failed (%d),"
+                               " use line based.\n", bfad->inst_no, error);
+
+                       goto line_based;
+               }
+
+               /* Save the vectors */
+               for (i = 0; i < bfad->nvec; i++) {
+                       bfa_trc(bfad, msix_entries[i].vector);
+                       bfad->msix_tab[i].msix.vector = msix_entries[i].vector;
+               }
+
+               bfa_msix_init(&bfad->bfa, bfad->nvec);
+
+               bfad->bfad_flags |= BFAD_MSIX_ON;
+
+               return error;
+       }
+
+line_based:
+       error = 0;
+       if (request_irq
+           (bfad->pcidev->irq, (irq_handler_t) bfad_intx, BFAD_IRQ_FLAGS,
+            BFAD_DRIVER_NAME, bfad) != 0) {
+               /* Enable interrupt handler failed */
+               return 1;
+       }
+
+       return error;
+}
+
+void
+bfad_remove_intr(struct bfad_s *bfad)
+{
+       int             i;
+
+       if (bfad->bfad_flags & BFAD_MSIX_ON) {
+               for (i = 0; i < bfad->nvec; i++)
+                       free_irq(bfad->msix_tab[i].msix.vector,
+                                       &bfad->msix_tab[i]);
+
+               pci_disable_msix(bfad->pcidev);
+               bfad->bfad_flags &= ~BFAD_MSIX_ON;
+       } else {
+               free_irq(bfad->pcidev->irq, bfad);
+       }
+}
+
+
diff --git a/drivers/scsi/bfa/bfad_ipfc.h b/drivers/scsi/bfa/bfad_ipfc.h
new file mode 100644 (file)
index 0000000..718bc52
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ */
+#ifndef __BFA_DRV_IPFC_H__
+#define __BFA_DRV_IPFC_H__
+
+
+#define IPFC_NAME ""
+
+#define bfad_ipfc_module_init(x) do {} while (0)
+#define bfad_ipfc_module_exit(x) do {} while (0)
+#define bfad_ipfc_probe(x) do {} while (0)
+#define bfad_ipfc_probe_undo(x) do {} while (0)
+#define bfad_ipfc_port_config(x, y) BFA_STATUS_OK
+#define bfad_ipfc_port_unconfig(x, y) do {} while (0)
+
+#define bfad_ipfc_probe_post(x) do {} while (0)
+#define bfad_ipfc_port_new(x, y, z) BFA_STATUS_OK
+#define bfad_ipfc_port_delete(x, y) do {} while (0)
+#define bfad_ipfc_port_online(x, y) do {} while (0)
+#define bfad_ipfc_port_offline(x, y) do {} while (0)
+
+#define bfad_ip_get_attr(x) BFA_STATUS_FAILED
+#define bfad_ip_reset_drv_stats(x) BFA_STATUS_FAILED
+#define bfad_ip_get_drv_stats(x, y) BFA_STATUS_FAILED
+#define bfad_ip_enable_ipfc(x, y, z) BFA_STATUS_FAILED
+
+
+#endif
diff --git a/drivers/scsi/bfa/bfad_os.c b/drivers/scsi/bfa/bfad_os.c
new file mode 100644 (file)
index 0000000..faf47b4
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) 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.
+ */
+
+/**
+ *  bfad_os.c Linux driver OS specific calls.
+ */
+
+#include "bfa_os_inc.h"
+#include "bfad_drv.h"
+
+void
+bfa_os_gettimeofday(struct bfa_timeval_s *tv)
+{
+       struct timeval  tmp_tv;
+
+       do_gettimeofday(&tmp_tv);
+       tv->tv_sec = (u32) tmp_tv.tv_sec;
+       tv->tv_usec = (u32) tmp_tv.tv_usec;
+}
+
+void
+bfa_os_printf(struct bfa_log_mod_s *log_mod, u32 msg_id,
+                       const char *fmt, ...)
+{
+       va_list ap;
+       #define BFA_STRING_256  256
+       char tmp[BFA_STRING_256];
+
+       va_start(ap, fmt);
+       vsprintf(tmp, fmt, ap);
+       va_end(ap);
+
+       printk(tmp);
+}
+
+
diff --git a/drivers/scsi/bfa/bfad_tm.h b/drivers/scsi/bfa/bfad_tm.h
new file mode 100644 (file)
index 0000000..4901b1b
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) 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.
+ */
+
+/*
+ * Brocade Fibre Channel HBA Linux Target Mode Driver
+ */
+
+/**
+ *  tm/dummy/bfad_tm.h BFA callback dummy header file for BFA Linux target mode PCI interface module.
+ */
+
+#ifndef __BFAD_TM_H__
+#define __BFAD_TM_H__
+
+#include <defs/bfa_defs_status.h>
+
+#define FCPT_NAME              ""
+
+/*
+ * Called from base Linux driver on (De)Init events
+ */
+
+/* attach tgt template with scst */
+#define bfad_tm_module_init()  do {} while (0)
+
+/* detach/release tgt template */
+#define bfad_tm_module_exit()  do {} while (0)
+
+#define bfad_tm_probe(x)       do {} while (0)
+#define bfad_tm_probe_undo(x)  do {} while (0)
+#define bfad_tm_probe_post(x)  do {} while (0)
+
+/*
+ * Called by base Linux driver but triggered by BFA FCS on config events
+ */
+#define bfad_tm_port_new(x, y)         BFA_STATUS_OK
+#define bfad_tm_port_delete(x, y)      do {} while (0)
+
+/*
+ * Called by base Linux driver but triggered by BFA FCS on PLOGI/O events
+ */
+#define bfad_tm_port_online(x, y)      do {} while (0)
+#define bfad_tm_port_offline(x, y)     do {} while (0)
+
+#endif
diff --git a/drivers/scsi/bfa/bfad_trcmod.h b/drivers/scsi/bfa/bfad_trcmod.h
new file mode 100644 (file)
index 0000000..2827b2a
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) 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.
+ */
+
+/**
+ *  bfad_trcmod.h Linux driver trace modules
+ */
+
+
+#ifndef __BFAD_TRCMOD_H__
+#define __BFAD_TRCMOD_H__
+
+#include <cs/bfa_trc.h>
+
+/*
+ * !!! Only append to the enums defined here to avoid any versioning
+ * !!! needed between trace utility and driver version
+ */
+enum {
+       /* 2.6 Driver */
+       BFA_TRC_LDRV_BFAD               = 1,
+       BFA_TRC_LDRV_BFAD_2_6           = 2,
+       BFA_TRC_LDRV_BFAD_2_6_9         = 3,
+       BFA_TRC_LDRV_BFAD_2_6_10        = 4,
+       BFA_TRC_LDRV_INTR               = 5,
+       BFA_TRC_LDRV_IOCTL              = 6,
+       BFA_TRC_LDRV_OS                 = 7,
+       BFA_TRC_LDRV_IM                 = 8,
+       BFA_TRC_LDRV_IM_2_6             = 9,
+       BFA_TRC_LDRV_IM_2_6_9           = 10,
+       BFA_TRC_LDRV_IM_2_6_10          = 11,
+       BFA_TRC_LDRV_TM                 = 12,
+       BFA_TRC_LDRV_IPFC               = 13,
+       BFA_TRC_LDRV_IM_2_4             = 14,
+       BFA_TRC_LDRV_IM_VMW             = 15,
+       BFA_TRC_LDRV_IM_LT_2_6_10       = 16,
+};
+
+#endif /* __BFAD_TRCMOD_H__ */
diff --git a/drivers/scsi/bfa/fab.c b/drivers/scsi/bfa/fab.c
new file mode 100644 (file)
index 0000000..7e3a4d5
--- /dev/null
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ */
+
+#include <bfa.h>
+#include <bfa_svc.h>
+#include "fcs_lport.h"
+#include "fcs_rport.h"
+#include "lport_priv.h"
+
+/**
+ *  fab.c port fab implementation.
+ */
+
+/**
+ *  bfa_fcs_port_fab_public port fab public functions
+ */
+
+/**
+ *   Called by port to initialize fabric services of the base port.
+ */
+void
+bfa_fcs_port_fab_init(struct bfa_fcs_port_s *port)
+{
+       bfa_fcs_port_ns_init(port);
+       bfa_fcs_port_scn_init(port);
+       bfa_fcs_port_ms_init(port);
+}
+
+/**
+ *   Called by port to notify transition to online state.
+ */
+void
+bfa_fcs_port_fab_online(struct bfa_fcs_port_s *port)
+{
+       bfa_fcs_port_ns_online(port);
+       bfa_fcs_port_scn_online(port);
+}
+
+/**
+ *   Called by port to notify transition to offline state.
+ */
+void
+bfa_fcs_port_fab_offline(struct bfa_fcs_port_s *port)
+{
+       bfa_fcs_port_ns_offline(port);
+       bfa_fcs_port_scn_offline(port);
+       bfa_fcs_port_ms_offline(port);
+}
diff --git a/drivers/scsi/bfa/fabric.c b/drivers/scsi/bfa/fabric.c
new file mode 100644 (file)
index 0000000..a8b14c4
--- /dev/null
@@ -0,0 +1,1278 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) 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.
+ */
+
+/**
+ *  fabric.c Fabric module implementation.
+ */
+
+#include "fcs_fabric.h"
+#include "fcs_lport.h"
+#include "fcs_vport.h"
+#include "fcs_trcmod.h"
+#include "fcs_fcxp.h"
+#include "fcs_auth.h"
+#include "fcs.h"
+#include "fcbuild.h"
+#include <log/bfa_log_fcs.h>
+#include <aen/bfa_aen_port.h>
+#include <bfa_svc.h>
+
+BFA_TRC_FILE(FCS, FABRIC);
+
+#define BFA_FCS_FABRIC_RETRY_DELAY     (2000)  /* Milliseconds */
+#define BFA_FCS_FABRIC_CLEANUP_DELAY   (10000) /* Milliseconds */
+
+#define bfa_fcs_fabric_set_opertype(__fabric) do {          \
+    if (bfa_pport_get_topology((__fabric)->fcs->bfa)    \
+                               == BFA_PPORT_TOPOLOGY_P2P)   \
+           (__fabric)->oper_type = BFA_PPORT_TYPE_NPORT;       \
+    else                                                    \
+           (__fabric)->oper_type = BFA_PPORT_TYPE_NLPORT;      \
+} while (0)
+
+/*
+ * forward declarations
+ */
+static void     bfa_fcs_fabric_init(struct bfa_fcs_fabric_s *fabric);
+static void     bfa_fcs_fabric_login(struct bfa_fcs_fabric_s *fabric);
+static void     bfa_fcs_fabric_notify_online(struct bfa_fcs_fabric_s *fabric);
+static void     bfa_fcs_fabric_notify_offline(struct bfa_fcs_fabric_s *fabric);
+static void     bfa_fcs_fabric_delay(void *cbarg);
+static void     bfa_fcs_fabric_delete(struct bfa_fcs_fabric_s *fabric);
+static void     bfa_fcs_fabric_delete_comp(void *cbarg);
+static void     bfa_fcs_fabric_process_uf(struct bfa_fcs_fabric_s *fabric,
+                                         struct fchs_s *fchs, u16 len);
+static void     bfa_fcs_fabric_process_flogi(struct bfa_fcs_fabric_s *fabric,
+                                            struct fchs_s *fchs, u16 len);
+static void     bfa_fcs_fabric_send_flogi_acc(struct bfa_fcs_fabric_s *fabric);
+static void     bfa_fcs_fabric_flogiacc_comp(void *fcsarg,
+                                            struct bfa_fcxp_s *fcxp,
+                                            void *cbarg, bfa_status_t status,
+                                            u32 rsp_len,
+                                            u32 resid_len,
+                                            struct fchs_s *rspfchs);
+/**
+ *  fcs_fabric_sm fabric state machine functions
+ */
+
+/**
+ * Fabric state machine events
+ */
+enum bfa_fcs_fabric_event {
+       BFA_FCS_FABRIC_SM_CREATE = 1,   /*  fabric create from driver */
+       BFA_FCS_FABRIC_SM_DELETE = 2,   /*  fabric delete from driver */
+       BFA_FCS_FABRIC_SM_LINK_DOWN = 3,        /*  link down from port */
+       BFA_FCS_FABRIC_SM_LINK_UP = 4,  /*  link up from port */
+       BFA_FCS_FABRIC_SM_CONT_OP = 5,  /*  continue op from flogi/auth */
+       BFA_FCS_FABRIC_SM_RETRY_OP = 6, /*  continue op from flogi/auth */
+       BFA_FCS_FABRIC_SM_NO_FABRIC = 7,        /*  no fabric from flogi/auth
+                                                */
+       BFA_FCS_FABRIC_SM_PERF_EVFP = 8,        /*  perform EVFP from
+                                                *flogi/auth */
+       BFA_FCS_FABRIC_SM_ISOLATE = 9,  /*  isolate from EVFP processing */
+       BFA_FCS_FABRIC_SM_NO_TAGGING = 10,/*  no VFT tagging from EVFP */
+       BFA_FCS_FABRIC_SM_DELAYED = 11, /*  timeout delay event */
+       BFA_FCS_FABRIC_SM_AUTH_FAILED = 12,     /*  authentication failed */
+       BFA_FCS_FABRIC_SM_AUTH_SUCCESS = 13,    /*  authentication successful
+                                                */
+       BFA_FCS_FABRIC_SM_DELCOMP = 14, /*  all vports deleted event */
+       BFA_FCS_FABRIC_SM_LOOPBACK = 15,        /*  Received our own FLOGI */
+       BFA_FCS_FABRIC_SM_START = 16,   /*  fabric delete from driver */
+};
+
+static void     bfa_fcs_fabric_sm_uninit(struct bfa_fcs_fabric_s *fabric,
+                                        enum bfa_fcs_fabric_event event);
+static void     bfa_fcs_fabric_sm_created(struct bfa_fcs_fabric_s *fabric,
+                                         enum bfa_fcs_fabric_event event);
+static void     bfa_fcs_fabric_sm_linkdown(struct bfa_fcs_fabric_s *fabric,
+                                          enum bfa_fcs_fabric_event event);
+static void     bfa_fcs_fabric_sm_flogi(struct bfa_fcs_fabric_s *fabric,
+                                       enum bfa_fcs_fabric_event event);
+static void     bfa_fcs_fabric_sm_flogi_retry(struct bfa_fcs_fabric_s *fabric,
+                                             enum bfa_fcs_fabric_event event);
+static void     bfa_fcs_fabric_sm_auth(struct bfa_fcs_fabric_s *fabric,
+                                      enum bfa_fcs_fabric_event event);
+static void     bfa_fcs_fabric_sm_auth_failed(struct bfa_fcs_fabric_s *fabric,
+                                             enum bfa_fcs_fabric_event event);
+static void     bfa_fcs_fabric_sm_loopback(struct bfa_fcs_fabric_s *fabric,
+                                          enum bfa_fcs_fabric_event event);
+static void     bfa_fcs_fabric_sm_nofabric(struct bfa_fcs_fabric_s *fabric,
+                                          enum bfa_fcs_fabric_event event);
+static void     bfa_fcs_fabric_sm_online(struct bfa_fcs_fabric_s *fabric,
+                                        enum bfa_fcs_fabric_event event);
+static void     bfa_fcs_fabric_sm_evfp(struct bfa_fcs_fabric_s *fabric,
+                                      enum bfa_fcs_fabric_event event);
+static void     bfa_fcs_fabric_sm_evfp_done(struct bfa_fcs_fabric_s *fabric,
+                                           enum bfa_fcs_fabric_event event);
+static void     bfa_fcs_fabric_sm_isolated(struct bfa_fcs_fabric_s *fabric,
+                                          enum bfa_fcs_fabric_event event);
+static void     bfa_fcs_fabric_sm_deleting(struct bfa_fcs_fabric_s *fabric,
+                                          enum bfa_fcs_fabric_event event);
+/**
+ *   Beginning state before fabric creation.
+ */
+static void
+bfa_fcs_fabric_sm_uninit(struct bfa_fcs_fabric_s *fabric,
+                        enum bfa_fcs_fabric_event event)
+{
+       bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);
+       bfa_trc(fabric->fcs, event);
+
+       switch (event) {
+       case BFA_FCS_FABRIC_SM_CREATE:
+               bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_created);
+               bfa_fcs_fabric_init(fabric);
+               bfa_fcs_lport_init(&fabric->bport, fabric->fcs, FC_VF_ID_NULL,
+                                  &fabric->bport.port_cfg, NULL);
+               break;
+
+       case BFA_FCS_FABRIC_SM_LINK_UP:
+       case BFA_FCS_FABRIC_SM_LINK_DOWN:
+               break;
+
+       default:
+               bfa_sm_fault(fabric->fcs, event);
+       }
+}
+
+/**
+ *   Beginning state before fabric creation.
+ */
+static void
+bfa_fcs_fabric_sm_created(struct bfa_fcs_fabric_s *fabric,
+                         enum bfa_fcs_fabric_event event)
+{
+       bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);
+       bfa_trc(fabric->fcs, event);
+
+       switch (event) {
+       case BFA_FCS_FABRIC_SM_START:
+               if (bfa_pport_is_linkup(fabric->fcs->bfa)) {
+                       bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_flogi);
+                       bfa_fcs_fabric_login(fabric);
+               } else
+                       bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_linkdown);
+               break;
+
+       case BFA_FCS_FABRIC_SM_LINK_UP:
+       case BFA_FCS_FABRIC_SM_LINK_DOWN:
+               break;
+
+       case BFA_FCS_FABRIC_SM_DELETE:
+               bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_uninit);
+               bfa_fcs_modexit_comp(fabric->fcs);
+               break;
+
+       default:
+               bfa_sm_fault(fabric->fcs, event);
+       }
+}
+
+/**
+ *   Link is down, awaiting LINK UP event from port. This is also the
+ *   first state at fabric creation.
+ */
+static void
+bfa_fcs_fabric_sm_linkdown(struct bfa_fcs_fabric_s *fabric,
+                          enum bfa_fcs_fabric_event event)
+{
+       bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);
+       bfa_trc(fabric->fcs, event);
+
+       switch (event) {
+       case BFA_FCS_FABRIC_SM_LINK_UP:
+               bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_flogi);
+               bfa_fcs_fabric_login(fabric);
+               break;
+
+       case BFA_FCS_FABRIC_SM_RETRY_OP:
+               break;
+
+       case BFA_FCS_FABRIC_SM_DELETE:
+               bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_deleting);
+               bfa_fcs_fabric_delete(fabric);
+               break;
+
+       default:
+               bfa_sm_fault(fabric->fcs, event);
+       }
+}
+
+/**
+ *   FLOGI is in progress, awaiting FLOGI reply.
+ */
+static void
+bfa_fcs_fabric_sm_flogi(struct bfa_fcs_fabric_s *fabric,
+                       enum bfa_fcs_fabric_event event)
+{
+       bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);
+       bfa_trc(fabric->fcs, event);
+
+       switch (event) {
+       case BFA_FCS_FABRIC_SM_CONT_OP:
+
+               bfa_pport_set_tx_bbcredit(fabric->fcs->bfa, fabric->bb_credit);
+               fabric->fab_type = BFA_FCS_FABRIC_SWITCHED;
+
+               if (fabric->auth_reqd && fabric->is_auth) {
+                       bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_auth);
+                       bfa_trc(fabric->fcs, event);
+               } else {
+                       bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_online);
+                       bfa_fcs_fabric_notify_online(fabric);
+               }
+               break;
+
+       case BFA_FCS_FABRIC_SM_RETRY_OP:
+               bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_flogi_retry);
+               bfa_timer_start(fabric->fcs->bfa, &fabric->delay_timer,
+                               bfa_fcs_fabric_delay, fabric,
+                               BFA_FCS_FABRIC_RETRY_DELAY);
+               break;
+
+       case BFA_FCS_FABRIC_SM_LOOPBACK:
+               bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_loopback);
+               bfa_lps_discard(fabric->lps);
+               bfa_fcs_fabric_set_opertype(fabric);
+               break;
+
+       case BFA_FCS_FABRIC_SM_NO_FABRIC:
+               fabric->fab_type = BFA_FCS_FABRIC_N2N;
+               bfa_pport_set_tx_bbcredit(fabric->fcs->bfa, fabric->bb_credit);
+               bfa_fcs_fabric_notify_online(fabric);
+               bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_nofabric);
+               break;
+
+       case BFA_FCS_FABRIC_SM_LINK_DOWN:
+               bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_linkdown);
+               bfa_lps_discard(fabric->lps);
+               break;
+
+       case BFA_FCS_FABRIC_SM_DELETE:
+               bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_deleting);
+               bfa_lps_discard(fabric->lps);
+               bfa_fcs_fabric_delete(fabric);
+               break;
+
+       default:
+               bfa_sm_fault(fabric->fcs, event);
+       }
+}
+
+
+static void
+bfa_fcs_fabric_sm_flogi_retry(struct bfa_fcs_fabric_s *fabric,
+                             enum bfa_fcs_fabric_event event)
+{
+       bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);
+       bfa_trc(fabric->fcs, event);
+
+       switch (event) {
+       case BFA_FCS_FABRIC_SM_DELAYED:
+               bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_flogi);
+               bfa_fcs_fabric_login(fabric);
+               break;
+
+       case BFA_FCS_FABRIC_SM_LINK_DOWN:
+               bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_linkdown);
+               bfa_timer_stop(&fabric->delay_timer);
+               break;
+
+       case BFA_FCS_FABRIC_SM_DELETE:
+               bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_deleting);
+               bfa_timer_stop(&fabric->delay_timer);
+               bfa_fcs_fabric_delete(fabric);
+               break;
+
+       default:
+               bfa_sm_fault(fabric->fcs, event);
+       }
+}
+
+/**
+ *   Authentication is in progress, awaiting authentication results.
+ */
+static void
+bfa_fcs_fabric_sm_auth(struct bfa_fcs_fabric_s *fabric,
+                      enum bfa_fcs_fabric_event event)
+{
+       bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);
+       bfa_trc(fabric->fcs, event);
+
+       switch (event) {
+       case BFA_FCS_FABRIC_SM_AUTH_FAILED:
+               bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_auth_failed);
+               bfa_lps_discard(fabric->lps);
+               break;
+
+       case BFA_FCS_FABRIC_SM_AUTH_SUCCESS:
+               bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_online);
+               bfa_fcs_fabric_notify_online(fabric);
+               break;
+
+       case BFA_FCS_FABRIC_SM_PERF_EVFP:
+               bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_evfp);
+               break;
+
+       case BFA_FCS_FABRIC_SM_LINK_DOWN:
+               bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_linkdown);
+               bfa_lps_discard(fabric->lps);
+               break;
+
+       case BFA_FCS_FABRIC_SM_DELETE:
+               bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_deleting);
+               bfa_fcs_fabric_delete(fabric);
+               break;
+
+       default:
+               bfa_sm_fault(fabric->fcs, event);
+       }
+}
+
+/**
+ *   Authentication failed
+ */
+static void
+bfa_fcs_fabric_sm_auth_failed(struct bfa_fcs_fabric_s *fabric,
+                             enum bfa_fcs_fabric_event event)
+{
+       bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);
+       bfa_trc(fabric->fcs, event);
+
+       switch (event) {
+       case BFA_FCS_FABRIC_SM_LINK_DOWN:
+               bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_linkdown);
+               bfa_fcs_fabric_notify_offline(fabric);
+               break;
+
+       case BFA_FCS_FABRIC_SM_DELETE:
+               bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_deleting);
+               bfa_fcs_fabric_delete(fabric);
+               break;
+
+       default:
+               bfa_sm_fault(fabric->fcs, event);
+       }
+}
+
+/**
+ *   Port is in loopback mode.
+ */
+static void
+bfa_fcs_fabric_sm_loopback(struct bfa_fcs_fabric_s *fabric,
+                          enum bfa_fcs_fabric_event event)
+{
+       bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);
+       bfa_trc(fabric->fcs, event);
+
+       switch (event) {
+       case BFA_FCS_FABRIC_SM_LINK_DOWN:
+               bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_linkdown);
+               bfa_fcs_fabric_notify_offline(fabric);
+               break;
+
+       case BFA_FCS_FABRIC_SM_DELETE:
+               bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_deleting);
+               bfa_fcs_fabric_delete(fabric);
+               break;
+
+       default:
+               bfa_sm_fault(fabric->fcs, event);
+       }
+}
+
+/**
+ *   There is no attached fabric - private loop or NPort-to-NPort topology.
+ */
+static void
+bfa_fcs_fabric_sm_nofabric(struct bfa_fcs_fabric_s *fabric,
+                          enum bfa_fcs_fabric_event event)
+{
+       bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);
+       bfa_trc(fabric->fcs, event);
+
+       switch (event) {
+       case BFA_FCS_FABRIC_SM_LINK_DOWN:
+               bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_linkdown);
+               bfa_lps_discard(fabric->lps);
+               bfa_fcs_fabric_notify_offline(fabric);
+               break;
+
+       case BFA_FCS_FABRIC_SM_DELETE:
+               bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_deleting);
+               bfa_fcs_fabric_delete(fabric);
+               break;
+
+       case BFA_FCS_FABRIC_SM_NO_FABRIC:
+               bfa_trc(fabric->fcs, fabric->bb_credit);
+               bfa_pport_set_tx_bbcredit(fabric->fcs->bfa, fabric->bb_credit);
+               break;
+
+       default:
+               bfa_sm_fault(fabric->fcs, event);
+       }
+}
+
+/**
+ *   Fabric is online - normal operating state.
+ */
+static void
+bfa_fcs_fabric_sm_online(struct bfa_fcs_fabric_s *fabric,
+                        enum bfa_fcs_fabric_event event)
+{
+       bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);
+       bfa_trc(fabric->fcs, event);
+
+       switch (event) {
+       case BFA_FCS_FABRIC_SM_LINK_DOWN:
+               bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_linkdown);
+               bfa_lps_discard(fabric->lps);
+               bfa_fcs_fabric_notify_offline(fabric);
+               break;
+
+       case BFA_FCS_FABRIC_SM_DELETE:
+               bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_deleting);
+               bfa_fcs_fabric_delete(fabric);
+               break;
+
+       case BFA_FCS_FABRIC_SM_AUTH_FAILED:
+               bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_auth_failed);
+               bfa_lps_discard(fabric->lps);
+               break;
+
+       case BFA_FCS_FABRIC_SM_AUTH_SUCCESS:
+               break;
+
+       default:
+               bfa_sm_fault(fabric->fcs, event);
+       }
+}
+
+/**
+ *   Exchanging virtual fabric parameters.
+ */
+static void
+bfa_fcs_fabric_sm_evfp(struct bfa_fcs_fabric_s *fabric,
+                      enum bfa_fcs_fabric_event event)
+{
+       bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);
+       bfa_trc(fabric->fcs, event);
+
+       switch (event) {
+       case BFA_FCS_FABRIC_SM_CONT_OP:
+               bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_evfp_done);
+               break;
+
+       case BFA_FCS_FABRIC_SM_ISOLATE:
+               bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_isolated);
+               break;
+
+       default:
+               bfa_sm_fault(fabric->fcs, event);
+       }
+}
+
+/**
+ *   EVFP exchange complete and VFT tagging is enabled.
+ */
+static void
+bfa_fcs_fabric_sm_evfp_done(struct bfa_fcs_fabric_s *fabric,
+                           enum bfa_fcs_fabric_event event)
+{
+       bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);
+       bfa_trc(fabric->fcs, event);
+}
+
+/**
+ *   Port is isolated after EVFP exchange due to VF_ID mismatch (N and F).
+ */
+static void
+bfa_fcs_fabric_sm_isolated(struct bfa_fcs_fabric_s *fabric,
+                          enum bfa_fcs_fabric_event event)
+{
+       bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);
+       bfa_trc(fabric->fcs, event);
+
+       bfa_log(fabric->fcs->logm, BFA_LOG_FCS_FABRIC_ISOLATED,
+               fabric->bport.port_cfg.pwwn, fabric->fcs->port_vfid,
+               fabric->event_arg.swp_vfid);
+}
+
+/**
+ *   Fabric is being deleted, awaiting vport delete completions.
+ */
+static void
+bfa_fcs_fabric_sm_deleting(struct bfa_fcs_fabric_s *fabric,
+                          enum bfa_fcs_fabric_event event)
+{
+       bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);
+       bfa_trc(fabric->fcs, event);
+
+       switch (event) {
+       case BFA_FCS_FABRIC_SM_DELCOMP:
+               bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_uninit);
+               bfa_fcs_modexit_comp(fabric->fcs);
+               break;
+
+       case BFA_FCS_FABRIC_SM_LINK_UP:
+               break;
+
+       case BFA_FCS_FABRIC_SM_LINK_DOWN:
+               bfa_fcs_fabric_notify_offline(fabric);
+               break;
+
+       default:
+               bfa_sm_fault(fabric->fcs, event);
+       }
+}
+
+
+
+/**
+ *  fcs_fabric_private fabric private functions
+ */
+
+static void
+bfa_fcs_fabric_init(struct bfa_fcs_fabric_s *fabric)
+{
+       struct bfa_port_cfg_s *port_cfg = &fabric->bport.port_cfg;
+
+       port_cfg->roles = BFA_PORT_ROLE_FCP_IM;
+       port_cfg->nwwn = bfa_ioc_get_nwwn(&fabric->fcs->bfa->ioc);
+       port_cfg->pwwn = bfa_ioc_get_pwwn(&fabric->fcs->bfa->ioc);
+}
+
+/**
+ * Port Symbolic Name Creation for base port.
+ */
+void
+bfa_fcs_fabric_psymb_init(struct bfa_fcs_fabric_s *fabric)
+{
+       struct bfa_port_cfg_s *port_cfg = &fabric->bport.port_cfg;
+       struct bfa_adapter_attr_s adapter_attr;
+       struct bfa_fcs_driver_info_s *driver_info = &fabric->fcs->driver_info;
+
+       bfa_os_memset((void *)&adapter_attr, 0,
+                     sizeof(struct bfa_adapter_attr_s));
+       bfa_ioc_get_adapter_attr(&fabric->fcs->bfa->ioc, &adapter_attr);
+
+       /*
+        * Model name/number
+        */
+       strncpy((char *)&port_cfg->sym_name, adapter_attr.model,
+               BFA_FCS_PORT_SYMBNAME_MODEL_SZ);
+       strncat((char *)&port_cfg->sym_name, BFA_FCS_PORT_SYMBNAME_SEPARATOR,
+               sizeof(BFA_FCS_PORT_SYMBNAME_SEPARATOR));
+
+       /*
+        * Driver Version
+        */
+       strncat((char *)&port_cfg->sym_name, (char *)driver_info->version,
+               BFA_FCS_PORT_SYMBNAME_VERSION_SZ);
+       strncat((char *)&port_cfg->sym_name, BFA_FCS_PORT_SYMBNAME_SEPARATOR,
+               sizeof(BFA_FCS_PORT_SYMBNAME_SEPARATOR));
+
+       /*
+        * Host machine name
+        */
+       strncat((char *)&port_cfg->sym_name,
+               (char *)driver_info->host_machine_name,
+               BFA_FCS_PORT_SYMBNAME_MACHINENAME_SZ);
+       strncat((char *)&port_cfg->sym_name, BFA_FCS_PORT_SYMBNAME_SEPARATOR,
+               sizeof(BFA_FCS_PORT_SYMBNAME_SEPARATOR));
+
+       /*
+        * Host OS Info :
+        * If OS Patch Info is not there, do not truncate any bytes from the
+        * OS name string and instead copy the entire OS info string (64 bytes).
+        */
+       if (driver_info->host_os_patch[0] == '\0') {
+               strncat((char *)&port_cfg->sym_name,
+                       (char *)driver_info->host_os_name, BFA_FCS_OS_STR_LEN);
+               strncat((char *)&port_cfg->sym_name,
+                       BFA_FCS_PORT_SYMBNAME_SEPARATOR,
+                       sizeof(BFA_FCS_PORT_SYMBNAME_SEPARATOR));
+       } else {
+               strncat((char *)&port_cfg->sym_name,
+                       (char *)driver_info->host_os_name,
+                       BFA_FCS_PORT_SYMBNAME_OSINFO_SZ);
+               strncat((char *)&port_cfg->sym_name,
+                       BFA_FCS_PORT_SYMBNAME_SEPARATOR,
+                       sizeof(BFA_FCS_PORT_SYMBNAME_SEPARATOR));
+
+               /*
+                * Append host OS Patch Info
+                */
+               strncat((char *)&port_cfg->sym_name,
+                       (char *)driver_info->host_os_patch,
+                       BFA_FCS_PORT_SYMBNAME_OSPATCH_SZ);
+       }
+
+       /*
+        * null terminate
+        */
+       port_cfg->sym_name.symname[BFA_SYMNAME_MAXLEN - 1] = 0;
+}
+
+/**
+ * bfa lps login completion callback
+ */
+void
+bfa_cb_lps_flogi_comp(void *bfad, void *uarg, bfa_status_t status)
+{
+       struct bfa_fcs_fabric_s *fabric = uarg;
+
+       bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);
+       bfa_trc(fabric->fcs, status);
+
+       switch (status) {
+       case BFA_STATUS_OK:
+               fabric->stats.flogi_accepts++;
+               break;
+
+       case BFA_STATUS_INVALID_MAC:
+               /*
+                * Only for CNA
+                */
+               fabric->stats.flogi_acc_err++;
+               bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_RETRY_OP);
+
+               return;
+
+       case BFA_STATUS_EPROTOCOL:
+               switch (bfa_lps_get_extstatus(fabric->lps)) {
+               case BFA_EPROTO_BAD_ACCEPT:
+                       fabric->stats.flogi_acc_err++;
+                       break;
+
+               case BFA_EPROTO_UNKNOWN_RSP:
+                       fabric->stats.flogi_unknown_rsp++;
+                       break;
+
+               default:
+                       break;
+               }
+               bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_RETRY_OP);
+
+               return;
+
+       case BFA_STATUS_FABRIC_RJT:
+               fabric->stats.flogi_rejects++;
+               bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_RETRY_OP);
+               return;
+
+       default:
+               fabric->stats.flogi_rsp_err++;
+               bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_RETRY_OP);
+               return;
+       }
+
+       fabric->bb_credit = bfa_lps_get_peer_bbcredit(fabric->lps);
+       bfa_trc(fabric->fcs, fabric->bb_credit);
+
+       if (!bfa_lps_is_brcd_fabric(fabric->lps))
+               fabric->fabric_name = bfa_lps_get_peer_nwwn(fabric->lps);
+
+       /*
+        * Check port type. It should be 1 = F-port.
+        */
+       if (bfa_lps_is_fport(fabric->lps)) {
+               fabric->bport.pid = bfa_lps_get_pid(fabric->lps);
+               fabric->is_npiv = bfa_lps_is_npiv_en(fabric->lps);
+               fabric->is_auth = bfa_lps_is_authreq(fabric->lps);
+               bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_CONT_OP);
+       } else {
+               /*
+                * Nport-2-Nport direct attached
+                */
+               fabric->bport.port_topo.pn2n.rem_port_wwn =
+                       bfa_lps_get_peer_pwwn(fabric->lps);
+               bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_NO_FABRIC);
+       }
+
+       bfa_trc(fabric->fcs, fabric->bport.pid);
+       bfa_trc(fabric->fcs, fabric->is_npiv);
+       bfa_trc(fabric->fcs, fabric->is_auth);
+}
+
+/**
+ *             Allocate and send FLOGI.
+ */
+static void
+bfa_fcs_fabric_login(struct bfa_fcs_fabric_s *fabric)
+{
+       struct bfa_s   *bfa = fabric->fcs->bfa;
+       struct bfa_port_cfg_s *pcfg = &fabric->bport.port_cfg;
+       u8         alpa = 0;
+
+       if (bfa_pport_get_topology(bfa) == BFA_PPORT_TOPOLOGY_LOOP)
+               alpa = bfa_pport_get_myalpa(bfa);
+
+       bfa_lps_flogi(fabric->lps, fabric, alpa, bfa_pport_get_maxfrsize(bfa),
+                     pcfg->pwwn, pcfg->nwwn, fabric->auth_reqd);
+
+       fabric->stats.flogi_sent++;
+}
+
+static void
+bfa_fcs_fabric_notify_online(struct bfa_fcs_fabric_s *fabric)
+{
+       struct bfa_fcs_vport_s *vport;
+       struct list_head *qe, *qen;
+
+       bfa_trc(fabric->fcs, fabric->fabric_name);
+
+       bfa_fcs_fabric_set_opertype(fabric);
+       fabric->stats.fabric_onlines++;
+
+       /**
+        * notify online event to base and then virtual ports
+        */
+       bfa_fcs_port_online(&fabric->bport);
+
+       list_for_each_safe(qe, qen, &fabric->vport_q) {
+               vport = (struct bfa_fcs_vport_s *)qe;
+               bfa_fcs_vport_online(vport);
+       }
+}
+
+static void
+bfa_fcs_fabric_notify_offline(struct bfa_fcs_fabric_s *fabric)
+{
+       struct bfa_fcs_vport_s *vport;
+       struct list_head *qe, *qen;
+
+       bfa_trc(fabric->fcs, fabric->fabric_name);
+       fabric->stats.fabric_offlines++;
+
+       /**
+        * notify offline event first to vports and then base port.
+        */
+       list_for_each_safe(qe, qen, &fabric->vport_q) {
+               vport = (struct bfa_fcs_vport_s *)qe;
+               bfa_fcs_vport_offline(vport);
+       }
+
+       bfa_fcs_port_offline(&fabric->bport);
+
+       fabric->fabric_name = 0;
+       fabric->fabric_ip_addr[0] = 0;
+}
+
+static void
+bfa_fcs_fabric_delay(void *cbarg)
+{
+       struct bfa_fcs_fabric_s *fabric = cbarg;
+
+       bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_DELAYED);
+}
+
+/**
+ * Delete all vports and wait for vport delete completions.
+ */
+static void
+bfa_fcs_fabric_delete(struct bfa_fcs_fabric_s *fabric)
+{
+       struct bfa_fcs_vport_s *vport;
+       struct list_head *qe, *qen;
+
+       list_for_each_safe(qe, qen, &fabric->vport_q) {
+               vport = (struct bfa_fcs_vport_s *)qe;
+               bfa_fcs_vport_delete(vport);
+       }
+
+       bfa_fcs_port_delete(&fabric->bport);
+       bfa_wc_wait(&fabric->wc);
+}
+
+static void
+bfa_fcs_fabric_delete_comp(void *cbarg)
+{
+       struct bfa_fcs_fabric_s *fabric = cbarg;
+
+       bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_DELCOMP);
+}
+
+
+
+/**
+ *  fcs_fabric_public fabric public functions
+ */
+
+/**
+ *   Module initialization
+ */
+void
+bfa_fcs_fabric_modinit(struct bfa_fcs_s *fcs)
+{
+       struct bfa_fcs_fabric_s *fabric;
+
+       fabric = &fcs->fabric;
+       bfa_os_memset(fabric, 0, sizeof(struct bfa_fcs_fabric_s));
+
+       /**
+        * Initialize base fabric.
+        */
+       fabric->fcs = fcs;
+       INIT_LIST_HEAD(&fabric->vport_q);
+       INIT_LIST_HEAD(&fabric->vf_q);
+       fabric->lps = bfa_lps_alloc(fcs->bfa);
+       bfa_assert(fabric->lps);
+
+       /**
+        * Initialize fabric delete completion handler. Fabric deletion is complete
+        * when the last vport delete is complete.
+        */
+       bfa_wc_init(&fabric->wc, bfa_fcs_fabric_delete_comp, fabric);
+       bfa_wc_up(&fabric->wc); /* For the base port */
+
+       bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_uninit);
+       bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_CREATE);
+       bfa_trc(fcs, 0);
+}
+
+/**
+ *   Module cleanup
+ */
+void
+bfa_fcs_fabric_modexit(struct bfa_fcs_s *fcs)
+{
+       struct bfa_fcs_fabric_s *fabric;
+
+       bfa_trc(fcs, 0);
+
+       /**
+        * Cleanup base fabric.
+        */
+       fabric = &fcs->fabric;
+       bfa_lps_delete(fabric->lps);
+       bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_DELETE);
+}
+
+/**
+ * Fabric module start -- kick starts FCS actions
+ */
+void
+bfa_fcs_fabric_modstart(struct bfa_fcs_s *fcs)
+{
+       struct bfa_fcs_fabric_s *fabric;
+
+       bfa_trc(fcs, 0);
+       fabric = &fcs->fabric;
+       bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_START);
+}
+
+/**
+ *   Suspend fabric activity as part of driver suspend.
+ */
+void
+bfa_fcs_fabric_modsusp(struct bfa_fcs_s *fcs)
+{
+}
+
+bfa_boolean_t
+bfa_fcs_fabric_is_loopback(struct bfa_fcs_fabric_s *fabric)
+{
+       return (bfa_sm_cmp_state(fabric, bfa_fcs_fabric_sm_loopback));
+}
+
+enum bfa_pport_type
+bfa_fcs_fabric_port_type(struct bfa_fcs_fabric_s *fabric)
+{
+       return fabric->oper_type;
+}
+
+/**
+ *   Link up notification from BFA physical port module.
+ */
+void
+bfa_fcs_fabric_link_up(struct bfa_fcs_fabric_s *fabric)
+{
+       bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);
+       bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_LINK_UP);
+}
+
+/**
+ *   Link down notification from BFA physical port module.
+ */
+void
+bfa_fcs_fabric_link_down(struct bfa_fcs_fabric_s *fabric)
+{
+       bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);
+       bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_LINK_DOWN);
+}
+
+/**
+ *   A child vport is being created in the fabric.
+ *
+ *   Call from vport module at vport creation. A list of base port and vports
+ *   belonging to a fabric is maintained to propagate link events.
+ *
+ *   param[in] fabric - Fabric instance. This can be a base fabric or vf.
+ *   param[in] vport  - Vport being created.
+ *
+ *   @return None (always succeeds)
+ */
+void
+bfa_fcs_fabric_addvport(struct bfa_fcs_fabric_s *fabric,
+                       struct bfa_fcs_vport_s *vport)
+{
+       /**
+        * - add vport to fabric's vport_q
+        */
+       bfa_trc(fabric->fcs, fabric->vf_id);
+
+       list_add_tail(&vport->qe, &fabric->vport_q);
+       fabric->num_vports++;
+       bfa_wc_up(&fabric->wc);
+}
+
+/**
+ *   A child vport is being deleted from fabric.
+ *
+ *   Vport is being deleted.
+ */
+void
+bfa_fcs_fabric_delvport(struct bfa_fcs_fabric_s *fabric,
+                       struct bfa_fcs_vport_s *vport)
+{
+       list_del(&vport->qe);
+       fabric->num_vports--;
+       bfa_wc_down(&fabric->wc);
+}
+
+/**
+ *   Base port is deleted.
+ */
+void
+bfa_fcs_fabric_port_delete_comp(struct bfa_fcs_fabric_s *fabric)
+{
+       bfa_wc_down(&fabric->wc);
+}
+
+/**
+ *    Check if fabric is online.
+ *
+ *   param[in] fabric - Fabric instance. This can be a base fabric or vf.
+ *
+ *   @return  TRUE/FALSE
+ */
+int
+bfa_fcs_fabric_is_online(struct bfa_fcs_fabric_s *fabric)
+{
+       return (bfa_sm_cmp_state(fabric, bfa_fcs_fabric_sm_online));
+}
+
+
+bfa_status_t
+bfa_fcs_fabric_addvf(struct bfa_fcs_fabric_s *vf, struct bfa_fcs_s *fcs,
+                    struct bfa_port_cfg_s *port_cfg,
+                    struct bfad_vf_s *vf_drv)
+{
+       bfa_sm_set_state(vf, bfa_fcs_fabric_sm_uninit);
+       return BFA_STATUS_OK;
+}
+
+/**
+ * Lookup for a vport withing a fabric given its pwwn
+ */
+struct bfa_fcs_vport_s *
+bfa_fcs_fabric_vport_lookup(struct bfa_fcs_fabric_s *fabric, wwn_t pwwn)
+{
+       struct bfa_fcs_vport_s *vport;
+       struct list_head *qe;
+
+       list_for_each(qe, &fabric->vport_q) {
+               vport = (struct bfa_fcs_vport_s *)qe;
+               if (bfa_fcs_port_get_pwwn(&vport->lport) == pwwn)
+                       return vport;
+       }
+
+       return NULL;
+}
+
+/**
+ *    In a given fabric, return the number of lports.
+ *
+ *   param[in] fabric - Fabric instance. This can be a base fabric or vf.
+ *
+*    @return : 1 or more.
+ */
+u16
+bfa_fcs_fabric_vport_count(struct bfa_fcs_fabric_s *fabric)
+{
+       return (fabric->num_vports);
+}
+
+/**
+ *             Unsolicited frame receive handling.
+ */
+void
+bfa_fcs_fabric_uf_recv(struct bfa_fcs_fabric_s *fabric, struct fchs_s *fchs,
+                      u16 len)
+{
+       u32        pid = fchs->d_id;
+       struct bfa_fcs_vport_s *vport;
+       struct list_head *qe;
+       struct fc_els_cmd_s   *els_cmd = (struct fc_els_cmd_s *) (fchs + 1);
+       struct fc_logi_s     *flogi = (struct fc_logi_s *) els_cmd;
+
+       bfa_trc(fabric->fcs, len);
+       bfa_trc(fabric->fcs, pid);
+
+       /**
+        * Look for our own FLOGI frames being looped back. This means an
+        * external loopback cable is in place. Our own FLOGI frames are
+        * sometimes looped back when switch port gets temporarily bypassed.
+        */
+       if ((pid == bfa_os_ntoh3b(FC_FABRIC_PORT))
+           && (els_cmd->els_code == FC_ELS_FLOGI)
+           && (flogi->port_name == bfa_fcs_port_get_pwwn(&fabric->bport))) {
+               bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_LOOPBACK);
+               return;
+       }
+
+       /**
+        * FLOGI/EVFP exchanges should be consumed by base fabric.
+        */
+       if (fchs->d_id == bfa_os_hton3b(FC_FABRIC_PORT)) {
+               bfa_trc(fabric->fcs, pid);
+               bfa_fcs_fabric_process_uf(fabric, fchs, len);
+               return;
+       }
+
+       if (fabric->bport.pid == pid) {
+               /**
+                * All authentication frames should be routed to auth
+                */
+               bfa_trc(fabric->fcs, els_cmd->els_code);
+               if (els_cmd->els_code == FC_ELS_AUTH) {
+                       bfa_trc(fabric->fcs, els_cmd->els_code);
+                       fabric->auth.response = (u8 *) els_cmd;
+                       return;
+               }
+
+               bfa_trc(fabric->fcs, *(u8 *) ((u8 *) fchs));
+               bfa_fcs_port_uf_recv(&fabric->bport, fchs, len);
+               return;
+       }
+
+       /**
+        * look for a matching local port ID
+        */
+       list_for_each(qe, &fabric->vport_q) {
+               vport = (struct bfa_fcs_vport_s *)qe;
+               if (vport->lport.pid == pid) {
+                       bfa_fcs_port_uf_recv(&vport->lport, fchs, len);
+                       return;
+               }
+       }
+       bfa_trc(fabric->fcs, els_cmd->els_code);
+       bfa_fcs_port_uf_recv(&fabric->bport, fchs, len);
+}
+
+/**
+ *             Unsolicited frames to be processed by fabric.
+ */
+static void
+bfa_fcs_fabric_process_uf(struct bfa_fcs_fabric_s *fabric, struct fchs_s *fchs,
+                         u16 len)
+{
+       struct fc_els_cmd_s   *els_cmd = (struct fc_els_cmd_s *) (fchs + 1);
+
+       bfa_trc(fabric->fcs, els_cmd->els_code);
+
+       switch (els_cmd->els_code) {
+       case FC_ELS_FLOGI:
+               bfa_fcs_fabric_process_flogi(fabric, fchs, len);
+               break;
+
+       default:
+               /*
+                * need to generate a LS_RJT
+                */
+               break;
+       }
+}
+
+/**
+ *     Process incoming FLOGI
+ */
+static void
+bfa_fcs_fabric_process_flogi(struct bfa_fcs_fabric_s *fabric,
+                       struct fchs_s *fchs, u16 len)
+{
+       struct fc_logi_s     *flogi = (struct fc_logi_s *) (fchs + 1);
+       struct bfa_fcs_port_s *bport = &fabric->bport;
+
+       bfa_trc(fabric->fcs, fchs->s_id);
+
+       fabric->stats.flogi_rcvd++;
+       /*
+        * Check port type. It should be 0 = n-port.
+        */
+       if (flogi->csp.port_type) {
+               /*
+                * @todo: may need to send a LS_RJT
+                */
+               bfa_trc(fabric->fcs, flogi->port_name);
+               fabric->stats.flogi_rejected++;
+               return;
+       }
+
+       fabric->bb_credit = bfa_os_ntohs(flogi->csp.bbcred);
+       bport->port_topo.pn2n.rem_port_wwn = flogi->port_name;
+       bport->port_topo.pn2n.reply_oxid = fchs->ox_id;
+
+       /*
+        * Send a Flogi Acc
+        */
+       bfa_fcs_fabric_send_flogi_acc(fabric);
+       bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_NO_FABRIC);
+}
+
+static void
+bfa_fcs_fabric_send_flogi_acc(struct bfa_fcs_fabric_s *fabric)
+{
+       struct bfa_port_cfg_s *pcfg = &fabric->bport.port_cfg;
+       struct bfa_fcs_port_n2n_s *n2n_port = &fabric->bport.port_topo.pn2n;
+       struct bfa_s   *bfa = fabric->fcs->bfa;
+       struct bfa_fcxp_s *fcxp;
+       u16        reqlen;
+       struct fchs_s          fchs;
+
+       fcxp = bfa_fcs_fcxp_alloc(fabric->fcs);
+       /**
+        * Do not expect this failure -- expect remote node to retry
+        */
+       if (!fcxp)
+               return;
+
+       reqlen = fc_flogi_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
+                                   bfa_os_hton3b(FC_FABRIC_PORT),
+                                   n2n_port->reply_oxid, pcfg->pwwn,
+                                   pcfg->nwwn, bfa_pport_get_maxfrsize(bfa),
+                                   bfa_pport_get_rx_bbcredit(bfa));
+
+       bfa_fcxp_send(fcxp, NULL, fabric->vf_id, bfa_lps_get_tag(fabric->lps),
+                       BFA_FALSE, FC_CLASS_3, reqlen, &fchs,
+                       bfa_fcs_fabric_flogiacc_comp, fabric,
+                       FC_MAX_PDUSZ, 0); /* Timeout 0 indicates no
+                                          * response expected
+                                          */
+}
+
+/**
+ *   Flogi Acc completion callback.
+ */
+static void
+bfa_fcs_fabric_flogiacc_comp(void *fcsarg, struct bfa_fcxp_s *fcxp, void *cbarg,
+                            bfa_status_t status, u32 rsp_len,
+                            u32 resid_len, struct fchs_s *rspfchs)
+{
+       struct bfa_fcs_fabric_s *fabric = cbarg;
+
+       bfa_trc(fabric->fcs, status);
+}
+
+/*
+ *
+ * @param[in] fabric - fabric
+ * @param[in] result - 1
+ *
+ * @return - none
+ */
+void
+bfa_fcs_auth_finished(struct bfa_fcs_fabric_s *fabric, enum auth_status status)
+{
+       bfa_trc(fabric->fcs, status);
+
+       if (status == FC_AUTH_STATE_SUCCESS)
+               bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_AUTH_SUCCESS);
+       else
+               bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_AUTH_FAILED);
+}
+
+/**
+ * Send AEN notification
+ */
+static void
+bfa_fcs_fabric_aen_post(struct bfa_fcs_port_s *port,
+                       enum bfa_port_aen_event event)
+{
+       union bfa_aen_data_u aen_data;
+       struct bfa_log_mod_s *logmod = port->fcs->logm;
+       wwn_t           pwwn = bfa_fcs_port_get_pwwn(port);
+       wwn_t           fwwn = bfa_fcs_port_get_fabric_name(port);
+       char            pwwn_ptr[BFA_STRING_32];
+       char            fwwn_ptr[BFA_STRING_32];
+
+       wwn2str(pwwn_ptr, pwwn);
+       wwn2str(fwwn_ptr, fwwn);
+
+       switch (event) {
+       case BFA_PORT_AEN_FABRIC_NAME_CHANGE:
+               bfa_log(logmod, BFA_AEN_PORT_FABRIC_NAME_CHANGE, pwwn_ptr,
+                       fwwn_ptr);
+               break;
+       default:
+               break;
+       }
+
+       aen_data.port.pwwn = pwwn;
+       aen_data.port.fwwn = fwwn;
+}
+
+/*
+ *
+ * @param[in] fabric - fabric
+ * @param[in] wwn_t - new fabric name
+ *
+ * @return - none
+ */
+void
+bfa_fcs_fabric_set_fabric_name(struct bfa_fcs_fabric_s *fabric,
+                              wwn_t fabric_name)
+{
+       bfa_trc(fabric->fcs, fabric_name);
+
+       if (fabric->fabric_name == 0) {
+               /*
+                * With BRCD switches, we don't get Fabric Name in FLOGI.
+                * Don't generate a fabric name change event in this case.
+                */
+               fabric->fabric_name = fabric_name;
+       } else {
+               fabric->fabric_name = fabric_name;
+               /*
+                * Generate a Event
+                */
+               bfa_fcs_fabric_aen_post(&fabric->bport,
+                                       BFA_PORT_AEN_FABRIC_NAME_CHANGE);
+       }
+
+}
+
+/**
+ * Not used by FCS.
+ */
+void
+bfa_cb_lps_flogo_comp(void *bfad, void *uarg)
+{
+}
+
+
diff --git a/drivers/scsi/bfa/fcbuild.c b/drivers/scsi/bfa/fcbuild.c
new file mode 100644 (file)
index 0000000..d174706
--- /dev/null
@@ -0,0 +1,1449 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) 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.
+ */
+/*
+ * fcbuild.c - FC link service frame building and parsing routines
+ */
+
+#include <bfa_os_inc.h>
+#include "fcbuild.h"
+
+/*
+ * static build functions
+ */
+static void fc_els_rsp_build(struct fchs_s *fchs, u32 d_id, u32 s_id,
+                       u16 ox_id);
+static void fc_bls_rsp_build(struct fchs_s *fchs, u32 d_id, u32 s_id,
+                       u16 ox_id);
+static struct fchs_s   fc_els_req_tmpl;
+static struct fchs_s   fc_els_rsp_tmpl;
+static struct fchs_s   fc_bls_req_tmpl;
+static struct fchs_s   fc_bls_rsp_tmpl;
+static struct fc_ba_acc_s ba_acc_tmpl;
+static struct fc_logi_s plogi_tmpl;
+static struct fc_prli_s prli_tmpl;
+static struct fc_rrq_s rrq_tmpl;
+static struct fchs_s   fcp_fchs_tmpl;
+
+void
+fcbuild_init(void)
+{
+       /*
+        * fc_els_req_tmpl
+        */
+       fc_els_req_tmpl.routing = FC_RTG_EXT_LINK;
+       fc_els_req_tmpl.cat_info = FC_CAT_LD_REQUEST;
+       fc_els_req_tmpl.type = FC_TYPE_ELS;
+       fc_els_req_tmpl.f_ctl =
+               bfa_os_hton3b(FCTL_SEQ_INI | FCTL_FS_EXCH | FCTL_END_SEQ |
+                             FCTL_SI_XFER);
+       fc_els_req_tmpl.rx_id = FC_RXID_ANY;
+
+       /*
+        * fc_els_rsp_tmpl
+        */
+       fc_els_rsp_tmpl.routing = FC_RTG_EXT_LINK;
+       fc_els_rsp_tmpl.cat_info = FC_CAT_LD_REPLY;
+       fc_els_rsp_tmpl.type = FC_TYPE_ELS;
+       fc_els_rsp_tmpl.f_ctl =
+               bfa_os_hton3b(FCTL_EC_RESP | FCTL_SEQ_INI | FCTL_LS_EXCH |
+                             FCTL_END_SEQ | FCTL_SI_XFER);
+       fc_els_rsp_tmpl.rx_id = FC_RXID_ANY;
+
+       /*
+        * fc_bls_req_tmpl
+        */
+       fc_bls_req_tmpl.routing = FC_RTG_BASIC_LINK;
+       fc_bls_req_tmpl.type = FC_TYPE_BLS;
+       fc_bls_req_tmpl.f_ctl = bfa_os_hton3b(FCTL_END_SEQ | FCTL_SI_XFER);
+       fc_bls_req_tmpl.rx_id = FC_RXID_ANY;
+
+       /*
+        * fc_bls_rsp_tmpl
+        */
+       fc_bls_rsp_tmpl.routing = FC_RTG_BASIC_LINK;
+       fc_bls_rsp_tmpl.cat_info = FC_CAT_BA_ACC;
+       fc_bls_rsp_tmpl.type = FC_TYPE_BLS;
+       fc_bls_rsp_tmpl.f_ctl =
+               bfa_os_hton3b(FCTL_EC_RESP | FCTL_SEQ_INI | FCTL_LS_EXCH |
+                             FCTL_END_SEQ | FCTL_SI_XFER);
+       fc_bls_rsp_tmpl.rx_id = FC_RXID_ANY;
+
+       /*
+        * ba_acc_tmpl
+        */
+       ba_acc_tmpl.seq_id_valid = 0;
+       ba_acc_tmpl.low_seq_cnt = 0;
+       ba_acc_tmpl.high_seq_cnt = 0xFFFF;
+
+       /*
+        * plogi_tmpl
+        */
+       plogi_tmpl.csp.verhi = FC_PH_VER_PH_3;
+       plogi_tmpl.csp.verlo = FC_PH_VER_4_3;
+       plogi_tmpl.csp.bbcred = bfa_os_htons(0x0004);
+       plogi_tmpl.csp.ciro = 0x1;
+       plogi_tmpl.csp.cisc = 0x0;
+       plogi_tmpl.csp.altbbcred = 0x0;
+       plogi_tmpl.csp.conseq = bfa_os_htons(0x00FF);
+       plogi_tmpl.csp.ro_bitmap = bfa_os_htons(0x0002);
+       plogi_tmpl.csp.e_d_tov = bfa_os_htonl(2000);
+
+       plogi_tmpl.class3.class_valid = 1;
+       plogi_tmpl.class3.sequential = 1;
+       plogi_tmpl.class3.conseq = 0xFF;
+       plogi_tmpl.class3.ospx = 1;
+
+       /*
+        * prli_tmpl
+        */
+       prli_tmpl.command = FC_ELS_PRLI;
+       prli_tmpl.pglen = 0x10;
+       prli_tmpl.pagebytes = bfa_os_htons(0x0014);
+       prli_tmpl.parampage.type = FC_TYPE_FCP;
+       prli_tmpl.parampage.imagepair = 1;
+       prli_tmpl.parampage.servparams.rxrdisab = 1;
+
+       /*
+        * rrq_tmpl
+        */
+       rrq_tmpl.els_cmd.els_code = FC_ELS_RRQ;
+
+       /*
+        * fcp_fchs_tmpl
+        */
+       fcp_fchs_tmpl.routing = FC_RTG_FC4_DEV_DATA;
+       fcp_fchs_tmpl.cat_info = FC_CAT_UNSOLICIT_CMD;
+       fcp_fchs_tmpl.type = FC_TYPE_FCP;
+       fcp_fchs_tmpl.f_ctl =
+               bfa_os_hton3b(FCTL_FS_EXCH | FCTL_END_SEQ | FCTL_SI_XFER);
+       fcp_fchs_tmpl.seq_id = 1;
+       fcp_fchs_tmpl.rx_id = FC_RXID_ANY;
+}
+
+static void
+fc_gs_fchdr_build(struct fchs_s *fchs, u32 d_id, u32 s_id,
+                       u32 ox_id)
+{
+       bfa_os_memset(fchs, 0, sizeof(struct fchs_s));
+
+       fchs->routing = FC_RTG_FC4_DEV_DATA;
+       fchs->cat_info = FC_CAT_UNSOLICIT_CTRL;
+       fchs->type = FC_TYPE_SERVICES;
+       fchs->f_ctl =
+               bfa_os_hton3b(FCTL_SEQ_INI | FCTL_FS_EXCH | FCTL_END_SEQ |
+                             FCTL_SI_XFER);
+       fchs->rx_id = FC_RXID_ANY;
+       fchs->d_id = (d_id);
+       fchs->s_id = (s_id);
+       fchs->ox_id = bfa_os_htons(ox_id);
+
+       /**
+        * @todo no need to set ox_id for request
+        *       no need to set rx_id for response
+        */
+}
+
+void
+fc_els_req_build(struct fchs_s *fchs, u32 d_id, u32 s_id,
+                       u16 ox_id)
+{
+       bfa_os_memcpy(fchs, &fc_els_req_tmpl, sizeof(struct fchs_s));
+       fchs->d_id = (d_id);
+       fchs->s_id = (s_id);
+       fchs->ox_id = bfa_os_htons(ox_id);
+}
+
+static void
+fc_els_rsp_build(struct fchs_s *fchs, u32 d_id, u32 s_id,
+                       u16 ox_id)
+{
+       bfa_os_memcpy(fchs, &fc_els_rsp_tmpl, sizeof(struct fchs_s));
+       fchs->d_id = d_id;
+       fchs->s_id = s_id;
+       fchs->ox_id = ox_id;
+}
+
+enum fc_parse_status
+fc_els_rsp_parse(struct fchs_s *fchs, int len)
+{
+       struct fc_els_cmd_s   *els_cmd = (struct fc_els_cmd_s *) (fchs + 1);
+       struct fc_ls_rjt_s    *ls_rjt = (struct fc_ls_rjt_s *) els_cmd;
+
+       len = len;
+
+       switch (els_cmd->els_code) {
+       case FC_ELS_LS_RJT:
+               if (ls_rjt->reason_code == FC_LS_RJT_RSN_LOGICAL_BUSY)
+                       return (FC_PARSE_BUSY);
+               else
+                       return (FC_PARSE_FAILURE);
+
+       case FC_ELS_ACC:
+               return (FC_PARSE_OK);
+       }
+       return (FC_PARSE_OK);
+}
+
+static void
+fc_bls_rsp_build(struct fchs_s *fchs, u32 d_id, u32 s_id,
+                       u16 ox_id)
+{
+       bfa_os_memcpy(fchs, &fc_bls_rsp_tmpl, sizeof(struct fchs_s));
+       fchs->d_id = d_id;
+       fchs->s_id = s_id;
+       fchs->ox_id = ox_id;
+}
+
+static          u16
+fc_plogi_x_build(struct fchs_s *fchs, void *pld, u32 d_id, u32 s_id,
+                u16 ox_id, wwn_t port_name, wwn_t node_name,
+                u16 pdu_size, u8 els_code)
+{
+       struct fc_logi_s     *plogi = (struct fc_logi_s *) (pld);
+
+       bfa_os_memcpy(plogi, &plogi_tmpl, sizeof(struct fc_logi_s));
+
+       plogi->els_cmd.els_code = els_code;
+       if (els_code == FC_ELS_PLOGI)
+               fc_els_req_build(fchs, d_id, s_id, ox_id);
+       else
+               fc_els_rsp_build(fchs, d_id, s_id, ox_id);
+
+       plogi->csp.rxsz = plogi->class3.rxsz = bfa_os_htons(pdu_size);
+
+       bfa_os_memcpy(&plogi->port_name, &port_name, sizeof(wwn_t));
+       bfa_os_memcpy(&plogi->node_name, &node_name, sizeof(wwn_t));
+
+       return (sizeof(struct fc_logi_s));
+}
+
+u16
+fc_flogi_build(struct fchs_s *fchs, struct fc_logi_s *flogi, u32 s_id,
+               u16 ox_id, wwn_t port_name, wwn_t node_name,
+               u16 pdu_size, u8 set_npiv, u8 set_auth,
+               u16 local_bb_credits)
+{
+       u32        d_id = bfa_os_hton3b(FC_FABRIC_PORT);
+       u32     *vvl_info;
+
+       bfa_os_memcpy(flogi, &plogi_tmpl, sizeof(struct fc_logi_s));
+
+       flogi->els_cmd.els_code = FC_ELS_FLOGI;
+       fc_els_req_build(fchs, d_id, s_id, ox_id);
+
+       flogi->csp.rxsz = flogi->class3.rxsz = bfa_os_htons(pdu_size);
+       flogi->port_name = port_name;
+       flogi->node_name = node_name;
+
+       /*
+        * Set the NPIV Capability Bit ( word 1, bit 31) of Common
+        * Service Parameters.
+        */
+       flogi->csp.ciro = set_npiv;
+
+       /* set AUTH capability */
+       flogi->csp.security = set_auth;
+
+       flogi->csp.bbcred = bfa_os_htons(local_bb_credits);
+
+       /* Set brcd token in VVL */
+       vvl_info = (u32 *)&flogi->vvl[0];
+
+       /* set the flag to indicate the presence of VVL */
+       flogi->csp.npiv_supp    = 1; /* @todo. field name is not correct */
+       vvl_info[0]     = bfa_os_htonl(FLOGI_VVL_BRCD);
+
+       return (sizeof(struct fc_logi_s));
+}
+
+u16
+fc_flogi_acc_build(struct fchs_s *fchs, struct fc_logi_s *flogi, u32 s_id,
+                  u16 ox_id, wwn_t port_name, wwn_t node_name,
+                  u16 pdu_size, u16 local_bb_credits)
+{
+       u32        d_id = 0;
+
+       bfa_os_memcpy(flogi, &plogi_tmpl, sizeof(struct fc_logi_s));
+       fc_els_rsp_build(fchs, d_id, s_id, ox_id);
+
+       flogi->els_cmd.els_code = FC_ELS_ACC;
+       flogi->csp.rxsz = flogi->class3.rxsz = bfa_os_htons(pdu_size);
+       flogi->port_name = port_name;
+       flogi->node_name = node_name;
+
+       flogi->csp.bbcred = bfa_os_htons(local_bb_credits);
+
+       return (sizeof(struct fc_logi_s));
+}
+
+u16
+fc_fdisc_build(struct fchs_s *fchs, struct fc_logi_s *flogi, u32 s_id,
+               u16 ox_id, wwn_t port_name, wwn_t node_name,
+               u16 pdu_size)
+{
+       u32        d_id = bfa_os_hton3b(FC_FABRIC_PORT);
+
+       bfa_os_memcpy(flogi, &plogi_tmpl, sizeof(struct fc_logi_s));
+
+       flogi->els_cmd.els_code = FC_ELS_FDISC;
+       fc_els_req_build(fchs, d_id, s_id, ox_id);
+
+       flogi->csp.rxsz = flogi->class3.rxsz = bfa_os_htons(pdu_size);
+       flogi->port_name = port_name;
+       flogi->node_name = node_name;
+
+       return (sizeof(struct fc_logi_s));
+}
+
+u16
+fc_plogi_build(struct fchs_s *fchs, void *pld, u32 d_id, u32 s_id,
+              u16 ox_id, wwn_t port_name, wwn_t node_name,
+              u16 pdu_size)
+{
+       return fc_plogi_x_build(fchs, pld, d_id, s_id, ox_id, port_name,
+                               node_name, pdu_size, FC_ELS_PLOGI);
+}
+
+u16
+fc_plogi_acc_build(struct fchs_s *fchs, void *pld, u32 d_id, u32 s_id,
+                  u16 ox_id, wwn_t port_name, wwn_t node_name,
+                  u16 pdu_size)
+{
+       return fc_plogi_x_build(fchs, pld, d_id, s_id, ox_id, port_name,
+                               node_name, pdu_size, FC_ELS_ACC);
+}
+
+enum fc_parse_status
+fc_plogi_rsp_parse(struct fchs_s *fchs, int len, wwn_t port_name)
+{
+       struct fc_els_cmd_s   *els_cmd = (struct fc_els_cmd_s *) (fchs + 1);
+       struct fc_logi_s     *plogi;
+       struct fc_ls_rjt_s    *ls_rjt;
+
+       switch (els_cmd->els_code) {
+       case FC_ELS_LS_RJT:
+               ls_rjt = (struct fc_ls_rjt_s *) (fchs + 1);
+               if (ls_rjt->reason_code == FC_LS_RJT_RSN_LOGICAL_BUSY)
+                       return (FC_PARSE_BUSY);
+               else
+                       return (FC_PARSE_FAILURE);
+       case FC_ELS_ACC:
+               plogi = (struct fc_logi_s *) (fchs + 1);
+               if (len < sizeof(struct fc_logi_s))
+                       return (FC_PARSE_FAILURE);
+
+               if (!wwn_is_equal(plogi->port_name, port_name))
+                       return (FC_PARSE_FAILURE);
+
+               if (!plogi->class3.class_valid)
+                       return (FC_PARSE_FAILURE);
+
+               if (bfa_os_ntohs(plogi->class3.rxsz) < (FC_MIN_PDUSZ))
+                       return (FC_PARSE_FAILURE);
+
+               return (FC_PARSE_OK);
+       default:
+               return (FC_PARSE_FAILURE);
+       }
+}
+
+enum fc_parse_status
+fc_plogi_parse(struct fchs_s *fchs)
+{
+       struct fc_logi_s     *plogi = (struct fc_logi_s *) (fchs + 1);
+
+       if (plogi->class3.class_valid != 1)
+               return FC_PARSE_FAILURE;
+
+       if ((bfa_os_ntohs(plogi->class3.rxsz) < FC_MIN_PDUSZ)
+           || (bfa_os_ntohs(plogi->class3.rxsz) > FC_MAX_PDUSZ)
+           || (plogi->class3.rxsz == 0))
+               return (FC_PARSE_FAILURE);
+
+       return FC_PARSE_OK;
+}
+
+u16
+fc_prli_build(struct fchs_s *fchs, void *pld, u32 d_id, u32 s_id,
+             u16 ox_id)
+{
+       struct fc_prli_s      *prli = (struct fc_prli_s *) (pld);
+
+       fc_els_req_build(fchs, d_id, s_id, ox_id);
+       bfa_os_memcpy(prli, &prli_tmpl, sizeof(struct fc_prli_s));
+
+       prli->command = FC_ELS_PRLI;
+       prli->parampage.servparams.initiator     = 1;
+       prli->parampage.servparams.retry         = 1;
+       prli->parampage.servparams.rec_support   = 1;
+       prli->parampage.servparams.task_retry_id = 0;
+       prli->parampage.servparams.confirm       = 1;
+
+       return (sizeof(struct fc_prli_s));
+}
+
+u16
+fc_prli_acc_build(struct fchs_s *fchs, void *pld, u32 d_id, u32 s_id,
+                 u16 ox_id, enum bfa_port_role role)
+{
+       struct fc_prli_s      *prli = (struct fc_prli_s *) (pld);
+
+       fc_els_rsp_build(fchs, d_id, s_id, ox_id);
+       bfa_os_memcpy(prli, &prli_tmpl, sizeof(struct fc_prli_s));
+
+       prli->command = FC_ELS_ACC;
+
+       if ((role & BFA_PORT_ROLE_FCP_TM) == BFA_PORT_ROLE_FCP_TM)
+               prli->parampage.servparams.target = 1;
+       else
+               prli->parampage.servparams.initiator = 1;
+
+       prli->parampage.rspcode = FC_PRLI_ACC_XQTD;
+
+       return (sizeof(struct fc_prli_s));
+}
+
+enum fc_parse_status
+fc_prli_rsp_parse(struct fc_prli_s *prli, int len)
+{
+       if (len < sizeof(struct fc_prli_s))
+               return (FC_PARSE_FAILURE);
+
+       if (prli->command != FC_ELS_ACC)
+               return (FC_PARSE_FAILURE);
+
+       if ((prli->parampage.rspcode != FC_PRLI_ACC_XQTD)
+           && (prli->parampage.rspcode != FC_PRLI_ACC_PREDEF_IMG))
+               return (FC_PARSE_FAILURE);
+
+       if (prli->parampage.servparams.target != 1)
+               return (FC_PARSE_FAILURE);
+
+       return (FC_PARSE_OK);
+}
+
+enum fc_parse_status
+fc_prli_parse(struct fc_prli_s *prli)
+{
+       if (prli->parampage.type != FC_TYPE_FCP)
+               return (FC_PARSE_FAILURE);
+
+       if (!prli->parampage.imagepair)
+               return (FC_PARSE_FAILURE);
+
+       if (!prli->parampage.servparams.initiator)
+               return (FC_PARSE_FAILURE);
+
+       return (FC_PARSE_OK);
+}
+
+u16
+fc_logo_build(struct fchs_s *fchs, struct fc_logo_s *logo, u32 d_id,
+                       u32 s_id, u16 ox_id, wwn_t port_name)
+{
+       fc_els_req_build(fchs, d_id, s_id, ox_id);
+
+       memset(logo, '\0', sizeof(struct fc_logo_s));
+       logo->els_cmd.els_code = FC_ELS_LOGO;
+       logo->nport_id = (s_id);
+       logo->orig_port_name = port_name;
+
+       return (sizeof(struct fc_logo_s));
+}
+
+static          u16
+fc_adisc_x_build(struct fchs_s *fchs, struct fc_adisc_s *adisc, u32 d_id,
+                u32 s_id, u16 ox_id, wwn_t port_name,
+                wwn_t node_name, u8 els_code)
+{
+       memset(adisc, '\0', sizeof(struct fc_adisc_s));
+
+       adisc->els_cmd.els_code = els_code;
+
+       if (els_code == FC_ELS_ADISC)
+               fc_els_req_build(fchs, d_id, s_id, ox_id);
+       else
+               fc_els_rsp_build(fchs, d_id, s_id, ox_id);
+
+       adisc->orig_HA = 0;
+       adisc->orig_port_name = port_name;
+       adisc->orig_node_name = node_name;
+       adisc->nport_id = (s_id);
+
+       return (sizeof(struct fc_adisc_s));
+}
+
+u16
+fc_adisc_build(struct fchs_s *fchs, struct fc_adisc_s *adisc, u32 d_id,
+               u32 s_id, u16 ox_id, wwn_t port_name,
+               wwn_t node_name)
+{
+       return fc_adisc_x_build(fchs, adisc, d_id, s_id, ox_id, port_name,
+                               node_name, FC_ELS_ADISC);
+}
+
+u16
+fc_adisc_acc_build(struct fchs_s *fchs, struct fc_adisc_s *adisc, u32 d_id,
+                  u32 s_id, u16 ox_id, wwn_t port_name,
+                  wwn_t node_name)
+{
+       return fc_adisc_x_build(fchs, adisc, d_id, s_id, ox_id, port_name,
+                               node_name, FC_ELS_ACC);
+}
+
+enum fc_parse_status
+fc_adisc_rsp_parse(struct fc_adisc_s *adisc, int len, wwn_t port_name,
+                                wwn_t node_name)
+{
+
+       if (len < sizeof(struct fc_adisc_s))
+               return (FC_PARSE_FAILURE);
+
+       if (adisc->els_cmd.els_code != FC_ELS_ACC)
+               return (FC_PARSE_FAILURE);
+
+       if (!wwn_is_equal(adisc->orig_port_name, port_name))
+               return (FC_PARSE_FAILURE);
+
+       return (FC_PARSE_OK);
+}
+
+enum fc_parse_status
+fc_adisc_parse(struct fchs_s *fchs, void *pld, u32 host_dap,
+                wwn_t node_name, wwn_t port_name)
+{
+       struct fc_adisc_s     *adisc = (struct fc_adisc_s *) pld;
+
+       if (adisc->els_cmd.els_code != FC_ELS_ACC)
+               return (FC_PARSE_FAILURE);
+
+       if ((adisc->nport_id == (host_dap))
+           && wwn_is_equal(adisc->orig_port_name, port_name)
+           && wwn_is_equal(adisc->orig_node_name, node_name))
+               return (FC_PARSE_OK);
+
+       return (FC_PARSE_FAILURE);
+}
+
+enum fc_parse_status
+fc_pdisc_parse(struct fchs_s *fchs, wwn_t node_name, wwn_t port_name)
+{
+       struct fc_logi_s     *pdisc = (struct fc_logi_s *) (fchs + 1);
+
+       if (pdisc->class3.class_valid != 1)
+               return FC_PARSE_FAILURE;
+
+       if ((bfa_os_ntohs(pdisc->class3.rxsz) <
+                (FC_MIN_PDUSZ - sizeof(struct fchs_s)))
+           || (pdisc->class3.rxsz == 0))
+               return (FC_PARSE_FAILURE);
+
+       if (!wwn_is_equal(pdisc->port_name, port_name))
+               return (FC_PARSE_FAILURE);
+
+       if (!wwn_is_equal(pdisc->node_name, node_name))
+               return (FC_PARSE_FAILURE);
+
+       return FC_PARSE_OK;
+}
+
+u16
+fc_abts_build(struct fchs_s *fchs, u32 d_id, u32 s_id, u16 ox_id)
+{
+       bfa_os_memcpy(fchs, &fc_bls_req_tmpl, sizeof(struct fchs_s));
+       fchs->cat_info = FC_CAT_ABTS;
+       fchs->d_id = (d_id);
+       fchs->s_id = (s_id);
+       fchs->ox_id = bfa_os_htons(ox_id);
+
+       return (sizeof(struct fchs_s));
+}
+
+enum fc_parse_status
+fc_abts_rsp_parse(struct fchs_s *fchs, int len)
+{
+       if ((fchs->cat_info == FC_CAT_BA_ACC)
+           || (fchs->cat_info == FC_CAT_BA_RJT))
+               return (FC_PARSE_OK);
+
+       return (FC_PARSE_FAILURE);
+}
+
+u16
+fc_rrq_build(struct fchs_s *fchs, struct fc_rrq_s *rrq, u32 d_id,
+                        u32 s_id, u16 ox_id, u16 rrq_oxid)
+{
+       fc_els_req_build(fchs, d_id, s_id, ox_id);
+
+       /*
+        * build rrq payload
+        */
+       bfa_os_memcpy(rrq, &rrq_tmpl, sizeof(struct fc_rrq_s));
+       rrq->s_id = (s_id);
+       rrq->ox_id = bfa_os_htons(rrq_oxid);
+       rrq->rx_id = FC_RXID_ANY;
+
+       return (sizeof(struct fc_rrq_s));
+}
+
+u16
+fc_logo_acc_build(struct fchs_s *fchs, void *pld, u32 d_id, u32 s_id,
+                 u16 ox_id)
+{
+       struct fc_els_cmd_s   *acc = pld;
+
+       fc_els_rsp_build(fchs, d_id, s_id, ox_id);
+
+       memset(acc, 0, sizeof(struct fc_els_cmd_s));
+       acc->els_code = FC_ELS_ACC;
+
+       return (sizeof(struct fc_els_cmd_s));
+}
+
+u16
+fc_ls_rjt_build(struct fchs_s *fchs, struct fc_ls_rjt_s *ls_rjt, u32 d_id,
+               u32 s_id, u16 ox_id, u8 reason_code,
+               u8 reason_code_expl)
+{
+       fc_els_rsp_build(fchs, d_id, s_id, ox_id);
+       memset(ls_rjt, 0, sizeof(struct fc_ls_rjt_s));
+
+       ls_rjt->els_cmd.els_code = FC_ELS_LS_RJT;
+       ls_rjt->reason_code = reason_code;
+       ls_rjt->reason_code_expl = reason_code_expl;
+       ls_rjt->vendor_unique = 0x00;
+
+       return (sizeof(struct fc_ls_rjt_s));
+}
+
+u16
+fc_ba_acc_build(struct fchs_s *fchs, struct fc_ba_acc_s *ba_acc, u32 d_id,
+               u32 s_id, u16 ox_id, u16 rx_id)
+{
+       fc_bls_rsp_build(fchs, d_id, s_id, ox_id);
+
+       bfa_os_memcpy(ba_acc, &ba_acc_tmpl, sizeof(struct fc_ba_acc_s));
+
+       fchs->rx_id = rx_id;
+
+       ba_acc->ox_id = fchs->ox_id;
+       ba_acc->rx_id = fchs->rx_id;
+
+       return (sizeof(struct fc_ba_acc_s));
+}
+
+u16
+fc_ls_acc_build(struct fchs_s *fchs, struct fc_els_cmd_s *els_cmd,
+                       u32 d_id, u32 s_id, u16 ox_id)
+{
+       fc_els_rsp_build(fchs, d_id, s_id, ox_id);
+       memset(els_cmd, 0, sizeof(struct fc_els_cmd_s));
+       els_cmd->els_code = FC_ELS_ACC;
+
+       return (sizeof(struct fc_els_cmd_s));
+}
+
+int
+fc_logout_params_pages(struct fchs_s *fc_frame, u8 els_code)
+{
+       int             num_pages = 0;
+       struct fc_prlo_s      *prlo;
+       struct fc_tprlo_s     *tprlo;
+
+       if (els_code == FC_ELS_PRLO) {
+               prlo = (struct fc_prlo_s *) (fc_frame + 1);
+               num_pages = (bfa_os_ntohs(prlo->payload_len) - 4) / 16;
+       } else {
+               tprlo = (struct fc_tprlo_s *) (fc_frame + 1);
+               num_pages = (bfa_os_ntohs(tprlo->payload_len) - 4) / 16;
+       }
+       return num_pages;
+}
+
+u16
+fc_tprlo_acc_build(struct fchs_s *fchs, struct fc_tprlo_acc_s *tprlo_acc,
+                       u32 d_id, u32 s_id, u16 ox_id,
+                       int num_pages)
+{
+       int             page;
+
+       fc_els_rsp_build(fchs, d_id, s_id, ox_id);
+
+       memset(tprlo_acc, 0, (num_pages * 16) + 4);
+       tprlo_acc->command = FC_ELS_ACC;
+
+       tprlo_acc->page_len = 0x10;
+       tprlo_acc->payload_len = bfa_os_htons((num_pages * 16) + 4);
+
+       for (page = 0; page < num_pages; page++) {
+               tprlo_acc->tprlo_acc_params[page].opa_valid = 0;
+               tprlo_acc->tprlo_acc_params[page].rpa_valid = 0;
+               tprlo_acc->tprlo_acc_params[page].fc4type_csp = FC_TYPE_FCP;
+               tprlo_acc->tprlo_acc_params[page].orig_process_assc = 0;
+               tprlo_acc->tprlo_acc_params[page].resp_process_assc = 0;
+       }
+       return (bfa_os_ntohs(tprlo_acc->payload_len));
+}
+
+u16
+fc_prlo_acc_build(struct fchs_s *fchs, struct fc_prlo_acc_s *prlo_acc,
+                       u32 d_id, u32 s_id, u16 ox_id,
+                       int num_pages)
+{
+       int             page;
+
+       fc_els_rsp_build(fchs, d_id, s_id, ox_id);
+
+       memset(prlo_acc, 0, (num_pages * 16) + 4);
+       prlo_acc->command = FC_ELS_ACC;
+       prlo_acc->page_len = 0x10;
+       prlo_acc->payload_len = bfa_os_htons((num_pages * 16) + 4);
+
+       for (page = 0; page < num_pages; page++) {
+               prlo_acc->prlo_acc_params[page].opa_valid = 0;
+               prlo_acc->prlo_acc_params[page].rpa_valid = 0;
+               prlo_acc->prlo_acc_params[page].fc4type_csp = FC_TYPE_FCP;
+               prlo_acc->prlo_acc_params[page].orig_process_assc = 0;
+               prlo_acc->prlo_acc_params[page].resp_process_assc = 0;
+       }
+
+       return (bfa_os_ntohs(prlo_acc->payload_len));
+}
+
+u16
+fc_rnid_build(struct fchs_s *fchs, struct fc_rnid_cmd_s *rnid, u32 d_id,
+                       u32 s_id, u16 ox_id, u32 data_format)
+{
+       fc_els_req_build(fchs, d_id, s_id, ox_id);
+
+       memset(rnid, 0, sizeof(struct fc_rnid_cmd_s));
+
+       rnid->els_cmd.els_code = FC_ELS_RNID;
+       rnid->node_id_data_format = data_format;
+
+       return (sizeof(struct fc_rnid_cmd_s));
+}
+
+u16
+fc_rnid_acc_build(struct fchs_s *fchs, struct fc_rnid_acc_s *rnid_acc,
+                       u32 d_id, u32 s_id, u16 ox_id,
+                       u32 data_format,
+                       struct fc_rnid_common_id_data_s *common_id_data,
+                       struct fc_rnid_general_topology_data_s *gen_topo_data)
+{
+       memset(rnid_acc, 0, sizeof(struct fc_rnid_acc_s));
+
+       fc_els_rsp_build(fchs, d_id, s_id, ox_id);
+
+       rnid_acc->els_cmd.els_code = FC_ELS_ACC;
+       rnid_acc->node_id_data_format = data_format;
+       rnid_acc->common_id_data_length =
+                       sizeof(struct fc_rnid_common_id_data_s);
+       rnid_acc->common_id_data = *common_id_data;
+
+       if (data_format == RNID_NODEID_DATA_FORMAT_DISCOVERY) {
+               rnid_acc->specific_id_data_length =
+                       sizeof(struct fc_rnid_general_topology_data_s);
+               bfa_os_assign(rnid_acc->gen_topology_data, *gen_topo_data);
+               return (sizeof(struct fc_rnid_acc_s));
+       } else {
+               return (sizeof(struct fc_rnid_acc_s) -
+                       sizeof(struct fc_rnid_general_topology_data_s));
+       }
+
+}
+
+u16
+fc_rpsc_build(struct fchs_s *fchs, struct fc_rpsc_cmd_s *rpsc, u32 d_id,
+                       u32 s_id, u16 ox_id)
+{
+       fc_els_req_build(fchs, d_id, s_id, ox_id);
+
+       memset(rpsc, 0, sizeof(struct fc_rpsc_cmd_s));
+
+       rpsc->els_cmd.els_code = FC_ELS_RPSC;
+       return (sizeof(struct fc_rpsc_cmd_s));
+}
+
+u16
+fc_rpsc2_build(struct fchs_s *fchs, struct fc_rpsc2_cmd_s *rpsc2,
+                       u32 d_id, u32 s_id, u32 *pid_list,
+                       u16 npids)
+{
+       u32 dctlr_id = FC_DOMAIN_CTRLR(bfa_os_hton3b(d_id));
+       int i = 0;
+
+       fc_els_req_build(fchs, bfa_os_hton3b(dctlr_id), s_id, 0);
+
+       memset(rpsc2, 0, sizeof(struct fc_rpsc2_cmd_s));
+
+       rpsc2->els_cmd.els_code = FC_ELS_RPSC;
+       rpsc2->token = bfa_os_htonl(FC_BRCD_TOKEN);
+       rpsc2->num_pids  = bfa_os_htons(npids);
+       for (i = 0; i < npids; i++)
+               rpsc2->pid_list[i].pid = pid_list[i];
+
+       return (sizeof(struct fc_rpsc2_cmd_s) + ((npids - 1) *
+                       (sizeof(u32))));
+}
+
+u16
+fc_rpsc_acc_build(struct fchs_s *fchs, struct fc_rpsc_acc_s *rpsc_acc,
+                       u32 d_id, u32 s_id, u16 ox_id,
+                       struct fc_rpsc_speed_info_s *oper_speed)
+{
+       memset(rpsc_acc, 0, sizeof(struct fc_rpsc_acc_s));
+
+       fc_els_rsp_build(fchs, d_id, s_id, ox_id);
+
+       rpsc_acc->command = FC_ELS_ACC;
+       rpsc_acc->num_entries = bfa_os_htons(1);
+
+       rpsc_acc->speed_info[0].port_speed_cap =
+               bfa_os_htons(oper_speed->port_speed_cap);
+
+       rpsc_acc->speed_info[0].port_op_speed =
+               bfa_os_htons(oper_speed->port_op_speed);
+
+       return (sizeof(struct fc_rpsc_acc_s));
+
+}
+
+/*
+ * TBD -
+ * . get rid of unnecessary memsets
+ */
+
+u16
+fc_logo_rsp_parse(struct fchs_s *fchs, int len)
+{
+       struct fc_els_cmd_s   *els_cmd = (struct fc_els_cmd_s *) (fchs + 1);
+
+       len = len;
+       if (els_cmd->els_code != FC_ELS_ACC)
+               return FC_PARSE_FAILURE;
+
+       return FC_PARSE_OK;
+}
+
+u16
+fc_pdisc_build(struct fchs_s *fchs, u32 d_id, u32 s_id,
+                       u16 ox_id, wwn_t port_name, wwn_t node_name,
+                       u16 pdu_size)
+{
+       struct fc_logi_s     *pdisc = (struct fc_logi_s *) (fchs + 1);
+
+       bfa_os_memcpy(pdisc, &plogi_tmpl, sizeof(struct fc_logi_s));
+
+       pdisc->els_cmd.els_code = FC_ELS_PDISC;
+       fc_els_req_build(fchs, d_id, s_id, ox_id);
+
+       pdisc->csp.rxsz = pdisc->class3.rxsz = bfa_os_htons(pdu_size);
+       pdisc->port_name = port_name;
+       pdisc->node_name = node_name;
+
+       return (sizeof(struct fc_logi_s));
+}
+
+u16
+fc_pdisc_rsp_parse(struct fchs_s *fchs, int len, wwn_t port_name)
+{
+       struct fc_logi_s     *pdisc = (struct fc_logi_s *) (fchs + 1);
+
+       if (len < sizeof(struct fc_logi_s))
+               return (FC_PARSE_LEN_INVAL);
+
+       if (pdisc->els_cmd.els_code != FC_ELS_ACC)
+               return (FC_PARSE_ACC_INVAL);
+
+       if (!wwn_is_equal(pdisc->port_name, port_name))
+               return (FC_PARSE_PWWN_NOT_EQUAL);
+
+       if (!pdisc->class3.class_valid)
+               return (FC_PARSE_NWWN_NOT_EQUAL);
+
+       if (bfa_os_ntohs(pdisc->class3.rxsz) < (FC_MIN_PDUSZ))
+               return (FC_PARSE_RXSZ_INVAL);
+
+       return (FC_PARSE_OK);
+}
+
+u16
+fc_prlo_build(struct fchs_s *fchs, u32 d_id, u32 s_id, u16 ox_id,
+             int num_pages)
+{
+       struct fc_prlo_s      *prlo = (struct fc_prlo_s *) (fchs + 1);
+       int             page;
+
+       fc_els_req_build(fchs, d_id, s_id, ox_id);
+       memset(prlo, 0, (num_pages * 16) + 4);
+       prlo->command = FC_ELS_PRLO;
+       prlo->page_len = 0x10;
+       prlo->payload_len = bfa_os_htons((num_pages * 16) + 4);
+
+       for (page = 0; page < num_pages; page++) {
+               prlo->prlo_params[page].type = FC_TYPE_FCP;
+               prlo->prlo_params[page].opa_valid = 0;
+               prlo->prlo_params[page].rpa_valid = 0;
+               prlo->prlo_params[page].orig_process_assc = 0;
+               prlo->prlo_params[page].resp_process_assc = 0;
+       }
+
+       return (bfa_os_ntohs(prlo->payload_len));
+}
+
+u16
+fc_prlo_rsp_parse(struct fchs_s *fchs, int len)
+{
+       struct fc_prlo_acc_s  *prlo = (struct fc_prlo_acc_s *) (fchs + 1);
+       int             num_pages = 0;
+       int             page = 0;
+
+       len = len;
+
+       if (prlo->command != FC_ELS_ACC)
+               return (FC_PARSE_FAILURE);
+
+       num_pages = ((bfa_os_ntohs(prlo->payload_len)) - 4) / 16;
+
+       for (page = 0; page < num_pages; page++) {
+               if (prlo->prlo_acc_params[page].type != FC_TYPE_FCP)
+                       return FC_PARSE_FAILURE;
+
+               if (prlo->prlo_acc_params[page].opa_valid != 0)
+                       return FC_PARSE_FAILURE;
+
+               if (prlo->prlo_acc_params[page].rpa_valid != 0)
+                       return FC_PARSE_FAILURE;
+
+               if (prlo->prlo_acc_params[page].orig_process_assc != 0)
+                       return FC_PARSE_FAILURE;
+
+               if (prlo->prlo_acc_params[page].resp_process_assc != 0)
+                       return FC_PARSE_FAILURE;
+       }
+       return (FC_PARSE_OK);
+
+}
+
+u16
+fc_tprlo_build(struct fchs_s *fchs, u32 d_id, u32 s_id,
+                       u16 ox_id, int num_pages,
+                       enum fc_tprlo_type tprlo_type, u32 tpr_id)
+{
+       struct fc_tprlo_s     *tprlo = (struct fc_tprlo_s *) (fchs + 1);
+       int             page;
+
+       fc_els_req_build(fchs, d_id, s_id, ox_id);
+       memset(tprlo, 0, (num_pages * 16) + 4);
+       tprlo->command = FC_ELS_TPRLO;
+       tprlo->page_len = 0x10;
+       tprlo->payload_len = bfa_os_htons((num_pages * 16) + 4);
+
+       for (page = 0; page < num_pages; page++) {
+               tprlo->tprlo_params[page].type = FC_TYPE_FCP;
+               tprlo->tprlo_params[page].opa_valid = 0;
+               tprlo->tprlo_params[page].rpa_valid = 0;
+               tprlo->tprlo_params[page].orig_process_assc = 0;
+               tprlo->tprlo_params[page].resp_process_assc = 0;
+               if (tprlo_type == FC_GLOBAL_LOGO) {
+                       tprlo->tprlo_params[page].global_process_logout = 1;
+               } else if (tprlo_type == FC_TPR_LOGO) {
+                       tprlo->tprlo_params[page].tpo_nport_valid = 1;
+                       tprlo->tprlo_params[page].tpo_nport_id = (tpr_id);
+               }
+       }
+
+       return (bfa_os_ntohs(tprlo->payload_len));
+}
+
+u16
+fc_tprlo_rsp_parse(struct fchs_s *fchs, int len)
+{
+       struct fc_tprlo_acc_s *tprlo = (struct fc_tprlo_acc_s *) (fchs + 1);
+       int             num_pages = 0;
+       int             page = 0;
+
+       len = len;
+
+       if (tprlo->command != FC_ELS_ACC)
+               return (FC_PARSE_ACC_INVAL);
+
+       num_pages = (bfa_os_ntohs(tprlo->payload_len) - 4) / 16;
+
+       for (page = 0; page < num_pages; page++) {
+               if (tprlo->tprlo_acc_params[page].type != FC_TYPE_FCP)
+                       return (FC_PARSE_NOT_FCP);
+               if (tprlo->tprlo_acc_params[page].opa_valid != 0)
+                       return (FC_PARSE_OPAFLAG_INVAL);
+               if (tprlo->tprlo_acc_params[page].rpa_valid != 0)
+                       return (FC_PARSE_RPAFLAG_INVAL);
+               if (tprlo->tprlo_acc_params[page].orig_process_assc != 0)
+                       return (FC_PARSE_OPA_INVAL);
+               if (tprlo->tprlo_acc_params[page].resp_process_assc != 0)
+                       return (FC_PARSE_RPA_INVAL);
+       }
+       return (FC_PARSE_OK);
+}
+
+enum fc_parse_status
+fc_rrq_rsp_parse(struct fchs_s *fchs, int len)
+{
+       struct fc_els_cmd_s   *els_cmd = (struct fc_els_cmd_s *) (fchs + 1);
+
+       len = len;
+       if (els_cmd->els_code != FC_ELS_ACC)
+               return FC_PARSE_FAILURE;
+
+       return FC_PARSE_OK;
+}
+
+u16
+fc_ba_rjt_build(struct fchs_s *fchs, u32 d_id, u32 s_id,
+                       u16 ox_id, u32 reason_code,
+                       u32 reason_expl)
+{
+       struct fc_ba_rjt_s    *ba_rjt = (struct fc_ba_rjt_s *) (fchs + 1);
+
+       fc_bls_rsp_build(fchs, d_id, s_id, ox_id);
+
+       fchs->cat_info = FC_CAT_BA_RJT;
+       ba_rjt->reason_code = reason_code;
+       ba_rjt->reason_expl = reason_expl;
+       return (sizeof(struct fc_ba_rjt_s));
+}
+
+static void
+fc_gs_cthdr_build(struct ct_hdr_s *cthdr, u32 s_id, u16 cmd_code)
+{
+       bfa_os_memset(cthdr, 0, sizeof(struct ct_hdr_s));
+       cthdr->rev_id = CT_GS3_REVISION;
+       cthdr->gs_type = CT_GSTYPE_DIRSERVICE;
+       cthdr->gs_sub_type = CT_GSSUBTYPE_NAMESERVER;
+       cthdr->cmd_rsp_code = bfa_os_htons(cmd_code);
+}
+
+static void
+fc_gs_fdmi_cthdr_build(struct ct_hdr_s *cthdr, u32 s_id, u16 cmd_code)
+{
+       bfa_os_memset(cthdr, 0, sizeof(struct ct_hdr_s));
+       cthdr->rev_id = CT_GS3_REVISION;
+       cthdr->gs_type = CT_GSTYPE_MGMTSERVICE;
+       cthdr->gs_sub_type = CT_GSSUBTYPE_HBA_MGMTSERVER;
+       cthdr->cmd_rsp_code = bfa_os_htons(cmd_code);
+}
+
+static void
+fc_gs_ms_cthdr_build(struct ct_hdr_s *cthdr, u32 s_id, u16 cmd_code,
+                                        u8 sub_type)
+{
+       bfa_os_memset(cthdr, 0, sizeof(struct ct_hdr_s));
+       cthdr->rev_id = CT_GS3_REVISION;
+       cthdr->gs_type = CT_GSTYPE_MGMTSERVICE;
+       cthdr->gs_sub_type = sub_type;
+       cthdr->cmd_rsp_code = bfa_os_htons(cmd_code);
+}
+
+u16
+fc_gidpn_build(struct fchs_s *fchs, void *pyld, u32 s_id, u16 ox_id,
+              wwn_t port_name)
+{
+
+       struct ct_hdr_s       *cthdr = (struct ct_hdr_s *) pyld;
+       struct fcgs_gidpn_req_s *gidpn =
+                       (struct fcgs_gidpn_req_s *) (cthdr + 1);
+       u32        d_id = bfa_os_hton3b(FC_NAME_SERVER);
+
+       fc_gs_fchdr_build(fchs, d_id, s_id, ox_id);
+       fc_gs_cthdr_build(cthdr, s_id, GS_GID_PN);
+
+       bfa_os_memset(gidpn, 0, sizeof(struct fcgs_gidpn_req_s));
+       gidpn->port_name = port_name;
+       return (sizeof(struct fcgs_gidpn_req_s) + sizeof(struct ct_hdr_s));
+}
+
+u16
+fc_gpnid_build(struct fchs_s *fchs, void *pyld, u32 s_id, u16 ox_id,
+              u32 port_id)
+{
+
+       struct ct_hdr_s       *cthdr = (struct ct_hdr_s *) pyld;
+       fcgs_gpnid_req_t *gpnid = (fcgs_gpnid_req_t *) (cthdr + 1);
+       u32        d_id = bfa_os_hton3b(FC_NAME_SERVER);
+
+       fc_gs_fchdr_build(fchs, d_id, s_id, ox_id);
+       fc_gs_cthdr_build(cthdr, s_id, GS_GPN_ID);
+
+       bfa_os_memset(gpnid, 0, sizeof(fcgs_gpnid_req_t));
+       gpnid->dap = port_id;
+       return (sizeof(fcgs_gpnid_req_t) + sizeof(struct ct_hdr_s));
+}
+
+u16
+fc_gnnid_build(struct fchs_s *fchs, void *pyld, u32 s_id, u16 ox_id,
+              u32 port_id)
+{
+
+       struct ct_hdr_s       *cthdr = (struct ct_hdr_s *) pyld;
+       fcgs_gnnid_req_t *gnnid = (fcgs_gnnid_req_t *) (cthdr + 1);
+       u32        d_id = bfa_os_hton3b(FC_NAME_SERVER);
+
+       fc_gs_fchdr_build(fchs, d_id, s_id, ox_id);
+       fc_gs_cthdr_build(cthdr, s_id, GS_GNN_ID);
+
+       bfa_os_memset(gnnid, 0, sizeof(fcgs_gnnid_req_t));
+       gnnid->dap = port_id;
+       return (sizeof(fcgs_gnnid_req_t) + sizeof(struct ct_hdr_s));
+}
+
+u16
+fc_ct_rsp_parse(struct ct_hdr_s *cthdr)
+{
+       if (bfa_os_ntohs(cthdr->cmd_rsp_code) != CT_RSP_ACCEPT) {
+               if (cthdr->reason_code == CT_RSN_LOGICAL_BUSY)
+                       return FC_PARSE_BUSY;
+               else
+                       return FC_PARSE_FAILURE;
+       }
+
+       return FC_PARSE_OK;
+}
+
+u16
+fc_scr_build(struct fchs_s *fchs, struct fc_scr_s *scr, u8 set_br_reg,
+                       u32 s_id, u16 ox_id)
+{
+       u32        d_id = bfa_os_hton3b(FC_FABRIC_CONTROLLER);
+
+       fc_els_req_build(fchs, d_id, s_id, ox_id);
+
+       bfa_os_memset(scr, 0, sizeof(struct fc_scr_s));
+       scr->command = FC_ELS_SCR;
+       scr->reg_func = FC_SCR_REG_FUNC_FULL;
+       if (set_br_reg)
+               scr->vu_reg_func = FC_VU_SCR_REG_FUNC_FABRIC_NAME_CHANGE;
+
+       return (sizeof(struct fc_scr_s));
+}
+
+u16
+fc_rscn_build(struct fchs_s *fchs, struct fc_rscn_pl_s *rscn, u32 s_id,
+                       u16 ox_id)
+{
+       u32        d_id = bfa_os_hton3b(FC_FABRIC_CONTROLLER);
+       u16        payldlen;
+
+       fc_els_req_build(fchs, d_id, s_id, ox_id);
+       rscn->command = FC_ELS_RSCN;
+       rscn->pagelen = sizeof(rscn->event[0]);
+
+       payldlen = sizeof(u32) + rscn->pagelen;
+       rscn->payldlen = bfa_os_htons(payldlen);
+
+       rscn->event[0].format = FC_RSCN_FORMAT_PORTID;
+       rscn->event[0].portid = s_id;
+
+       return (sizeof(struct fc_rscn_pl_s));
+}
+
+u16
+fc_rftid_build(struct fchs_s *fchs, void *pyld, u32 s_id, u16 ox_id,
+              enum bfa_port_role roles)
+{
+       struct ct_hdr_s       *cthdr = (struct ct_hdr_s *) pyld;
+       struct fcgs_rftid_req_s *rftid =
+                       (struct fcgs_rftid_req_s *) (cthdr + 1);
+       u32        type_value, d_id = bfa_os_hton3b(FC_NAME_SERVER);
+       u8         index;
+
+       fc_gs_fchdr_build(fchs, d_id, s_id, ox_id);
+       fc_gs_cthdr_build(cthdr, s_id, GS_RFT_ID);
+
+       bfa_os_memset(rftid, 0, sizeof(struct fcgs_rftid_req_s));
+
+       rftid->dap = s_id;
+
+       /* By default, FCP FC4 Type is registered */
+       index = FC_TYPE_FCP >> 5;
+       type_value = 1 << (FC_TYPE_FCP % 32);
+       rftid->fc4_type[index] = bfa_os_htonl(type_value);
+
+       if (roles & BFA_PORT_ROLE_FCP_IPFC) {
+               index = FC_TYPE_IP >> 5;
+               type_value = 1 << (FC_TYPE_IP % 32);
+               rftid->fc4_type[index] |= bfa_os_htonl(type_value);
+       }
+
+       return (sizeof(struct fcgs_rftid_req_s) + sizeof(struct ct_hdr_s));
+}
+
+u16
+fc_rftid_build_sol(struct fchs_s *fchs, void *pyld, u32 s_id,
+                       u16 ox_id, u8 *fc4_bitmap,
+                       u32 bitmap_size)
+{
+       struct ct_hdr_s       *cthdr = (struct ct_hdr_s *) pyld;
+       struct fcgs_rftid_req_s *rftid =
+                       (struct fcgs_rftid_req_s *) (cthdr + 1);
+       u32        d_id = bfa_os_hton3b(FC_NAME_SERVER);
+
+       fc_gs_fchdr_build(fchs, d_id, s_id, ox_id);
+       fc_gs_cthdr_build(cthdr, s_id, GS_RFT_ID);
+
+       bfa_os_memset(rftid, 0, sizeof(struct fcgs_rftid_req_s));
+
+       rftid->dap = s_id;
+       bfa_os_memcpy((void *)rftid->fc4_type, (void *)fc4_bitmap,
+                       (bitmap_size < 32 ? bitmap_size : 32));
+
+       return (sizeof(struct fcgs_rftid_req_s) + sizeof(struct ct_hdr_s));
+}
+
+u16
+fc_rffid_build(struct fchs_s *fchs, void *pyld, u32 s_id, u16 ox_id,
+              u8 fc4_type, u8 fc4_ftrs)
+{
+       struct ct_hdr_s         *cthdr = (struct ct_hdr_s *) pyld;
+       struct fcgs_rffid_req_s *rffid =
+                       (struct fcgs_rffid_req_s *) (cthdr + 1);
+       u32         d_id = bfa_os_hton3b(FC_NAME_SERVER);
+
+       fc_gs_fchdr_build(fchs, d_id, s_id, ox_id);
+       fc_gs_cthdr_build(cthdr, s_id, GS_RFF_ID);
+
+       bfa_os_memset(rffid, 0, sizeof(struct fcgs_rffid_req_s));
+
+       rffid->dap                      = s_id;
+       rffid->fc4ftr_bits  = fc4_ftrs;
+       rffid->fc4_type         = fc4_type;
+
+       return (sizeof(struct fcgs_rffid_req_s) + sizeof(struct ct_hdr_s));
+}
+
+u16
+fc_rspnid_build(struct fchs_s *fchs, void *pyld, u32 s_id, u16 ox_id,
+               u8 *name)
+{
+
+       struct ct_hdr_s       *cthdr = (struct ct_hdr_s *) pyld;
+       struct fcgs_rspnid_req_s *rspnid =
+                       (struct fcgs_rspnid_req_s *) (cthdr + 1);
+       u32        d_id = bfa_os_hton3b(FC_NAME_SERVER);
+
+       fc_gs_fchdr_build(fchs, d_id, s_id, ox_id);
+       fc_gs_cthdr_build(cthdr, s_id, GS_RSPN_ID);
+
+       bfa_os_memset(rspnid, 0, sizeof(struct fcgs_rspnid_req_s));
+
+       rspnid->dap = s_id;
+       rspnid->spn_len = (u8) strlen((char *)name);
+       strncpy((char *)rspnid->spn, (char *)name, rspnid->spn_len);
+
+       return (sizeof(struct fcgs_rspnid_req_s) + sizeof(struct ct_hdr_s));
+}
+
+u16
+fc_gid_ft_build(struct fchs_s *fchs, void *pyld, u32 s_id,
+                       u8 fc4_type)
+{
+
+       struct ct_hdr_s       *cthdr = (struct ct_hdr_s *) pyld;
+       struct fcgs_gidft_req_s *gidft =
+                       (struct fcgs_gidft_req_s *) (cthdr + 1);
+       u32        d_id = bfa_os_hton3b(FC_NAME_SERVER);
+
+       fc_gs_fchdr_build(fchs, d_id, s_id, 0);
+
+       fc_gs_cthdr_build(cthdr, s_id, GS_GID_FT);
+
+       bfa_os_memset(gidft, 0, sizeof(struct fcgs_gidft_req_s));
+       gidft->fc4_type = fc4_type;
+       gidft->domain_id = 0;
+       gidft->area_id = 0;
+
+       return (sizeof(struct fcgs_gidft_req_s) + sizeof(struct ct_hdr_s));
+}
+
+u16
+fc_rpnid_build(struct fchs_s *fchs, void *pyld, u32 s_id, u32 port_id,
+              wwn_t port_name)
+{
+       struct ct_hdr_s       *cthdr = (struct ct_hdr_s *) pyld;
+       struct fcgs_rpnid_req_s *rpnid =
+                       (struct fcgs_rpnid_req_s *) (cthdr + 1);
+       u32        d_id = bfa_os_hton3b(FC_NAME_SERVER);
+
+       fc_gs_fchdr_build(fchs, d_id, s_id, 0);
+       fc_gs_cthdr_build(cthdr, s_id, GS_RPN_ID);
+
+       bfa_os_memset(rpnid, 0, sizeof(struct fcgs_rpnid_req_s));
+       rpnid->port_id = port_id;
+       rpnid->port_name = port_name;
+
+       return (sizeof(struct fcgs_rpnid_req_s) + sizeof(struct ct_hdr_s));
+}
+
+u16
+fc_rnnid_build(struct fchs_s *fchs, void *pyld, u32 s_id, u32 port_id,
+              wwn_t node_name)
+{
+       struct ct_hdr_s       *cthdr = (struct ct_hdr_s *) pyld;
+       struct fcgs_rnnid_req_s *rnnid =
+                       (struct fcgs_rnnid_req_s *) (cthdr + 1);
+       u32        d_id = bfa_os_hton3b(FC_NAME_SERVER);
+
+       fc_gs_fchdr_build(fchs, d_id, s_id, 0);
+       fc_gs_cthdr_build(cthdr, s_id, GS_RNN_ID);
+
+       bfa_os_memset(rnnid, 0, sizeof(struct fcgs_rnnid_req_s));
+       rnnid->port_id = port_id;
+       rnnid->node_name = node_name;
+
+       return (sizeof(struct fcgs_rnnid_req_s) + sizeof(struct ct_hdr_s));
+}
+
+u16
+fc_rcsid_build(struct fchs_s *fchs, void *pyld, u32 s_id, u32 port_id,
+              u32 cos)
+{
+       struct ct_hdr_s       *cthdr = (struct ct_hdr_s *) pyld;
+       struct fcgs_rcsid_req_s *rcsid =
+                       (struct fcgs_rcsid_req_s *) (cthdr + 1);
+       u32        d_id = bfa_os_hton3b(FC_NAME_SERVER);
+
+       fc_gs_fchdr_build(fchs, d_id, s_id, 0);
+       fc_gs_cthdr_build(cthdr, s_id, GS_RCS_ID);
+
+       bfa_os_memset(rcsid, 0, sizeof(struct fcgs_rcsid_req_s));
+       rcsid->port_id = port_id;
+       rcsid->cos = cos;
+
+       return (sizeof(struct fcgs_rcsid_req_s) + sizeof(struct ct_hdr_s));
+}
+
+u16
+fc_rptid_build(struct fchs_s *fchs, void *pyld, u32 s_id, u32 port_id,
+              u8 port_type)
+{
+       struct ct_hdr_s       *cthdr = (struct ct_hdr_s *) pyld;
+       struct fcgs_rptid_req_s *rptid =
+                       (struct fcgs_rptid_req_s *) (cthdr + 1);
+       u32        d_id = bfa_os_hton3b(FC_NAME_SERVER);
+
+       fc_gs_fchdr_build(fchs, d_id, s_id, 0);
+       fc_gs_cthdr_build(cthdr, s_id, GS_RPT_ID);
+
+       bfa_os_memset(rptid, 0, sizeof(struct fcgs_rptid_req_s));
+       rptid->port_id = port_id;
+       rptid->port_type = port_type;
+
+       return (sizeof(struct fcgs_rptid_req_s) + sizeof(struct ct_hdr_s));
+}
+
+u16
+fc_ganxt_build(struct fchs_s *fchs, void *pyld, u32 s_id, u32 port_id)
+{
+       struct ct_hdr_s       *cthdr = (struct ct_hdr_s *) pyld;
+       struct fcgs_ganxt_req_s *ganxt =
+                       (struct fcgs_ganxt_req_s *) (cthdr + 1);
+       u32        d_id = bfa_os_hton3b(FC_NAME_SERVER);
+
+       fc_gs_fchdr_build(fchs, d_id, s_id, 0);
+       fc_gs_cthdr_build(cthdr, s_id, GS_GA_NXT);
+
+       bfa_os_memset(ganxt, 0, sizeof(struct fcgs_ganxt_req_s));
+       ganxt->port_id = port_id;
+
+       return (sizeof(struct ct_hdr_s) + sizeof(struct fcgs_ganxt_req_s));
+}
+
+/*
+ * Builds fc hdr and ct hdr for FDMI requests.
+ */
+u16
+fc_fdmi_reqhdr_build(struct fchs_s *fchs, void *pyld, u32 s_id,
+                    u16 cmd_code)
+{
+
+       struct ct_hdr_s       *cthdr = (struct ct_hdr_s *) pyld;
+       u32        d_id = bfa_os_hton3b(FC_MGMT_SERVER);
+
+       fc_gs_fchdr_build(fchs, d_id, s_id, 0);
+       fc_gs_fdmi_cthdr_build(cthdr, s_id, cmd_code);
+
+       return (sizeof(struct ct_hdr_s));
+}
+
+/*
+ * Given a FC4 Type, this function returns a fc4 type bitmask
+ */
+void
+fc_get_fc4type_bitmask(u8 fc4_type, u8 *bit_mask)
+{
+       u8         index;
+       u32       *ptr = (u32 *) bit_mask;
+       u32        type_value;
+
+       /*
+        * @todo : Check for bitmask size
+        */
+
+       index = fc4_type >> 5;
+       type_value = 1 << (fc4_type % 32);
+       ptr[index] = bfa_os_htonl(type_value);
+
+}
+
+/*
+ * GMAL Request
+ */
+u16
+fc_gmal_req_build(struct fchs_s *fchs, void *pyld, u32 s_id, wwn_t wwn)
+{
+       struct ct_hdr_s       *cthdr = (struct ct_hdr_s *) pyld;
+       fcgs_gmal_req_t *gmal = (fcgs_gmal_req_t *) (cthdr + 1);
+       u32        d_id = bfa_os_hton3b(FC_MGMT_SERVER);
+
+       fc_gs_fchdr_build(fchs, d_id, s_id, 0);
+       fc_gs_ms_cthdr_build(cthdr, s_id, GS_FC_GMAL_CMD,
+                       CT_GSSUBTYPE_CFGSERVER);
+
+       bfa_os_memset(gmal, 0, sizeof(fcgs_gmal_req_t));
+       gmal->wwn = wwn;
+
+       return (sizeof(struct ct_hdr_s) + sizeof(fcgs_gmal_req_t));
+}
+
+/*
+ * GFN (Get Fabric Name) Request
+ */
+u16
+fc_gfn_req_build(struct fchs_s *fchs, void *pyld, u32 s_id, wwn_t wwn)
+{
+       struct ct_hdr_s       *cthdr = (struct ct_hdr_s *) pyld;
+       fcgs_gfn_req_t *gfn = (fcgs_gfn_req_t *) (cthdr + 1);
+       u32        d_id = bfa_os_hton3b(FC_MGMT_SERVER);
+
+       fc_gs_fchdr_build(fchs, d_id, s_id, 0);
+       fc_gs_ms_cthdr_build(cthdr, s_id, GS_FC_GFN_CMD,
+                       CT_GSSUBTYPE_CFGSERVER);
+
+       bfa_os_memset(gfn, 0, sizeof(fcgs_gfn_req_t));
+       gfn->wwn = wwn;
+
+       return (sizeof(struct ct_hdr_s) + sizeof(fcgs_gfn_req_t));
+}
diff --git a/drivers/scsi/bfa/fcbuild.h b/drivers/scsi/bfa/fcbuild.h
new file mode 100644 (file)
index 0000000..4d24842
--- /dev/null
@@ -0,0 +1,273 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) 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.
+ */
+/*
+ * fcbuild.h - FC link service frame building and parsing routines
+ */
+
+#ifndef __FCBUILD_H__
+#define __FCBUILD_H__
+
+#include <bfa_os_inc.h>
+#include <protocol/fc.h>
+#include <protocol/fcp.h>
+#include <protocol/ct.h>
+#include <defs/bfa_defs_port.h>
+#include <defs/bfa_defs_pport.h>
+
+/*
+ * Utility Macros/functions
+ */
+
+#define fcif_sof_set(_ifhdr, _sof)     (_ifhdr)->sof = FC_ ## _sof
+#define fcif_eof_set(_ifhdr, _eof)     (_ifhdr)->eof = FC_ ## _eof
+
+#define wwn_is_equal(_wwn1, _wwn2)             \
+       (memcmp(&(_wwn1), &(_wwn2), sizeof(wwn_t)) == 0)
+
+#define fc_roundup(_l, _s) (((_l) + ((_s) - 1)) & ~((_s) - 1))
+
+/*
+ * Given the fc response length, this routine will return
+ * the length of the actual payload bytes following the CT header.
+ *
+ * Assumes the input response length does not include the crc, eof, etc.
+ */
+static inline   u32
+fc_get_ctresp_pyld_len(u32 resp_len)
+{
+       return (resp_len - sizeof(struct ct_hdr_s));
+}
+
+/*
+ * Convert bfa speed to rpsc speed value.
+ */
+static inline enum bfa_pport_speed
+fc_rpsc_operspeed_to_bfa_speed(enum fc_rpsc_op_speed_s speed)
+{
+       switch (speed) {
+
+       case RPSC_OP_SPEED_1G:
+               return BFA_PPORT_SPEED_1GBPS;
+
+       case RPSC_OP_SPEED_2G:
+               return BFA_PPORT_SPEED_2GBPS;
+
+       case RPSC_OP_SPEED_4G:
+               return BFA_PPORT_SPEED_4GBPS;
+
+       case RPSC_OP_SPEED_8G:
+               return BFA_PPORT_SPEED_8GBPS;
+
+       default:
+               return BFA_PPORT_SPEED_UNKNOWN;
+       }
+}
+
+/*
+ * Convert RPSC speed to bfa speed value.
+ */
+static inline   enum fc_rpsc_op_speed_s
+fc_bfa_speed_to_rpsc_operspeed(enum bfa_pport_speed op_speed)
+{
+       switch (op_speed) {
+
+       case BFA_PPORT_SPEED_1GBPS:
+               return RPSC_OP_SPEED_1G;
+
+       case BFA_PPORT_SPEED_2GBPS:
+               return RPSC_OP_SPEED_2G;
+
+       case BFA_PPORT_SPEED_4GBPS:
+               return RPSC_OP_SPEED_4G;
+
+       case BFA_PPORT_SPEED_8GBPS:
+               return RPSC_OP_SPEED_8G;
+
+       default:
+               return RPSC_OP_SPEED_NOT_EST;
+       }
+}
+enum fc_parse_status {
+       FC_PARSE_OK = 0,
+       FC_PARSE_FAILURE = 1,
+       FC_PARSE_BUSY = 2,
+       FC_PARSE_LEN_INVAL,
+       FC_PARSE_ACC_INVAL,
+       FC_PARSE_PWWN_NOT_EQUAL,
+       FC_PARSE_NWWN_NOT_EQUAL,
+       FC_PARSE_RXSZ_INVAL,
+       FC_PARSE_NOT_FCP,
+       FC_PARSE_OPAFLAG_INVAL,
+       FC_PARSE_RPAFLAG_INVAL,
+       FC_PARSE_OPA_INVAL,
+       FC_PARSE_RPA_INVAL,
+
+};
+
+struct fc_templates_s {
+       struct fchs_s          fc_els_req;
+       struct fchs_s          fc_bls_req;
+       struct fc_logi_s      plogi;
+       struct fc_rrq_s        rrq;
+};
+
+void fcbuild_init(void);
+
+u16 fc_flogi_build(struct fchs_s *fchs, struct fc_logi_s *flogi,
+                       u32 s_id, u16 ox_id, wwn_t port_name,
+                       wwn_t node_name, u16 pdu_size, u8 set_npiv,
+                       u8 set_auth, u16 local_bb_credits);
+u16 fc_fdisc_build(struct fchs_s *buf, struct fc_logi_s *flogi,
+                       u32 s_id, u16 ox_id, wwn_t port_name,
+                       wwn_t node_name, u16 pdu_size);
+u16 fc_flogi_acc_build(struct fchs_s *fchs, struct fc_logi_s *flogi,
+                       u32 s_id, u16 ox_id, wwn_t port_name,
+                       wwn_t node_name, u16 pdu_size,
+                       u16 local_bb_credits);
+u16 fc_plogi_build(struct fchs_s *fchs, void *pld, u32 d_id,
+                       u32 s_id, u16 ox_id, wwn_t port_name,
+                       wwn_t node_name, u16 pdu_size);
+enum fc_parse_status fc_plogi_parse(struct fchs_s *fchs);
+u16 fc_abts_build(struct fchs_s *buf, u32 d_id, u32 s_id,
+                       u16 ox_id);
+enum fc_parse_status fc_abts_rsp_parse(struct fchs_s *buf, int len);
+u16 fc_rrq_build(struct fchs_s *buf, struct fc_rrq_s *rrq, u32 d_id,
+                       u32 s_id, u16 ox_id, u16 rrq_oxid);
+enum fc_parse_status fc_rrq_rsp_parse(struct fchs_s *buf, int len);
+u16 fc_rspnid_build(struct fchs_s *fchs, void *pld, u32 s_id,
+                       u16 ox_id, u8 *name);
+u16 fc_rftid_build(struct fchs_s *fchs, void *pld, u32 s_id,
+                       u16 ox_id, enum bfa_port_role role);
+u16 fc_rftid_build_sol(struct fchs_s *fchs, void *pyld, u32 s_id,
+                       u16 ox_id, u8 *fc4_bitmap,
+                       u32 bitmap_size);
+u16 fc_rffid_build(struct fchs_s *fchs, void *pyld, u32 s_id,
+                       u16 ox_id, u8 fc4_type, u8 fc4_ftrs);
+u16 fc_gidpn_build(struct fchs_s *fchs, void *pyld, u32 s_id,
+                       u16 ox_id, wwn_t port_name);
+u16 fc_gpnid_build(struct fchs_s *fchs, void *pld, u32 s_id,
+                       u16 ox_id, u32 port_id);
+u16 fc_scr_build(struct fchs_s *fchs, struct fc_scr_s *scr,
+                       u8 set_br_reg, u32 s_id, u16 ox_id);
+u16 fc_plogi_acc_build(struct fchs_s *fchs, void *pld, u32 d_id,
+                       u32 s_id, u16 ox_id,
+                       wwn_t port_name, wwn_t node_name, u16 pdu_size);
+
+u16 fc_adisc_build(struct fchs_s *fchs, struct fc_adisc_s *adisc,
+                       u32 d_id, u32 s_id, u16 ox_id,
+                       wwn_t port_name, wwn_t node_name);
+enum fc_parse_status fc_adisc_parse(struct fchs_s *fchs, void *pld,
+                       u32 host_dap,
+                       wwn_t node_name, wwn_t port_name);
+enum fc_parse_status fc_adisc_rsp_parse(struct fc_adisc_s *adisc, int len,
+                       wwn_t port_name, wwn_t node_name);
+u16 fc_adisc_acc_build(struct fchs_s *fchs, struct fc_adisc_s *adisc,
+                       u32 d_id, u32 s_id, u16 ox_id,
+                       wwn_t port_name, wwn_t node_name);
+u16 fc_ls_rjt_build(struct fchs_s *fchs, struct fc_ls_rjt_s *ls_rjt,
+                       u32 d_id, u32 s_id, u16 ox_id,
+                       u8 reason_code, u8 reason_code_expl);
+u16 fc_ls_acc_build(struct fchs_s *fchs, struct fc_els_cmd_s *els_cmd,
+                       u32 d_id, u32 s_id, u16 ox_id);
+u16 fc_prli_build(struct fchs_s *fchs, void *pld, u32 d_id,
+                       u32 s_id, u16 ox_id);
+enum fc_parse_status fc_prli_rsp_parse(struct fc_prli_s *prli, int len);
+
+u16 fc_prli_acc_build(struct fchs_s *fchs, void *pld, u32 d_id,
+                       u32 s_id, u16 ox_id,
+                       enum bfa_port_role role);
+u16 fc_rnid_build(struct fchs_s *fchs, struct fc_rnid_cmd_s *rnid,
+                       u32 d_id, u32 s_id, u16 ox_id,
+                       u32 data_format);
+u16 fc_rnid_acc_build(struct fchs_s *fchs, struct fc_rnid_acc_s *rnid_acc,
+                       u32 d_id, u32 s_id, u16 ox_id,
+                       u32 data_format,
+                       struct fc_rnid_common_id_data_s *common_id_data,
+                       struct fc_rnid_general_topology_data_s *
+                       gen_topo_data);
+u16 fc_rpsc2_build(struct fchs_s *fchs, struct fc_rpsc2_cmd_s *rps2c,
+                       u32 d_id, u32 s_id,
+                       u32 *pid_list, u16 npids);
+u16 fc_rpsc_build(struct fchs_s *fchs, struct fc_rpsc_cmd_s *rpsc,
+                       u32 d_id, u32 s_id, u16 ox_id);
+u16 fc_rpsc_acc_build(struct fchs_s *fchs, struct fc_rpsc_acc_s *rpsc_acc,
+                       u32 d_id, u32 s_id, u16 ox_id,
+                       struct fc_rpsc_speed_info_s *oper_speed);
+u16 fc_gid_ft_build(struct fchs_s *fchs, void *pld, u32 s_id,
+                       u8 fc4_type);
+u16 fc_rpnid_build(struct fchs_s *fchs, void *pyld, u32 s_id,
+                       u32 port_id, wwn_t port_name);
+u16 fc_rnnid_build(struct fchs_s *fchs, void *pyld, u32 s_id,
+                       u32 port_id, wwn_t node_name);
+u16 fc_rcsid_build(struct fchs_s *fchs, void *pyld, u32 s_id,
+                       u32 port_id, u32 cos);
+u16 fc_rptid_build(struct fchs_s *fchs, void *pyld, u32 s_id,
+                       u32 port_id, u8 port_type);
+u16 fc_ganxt_build(struct fchs_s *fchs, void *pyld, u32 s_id,
+                       u32 port_id);
+u16 fc_logo_build(struct fchs_s *fchs, struct fc_logo_s *logo,
+                       u32 d_id, u32 s_id, u16 ox_id,
+                       wwn_t port_name);
+u16 fc_logo_acc_build(struct fchs_s *fchs, void *pld, u32 d_id,
+                       u32 s_id, u16 ox_id);
+u16 fc_fdmi_reqhdr_build(struct fchs_s *fchs, void *pyld, u32 s_id,
+                       u16 cmd_code);
+u16 fc_gmal_req_build(struct fchs_s *fchs, void *pyld, u32 s_id,
+                       wwn_t wwn);
+u16 fc_gfn_req_build(struct fchs_s *fchs, void *pyld, u32 s_id,
+                       wwn_t wwn);
+void fc_get_fc4type_bitmask(u8 fc4_type, u8 *bit_mask);
+void fc_els_req_build(struct fchs_s *fchs, u32 d_id, u32 s_id,
+                       u16 ox_id);
+enum fc_parse_status fc_els_rsp_parse(struct fchs_s *fchs, int len);
+enum fc_parse_status fc_plogi_rsp_parse(struct fchs_s *fchs, int len,
+                        wwn_t port_name);
+enum fc_parse_status fc_prli_parse(struct fc_prli_s *prli);
+enum fc_parse_status fc_pdisc_parse(struct fchs_s *fchs, wwn_t node_name,
+                       wwn_t port_name);
+u16 fc_ba_acc_build(struct fchs_s *fchs, struct fc_ba_acc_s *ba_acc,
+                       u32 d_id, u32 s_id, u16 ox_id,
+                       u16 rx_id);
+int fc_logout_params_pages(struct fchs_s *fc_frame, u8 els_code);
+u16 fc_tprlo_acc_build(struct fchs_s *fchs,
+                       struct fc_tprlo_acc_s *tprlo_acc,
+                       u32 d_id, u32 s_id, u16 ox_id,
+                       int num_pages);
+u16 fc_prlo_acc_build(struct fchs_s *fchs, struct fc_prlo_acc_s *prlo_acc,
+                       u32 d_id, u32 s_id, u16 ox_id,
+                       int num_pages);
+u16 fc_logo_rsp_parse(struct fchs_s *fchs, int len);
+u16 fc_pdisc_build(struct fchs_s *fchs, u32 d_id, u32 s_id,
+                       u16 ox_id, wwn_t port_name, wwn_t node_name,
+                       u16 pdu_size);
+u16 fc_pdisc_rsp_parse(struct fchs_s *fchs, int len, wwn_t port_name);
+u16 fc_prlo_build(struct fchs_s *fchs, u32 d_id, u32 s_id,
+                       u16 ox_id, int num_pages);
+u16 fc_prlo_rsp_parse(struct fchs_s *fchs, int len);
+u16 fc_tprlo_build(struct fchs_s *fchs, u32 d_id, u32 s_id,
+                       u16 ox_id, int num_pages,
+                       enum fc_tprlo_type tprlo_type, u32 tpr_id);
+u16 fc_tprlo_rsp_parse(struct fchs_s *fchs, int len);
+u16 fc_ba_rjt_build(struct fchs_s *fchs, u32 d_id, u32 s_id,
+                       u16 ox_id, u32 reason_code,
+                       u32 reason_expl);
+u16 fc_gnnid_build(struct fchs_s *fchs, void *pyld, u32 s_id,
+                       u16 ox_id, u32 port_id);
+u16 fc_ct_rsp_parse(struct ct_hdr_s *cthdr);
+u16 fc_rscn_build(struct fchs_s *fchs, struct fc_rscn_pl_s *rscn,
+                       u32 s_id, u16 ox_id);
+#endif
diff --git a/drivers/scsi/bfa/fcpim.c b/drivers/scsi/bfa/fcpim.c
new file mode 100644 (file)
index 0000000..8ce5d89
--- /dev/null
@@ -0,0 +1,844 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) 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.
+ */
+
+/**
+ *  fcpim.c - FCP initiator mode i-t nexus state machine
+ */
+
+#include <bfa.h>
+#include <bfa_svc.h>
+#include "fcs_fcpim.h"
+#include "fcs_rport.h"
+#include "fcs_lport.h"
+#include "fcs_trcmod.h"
+#include "fcs_fcxp.h"
+#include "fcs.h"
+#include <fcs/bfa_fcs_fcpim.h>
+#include <fcb/bfa_fcb_fcpim.h>
+#include <aen/bfa_aen_itnim.h>
+
+BFA_TRC_FILE(FCS, FCPIM);
+
+/*
+ * forward declarations
+ */
+static void     bfa_fcs_itnim_timeout(void *arg);
+static void     bfa_fcs_itnim_free(struct bfa_fcs_itnim_s *itnim);
+static void     bfa_fcs_itnim_send_prli(void *itnim_cbarg,
+                                       struct bfa_fcxp_s *fcxp_alloced);
+static void     bfa_fcs_itnim_prli_response(void *fcsarg,
+                                           struct bfa_fcxp_s *fcxp,
+                                           void *cbarg,
+                                           bfa_status_t req_status,
+                                           u32 rsp_len,
+                                           u32 resid_len,
+                                           struct fchs_s *rsp_fchs);
+static void     bfa_fcs_itnim_aen_post(struct bfa_fcs_itnim_s *itnim,
+                                      enum bfa_itnim_aen_event event);
+
+/**
+ *  fcs_itnim_sm FCS itnim state machine events
+ */
+
+enum bfa_fcs_itnim_event {
+       BFA_FCS_ITNIM_SM_ONLINE = 1,    /*  rport online event */
+       BFA_FCS_ITNIM_SM_OFFLINE = 2,   /*  rport offline */
+       BFA_FCS_ITNIM_SM_FRMSENT = 3,   /*  prli frame is sent */
+       BFA_FCS_ITNIM_SM_RSP_OK = 4,    /*  good response */
+       BFA_FCS_ITNIM_SM_RSP_ERROR = 5, /*  error response */
+       BFA_FCS_ITNIM_SM_TIMEOUT = 6,   /*  delay timeout */
+       BFA_FCS_ITNIM_SM_HCB_OFFLINE = 7,       /*  BFA online callback */
+       BFA_FCS_ITNIM_SM_HCB_ONLINE = 8,        /*  BFA offline callback */
+       BFA_FCS_ITNIM_SM_INITIATOR = 9, /*  rport is initiator */
+       BFA_FCS_ITNIM_SM_DELETE = 10,   /*  delete event from rport */
+       BFA_FCS_ITNIM_SM_PRLO = 11,     /*  delete event from rport */
+};
+
+static void     bfa_fcs_itnim_sm_offline(struct bfa_fcs_itnim_s *itnim,
+                                        enum bfa_fcs_itnim_event event);
+static void     bfa_fcs_itnim_sm_prli_send(struct bfa_fcs_itnim_s *itnim,
+                                          enum bfa_fcs_itnim_event event);
+static void     bfa_fcs_itnim_sm_prli(struct bfa_fcs_itnim_s *itnim,
+                                     enum bfa_fcs_itnim_event event);
+static void     bfa_fcs_itnim_sm_prli_retry(struct bfa_fcs_itnim_s *itnim,
+                                           enum bfa_fcs_itnim_event event);
+static void     bfa_fcs_itnim_sm_hcb_online(struct bfa_fcs_itnim_s *itnim,
+                                           enum bfa_fcs_itnim_event event);
+static void     bfa_fcs_itnim_sm_online(struct bfa_fcs_itnim_s *itnim,
+                                       enum bfa_fcs_itnim_event event);
+static void     bfa_fcs_itnim_sm_hcb_offline(struct bfa_fcs_itnim_s *itnim,
+                                            enum bfa_fcs_itnim_event event);
+static void     bfa_fcs_itnim_sm_initiator(struct bfa_fcs_itnim_s *itnim,
+                                          enum bfa_fcs_itnim_event event);
+
+static struct bfa_sm_table_s itnim_sm_table[] = {
+       {BFA_SM(bfa_fcs_itnim_sm_offline), BFA_ITNIM_OFFLINE},
+       {BFA_SM(bfa_fcs_itnim_sm_prli_send), BFA_ITNIM_PRLI_SEND},
+       {BFA_SM(bfa_fcs_itnim_sm_prli), BFA_ITNIM_PRLI_SENT},
+       {BFA_SM(bfa_fcs_itnim_sm_prli_retry), BFA_ITNIM_PRLI_RETRY},
+       {BFA_SM(bfa_fcs_itnim_sm_hcb_online), BFA_ITNIM_HCB_ONLINE},
+       {BFA_SM(bfa_fcs_itnim_sm_online), BFA_ITNIM_ONLINE},
+       {BFA_SM(bfa_fcs_itnim_sm_hcb_offline), BFA_ITNIM_HCB_OFFLINE},
+       {BFA_SM(bfa_fcs_itnim_sm_initiator), BFA_ITNIM_INITIATIOR},
+};
+
+/**
+ *  fcs_itnim_sm FCS itnim state machine
+ */
+
+static void
+bfa_fcs_itnim_sm_offline(struct bfa_fcs_itnim_s *itnim,
+                        enum bfa_fcs_itnim_event event)
+{
+       bfa_trc(itnim->fcs, itnim->rport->pwwn);
+       bfa_trc(itnim->fcs, event);
+
+       switch (event) {
+       case BFA_FCS_ITNIM_SM_ONLINE:
+               bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_prli_send);
+               bfa_fcs_itnim_send_prli(itnim, NULL);
+               break;
+
+       case BFA_FCS_ITNIM_SM_OFFLINE:
+               bfa_fcs_rport_itnim_ack(itnim->rport);
+               break;
+
+       case BFA_FCS_ITNIM_SM_INITIATOR:
+               bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_initiator);
+               break;
+
+       case BFA_FCS_ITNIM_SM_DELETE:
+               bfa_fcs_itnim_free(itnim);
+               break;
+
+       default:
+               bfa_assert(0);
+       }
+
+}
+
+static void
+bfa_fcs_itnim_sm_prli_send(struct bfa_fcs_itnim_s *itnim,
+                          enum bfa_fcs_itnim_event event)
+{
+       bfa_trc(itnim->fcs, itnim->rport->pwwn);
+       bfa_trc(itnim->fcs, event);
+
+       switch (event) {
+       case BFA_FCS_ITNIM_SM_FRMSENT:
+               bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_prli);
+               break;
+
+       case BFA_FCS_ITNIM_SM_INITIATOR:
+               bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_initiator);
+               bfa_fcxp_walloc_cancel(itnim->fcs->bfa, &itnim->fcxp_wqe);
+               break;
+
+       case BFA_FCS_ITNIM_SM_OFFLINE:
+               bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline);
+               bfa_fcxp_walloc_cancel(itnim->fcs->bfa, &itnim->fcxp_wqe);
+               bfa_fcs_rport_itnim_ack(itnim->rport);
+               break;
+
+       case BFA_FCS_ITNIM_SM_DELETE:
+               bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline);
+               bfa_fcxp_walloc_cancel(itnim->fcs->bfa, &itnim->fcxp_wqe);
+               bfa_fcs_itnim_free(itnim);
+               break;
+
+       default:
+               bfa_assert(0);
+       }
+}
+
+static void
+bfa_fcs_itnim_sm_prli(struct bfa_fcs_itnim_s *itnim,
+                     enum bfa_fcs_itnim_event event)
+{
+       bfa_trc(itnim->fcs, itnim->rport->pwwn);
+       bfa_trc(itnim->fcs, event);
+
+       switch (event) {
+       case BFA_FCS_ITNIM_SM_RSP_OK:
+               bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_hcb_online);
+               bfa_itnim_online(itnim->bfa_itnim, itnim->seq_rec);
+               break;
+
+       case BFA_FCS_ITNIM_SM_RSP_ERROR:
+               bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_prli_retry);
+               bfa_timer_start(itnim->fcs->bfa, &itnim->timer,
+                               bfa_fcs_itnim_timeout, itnim,
+                               BFA_FCS_RETRY_TIMEOUT);
+               break;
+
+       case BFA_FCS_ITNIM_SM_OFFLINE:
+               bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline);
+               bfa_fcxp_discard(itnim->fcxp);
+               bfa_fcs_rport_itnim_ack(itnim->rport);
+               break;
+
+       case BFA_FCS_ITNIM_SM_INITIATOR:
+               bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_initiator);
+               /*
+                * dont discard fcxp. accept will reach same state
+                */
+               break;
+
+       case BFA_FCS_ITNIM_SM_DELETE:
+               bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline);
+               bfa_fcxp_discard(itnim->fcxp);
+               bfa_fcs_itnim_free(itnim);
+               break;
+
+       default:
+               bfa_assert(0);
+       }
+}
+
+static void
+bfa_fcs_itnim_sm_prli_retry(struct bfa_fcs_itnim_s *itnim,
+                           enum bfa_fcs_itnim_event event)
+{
+       bfa_trc(itnim->fcs, itnim->rport->pwwn);
+       bfa_trc(itnim->fcs, event);
+
+       switch (event) {
+       case BFA_FCS_ITNIM_SM_TIMEOUT:
+               bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_prli_send);
+               bfa_fcs_itnim_send_prli(itnim, NULL);
+               break;
+
+       case BFA_FCS_ITNIM_SM_OFFLINE:
+               bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline);
+               bfa_timer_stop(&itnim->timer);
+               bfa_fcs_rport_itnim_ack(itnim->rport);
+               break;
+
+       case BFA_FCS_ITNIM_SM_INITIATOR:
+               bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_initiator);
+               bfa_timer_stop(&itnim->timer);
+               break;
+
+       case BFA_FCS_ITNIM_SM_DELETE:
+               bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline);
+               bfa_timer_stop(&itnim->timer);
+               bfa_fcs_itnim_free(itnim);
+               break;
+
+       default:
+               bfa_assert(0);
+       }
+}
+
+static void
+bfa_fcs_itnim_sm_hcb_online(struct bfa_fcs_itnim_s *itnim,
+                           enum bfa_fcs_itnim_event event)
+{
+       bfa_trc(itnim->fcs, itnim->rport->pwwn);
+       bfa_trc(itnim->fcs, event);
+
+       switch (event) {
+       case BFA_FCS_ITNIM_SM_HCB_ONLINE:
+               bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_online);
+               bfa_fcb_itnim_online(itnim->itnim_drv);
+               bfa_fcs_itnim_aen_post(itnim, BFA_ITNIM_AEN_ONLINE);
+               break;
+
+       case BFA_FCS_ITNIM_SM_OFFLINE:
+               bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline);
+               bfa_itnim_offline(itnim->bfa_itnim);
+               bfa_fcs_rport_itnim_ack(itnim->rport);
+               break;
+
+       case BFA_FCS_ITNIM_SM_DELETE:
+               bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline);
+               bfa_fcs_itnim_free(itnim);
+               break;
+
+       default:
+               bfa_assert(0);
+       }
+}
+
+static void
+bfa_fcs_itnim_sm_online(struct bfa_fcs_itnim_s *itnim,
+                       enum bfa_fcs_itnim_event event)
+{
+       bfa_trc(itnim->fcs, itnim->rport->pwwn);
+       bfa_trc(itnim->fcs, event);
+
+       switch (event) {
+       case BFA_FCS_ITNIM_SM_OFFLINE:
+               bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_hcb_offline);
+               bfa_fcb_itnim_offline(itnim->itnim_drv);
+               bfa_itnim_offline(itnim->bfa_itnim);
+               if (bfa_fcs_port_is_online(itnim->rport->port) == BFA_TRUE) {
+                       bfa_fcs_itnim_aen_post(itnim, BFA_ITNIM_AEN_DISCONNECT);
+               } else {
+                       bfa_fcs_itnim_aen_post(itnim, BFA_ITNIM_AEN_OFFLINE);
+               }
+               break;
+
+       case BFA_FCS_ITNIM_SM_DELETE:
+               bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline);
+               bfa_fcs_itnim_free(itnim);
+               break;
+
+       default:
+               bfa_assert(0);
+       }
+}
+
+static void
+bfa_fcs_itnim_sm_hcb_offline(struct bfa_fcs_itnim_s *itnim,
+                            enum bfa_fcs_itnim_event event)
+{
+       bfa_trc(itnim->fcs, itnim->rport->pwwn);
+       bfa_trc(itnim->fcs, event);
+
+       switch (event) {
+       case BFA_FCS_ITNIM_SM_HCB_OFFLINE:
+               bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline);
+               bfa_fcs_rport_itnim_ack(itnim->rport);
+               break;
+
+       case BFA_FCS_ITNIM_SM_DELETE:
+               bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline);
+               bfa_fcs_itnim_free(itnim);
+               break;
+
+       default:
+               bfa_assert(0);
+       }
+}
+
+/*
+ * This state is set when a discovered rport is also in intiator mode.
+ * This ITN is marked as no_op and is not active and will not be truned into
+ * online state.
+ */
+static void
+bfa_fcs_itnim_sm_initiator(struct bfa_fcs_itnim_s *itnim,
+                          enum bfa_fcs_itnim_event event)
+{
+       bfa_trc(itnim->fcs, itnim->rport->pwwn);
+       bfa_trc(itnim->fcs, event);
+
+       switch (event) {
+       case BFA_FCS_ITNIM_SM_OFFLINE:
+               bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline);
+               bfa_fcs_rport_itnim_ack(itnim->rport);
+               break;
+
+       case BFA_FCS_ITNIM_SM_RSP_ERROR:
+       case BFA_FCS_ITNIM_SM_ONLINE:
+       case BFA_FCS_ITNIM_SM_INITIATOR:
+               break;
+
+       case BFA_FCS_ITNIM_SM_DELETE:
+               bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline);
+               bfa_fcs_itnim_free(itnim);
+               break;
+
+       default:
+               bfa_assert(0);
+       }
+}
+
+
+
+/**
+ *  itnim_private FCS ITNIM private interfaces
+ */
+
+static void
+bfa_fcs_itnim_aen_post(struct bfa_fcs_itnim_s *itnim,
+                      enum bfa_itnim_aen_event event)
+{
+       struct bfa_fcs_rport_s *rport = itnim->rport;
+       union bfa_aen_data_u aen_data;
+       struct bfa_log_mod_s *logmod = rport->fcs->logm;
+       wwn_t           lpwwn = bfa_fcs_port_get_pwwn(rport->port);
+       wwn_t           rpwwn = rport->pwwn;
+       char            lpwwn_ptr[BFA_STRING_32];
+       char            rpwwn_ptr[BFA_STRING_32];
+
+       /*
+        * Don't post events for well known addresses
+        */
+       if (BFA_FCS_PID_IS_WKA(rport->pid))
+               return;
+
+       wwn2str(lpwwn_ptr, lpwwn);
+       wwn2str(rpwwn_ptr, rpwwn);
+
+       switch (event) {
+       case BFA_ITNIM_AEN_ONLINE:
+               bfa_log(logmod, BFA_AEN_ITNIM_ONLINE, rpwwn_ptr, lpwwn_ptr);
+               break;
+       case BFA_ITNIM_AEN_OFFLINE:
+               bfa_log(logmod, BFA_AEN_ITNIM_OFFLINE, rpwwn_ptr, lpwwn_ptr);
+               break;
+       case BFA_ITNIM_AEN_DISCONNECT:
+               bfa_log(logmod, BFA_AEN_ITNIM_DISCONNECT, rpwwn_ptr, lpwwn_ptr);
+               break;
+       default:
+               break;
+       }
+
+       aen_data.itnim.vf_id = rport->port->fabric->vf_id;
+       aen_data.itnim.ppwwn =
+               bfa_fcs_port_get_pwwn(bfa_fcs_get_base_port(itnim->fcs));
+       aen_data.itnim.lpwwn = lpwwn;
+       aen_data.itnim.rpwwn = rpwwn;
+}
+
+static void
+bfa_fcs_itnim_send_prli(void *itnim_cbarg, struct bfa_fcxp_s *fcxp_alloced)
+{
+       struct bfa_fcs_itnim_s *itnim = itnim_cbarg;
+       struct bfa_fcs_rport_s *rport = itnim->rport;
+       struct bfa_fcs_port_s *port = rport->port;
+       struct fchs_s          fchs;
+       struct bfa_fcxp_s *fcxp;
+       int             len;
+
+       bfa_trc(itnim->fcs, itnim->rport->pwwn);
+
+       fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
+       if (!fcxp) {
+               itnim->stats.fcxp_alloc_wait++;
+               bfa_fcxp_alloc_wait(port->fcs->bfa, &itnim->fcxp_wqe,
+                                   bfa_fcs_itnim_send_prli, itnim);
+               return;
+       }
+       itnim->fcxp = fcxp;
+
+       len = fc_prli_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), itnim->rport->pid,
+                           bfa_fcs_port_get_fcid(port), 0);
+
+       bfa_fcxp_send(fcxp, rport->bfa_rport, port->fabric->vf_id, port->lp_tag,
+                     BFA_FALSE, FC_CLASS_3, len, &fchs,
+                     bfa_fcs_itnim_prli_response, (void *)itnim, FC_MAX_PDUSZ,
+                     FC_RA_TOV);
+
+       itnim->stats.prli_sent++;
+       bfa_sm_send_event(itnim, BFA_FCS_ITNIM_SM_FRMSENT);
+}
+
+static void
+bfa_fcs_itnim_prli_response(void *fcsarg, struct bfa_fcxp_s *fcxp, void *cbarg,
+                           bfa_status_t req_status, u32 rsp_len,
+                           u32 resid_len, struct fchs_s *rsp_fchs)
+{
+       struct bfa_fcs_itnim_s *itnim = (struct bfa_fcs_itnim_s *)cbarg;
+       struct fc_els_cmd_s   *els_cmd;
+       struct fc_prli_s      *prli_resp;
+       struct fc_ls_rjt_s    *ls_rjt;
+       struct fc_prli_params_s *sparams;
+
+       bfa_trc(itnim->fcs, req_status);
+
+       /*
+        * Sanity Checks
+        */
+       if (req_status != BFA_STATUS_OK) {
+               itnim->stats.prli_rsp_err++;
+               bfa_sm_send_event(itnim, BFA_FCS_ITNIM_SM_RSP_ERROR);
+               return;
+       }
+
+       els_cmd = (struct fc_els_cmd_s *) BFA_FCXP_RSP_PLD(fcxp);
+
+       if (els_cmd->els_code == FC_ELS_ACC) {
+               prli_resp = (struct fc_prli_s *) els_cmd;
+
+               if (fc_prli_rsp_parse(prli_resp, rsp_len) != FC_PARSE_OK) {
+                       bfa_trc(itnim->fcs, rsp_len);
+                       /*
+                        * Check if this  r-port is also in Initiator mode.
+                        * If so, we need to set this ITN as a no-op.
+                        */
+                       if (prli_resp->parampage.servparams.initiator) {
+                               bfa_trc(itnim->fcs, prli_resp->parampage.type);
+                               itnim->rport->scsi_function =
+                                       BFA_RPORT_INITIATOR;
+                               itnim->stats.prli_rsp_acc++;
+                               bfa_sm_send_event(itnim,
+                                                 BFA_FCS_ITNIM_SM_INITIATOR);
+                               return;
+                       }
+
+                       itnim->stats.prli_rsp_parse_err++;
+                       return;
+               }
+               itnim->rport->scsi_function = BFA_RPORT_TARGET;
+
+               sparams = &prli_resp->parampage.servparams;
+               itnim->seq_rec = sparams->retry;
+               itnim->rec_support = sparams->rec_support;
+               itnim->task_retry_id = sparams->task_retry_id;
+               itnim->conf_comp = sparams->confirm;
+
+               itnim->stats.prli_rsp_acc++;
+               bfa_sm_send_event(itnim, BFA_FCS_ITNIM_SM_RSP_OK);
+       } else {
+               ls_rjt = (struct fc_ls_rjt_s *) BFA_FCXP_RSP_PLD(fcxp);
+
+               bfa_trc(itnim->fcs, ls_rjt->reason_code);
+               bfa_trc(itnim->fcs, ls_rjt->reason_code_expl);
+
+               itnim->stats.prli_rsp_rjt++;
+               bfa_sm_send_event(itnim, BFA_FCS_ITNIM_SM_RSP_ERROR);
+       }
+}
+
+static void
+bfa_fcs_itnim_timeout(void *arg)
+{
+       struct bfa_fcs_itnim_s *itnim = (struct bfa_fcs_itnim_s *)arg;
+
+       itnim->stats.timeout++;
+       bfa_sm_send_event(itnim, BFA_FCS_ITNIM_SM_TIMEOUT);
+}
+
+static void
+bfa_fcs_itnim_free(struct bfa_fcs_itnim_s *itnim)
+{
+       bfa_itnim_delete(itnim->bfa_itnim);
+       bfa_fcb_itnim_free(itnim->fcs->bfad, itnim->itnim_drv);
+}
+
+
+
+/**
+ *  itnim_public FCS ITNIM public interfaces
+ */
+
+/**
+ *     Called by rport when a new rport is created.
+ *
+ * @param[in] rport    -  remote port.
+ */
+struct bfa_fcs_itnim_s *
+bfa_fcs_itnim_create(struct bfa_fcs_rport_s *rport)
+{
+       struct bfa_fcs_port_s *port = rport->port;
+       struct bfa_fcs_itnim_s *itnim;
+       struct bfad_itnim_s *itnim_drv;
+       struct bfa_itnim_s *bfa_itnim;
+
+       /*
+        * call bfad to allocate the itnim
+        */
+       bfa_fcb_itnim_alloc(port->fcs->bfad, &itnim, &itnim_drv);
+       if (itnim == NULL) {
+               bfa_trc(port->fcs, rport->pwwn);
+               return NULL;
+       }
+
+       /*
+        * Initialize itnim
+        */
+       itnim->rport = rport;
+       itnim->fcs = rport->fcs;
+       itnim->itnim_drv = itnim_drv;
+
+       /*
+        * call BFA to create the itnim
+        */
+       bfa_itnim = bfa_itnim_create(port->fcs->bfa, rport->bfa_rport, itnim);
+
+       if (bfa_itnim == NULL) {
+               bfa_trc(port->fcs, rport->pwwn);
+               bfa_fcb_itnim_free(port->fcs->bfad, itnim_drv);
+               bfa_assert(0);
+               return NULL;
+       }
+
+       itnim->bfa_itnim = bfa_itnim;
+       itnim->seq_rec = BFA_FALSE;
+       itnim->rec_support = BFA_FALSE;
+       itnim->conf_comp = BFA_FALSE;
+       itnim->task_retry_id = BFA_FALSE;
+
+       /*
+        * Set State machine
+        */
+       bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline);
+
+       return itnim;
+}
+
+/**
+ *     Called by rport to delete  the instance of FCPIM.
+ *
+ * @param[in] rport    -  remote port.
+ */
+void
+bfa_fcs_itnim_delete(struct bfa_fcs_itnim_s *itnim)
+{
+       bfa_trc(itnim->fcs, itnim->rport->pid);
+       bfa_sm_send_event(itnim, BFA_FCS_ITNIM_SM_DELETE);
+}
+
+/**
+ * Notification from rport that PLOGI is complete to initiate FC-4 session.
+ */
+void
+bfa_fcs_itnim_rport_online(struct bfa_fcs_itnim_s *itnim)
+{
+       itnim->stats.onlines++;
+
+       if (!BFA_FCS_PID_IS_WKA(itnim->rport->pid)) {
+               bfa_sm_send_event(itnim, BFA_FCS_ITNIM_SM_ONLINE);
+       } else {
+               /*
+                * For well known addresses, we set the itnim to initiator
+                * state
+                */
+               itnim->stats.initiator++;
+               bfa_sm_send_event(itnim, BFA_FCS_ITNIM_SM_INITIATOR);
+       }
+}
+
+/**
+ * Called by rport to handle a remote device offline.
+ */
+void
+bfa_fcs_itnim_rport_offline(struct bfa_fcs_itnim_s *itnim)
+{
+       itnim->stats.offlines++;
+       bfa_sm_send_event(itnim, BFA_FCS_ITNIM_SM_OFFLINE);
+}
+
+/**
+ * Called by rport when remote port is known to be an initiator from
+ * PRLI received.
+ */
+void
+bfa_fcs_itnim_is_initiator(struct bfa_fcs_itnim_s *itnim)
+{
+       bfa_trc(itnim->fcs, itnim->rport->pid);
+       itnim->stats.initiator++;
+       bfa_sm_send_event(itnim, BFA_FCS_ITNIM_SM_INITIATOR);
+}
+
+/**
+ * Called by rport to check if the itnim is online.
+ */
+bfa_status_t
+bfa_fcs_itnim_get_online_state(struct bfa_fcs_itnim_s *itnim)
+{
+       bfa_trc(itnim->fcs, itnim->rport->pid);
+       switch (bfa_sm_to_state(itnim_sm_table, itnim->sm)) {
+       case BFA_ITNIM_ONLINE:
+       case BFA_ITNIM_INITIATIOR:
+               return BFA_STATUS_OK;
+
+       default:
+               return BFA_STATUS_NO_FCPIM_NEXUS;
+
+       }
+}
+
+/**
+ * BFA completion callback for bfa_itnim_online().
+ */
+void
+bfa_cb_itnim_online(void *cbarg)
+{
+       struct bfa_fcs_itnim_s *itnim = (struct bfa_fcs_itnim_s *)cbarg;
+
+       bfa_trc(itnim->fcs, itnim->rport->pwwn);
+       bfa_sm_send_event(itnim, BFA_FCS_ITNIM_SM_HCB_ONLINE);
+}
+
+/**
+ * BFA completion callback for bfa_itnim_offline().
+ */
+void
+bfa_cb_itnim_offline(void *cb_arg)
+{
+       struct bfa_fcs_itnim_s *itnim = (struct bfa_fcs_itnim_s *)cb_arg;
+
+       bfa_trc(itnim->fcs, itnim->rport->pwwn);
+       bfa_sm_send_event(itnim, BFA_FCS_ITNIM_SM_HCB_OFFLINE);
+}
+
+/**
+ * Mark the beginning of PATH TOV handling. IO completion callbacks
+ * are still pending.
+ */
+void
+bfa_cb_itnim_tov_begin(void *cb_arg)
+{
+       struct bfa_fcs_itnim_s *itnim = (struct bfa_fcs_itnim_s *)cb_arg;
+
+       bfa_trc(itnim->fcs, itnim->rport->pwwn);
+       bfa_fcb_itnim_tov_begin(itnim->itnim_drv);
+}
+
+/**
+ * Mark the end of PATH TOV handling. All pending IOs are already cleaned up.
+ */
+void
+bfa_cb_itnim_tov(void *cb_arg)
+{
+       struct bfa_fcs_itnim_s *itnim = (struct bfa_fcs_itnim_s *)cb_arg;
+
+       bfa_trc(itnim->fcs, itnim->rport->pwwn);
+       bfa_fcb_itnim_tov(itnim->itnim_drv);
+}
+
+/**
+ *             BFA notification to FCS/driver for second level error recovery.
+ *
+ * Atleast one I/O request has timedout and target is unresponsive to
+ * repeated abort requests. Second level error recovery should be initiated
+ * by starting implicit logout and recovery procedures.
+ */
+void
+bfa_cb_itnim_sler(void *cb_arg)
+{
+       struct bfa_fcs_itnim_s *itnim = (struct bfa_fcs_itnim_s *)cb_arg;
+
+       itnim->stats.sler++;
+       bfa_trc(itnim->fcs, itnim->rport->pwwn);
+       bfa_fcs_rport_logo_imp(itnim->rport);
+}
+
+struct bfa_fcs_itnim_s *
+bfa_fcs_itnim_lookup(struct bfa_fcs_port_s *port, wwn_t rpwwn)
+{
+       struct bfa_fcs_rport_s *rport;
+       rport = bfa_fcs_rport_lookup(port, rpwwn);
+
+       if (!rport)
+               return NULL;
+
+       bfa_assert(rport->itnim != NULL);
+       return (rport->itnim);
+}
+
+bfa_status_t
+bfa_fcs_itnim_attr_get(struct bfa_fcs_port_s *port, wwn_t rpwwn,
+                      struct bfa_itnim_attr_s *attr)
+{
+       struct bfa_fcs_itnim_s *itnim = NULL;
+
+       itnim = bfa_fcs_itnim_lookup(port, rpwwn);
+
+       if (itnim == NULL)
+               return BFA_STATUS_NO_FCPIM_NEXUS;
+
+       attr->state = bfa_sm_to_state(itnim_sm_table, itnim->sm);
+       attr->retry = itnim->seq_rec;
+       attr->rec_support = itnim->rec_support;
+       attr->conf_comp = itnim->conf_comp;
+       attr->task_retry_id = itnim->task_retry_id;
+
+       return BFA_STATUS_OK;
+}
+
+bfa_status_t
+bfa_fcs_itnim_stats_get(struct bfa_fcs_port_s *port, wwn_t rpwwn,
+                       struct bfa_itnim_stats_s *stats)
+{
+       struct bfa_fcs_itnim_s *itnim = NULL;
+
+       bfa_assert(port != NULL);
+
+       itnim = bfa_fcs_itnim_lookup(port, rpwwn);
+
+       if (itnim == NULL)
+               return BFA_STATUS_NO_FCPIM_NEXUS;
+
+       bfa_os_memcpy(stats, &itnim->stats, sizeof(struct bfa_itnim_stats_s));
+
+       return BFA_STATUS_OK;
+}
+
+bfa_status_t
+bfa_fcs_itnim_stats_clear(struct bfa_fcs_port_s *port, wwn_t rpwwn)
+{
+       struct bfa_fcs_itnim_s *itnim = NULL;
+
+       bfa_assert(port != NULL);
+
+       itnim = bfa_fcs_itnim_lookup(port, rpwwn);
+
+       if (itnim == NULL)
+               return BFA_STATUS_NO_FCPIM_NEXUS;
+
+       bfa_os_memset(&itnim->stats, 0, sizeof(struct bfa_itnim_stats_s));
+       return BFA_STATUS_OK;
+}
+
+void
+bfa_fcs_fcpim_uf_recv(struct bfa_fcs_itnim_s *itnim, struct fchs_s *fchs,
+                     u16 len)
+{
+       struct fc_els_cmd_s   *els_cmd;
+
+       bfa_trc(itnim->fcs, fchs->type);
+
+       if (fchs->type != FC_TYPE_ELS)
+               return;
+
+       els_cmd = (struct fc_els_cmd_s *) (fchs + 1);
+
+       bfa_trc(itnim->fcs, els_cmd->els_code);
+
+       switch (els_cmd->els_code) {
+       case FC_ELS_PRLO:
+               /* bfa_sm_send_event(itnim, BFA_FCS_ITNIM_SM_PRLO); */
+               break;
+
+       default:
+               bfa_assert(0);
+       }
+}
+
+void
+bfa_fcs_itnim_pause(struct bfa_fcs_itnim_s *itnim)
+{
+}
+
+void
+bfa_fcs_itnim_resume(struct bfa_fcs_itnim_s *itnim)
+{
+}
+
+/**
+ *   Module initialization
+ */
+void
+bfa_fcs_fcpim_modinit(struct bfa_fcs_s *fcs)
+{
+}
+
+/**
+ *   Module cleanup
+ */
+void
+bfa_fcs_fcpim_modexit(struct bfa_fcs_s *fcs)
+{
+       bfa_fcs_modexit_comp(fcs);
+}
+
+
diff --git a/drivers/scsi/bfa/fcptm.c b/drivers/scsi/bfa/fcptm.c
new file mode 100644 (file)
index 0000000..8c8b08c
--- /dev/null
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) 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.
+ */
+
+/**
+ * This file contains dummy FCPTM routines to aid in Initiator Mode only
+ * compilation of OS driver.
+ *
+ */
+
+#include "bfa_os_inc.h"
+#include "fcs_rport.h"
+#include "fcs_fcptm.h"
+#include "fcs/bfa_fcs_rport.h"
+
+struct bfa_fcs_tin_s *
+bfa_fcs_tin_create(struct bfa_fcs_rport_s *rport)
+{
+       return NULL;
+}
+
+void
+bfa_fcs_tin_delete(struct bfa_fcs_tin_s *tin)
+{
+}
+
+void
+bfa_fcs_tin_rport_offline(struct bfa_fcs_tin_s *tin)
+{
+}
+
+void
+bfa_fcs_tin_rport_online(struct bfa_fcs_tin_s *tin)
+{
+}
+
+void
+bfa_fcs_tin_rx_prli(struct bfa_fcs_tin_s *tin, struct fchs_s *fchs, u16 len)
+{
+}
+
+void
+bfa_fcs_fcptm_uf_recv(struct bfa_fcs_tin_s *tin, struct fchs_s *fchs, u16 len)
+{
+}
+
+void
+bfa_fcs_tin_pause(struct bfa_fcs_tin_s *tin)
+{
+}
+
+void
+bfa_fcs_tin_resume(struct bfa_fcs_tin_s *tin)
+{
+}
diff --git a/drivers/scsi/bfa/fcs.h b/drivers/scsi/bfa/fcs.h
new file mode 100644 (file)
index 0000000..deee685
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) 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.
+ */
+
+/**
+ *  fcs.h FCS module functions
+ */
+
+
+#ifndef __FCS_H__
+#define __FCS_H__
+
+#define __fcs_min_cfg(__fcs)       (__fcs)->min_cfg
+
+void bfa_fcs_modexit_comp(struct bfa_fcs_s *fcs);
+
+#endif /* __FCS_H__ */
diff --git a/drivers/scsi/bfa/fcs_auth.h b/drivers/scsi/bfa/fcs_auth.h
new file mode 100644 (file)
index 0000000..65d155f
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) 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.
+ */
+
+/**
+ *  fcs_uf.h FCS unsolicited frame receive
+ */
+
+
+#ifndef __FCS_AUTH_H__
+#define __FCS_AUTH_H__
+
+#include <fcs/bfa_fcs.h>
+#include <fcs/bfa_fcs_vport.h>
+#include <fcs/bfa_fcs_lport.h>
+
+/*
+ * fcs friend functions: only between fcs modules
+ */
+void bfa_fcs_auth_uf_recv(struct bfa_fcs_fabric_s *fabric, int len);
+void bfa_fcs_auth_start(struct bfa_fcs_fabric_s *fabric);
+void bfa_fcs_auth_stop(struct bfa_fcs_fabric_s *fabric);
+
+#endif /* __FCS_UF_H__ */
diff --git a/drivers/scsi/bfa/fcs_fabric.h b/drivers/scsi/bfa/fcs_fabric.h
new file mode 100644 (file)
index 0000000..eee9608
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) 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.
+ */
+
+/**
+ *  fcs_lport.h FCS logical port interfaces
+ */
+
+#ifndef __FCS_FABRIC_H__
+#define __FCS_FABRIC_H__
+
+#include <fcs/bfa_fcs.h>
+#include <fcs/bfa_fcs_vport.h>
+#include <fcs/bfa_fcs_lport.h>
+
+/*
+* fcs friend functions: only between fcs modules
+ */
+void            bfa_fcs_fabric_modinit(struct bfa_fcs_s *fcs);
+void            bfa_fcs_fabric_modexit(struct bfa_fcs_s *fcs);
+void            bfa_fcs_fabric_modsusp(struct bfa_fcs_s *fcs);
+void            bfa_fcs_fabric_link_up(struct bfa_fcs_fabric_s *fabric);
+void            bfa_fcs_fabric_link_down(struct bfa_fcs_fabric_s *fabric);
+void            bfa_fcs_fabric_addvport(struct bfa_fcs_fabric_s *fabric,
+                                       struct bfa_fcs_vport_s *vport);
+void            bfa_fcs_fabric_delvport(struct bfa_fcs_fabric_s *fabric,
+                                       struct bfa_fcs_vport_s *vport);
+int             bfa_fcs_fabric_is_online(struct bfa_fcs_fabric_s *fabric);
+struct bfa_fcs_vport_s *bfa_fcs_fabric_vport_lookup(
+                       struct bfa_fcs_fabric_s *fabric, wwn_t pwwn);
+void            bfa_fcs_fabric_modstart(struct bfa_fcs_s *fcs);
+void            bfa_fcs_fabric_uf_recv(struct bfa_fcs_fabric_s *fabric,
+                       struct fchs_s *fchs, u16 len);
+u16        bfa_fcs_fabric_vport_count(struct bfa_fcs_fabric_s *fabric);
+bfa_boolean_t   bfa_fcs_fabric_is_loopback(struct bfa_fcs_fabric_s *fabric);
+enum bfa_pport_type bfa_fcs_fabric_port_type(struct bfa_fcs_fabric_s *fabric);
+void           bfa_fcs_fabric_psymb_init(struct bfa_fcs_fabric_s *fabric);
+void bfa_fcs_fabric_port_delete_comp(struct bfa_fcs_fabric_s *fabric);
+
+bfa_status_t bfa_fcs_fabric_addvf(struct bfa_fcs_fabric_s *vf,
+                       struct bfa_fcs_s *fcs, struct bfa_port_cfg_s *port_cfg,
+                       struct bfad_vf_s *vf_drv);
+void bfa_fcs_auth_finished(struct bfa_fcs_fabric_s *fabric,
+                       enum auth_status status);
+
+void bfa_fcs_fabric_set_fabric_name(struct bfa_fcs_fabric_s *fabric,
+                       wwn_t fabric_name);
+#endif /* __FCS_FABRIC_H__ */
diff --git a/drivers/scsi/bfa/fcs_fcpim.h b/drivers/scsi/bfa/fcs_fcpim.h
new file mode 100644 (file)
index 0000000..61e9e26
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ */
+#ifndef __FCS_FCPIM_H__
+#define __FCS_FCPIM_H__
+
+#include <defs/bfa_defs_port.h>
+#include <fcs/bfa_fcs_lport.h>
+#include <fcs/bfa_fcs_rport.h>
+
+/*
+ * Following routines are from FCPIM and will be called by rport.
+ */
+struct bfa_fcs_itnim_s *bfa_fcs_itnim_create(struct bfa_fcs_rport_s *rport);
+void bfa_fcs_itnim_delete(struct bfa_fcs_itnim_s *itnim);
+void bfa_fcs_itnim_rport_offline(struct bfa_fcs_itnim_s *itnim);
+void bfa_fcs_itnim_rport_online(struct bfa_fcs_itnim_s *itnim);
+bfa_status_t bfa_fcs_itnim_get_online_state(struct bfa_fcs_itnim_s *itnim);
+
+void bfa_fcs_itnim_is_initiator(struct bfa_fcs_itnim_s *itnim);
+void bfa_fcs_itnim_pause(struct bfa_fcs_itnim_s *itnim);
+void bfa_fcs_itnim_resume(struct bfa_fcs_itnim_s *itnim);
+
+/*
+ * Modudle init/cleanup routines.
+ */
+void bfa_fcs_fcpim_modinit(struct bfa_fcs_s *fcs);
+void bfa_fcs_fcpim_modexit(struct bfa_fcs_s *fcs);
+void bfa_fcs_fcpim_uf_recv(struct bfa_fcs_itnim_s *itnim, struct fchs_s *fchs,
+                       u16 len);
+#endif /* __FCS_FCPIM_H__ */
diff --git a/drivers/scsi/bfa/fcs_fcptm.h b/drivers/scsi/bfa/fcs_fcptm.h
new file mode 100644 (file)
index 0000000..ffff082
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ */
+
+#ifndef __FCS_FCPTM_H__
+#define __FCS_FCPTM_H__
+
+#include <defs/bfa_defs_port.h>
+#include <fcs/bfa_fcs_lport.h>
+#include <fcs/bfa_fcs_rport.h>
+
+/*
+ * Following routines are from FCPTM and will be called by rport.
+ */
+struct bfa_fcs_tin_s *bfa_fcs_tin_create(struct bfa_fcs_rport_s *rport);
+void bfa_fcs_tin_rport_offline(struct bfa_fcs_tin_s *tin);
+void bfa_fcs_tin_rport_online(struct bfa_fcs_tin_s *tin);
+void bfa_fcs_tin_delete(struct bfa_fcs_tin_s *tin);
+void bfa_fcs_tin_rx_prli(struct bfa_fcs_tin_s *tin, struct fchs_s *fchs,
+                       u16 len);
+void bfa_fcs_tin_pause(struct bfa_fcs_tin_s *tin);
+void bfa_fcs_tin_resume(struct bfa_fcs_tin_s *tin);
+
+/*
+ * Modudle init/cleanup routines.
+ */
+void bfa_fcs_fcptm_modinit(struct bfa_fcs_s *fcs);
+void bfa_fcs_fcptm_modexit(struct bfa_fcs_s *fcs);
+void bfa_fcs_fcptm_uf_recv(struct bfa_fcs_tin_s *tin, struct fchs_s *fchs,
+                       u16 len);
+
+#endif /* __FCS_FCPTM_H__ */
diff --git a/drivers/scsi/bfa/fcs_fcxp.h b/drivers/scsi/bfa/fcs_fcxp.h
new file mode 100644 (file)
index 0000000..8277fe9
--- /dev/null
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) 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.
+ */
+
+/**
+ *  fcs_fcxp.h FCXP helper macros for FCS
+ */
+
+
+#ifndef __FCS_FCXP_H__
+#define __FCS_FCXP_H__
+
+#define bfa_fcs_fcxp_alloc(__fcs)      \
+       bfa_fcxp_alloc(NULL, (__fcs)->bfa, 0, 0, NULL, NULL, NULL, NULL)
+
+#endif /* __FCS_FCXP_H__ */
diff --git a/drivers/scsi/bfa/fcs_lport.h b/drivers/scsi/bfa/fcs_lport.h
new file mode 100644 (file)
index 0000000..ae744ba
--- /dev/null
@@ -0,0 +1,117 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) 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.
+ */
+
+/**
+ *  fcs_lport.h FCS logical port interfaces
+ */
+
+#ifndef __FCS_LPORT_H__
+#define __FCS_LPORT_H__
+
+#define __VPORT_H__
+#include <defs/bfa_defs_port.h>
+#include <bfa_svc.h>
+#include <fcs/bfa_fcs_lport.h>
+#include <fcs/bfa_fcs_rport.h>
+#include <fcs/bfa_fcs_vport.h>
+#include <fcs_fabric.h>
+#include <fcs_ms.h>
+#include <cs/bfa_q.h>
+#include <fcbuild.h>
+
+/*
+ * PID used in P2P/N2N ( In Big Endian)
+ */
+#define N2N_LOCAL_PID      0x010000
+#define N2N_REMOTE_PID         0x020000
+
+/*
+ * Misc Timeouts
+ */
+/*
+ * To be used when spawning a timer before retrying a failed command. Milli
+ * Secs.
+ */
+#define        BFA_FCS_RETRY_TIMEOUT 2000
+
+/*
+ * Check for Port/Vport Mode/Role
+ */
+#define        BFA_FCS_VPORT_IS_INITIATOR_MODE(port) \
+               (port->port_cfg.roles & BFA_PORT_ROLE_FCP_IM)
+
+#define        BFA_FCS_VPORT_IS_TARGET_MODE(port) \
+               (port->port_cfg.roles & BFA_PORT_ROLE_FCP_TM)
+
+#define        BFA_FCS_VPORT_IS_IPFC_MODE(port) \
+               (port->port_cfg.roles & BFA_PORT_ROLE_FCP_IPFC)
+
+/*
+ * Is this a Well Known Address
+ */
+#define BFA_FCS_PID_IS_WKA(pid)  ((bfa_os_ntoh3b(pid) > 0xFFF000) ?  1 : 0)
+
+/*
+ * Pointer to elements within Port
+ */
+#define BFA_FCS_GET_HAL_FROM_PORT(port)  (port->fcs->bfa)
+#define BFA_FCS_GET_NS_FROM_PORT(port)  (&port->port_topo.pfab.ns)
+#define BFA_FCS_GET_SCN_FROM_PORT(port)  (&port->port_topo.pfab.scn)
+#define BFA_FCS_GET_MS_FROM_PORT(port)  (&port->port_topo.pfab.ms)
+#define BFA_FCS_GET_FDMI_FROM_PORT(port)  (&port->port_topo.pfab.ms.fdmi)
+
+/*
+ * handler for unsolicied frames
+ */
+void bfa_fcs_port_uf_recv(struct bfa_fcs_port_s *lport, struct fchs_s *fchs,
+                       u16 len);
+
+/*
+ * Following routines will be called by Fabric to indicate port
+ * online/offline to vport.
+ */
+void bfa_fcs_lport_init(struct bfa_fcs_port_s *lport, struct bfa_fcs_s *fcs,
+                       u16 vf_id, struct bfa_port_cfg_s *port_cfg,
+                       struct bfa_fcs_vport_s *vport);
+void bfa_fcs_port_online(struct bfa_fcs_port_s *port);
+void bfa_fcs_port_offline(struct bfa_fcs_port_s *port);
+void bfa_fcs_port_delete(struct bfa_fcs_port_s *port);
+bfa_boolean_t   bfa_fcs_port_is_online(struct bfa_fcs_port_s *port);
+
+/*
+ * Lookup rport based on PID
+ */
+struct bfa_fcs_rport_s *bfa_fcs_port_get_rport_by_pid(
+                       struct bfa_fcs_port_s *port, u32 pid);
+
+/*
+ * Lookup rport based on PWWN
+ */
+struct bfa_fcs_rport_s *bfa_fcs_port_get_rport_by_pwwn(
+                       struct bfa_fcs_port_s *port, wwn_t pwwn);
+struct bfa_fcs_rport_s *bfa_fcs_port_get_rport_by_nwwn(
+                       struct bfa_fcs_port_s *port, wwn_t nwwn);
+void bfa_fcs_port_add_rport(struct bfa_fcs_port_s *port,
+                       struct bfa_fcs_rport_s *rport);
+void bfa_fcs_port_del_rport(struct bfa_fcs_port_s *port,
+                       struct bfa_fcs_rport_s *rport);
+
+void bfa_fcs_port_modinit(struct bfa_fcs_s *fcs);
+void bfa_fcs_port_modexit(struct bfa_fcs_s *fcs);
+void bfa_fcs_port_lip(struct bfa_fcs_port_s *port);
+
+#endif /* __FCS_LPORT_H__ */
diff --git a/drivers/scsi/bfa/fcs_ms.h b/drivers/scsi/bfa/fcs_ms.h
new file mode 100644 (file)
index 0000000..b6a8c12
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) 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.
+ */
+
+/**
+ *  fcs_ms.h FCS ms interfaces
+ */
+#ifndef __FCS_MS_H__
+#define __FCS_MS_H__
+
+/* MS FCS routines */
+void bfa_fcs_port_ms_init(struct bfa_fcs_port_s *port);
+void bfa_fcs_port_ms_offline(struct bfa_fcs_port_s *port);
+void bfa_fcs_port_ms_online(struct bfa_fcs_port_s *port);
+void bfa_fcs_port_ms_fabric_rscn(struct bfa_fcs_port_s *port);
+
+/* FDMI FCS routines */
+void bfa_fcs_port_fdmi_init(struct bfa_fcs_port_ms_s *ms);
+void bfa_fcs_port_fdmi_offline(struct bfa_fcs_port_ms_s *ms);
+void bfa_fcs_port_fdmi_online(struct bfa_fcs_port_ms_s *ms);
+
+#endif
diff --git a/drivers/scsi/bfa/fcs_port.h b/drivers/scsi/bfa/fcs_port.h
new file mode 100644 (file)
index 0000000..abb6519
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) 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.
+ */
+
+/**
+ *  fcs_pport.h FCS physical port interfaces
+ */
+
+
+#ifndef __FCS_PPORT_H__
+#define __FCS_PPORT_H__
+
+/*
+ * fcs friend functions: only between fcs modules
+ */
+void bfa_fcs_pport_modinit(struct bfa_fcs_s *fcs);
+void bfa_fcs_pport_modexit(struct bfa_fcs_s *fcs);
+
+#endif /* __FCS_PPORT_H__ */
diff --git a/drivers/scsi/bfa/fcs_rport.h b/drivers/scsi/bfa/fcs_rport.h
new file mode 100644 (file)
index 0000000..f601e9d
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) 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.
+ */
+
+/**
+ *  fcs_rport.h FCS rport interfaces and defines
+ */
+
+#ifndef __FCS_RPORT_H__
+#define __FCS_RPORT_H__
+
+#include <fcs/bfa_fcs_rport.h>
+
+void bfa_fcs_rport_modinit(struct bfa_fcs_s *fcs);
+void bfa_fcs_rport_modexit(struct bfa_fcs_s *fcs);
+
+void bfa_fcs_rport_uf_recv(struct bfa_fcs_rport_s *rport, struct fchs_s *fchs,
+                       u16 len);
+void bfa_fcs_rport_scn(struct bfa_fcs_rport_s *rport);
+
+struct bfa_fcs_rport_s *bfa_fcs_rport_create(struct bfa_fcs_port_s *port,
+                       u32 pid);
+void bfa_fcs_rport_delete(struct bfa_fcs_rport_s *rport);
+void bfa_fcs_rport_online(struct bfa_fcs_rport_s *rport);
+void bfa_fcs_rport_offline(struct bfa_fcs_rport_s *rport);
+void bfa_fcs_rport_start(struct bfa_fcs_port_s *port, struct fchs_s *rx_fchs,
+                       struct fc_logi_s *plogi_rsp);
+void bfa_fcs_rport_plogi_create(struct bfa_fcs_port_s *port,
+                       struct fchs_s *rx_fchs,
+                       struct fc_logi_s *plogi);
+void bfa_fcs_rport_plogi(struct bfa_fcs_rport_s *rport, struct fchs_s *fchs,
+                       struct fc_logi_s *plogi);
+void bfa_fcs_rport_logo_imp(struct bfa_fcs_rport_s *rport);
+void bfa_fcs_rport_itnim_ack(struct bfa_fcs_rport_s *rport);
+void bfa_fcs_rport_itntm_ack(struct bfa_fcs_rport_s *rport);
+void bfa_fcs_rport_tin_ack(struct bfa_fcs_rport_s *rport);
+void bfa_fcs_rport_fcptm_offline_done(struct bfa_fcs_rport_s *rport);
+int  bfa_fcs_rport_get_state(struct bfa_fcs_rport_s *rport);
+struct bfa_fcs_rport_s *bfa_fcs_rport_create_by_wwn(struct bfa_fcs_port_s *port,
+                       wwn_t wwn);
+
+
+/* Rport Features */
+void  bfa_fcs_rpf_init(struct bfa_fcs_rport_s *rport);
+void  bfa_fcs_rpf_rport_online(struct bfa_fcs_rport_s *rport);
+void  bfa_fcs_rpf_rport_offline(struct bfa_fcs_rport_s *rport);
+
+#endif /* __FCS_RPORT_H__ */
diff --git a/drivers/scsi/bfa/fcs_trcmod.h b/drivers/scsi/bfa/fcs_trcmod.h
new file mode 100644 (file)
index 0000000..41b5ae8
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) 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.
+ */
+
+/**
+ *  fcs_trcmod.h BFA FCS trace modules
+ */
+
+#ifndef __FCS_TRCMOD_H__
+#define __FCS_TRCMOD_H__
+
+#include <cs/bfa_trc.h>
+
+/*
+ * !!! Only append to the enums defined here to avoid any versioning
+ * !!! needed between trace utility and driver version
+ */
+enum {
+       BFA_TRC_FCS_FABRIC              = 1,
+       BFA_TRC_FCS_VFAPI               = 2,
+       BFA_TRC_FCS_PORT                = 3,
+       BFA_TRC_FCS_VPORT               = 4,
+       BFA_TRC_FCS_VP_API              = 5,
+       BFA_TRC_FCS_VPS                 = 6,
+       BFA_TRC_FCS_RPORT               = 7,
+       BFA_TRC_FCS_FCPIM               = 8,
+       BFA_TRC_FCS_FCPTM               = 9,
+       BFA_TRC_FCS_NS                  = 10,
+       BFA_TRC_FCS_SCN                 = 11,
+       BFA_TRC_FCS_LOOP                = 12,
+       BFA_TRC_FCS_UF                  = 13,
+       BFA_TRC_FCS_PPORT               = 14,
+       BFA_TRC_FCS_FCPIP               = 15,
+       BFA_TRC_FCS_PORT_API    = 16,
+       BFA_TRC_FCS_RPORT_API   = 17,
+       BFA_TRC_FCS_AUTH                = 18,
+       BFA_TRC_FCS_N2N                 = 19,
+       BFA_TRC_FCS_MS                  = 20,
+       BFA_TRC_FCS_FDMI                = 21,
+       BFA_TRC_FCS_RPORT_FTRS  = 22,
+};
+
+#endif /* __FCS_TRCMOD_H__ */
diff --git a/drivers/scsi/bfa/fcs_uf.h b/drivers/scsi/bfa/fcs_uf.h
new file mode 100644 (file)
index 0000000..96f1bdc
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) 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.
+ */
+
+/**
+ *  fcs_uf.h FCS unsolicited frame receive
+ */
+
+
+#ifndef __FCS_UF_H__
+#define __FCS_UF_H__
+
+/*
+ * fcs friend functions: only between fcs modules
+ */
+void bfa_fcs_uf_modinit(struct bfa_fcs_s *fcs);
+void bfa_fcs_uf_modexit(struct bfa_fcs_s *fcs);
+
+#endif /* __FCS_UF_H__ */
diff --git a/drivers/scsi/bfa/fcs_vport.h b/drivers/scsi/bfa/fcs_vport.h
new file mode 100644 (file)
index 0000000..9e80b6a
--- /dev/null
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ */
+
+#ifndef __FCS_VPORT_H__
+#define __FCS_VPORT_H__
+
+#include <fcs/bfa_fcs_lport.h>
+#include <fcs/bfa_fcs_vport.h>
+#include <defs/bfa_defs_pci.h>
+
+/*
+ * Modudle init/cleanup routines.
+ */
+
+void bfa_fcs_vport_modinit(struct bfa_fcs_s *fcs);
+void bfa_fcs_vport_modexit(struct bfa_fcs_s *fcs);
+
+void bfa_fcs_vport_cleanup(struct bfa_fcs_vport_s *vport);
+void bfa_fcs_vport_online(struct bfa_fcs_vport_s *vport);
+void bfa_fcs_vport_offline(struct bfa_fcs_vport_s *vport);
+void bfa_fcs_vport_delete_comp(struct bfa_fcs_vport_s *vport);
+u32 bfa_fcs_vport_get_max(struct bfa_fcs_s *fcs);
+
+#endif /* __FCS_VPORT_H__ */
+
diff --git a/drivers/scsi/bfa/fdmi.c b/drivers/scsi/bfa/fdmi.c
new file mode 100644 (file)
index 0000000..b845eb2
--- /dev/null
@@ -0,0 +1,1223 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) 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.
+ */
+
+/**
+ *  port_api.c BFA FCS port
+ */
+
+
+#include <bfa.h>
+#include <bfa_svc.h>
+#include "fcs_lport.h"
+#include "fcs_rport.h"
+#include "lport_priv.h"
+#include "fcs_trcmod.h"
+#include "fcs_fcxp.h"
+#include <fcs/bfa_fcs_fdmi.h>
+
+BFA_TRC_FILE(FCS, FDMI);
+
+#define BFA_FCS_FDMI_CMD_MAX_RETRIES 2
+
+/*
+ * forward declarations
+ */
+static void     bfa_fcs_port_fdmi_send_rhba(void *fdmi_cbarg,
+                                           struct bfa_fcxp_s *fcxp_alloced);
+static void     bfa_fcs_port_fdmi_send_rprt(void *fdmi_cbarg,
+                                           struct bfa_fcxp_s *fcxp_alloced);
+static void     bfa_fcs_port_fdmi_send_rpa(void *fdmi_cbarg,
+                                          struct bfa_fcxp_s *fcxp_alloced);
+static void     bfa_fcs_port_fdmi_rhba_response(void *fcsarg,
+                                               struct bfa_fcxp_s *fcxp,
+                                               void *cbarg,
+                                               bfa_status_t req_status,
+                                               u32 rsp_len,
+                                               u32 resid_len,
+                                               struct fchs_s *rsp_fchs);
+static void     bfa_fcs_port_fdmi_rprt_response(void *fcsarg,
+                                               struct bfa_fcxp_s *fcxp,
+                                               void *cbarg,
+                                               bfa_status_t req_status,
+                                               u32 rsp_len,
+                                               u32 resid_len,
+                                               struct fchs_s *rsp_fchs);
+static void     bfa_fcs_port_fdmi_rpa_response(void *fcsarg,
+                                              struct bfa_fcxp_s *fcxp,
+                                              void *cbarg,
+                                              bfa_status_t req_status,
+                                              u32 rsp_len,
+                                              u32 resid_len,
+                                              struct fchs_s *rsp_fchs);
+static void     bfa_fcs_port_fdmi_timeout(void *arg);
+static u16 bfa_fcs_port_fdmi_build_rhba_pyld(
+                       struct bfa_fcs_port_fdmi_s *fdmi, u8 *pyld);
+static u16 bfa_fcs_port_fdmi_build_rprt_pyld(
+                       struct bfa_fcs_port_fdmi_s *fdmi, u8 *pyld);
+static u16 bfa_fcs_port_fdmi_build_rpa_pyld(
+                       struct bfa_fcs_port_fdmi_s *fdmi, u8 *pyld);
+static u16 bfa_fcs_port_fdmi_build_portattr_block(
+                       struct bfa_fcs_port_fdmi_s *fdmi, u8 *pyld);
+void bfa_fcs_fdmi_get_hbaattr(struct bfa_fcs_port_fdmi_s *fdmi,
+                       struct bfa_fcs_fdmi_hba_attr_s *hba_attr);
+void bfa_fcs_fdmi_get_portattr(struct bfa_fcs_port_fdmi_s *fdmi,
+                       struct bfa_fcs_fdmi_port_attr_s *port_attr);
+/**
+ *  fcs_fdmi_sm FCS FDMI state machine
+ */
+
+/**
+ *  FDMI State Machine events
+ */
+enum port_fdmi_event {
+       FDMISM_EVENT_PORT_ONLINE = 1,
+       FDMISM_EVENT_PORT_OFFLINE = 2,
+       FDMISM_EVENT_RSP_OK = 4,
+       FDMISM_EVENT_RSP_ERROR = 5,
+       FDMISM_EVENT_TIMEOUT = 6,
+       FDMISM_EVENT_RHBA_SENT = 7,
+       FDMISM_EVENT_RPRT_SENT = 8,
+       FDMISM_EVENT_RPA_SENT = 9,
+};
+
+static void bfa_fcs_port_fdmi_sm_offline(struct bfa_fcs_port_fdmi_s *fdmi,
+                       enum port_fdmi_event event);
+static void bfa_fcs_port_fdmi_sm_sending_rhba(struct bfa_fcs_port_fdmi_s *fdmi,
+                       enum port_fdmi_event event);
+static void bfa_fcs_port_fdmi_sm_rhba(struct bfa_fcs_port_fdmi_s *fdmi,
+                       enum port_fdmi_event event);
+static void bfa_fcs_port_fdmi_sm_rhba_retry(struct bfa_fcs_port_fdmi_s *fdmi,
+                       enum port_fdmi_event event);
+static void bfa_fcs_port_fdmi_sm_sending_rprt(struct bfa_fcs_port_fdmi_s *fdmi,
+                       enum port_fdmi_event event);
+static void bfa_fcs_port_fdmi_sm_rprt(struct bfa_fcs_port_fdmi_s *fdmi,
+                       enum port_fdmi_event event);
+static void bfa_fcs_port_fdmi_sm_rprt_retry(struct bfa_fcs_port_fdmi_s *fdmi,
+                       enum port_fdmi_event event);
+static void bfa_fcs_port_fdmi_sm_sending_rpa(struct bfa_fcs_port_fdmi_s *fdmi,
+                       enum port_fdmi_event event);
+static void     bfa_fcs_port_fdmi_sm_rpa(struct bfa_fcs_port_fdmi_s *fdmi,
+                       enum port_fdmi_event event);
+static void     bfa_fcs_port_fdmi_sm_rpa_retry(struct bfa_fcs_port_fdmi_s *fdmi,
+                       enum port_fdmi_event event);
+static void     bfa_fcs_port_fdmi_sm_online(struct bfa_fcs_port_fdmi_s *fdmi,
+                       enum port_fdmi_event event);
+/**
+ *             Start in offline state - awaiting MS to send start.
+ */
+static void
+bfa_fcs_port_fdmi_sm_offline(struct bfa_fcs_port_fdmi_s *fdmi,
+                            enum port_fdmi_event event)
+{
+       struct bfa_fcs_port_s *port = fdmi->ms->port;
+
+       bfa_trc(port->fcs, port->port_cfg.pwwn);
+       bfa_trc(port->fcs, event);
+
+       fdmi->retry_cnt = 0;
+
+       switch (event) {
+       case FDMISM_EVENT_PORT_ONLINE:
+               if (port->vport) {
+                       /*
+                        * For Vports, register a new port.
+                        */
+                       bfa_sm_set_state(fdmi,
+                                        bfa_fcs_port_fdmi_sm_sending_rprt);
+                       bfa_fcs_port_fdmi_send_rprt(fdmi, NULL);
+               } else {
+                       /*
+                        * For a base port, we should first register the HBA
+                        * atribute. The HBA attribute also contains the base
+                        *  port registration.
+                        */
+                       bfa_sm_set_state(fdmi,
+                                        bfa_fcs_port_fdmi_sm_sending_rhba);
+                       bfa_fcs_port_fdmi_send_rhba(fdmi, NULL);
+               }
+               break;
+
+       case FDMISM_EVENT_PORT_OFFLINE:
+               break;
+
+       default:
+               bfa_assert(0);
+       }
+}
+
+static void
+bfa_fcs_port_fdmi_sm_sending_rhba(struct bfa_fcs_port_fdmi_s *fdmi,
+                                 enum port_fdmi_event event)
+{
+       struct bfa_fcs_port_s *port = fdmi->ms->port;
+
+       bfa_trc(port->fcs, port->port_cfg.pwwn);
+       bfa_trc(port->fcs, event);
+
+       switch (event) {
+       case FDMISM_EVENT_RHBA_SENT:
+               bfa_sm_set_state(fdmi, bfa_fcs_port_fdmi_sm_rhba);
+               break;
+
+       case FDMISM_EVENT_PORT_OFFLINE:
+               bfa_sm_set_state(fdmi, bfa_fcs_port_fdmi_sm_offline);
+               bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(port),
+                                      &fdmi->fcxp_wqe);
+               break;
+
+       default:
+               bfa_assert(0);
+       }
+}
+
+static void
+bfa_fcs_port_fdmi_sm_rhba(struct bfa_fcs_port_fdmi_s *fdmi,
+                         enum port_fdmi_event event)
+{
+       struct bfa_fcs_port_s *port = fdmi->ms->port;
+
+       bfa_trc(port->fcs, port->port_cfg.pwwn);
+       bfa_trc(port->fcs, event);
+
+       switch (event) {
+       case FDMISM_EVENT_RSP_ERROR:
+               /*
+                * if max retries have not been reached, start timer for a
+                * delayed retry
+                */
+               if (fdmi->retry_cnt++ < BFA_FCS_FDMI_CMD_MAX_RETRIES) {
+                       bfa_sm_set_state(fdmi, bfa_fcs_port_fdmi_sm_rhba_retry);
+                       bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(port),
+                                       &fdmi->timer, bfa_fcs_port_fdmi_timeout,
+                                       fdmi, BFA_FCS_RETRY_TIMEOUT);
+               } else {
+                       /*
+                        * set state to offline
+                        */
+                       bfa_sm_set_state(fdmi, bfa_fcs_port_fdmi_sm_offline);
+               }
+               break;
+
+       case FDMISM_EVENT_RSP_OK:
+               /*
+                * Initiate Register Port Attributes
+                */
+               bfa_sm_set_state(fdmi, bfa_fcs_port_fdmi_sm_sending_rpa);
+               fdmi->retry_cnt = 0;
+               bfa_fcs_port_fdmi_send_rpa(fdmi, NULL);
+               break;
+
+       case FDMISM_EVENT_PORT_OFFLINE:
+               bfa_fcxp_discard(fdmi->fcxp);
+               bfa_sm_set_state(fdmi, bfa_fcs_port_fdmi_sm_offline);
+               break;
+
+       default:
+               bfa_assert(0);
+       }
+}
+
+static void
+bfa_fcs_port_fdmi_sm_rhba_retry(struct bfa_fcs_port_fdmi_s *fdmi,
+                               enum port_fdmi_event event)
+{
+       struct bfa_fcs_port_s *port = fdmi->ms->port;
+
+       bfa_trc(port->fcs, port->port_cfg.pwwn);
+       bfa_trc(port->fcs, event);
+
+       switch (event) {
+       case FDMISM_EVENT_TIMEOUT:
+               /*
+                * Retry Timer Expired. Re-send
+                */
+               bfa_sm_set_state(fdmi, bfa_fcs_port_fdmi_sm_sending_rhba);
+               bfa_fcs_port_fdmi_send_rhba(fdmi, NULL);
+               break;
+
+       case FDMISM_EVENT_PORT_OFFLINE:
+               bfa_sm_set_state(fdmi, bfa_fcs_port_fdmi_sm_offline);
+               bfa_timer_stop(&fdmi->timer);
+               break;
+
+       default:
+               bfa_assert(0);
+       }
+}
+
+/*
+* RPRT : Register Port
+ */
+static void
+bfa_fcs_port_fdmi_sm_sending_rprt(struct bfa_fcs_port_fdmi_s *fdmi,
+                                 enum port_fdmi_event event)
+{
+       struct bfa_fcs_port_s *port = fdmi->ms->port;
+
+       bfa_trc(port->fcs, port->port_cfg.pwwn);
+       bfa_trc(port->fcs, event);
+
+       switch (event) {
+       case FDMISM_EVENT_RPRT_SENT:
+               bfa_sm_set_state(fdmi, bfa_fcs_port_fdmi_sm_rprt);
+               break;
+
+       case FDMISM_EVENT_PORT_OFFLINE:
+               bfa_sm_set_state(fdmi, bfa_fcs_port_fdmi_sm_offline);
+               bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(port),
+                                      &fdmi->fcxp_wqe);
+               break;
+
+       default:
+               bfa_assert(0);
+       }
+}
+
+static void
+bfa_fcs_port_fdmi_sm_rprt(struct bfa_fcs_port_fdmi_s *fdmi,
+                         enum port_fdmi_event event)
+{
+       struct bfa_fcs_port_s *port = fdmi->ms->port;
+
+       bfa_trc(port->fcs, port->port_cfg.pwwn);
+       bfa_trc(port->fcs, event);
+
+       switch (event) {
+       case FDMISM_EVENT_RSP_ERROR:
+               /*
+                * if max retries have not been reached, start timer for a
+                * delayed retry
+                */
+               if (fdmi->retry_cnt++ < BFA_FCS_FDMI_CMD_MAX_RETRIES) {
+                       bfa_sm_set_state(fdmi, bfa_fcs_port_fdmi_sm_rprt_retry);
+                       bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(port),
+                                       &fdmi->timer, bfa_fcs_port_fdmi_timeout,
+                                       fdmi, BFA_FCS_RETRY_TIMEOUT);
+
+               } else {
+                       /*
+                        * set state to offline
+                        */
+                       bfa_sm_set_state(fdmi, bfa_fcs_port_fdmi_sm_offline);
+                       fdmi->retry_cnt = 0;
+               }
+               break;
+
+       case FDMISM_EVENT_RSP_OK:
+               fdmi->retry_cnt = 0;
+               bfa_sm_set_state(fdmi, bfa_fcs_port_fdmi_sm_online);
+               break;
+
+       case FDMISM_EVENT_PORT_OFFLINE:
+               bfa_fcxp_discard(fdmi->fcxp);
+               bfa_sm_set_state(fdmi, bfa_fcs_port_fdmi_sm_offline);
+               break;
+
+       default:
+               bfa_assert(0);
+       }
+}
+
+static void
+bfa_fcs_port_fdmi_sm_rprt_retry(struct bfa_fcs_port_fdmi_s *fdmi,
+                               enum port_fdmi_event event)
+{
+       struct bfa_fcs_port_s *port = fdmi->ms->port;
+
+       bfa_trc(port->fcs, port->port_cfg.pwwn);
+       bfa_trc(port->fcs, event);
+
+       switch (event) {
+       case FDMISM_EVENT_TIMEOUT:
+               /*
+                * Retry Timer Expired. Re-send
+                */
+               bfa_sm_set_state(fdmi, bfa_fcs_port_fdmi_sm_sending_rprt);
+               bfa_fcs_port_fdmi_send_rprt(fdmi, NULL);
+               break;
+
+       case FDMISM_EVENT_PORT_OFFLINE:
+               bfa_sm_set_state(fdmi, bfa_fcs_port_fdmi_sm_offline);
+               bfa_timer_stop(&fdmi->timer);
+               break;
+
+       default:
+               bfa_assert(0);
+       }
+}
+
+/*
+ * Register Port Attributes
+ */
+static void
+bfa_fcs_port_fdmi_sm_sending_rpa(struct bfa_fcs_port_fdmi_s *fdmi,
+                                enum port_fdmi_event event)
+{
+       struct bfa_fcs_port_s *port = fdmi->ms->port;
+
+       bfa_trc(port->fcs, port->port_cfg.pwwn);
+       bfa_trc(port->fcs, event);
+
+       switch (event) {
+       case FDMISM_EVENT_RPA_SENT:
+               bfa_sm_set_state(fdmi, bfa_fcs_port_fdmi_sm_rpa);
+               break;
+
+       case FDMISM_EVENT_PORT_OFFLINE:
+               bfa_sm_set_state(fdmi, bfa_fcs_port_fdmi_sm_offline);
+               bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(port),
+                                      &fdmi->fcxp_wqe);
+               break;
+
+       default:
+               bfa_assert(0);
+       }
+}
+
+static void
+bfa_fcs_port_fdmi_sm_rpa(struct bfa_fcs_port_fdmi_s *fdmi,
+                        enum port_fdmi_event event)
+{
+       struct bfa_fcs_port_s *port = fdmi->ms->port;
+
+       bfa_trc(port->fcs, port->port_cfg.pwwn);
+       bfa_trc(port->fcs, event);
+
+       switch (event) {
+       case FDMISM_EVENT_RSP_ERROR:
+               /*
+                * if max retries have not been reached, start timer for a
+                * delayed retry
+                */
+               if (fdmi->retry_cnt++ < BFA_FCS_FDMI_CMD_MAX_RETRIES) {
+                       bfa_sm_set_state(fdmi, bfa_fcs_port_fdmi_sm_rpa_retry);
+                       bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(port),
+                                       &fdmi->timer, bfa_fcs_port_fdmi_timeout,
+                                       fdmi, BFA_FCS_RETRY_TIMEOUT);
+               } else {
+                       /*
+                        * set state to offline
+                        */
+                       bfa_sm_set_state(fdmi, bfa_fcs_port_fdmi_sm_offline);
+                       fdmi->retry_cnt = 0;
+               }
+               break;
+
+       case FDMISM_EVENT_RSP_OK:
+               bfa_sm_set_state(fdmi, bfa_fcs_port_fdmi_sm_online);
+               fdmi->retry_cnt = 0;
+               break;
+
+       case FDMISM_EVENT_PORT_OFFLINE:
+               bfa_fcxp_discard(fdmi->fcxp);
+               bfa_sm_set_state(fdmi, bfa_fcs_port_fdmi_sm_offline);
+               break;
+
+       default:
+               bfa_assert(0);
+       }
+}
+
+static void
+bfa_fcs_port_fdmi_sm_rpa_retry(struct bfa_fcs_port_fdmi_s *fdmi,
+                              enum port_fdmi_event event)
+{
+       struct bfa_fcs_port_s *port = fdmi->ms->port;
+
+       bfa_trc(port->fcs, port->port_cfg.pwwn);
+       bfa_trc(port->fcs, event);
+
+       switch (event) {
+       case FDMISM_EVENT_TIMEOUT:
+               /*
+                * Retry Timer Expired. Re-send
+                */
+               bfa_sm_set_state(fdmi, bfa_fcs_port_fdmi_sm_sending_rpa);
+               bfa_fcs_port_fdmi_send_rpa(fdmi, NULL);
+               break;
+
+       case FDMISM_EVENT_PORT_OFFLINE:
+               bfa_sm_set_state(fdmi, bfa_fcs_port_fdmi_sm_offline);
+               bfa_timer_stop(&fdmi->timer);
+               break;
+
+       default:
+               bfa_assert(0);
+       }
+}
+
+static void
+bfa_fcs_port_fdmi_sm_online(struct bfa_fcs_port_fdmi_s *fdmi,
+                           enum port_fdmi_event event)
+{
+       struct bfa_fcs_port_s *port = fdmi->ms->port;
+
+       bfa_trc(port->fcs, port->port_cfg.pwwn);
+       bfa_trc(port->fcs, event);
+
+       switch (event) {
+       case FDMISM_EVENT_PORT_OFFLINE:
+               bfa_sm_set_state(fdmi, bfa_fcs_port_fdmi_sm_offline);
+               break;
+
+       default:
+               bfa_assert(0);
+       }
+}
+
+
+/**
+*   RHBA : Register HBA Attributes.
+ */
+static void
+bfa_fcs_port_fdmi_send_rhba(void *fdmi_cbarg, struct bfa_fcxp_s *fcxp_alloced)
+{
+       struct bfa_fcs_port_fdmi_s *fdmi = fdmi_cbarg;
+       struct bfa_fcs_port_s *port = fdmi->ms->port;
+       struct fchs_s          fchs;
+       int             len, attr_len;
+       struct bfa_fcxp_s *fcxp;
+       u8        *pyld;
+
+       bfa_trc(port->fcs, port->port_cfg.pwwn);
+
+       fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
+       if (!fcxp) {
+               bfa_fcxp_alloc_wait(port->fcs->bfa, &fdmi->fcxp_wqe,
+                                   bfa_fcs_port_fdmi_send_rhba, fdmi);
+               return;
+       }
+       fdmi->fcxp = fcxp;
+
+       pyld = bfa_fcxp_get_reqbuf(fcxp);
+       bfa_os_memset(pyld, 0, FC_MAX_PDUSZ);
+
+       len = fc_fdmi_reqhdr_build(&fchs, pyld, bfa_fcs_port_get_fcid(port),
+                                  FDMI_RHBA);
+
+       attr_len = bfa_fcs_port_fdmi_build_rhba_pyld(fdmi,
+                       (u8 *) ((struct ct_hdr_s *) pyld + 1));
+
+       bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
+                     FC_CLASS_3, (len + attr_len), &fchs,
+                     bfa_fcs_port_fdmi_rhba_response, (void *)fdmi,
+                     FC_MAX_PDUSZ, FC_RA_TOV);
+
+       bfa_sm_send_event(fdmi, FDMISM_EVENT_RHBA_SENT);
+}
+
+static          u16
+bfa_fcs_port_fdmi_build_rhba_pyld(struct bfa_fcs_port_fdmi_s *fdmi,
+                                 u8 *pyld)
+{
+       struct bfa_fcs_port_s *port = fdmi->ms->port;
+       struct bfa_fcs_fdmi_hba_attr_s hba_attr;        /* @todo */
+       struct bfa_fcs_fdmi_hba_attr_s *fcs_hba_attr = &hba_attr; /* @todo */
+       struct fdmi_rhba_s    *rhba = (struct fdmi_rhba_s *) pyld;
+       struct fdmi_attr_s    *attr;
+       u8        *curr_ptr;
+       u16        len, count;
+
+       /*
+        * get hba attributes
+        */
+       bfa_fcs_fdmi_get_hbaattr(fdmi, fcs_hba_attr);
+
+       rhba->hba_id = bfa_fcs_port_get_pwwn(port);
+       rhba->port_list.num_ports = bfa_os_htonl(1);
+       rhba->port_list.port_entry = bfa_fcs_port_get_pwwn(port);
+
+       len = sizeof(rhba->hba_id) + sizeof(rhba->port_list);
+
+       count = 0;
+       len += sizeof(rhba->hba_attr_blk.attr_count);
+
+       /*
+        * fill out the invididual entries of the HBA attrib Block
+        */
+       curr_ptr = (u8 *) &rhba->hba_attr_blk.hba_attr;
+
+       /*
+        * Node Name
+        */
+       attr = (struct fdmi_attr_s *) curr_ptr;
+       attr->type = bfa_os_htons(FDMI_HBA_ATTRIB_NODENAME);
+       attr->len = sizeof(wwn_t);
+       memcpy(attr->value, &bfa_fcs_port_get_nwwn(port), attr->len);
+       curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len;
+       len += attr->len;
+       count++;
+       attr->len =
+               bfa_os_htons(attr->len + sizeof(attr->type) +
+                            sizeof(attr->len));
+
+       /*
+        * Manufacturer
+        */
+       attr = (struct fdmi_attr_s *) curr_ptr;
+       attr->type = bfa_os_htons(FDMI_HBA_ATTRIB_MANUFACTURER);
+       attr->len = (u16) strlen(fcs_hba_attr->manufacturer);
+       memcpy(attr->value, fcs_hba_attr->manufacturer, attr->len);
+       /* variable fields need to be 4 byte aligned */
+       attr->len = fc_roundup(attr->len, sizeof(u32));
+       curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len;
+       len += attr->len;
+       count++;
+       attr->len =
+               bfa_os_htons(attr->len + sizeof(attr->type) +
+                            sizeof(attr->len));
+
+       /*
+        * Serial Number
+        */
+       attr = (struct fdmi_attr_s *) curr_ptr;
+       attr->type = bfa_os_htons(FDMI_HBA_ATTRIB_SERIALNUM);
+       attr->len = (u16) strlen(fcs_hba_attr->serial_num);
+       memcpy(attr->value, fcs_hba_attr->serial_num, attr->len);
+       /* variable fields need to be 4 byte aligned */
+       attr->len = fc_roundup(attr->len, sizeof(u32));
+       curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len;
+       len += attr->len;
+       count++;
+       attr->len =
+               bfa_os_htons(attr->len + sizeof(attr->type) +
+                            sizeof(attr->len));
+
+       /*
+        * Model
+        */
+       attr = (struct fdmi_attr_s *) curr_ptr;
+       attr->type = bfa_os_htons(FDMI_HBA_ATTRIB_MODEL);
+       attr->len = (u16) strlen(fcs_hba_attr->model);
+       memcpy(attr->value, fcs_hba_attr->model, attr->len);
+       /* variable fields need to be 4 byte aligned */
+       attr->len = fc_roundup(attr->len, sizeof(u32));
+       curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len;
+       len += attr->len;
+       count++;
+       attr->len =
+               bfa_os_htons(attr->len + sizeof(attr->type) +
+                            sizeof(attr->len));
+
+       /*
+        * Model Desc
+        */
+       attr = (struct fdmi_attr_s *) curr_ptr;
+       attr->type = bfa_os_htons(FDMI_HBA_ATTRIB_MODEL_DESC);
+       attr->len = (u16) strlen(fcs_hba_attr->model_desc);
+       memcpy(attr->value, fcs_hba_attr->model_desc, attr->len);
+       /* variable fields need to be 4 byte aligned */
+       attr->len = fc_roundup(attr->len, sizeof(u32));
+       curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len;
+       len += attr->len;
+       count++;
+       attr->len =
+               bfa_os_htons(attr->len + sizeof(attr->type) +
+                            sizeof(attr->len));
+
+       /*
+        * H/W Version
+        */
+       if (fcs_hba_attr->hw_version[0] != '\0') {
+               attr = (struct fdmi_attr_s *) curr_ptr;
+               attr->type = bfa_os_htons(FDMI_HBA_ATTRIB_HW_VERSION);
+               attr->len = (u16) strlen(fcs_hba_attr->hw_version);
+               memcpy(attr->value, fcs_hba_attr->hw_version, attr->len);
+               /* variable fields need to be 4 byte aligned */
+               attr->len = fc_roundup(attr->len, sizeof(u32));
+               curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len;
+               len += attr->len;
+               count++;
+               attr->len =
+                       bfa_os_htons(attr->len + sizeof(attr->type) +
+                                    sizeof(attr->len));
+       }
+
+       /*
+        * Driver Version
+        */
+       attr = (struct fdmi_attr_s *) curr_ptr;
+       attr->type = bfa_os_htons(FDMI_HBA_ATTRIB_DRIVER_VERSION);
+       attr->len = (u16) strlen(fcs_hba_attr->driver_version);
+       memcpy(attr->value, fcs_hba_attr->driver_version, attr->len);
+       /* variable fields need to be 4 byte aligned */
+       attr->len = fc_roundup(attr->len, sizeof(u32));
+       curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len;
+       len += attr->len;;
+       count++;
+       attr->len =
+               bfa_os_htons(attr->len + sizeof(attr->type) +
+                            sizeof(attr->len));
+
+       /*
+        * Option Rom Version
+        */
+       if (fcs_hba_attr->option_rom_ver[0] != '\0') {
+               attr = (struct fdmi_attr_s *) curr_ptr;
+               attr->type = bfa_os_htons(FDMI_HBA_ATTRIB_ROM_VERSION);
+               attr->len = (u16) strlen(fcs_hba_attr->option_rom_ver);
+               memcpy(attr->value, fcs_hba_attr->option_rom_ver, attr->len);
+               /* variable fields need to be 4 byte aligned */
+               attr->len = fc_roundup(attr->len, sizeof(u32));
+               curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len;
+               len += attr->len;
+               count++;
+               attr->len =
+                       bfa_os_htons(attr->len + sizeof(attr->type) +
+                                    sizeof(attr->len));
+       }
+
+       /*
+        * f/w Version = driver version
+        */
+       attr = (struct fdmi_attr_s *) curr_ptr;
+       attr->type = bfa_os_htons(FDMI_HBA_ATTRIB_FW_VERSION);
+       attr->len = (u16) strlen(fcs_hba_attr->driver_version);
+       memcpy(attr->value, fcs_hba_attr->driver_version, attr->len);
+       /* variable fields need to be 4 byte aligned */
+       attr->len = fc_roundup(attr->len, sizeof(u32));
+       curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len;
+       len += attr->len;
+       count++;
+       attr->len =
+               bfa_os_htons(attr->len + sizeof(attr->type) +
+                            sizeof(attr->len));
+
+       /*
+        * OS Name
+        */
+       if (fcs_hba_attr->os_name[0] != '\0') {
+               attr = (struct fdmi_attr_s *) curr_ptr;
+               attr->type = bfa_os_htons(FDMI_HBA_ATTRIB_OS_NAME);
+               attr->len = (u16) strlen(fcs_hba_attr->os_name);
+               memcpy(attr->value, fcs_hba_attr->os_name, attr->len);
+               /* variable fields need to be 4 byte aligned */
+               attr->len = fc_roundup(attr->len, sizeof(u32));
+               curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len;
+               len += attr->len;
+               count++;
+               attr->len =
+                       bfa_os_htons(attr->len + sizeof(attr->type) +
+                                    sizeof(attr->len));
+       }
+
+       /*
+        * MAX_CT_PAYLOAD
+        */
+       attr = (struct fdmi_attr_s *) curr_ptr;
+       attr->type = bfa_os_htons(FDMI_HBA_ATTRIB_MAX_CT);
+       attr->len = sizeof(fcs_hba_attr->max_ct_pyld);
+       memcpy(attr->value, &fcs_hba_attr->max_ct_pyld, attr->len);
+       len += attr->len;
+       count++;
+       attr->len =
+               bfa_os_htons(attr->len + sizeof(attr->type) +
+                            sizeof(attr->len));
+
+       /*
+        * Update size of payload
+        */
+       len += ((sizeof(attr->type) + sizeof(attr->len)) * count);
+
+       rhba->hba_attr_blk.attr_count = bfa_os_htonl(count);
+       return len;
+}
+
+static void
+bfa_fcs_port_fdmi_rhba_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
+                               void *cbarg, bfa_status_t req_status,
+                               u32 rsp_len, u32 resid_len,
+                               struct fchs_s *rsp_fchs)
+{
+       struct bfa_fcs_port_fdmi_s *fdmi = (struct bfa_fcs_port_fdmi_s *)cbarg;
+       struct bfa_fcs_port_s *port = fdmi->ms->port;
+       struct ct_hdr_s       *cthdr = NULL;
+
+       bfa_trc(port->fcs, port->port_cfg.pwwn);
+
+       /*
+        * Sanity Checks
+        */
+       if (req_status != BFA_STATUS_OK) {
+               bfa_trc(port->fcs, req_status);
+               bfa_sm_send_event(fdmi, FDMISM_EVENT_RSP_ERROR);
+               return;
+       }
+
+       cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp);
+       cthdr->cmd_rsp_code = bfa_os_ntohs(cthdr->cmd_rsp_code);
+
+       if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) {
+               bfa_sm_send_event(fdmi, FDMISM_EVENT_RSP_OK);
+               return;
+       }
+
+       bfa_trc(port->fcs, cthdr->reason_code);
+       bfa_trc(port->fcs, cthdr->exp_code);
+       bfa_sm_send_event(fdmi, FDMISM_EVENT_RSP_ERROR);
+}
+
+/**
+*   RPRT : Register Port
+ */
+static void
+bfa_fcs_port_fdmi_send_rprt(void *fdmi_cbarg, struct bfa_fcxp_s *fcxp_alloced)
+{
+       struct bfa_fcs_port_fdmi_s *fdmi = fdmi_cbarg;
+       struct bfa_fcs_port_s *port = fdmi->ms->port;
+       struct fchs_s          fchs;
+       u16        len, attr_len;
+       struct bfa_fcxp_s *fcxp;
+       u8        *pyld;
+
+       bfa_trc(port->fcs, port->port_cfg.pwwn);
+
+       fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
+       if (!fcxp) {
+               bfa_fcxp_alloc_wait(port->fcs->bfa, &fdmi->fcxp_wqe,
+                                   bfa_fcs_port_fdmi_send_rprt, fdmi);
+               return;
+       }
+       fdmi->fcxp = fcxp;
+
+       pyld = bfa_fcxp_get_reqbuf(fcxp);
+       bfa_os_memset(pyld, 0, FC_MAX_PDUSZ);
+
+       len = fc_fdmi_reqhdr_build(&fchs, pyld, bfa_fcs_port_get_fcid(port),
+                                  FDMI_RPRT);
+
+       attr_len = bfa_fcs_port_fdmi_build_rprt_pyld(fdmi,
+                       (u8 *) ((struct ct_hdr_s *) pyld + 1));
+
+       bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
+                     FC_CLASS_3, len + attr_len, &fchs,
+                     bfa_fcs_port_fdmi_rprt_response, (void *)fdmi,
+                     FC_MAX_PDUSZ, FC_RA_TOV);
+
+       bfa_sm_send_event(fdmi, FDMISM_EVENT_RPRT_SENT);
+}
+
+/**
+ * This routine builds Port Attribute Block that used in RPA, RPRT commands.
+ */
+static          u16
+bfa_fcs_port_fdmi_build_portattr_block(struct bfa_fcs_port_fdmi_s *fdmi,
+                                      u8 *pyld)
+{
+       struct bfa_fcs_fdmi_port_attr_s fcs_port_attr;
+       struct fdmi_port_attr_s *port_attrib = (struct fdmi_port_attr_s *) pyld;
+       struct fdmi_attr_s    *attr;
+       u8        *curr_ptr;
+       u16        len;
+       u8         count = 0;
+
+       /*
+        * get port attributes
+        */
+       bfa_fcs_fdmi_get_portattr(fdmi, &fcs_port_attr);
+
+       len = sizeof(port_attrib->attr_count);
+
+       /*
+        * fill out the invididual entries
+        */
+       curr_ptr = (u8 *) &port_attrib->port_attr;
+
+       /*
+        * FC4 Types
+        */
+       attr = (struct fdmi_attr_s *) curr_ptr;
+       attr->type = bfa_os_htons(FDMI_PORT_ATTRIB_FC4_TYPES);
+       attr->len = sizeof(fcs_port_attr.supp_fc4_types);
+       memcpy(attr->value, fcs_port_attr.supp_fc4_types, attr->len);
+       curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len;
+       len += attr->len;
+       ++count;
+       attr->len =
+               bfa_os_htons(attr->len + sizeof(attr->type) +
+                            sizeof(attr->len));
+
+       /*
+        * Supported Speed
+        */
+       attr = (struct fdmi_attr_s *) curr_ptr;
+       attr->type = bfa_os_htons(FDMI_PORT_ATTRIB_SUPP_SPEED);
+       attr->len = sizeof(fcs_port_attr.supp_speed);
+       memcpy(attr->value, &fcs_port_attr.supp_speed, attr->len);
+       curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len;
+       len += attr->len;
+       ++count;
+       attr->len =
+               bfa_os_htons(attr->len + sizeof(attr->type) +
+                            sizeof(attr->len));
+
+       /*
+        * current Port Speed
+        */
+       attr = (struct fdmi_attr_s *) curr_ptr;
+       attr->type = bfa_os_htons(FDMI_PORT_ATTRIB_PORT_SPEED);
+       attr->len = sizeof(fcs_port_attr.curr_speed);
+       memcpy(attr->value, &fcs_port_attr.curr_speed, attr->len);
+       curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len;
+       len += attr->len;
+       ++count;
+       attr->len =
+               bfa_os_htons(attr->len + sizeof(attr->type) +
+                            sizeof(attr->len));
+
+       /*
+        * max frame size
+        */
+       attr = (struct fdmi_attr_s *) curr_ptr;
+       attr->type = bfa_os_htons(FDMI_PORT_ATTRIB_FRAME_SIZE);
+       attr->len = sizeof(fcs_port_attr.max_frm_size);
+       memcpy(attr->value, &fcs_port_attr.max_frm_size, attr->len);
+       curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len;
+       len += attr->len;
+       ++count;
+       attr->len =
+               bfa_os_htons(attr->len + sizeof(attr->type) +
+                            sizeof(attr->len));
+
+       /*
+        * OS Device Name
+        */
+       if (fcs_port_attr.os_device_name[0] != '\0') {
+               attr = (struct fdmi_attr_s *) curr_ptr;
+               attr->type = bfa_os_htons(FDMI_PORT_ATTRIB_DEV_NAME);
+               attr->len = (u16) strlen(fcs_port_attr.os_device_name);
+               memcpy(attr->value, fcs_port_attr.os_device_name, attr->len);
+               /* variable fields need to be 4 byte aligned */
+               attr->len = fc_roundup(attr->len, sizeof(u32));
+               curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len;
+               len += attr->len;
+               ++count;
+               attr->len =
+                       bfa_os_htons(attr->len + sizeof(attr->type) +
+                                    sizeof(attr->len));
+
+       }
+       /*
+        * Host Name
+        */
+       if (fcs_port_attr.host_name[0] != '\0') {
+               attr = (struct fdmi_attr_s *) curr_ptr;
+               attr->type = bfa_os_htons(FDMI_PORT_ATTRIB_HOST_NAME);
+               attr->len = (u16) strlen(fcs_port_attr.host_name);
+               memcpy(attr->value, fcs_port_attr.host_name, attr->len);
+               /* variable fields need to be 4 byte aligned */
+               attr->len = fc_roundup(attr->len, sizeof(u32));
+               curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len;
+               len += attr->len;
+               ++count;
+               attr->len =
+                       bfa_os_htons(attr->len + sizeof(attr->type) +
+                                    sizeof(attr->len));
+
+       }
+
+       /*
+        * Update size of payload
+        */
+       port_attrib->attr_count = bfa_os_htonl(count);
+       len += ((sizeof(attr->type) + sizeof(attr->len)) * count);
+       return len;
+}
+
+static          u16
+bfa_fcs_port_fdmi_build_rprt_pyld(struct bfa_fcs_port_fdmi_s *fdmi,
+                                 u8 *pyld)
+{
+       struct bfa_fcs_port_s *port = fdmi->ms->port;
+       struct fdmi_rprt_s    *rprt = (struct fdmi_rprt_s *) pyld;
+       u16        len;
+
+       rprt->hba_id = bfa_fcs_port_get_pwwn(bfa_fcs_get_base_port(port->fcs));
+       rprt->port_name = bfa_fcs_port_get_pwwn(port);
+
+       len = bfa_fcs_port_fdmi_build_portattr_block(fdmi,
+                       (u8 *) &rprt->port_attr_blk);
+
+       len += sizeof(rprt->hba_id) + sizeof(rprt->port_name);
+
+       return len;
+}
+
+static void
+bfa_fcs_port_fdmi_rprt_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
+                               void *cbarg, bfa_status_t req_status,
+                               u32 rsp_len, u32 resid_len,
+                               struct fchs_s *rsp_fchs)
+{
+       struct bfa_fcs_port_fdmi_s *fdmi = (struct bfa_fcs_port_fdmi_s *)cbarg;
+       struct bfa_fcs_port_s *port = fdmi->ms->port;
+       struct ct_hdr_s       *cthdr = NULL;
+
+       bfa_trc(port->fcs, port->port_cfg.pwwn);
+
+       /*
+        * Sanity Checks
+        */
+       if (req_status != BFA_STATUS_OK) {
+               bfa_trc(port->fcs, req_status);
+               bfa_sm_send_event(fdmi, FDMISM_EVENT_RSP_ERROR);
+               return;
+       }
+
+       cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp);
+       cthdr->cmd_rsp_code = bfa_os_ntohs(cthdr->cmd_rsp_code);
+
+       if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) {
+               bfa_sm_send_event(fdmi, FDMISM_EVENT_RSP_OK);
+               return;
+       }
+
+       bfa_trc(port->fcs, cthdr->reason_code);
+       bfa_trc(port->fcs, cthdr->exp_code);
+       bfa_sm_send_event(fdmi, FDMISM_EVENT_RSP_ERROR);
+}
+
+/**
+*   RPA : Register Port Attributes.
+ */
+static void
+bfa_fcs_port_fdmi_send_rpa(void *fdmi_cbarg, struct bfa_fcxp_s *fcxp_alloced)
+{
+       struct bfa_fcs_port_fdmi_s *fdmi = fdmi_cbarg;
+       struct bfa_fcs_port_s *port = fdmi->ms->port;
+       struct fchs_s          fchs;
+       u16        len, attr_len;
+       struct bfa_fcxp_s *fcxp;
+       u8        *pyld;
+
+       bfa_trc(port->fcs, port->port_cfg.pwwn);
+
+       fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
+       if (!fcxp) {
+               bfa_fcxp_alloc_wait(port->fcs->bfa, &fdmi->fcxp_wqe,
+                                   bfa_fcs_port_fdmi_send_rpa, fdmi);
+               return;
+       }
+       fdmi->fcxp = fcxp;
+
+       pyld = bfa_fcxp_get_reqbuf(fcxp);
+       bfa_os_memset(pyld, 0, FC_MAX_PDUSZ);
+
+       len = fc_fdmi_reqhdr_build(&fchs, pyld, bfa_fcs_port_get_fcid(port),
+                                  FDMI_RPA);
+
+       attr_len = bfa_fcs_port_fdmi_build_rpa_pyld(fdmi,
+                       (u8 *) ((struct ct_hdr_s *) pyld + 1));
+
+       bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
+                     FC_CLASS_3, len + attr_len, &fchs,
+                     bfa_fcs_port_fdmi_rpa_response, (void *)fdmi,
+                     FC_MAX_PDUSZ, FC_RA_TOV);
+
+       bfa_sm_send_event(fdmi, FDMISM_EVENT_RPA_SENT);
+}
+
+static          u16
+bfa_fcs_port_fdmi_build_rpa_pyld(struct bfa_fcs_port_fdmi_s *fdmi,
+                                u8 *pyld)
+{
+       struct bfa_fcs_port_s *port = fdmi->ms->port;
+       struct fdmi_rpa_s     *rpa = (struct fdmi_rpa_s *) pyld;
+       u16        len;
+
+       rpa->port_name = bfa_fcs_port_get_pwwn(port);
+
+       len = bfa_fcs_port_fdmi_build_portattr_block(fdmi,
+                       (u8 *) &rpa->port_attr_blk);
+
+       len += sizeof(rpa->port_name);
+
+       return len;
+}
+
+static void
+bfa_fcs_port_fdmi_rpa_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
+                              void *cbarg, bfa_status_t req_status,
+                              u32 rsp_len, u32 resid_len,
+                              struct fchs_s *rsp_fchs)
+{
+       struct bfa_fcs_port_fdmi_s *fdmi = (struct bfa_fcs_port_fdmi_s *)cbarg;
+       struct bfa_fcs_port_s *port = fdmi->ms->port;
+       struct ct_hdr_s       *cthdr = NULL;
+
+       bfa_trc(port->fcs, port->port_cfg.pwwn);
+
+       /*
+        * Sanity Checks
+        */
+       if (req_status != BFA_STATUS_OK) {
+               bfa_trc(port->fcs, req_status);
+               bfa_sm_send_event(fdmi, FDMISM_EVENT_RSP_ERROR);
+               return;
+       }
+
+       cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp);
+       cthdr->cmd_rsp_code = bfa_os_ntohs(cthdr->cmd_rsp_code);
+
+       if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) {
+               bfa_sm_send_event(fdmi, FDMISM_EVENT_RSP_OK);
+               return;
+       }
+
+       bfa_trc(port->fcs, cthdr->reason_code);
+       bfa_trc(port->fcs, cthdr->exp_code);
+       bfa_sm_send_event(fdmi, FDMISM_EVENT_RSP_ERROR);
+}
+
+static void
+bfa_fcs_port_fdmi_timeout(void *arg)
+{
+       struct bfa_fcs_port_fdmi_s *fdmi = (struct bfa_fcs_port_fdmi_s *)arg;
+
+       bfa_sm_send_event(fdmi, FDMISM_EVENT_TIMEOUT);
+}
+
+void
+bfa_fcs_fdmi_get_hbaattr(struct bfa_fcs_port_fdmi_s *fdmi,
+                        struct bfa_fcs_fdmi_hba_attr_s *hba_attr)
+{
+       struct bfa_fcs_port_s *port = fdmi->ms->port;
+       struct bfa_fcs_driver_info_s *driver_info = &port->fcs->driver_info;
+       struct bfa_adapter_attr_s adapter_attr;
+
+       bfa_os_memset(hba_attr, 0, sizeof(struct bfa_fcs_fdmi_hba_attr_s));
+       bfa_os_memset(&adapter_attr, 0, sizeof(struct bfa_adapter_attr_s));
+
+       bfa_ioc_get_adapter_attr(&port->fcs->bfa->ioc, &adapter_attr);
+
+       strncpy(hba_attr->manufacturer, adapter_attr.manufacturer,
+               sizeof(adapter_attr.manufacturer));
+
+       strncpy(hba_attr->serial_num, adapter_attr.serial_num,
+               sizeof(adapter_attr.serial_num));
+
+       strncpy(hba_attr->model, adapter_attr.model, sizeof(hba_attr->model));
+
+       strncpy(hba_attr->model_desc, adapter_attr.model_descr,
+               sizeof(hba_attr->model_desc));
+
+       strncpy(hba_attr->hw_version, adapter_attr.hw_ver,
+               sizeof(hba_attr->hw_version));
+
+       strncpy(hba_attr->driver_version, (char *)driver_info->version,
+               sizeof(hba_attr->driver_version));
+
+       strncpy(hba_attr->option_rom_ver, adapter_attr.optrom_ver,
+               sizeof(hba_attr->option_rom_ver));
+
+       strncpy(hba_attr->fw_version, adapter_attr.fw_ver,
+               sizeof(hba_attr->fw_version));
+
+       strncpy(hba_attr->os_name, driver_info->host_os_name,
+               sizeof(hba_attr->os_name));
+
+       /*
+        * If there is a patch level, append it to the os name along with a
+        * separator
+        */
+       if (driver_info->host_os_patch[0] != '\0') {
+               strncat(hba_attr->os_name, BFA_FCS_PORT_SYMBNAME_SEPARATOR,
+                       sizeof(BFA_FCS_PORT_SYMBNAME_SEPARATOR));
+               strncat(hba_attr->os_name, driver_info->host_os_patch,
+                       sizeof(driver_info->host_os_patch));
+       }
+
+       hba_attr->max_ct_pyld = bfa_os_htonl(FC_MAX_PDUSZ);
+
+}
+
+void
+bfa_fcs_fdmi_get_portattr(struct bfa_fcs_port_fdmi_s *fdmi,
+                         struct bfa_fcs_fdmi_port_attr_s *port_attr)
+{
+       struct bfa_fcs_port_s *port = fdmi->ms->port;
+       struct bfa_fcs_driver_info_s *driver_info = &port->fcs->driver_info;
+       struct bfa_pport_attr_s pport_attr;
+
+       bfa_os_memset(port_attr, 0, sizeof(struct bfa_fcs_fdmi_port_attr_s));
+
+       /*
+        * get pport attributes from hal
+        */
+       bfa_pport_get_attr(port->fcs->bfa, &pport_attr);
+
+       /*
+        * get FC4 type Bitmask
+        */
+       fc_get_fc4type_bitmask(FC_TYPE_FCP, port_attr->supp_fc4_types);
+
+       /*
+        * Supported Speeds
+        */
+       port_attr->supp_speed = bfa_os_htonl(BFA_FCS_FDMI_SUPORTED_SPEEDS);
+
+       /*
+        * Current Speed
+        */
+       port_attr->curr_speed = bfa_os_htonl(pport_attr.speed);
+
+       /*
+        * Max PDU Size.
+        */
+       port_attr->max_frm_size = bfa_os_htonl(FC_MAX_PDUSZ);
+
+       /*
+        * OS device Name
+        */
+       strncpy(port_attr->os_device_name, (char *)driver_info->os_device_name,
+               sizeof(port_attr->os_device_name));
+
+       /*
+        * Host name
+        */
+       strncpy(port_attr->host_name, (char *)driver_info->host_machine_name,
+               sizeof(port_attr->host_name));
+
+}
+
+
+void
+bfa_fcs_port_fdmi_init(struct bfa_fcs_port_ms_s *ms)
+{
+       struct bfa_fcs_port_fdmi_s *fdmi = &ms->fdmi;
+
+       fdmi->ms = ms;
+       bfa_sm_set_state(fdmi, bfa_fcs_port_fdmi_sm_offline);
+}
+
+void
+bfa_fcs_port_fdmi_offline(struct bfa_fcs_port_ms_s *ms)
+{
+       struct bfa_fcs_port_fdmi_s *fdmi = &ms->fdmi;
+
+       fdmi->ms = ms;
+       bfa_sm_send_event(fdmi, FDMISM_EVENT_PORT_OFFLINE);
+}
+
+void
+bfa_fcs_port_fdmi_online(struct bfa_fcs_port_ms_s *ms)
+{
+       struct bfa_fcs_port_fdmi_s *fdmi = &ms->fdmi;
+
+       fdmi->ms = ms;
+       bfa_sm_send_event(fdmi, FDMISM_EVENT_PORT_ONLINE);
+}
diff --git a/drivers/scsi/bfa/include/aen/bfa_aen.h b/drivers/scsi/bfa/include/aen/bfa_aen.h
new file mode 100644 (file)
index 0000000..da8cac0
--- /dev/null
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ */
+#ifndef __BFA_AEN_H__
+#define __BFA_AEN_H__
+
+#include "defs/bfa_defs_aen.h"
+
+#define BFA_AEN_MAX_ENTRY   512
+
+extern s32 bfa_aen_max_cfg_entry;
+struct bfa_aen_s {
+       void            *bfad;
+       s32             max_entry;
+       s32             write_index;
+       s32             read_index;
+       u32     bfad_num;
+       u32     seq_num;
+       void            (*aen_cb_notify)(void *bfad);
+       void            (*gettimeofday)(struct bfa_timeval_s *tv);
+       struct bfa_trc_mod_s    *trcmod;
+       struct bfa_aen_entry_s  list[BFA_AEN_MAX_ENTRY]; /* Must be the last */
+};
+
+
+/**
+ * Public APIs
+ */
+static inline void
+bfa_aen_set_max_cfg_entry(int max_entry)
+{
+       bfa_aen_max_cfg_entry = max_entry;
+}
+
+static inline s32
+bfa_aen_get_max_cfg_entry(void)
+{
+       return bfa_aen_max_cfg_entry;
+}
+
+static inline s32
+bfa_aen_get_meminfo(void)
+{
+       return (sizeof(struct bfa_aen_entry_s) * bfa_aen_get_max_cfg_entry());
+}
+
+static inline s32
+bfa_aen_get_wi(struct bfa_aen_s *aen)
+{
+       return aen->write_index;
+}
+
+static inline s32
+bfa_aen_get_ri(struct bfa_aen_s *aen)
+{
+       return aen->read_index;
+}
+
+static inline s32
+bfa_aen_fetch_count(struct bfa_aen_s *aen, s32 read_index)
+{
+       return ((aen->write_index + aen->max_entry) - read_index)
+               % aen->max_entry;
+}
+
+s32 bfa_aen_init(struct bfa_aen_s *aen, struct bfa_trc_mod_s *trcmod,
+               void *bfad, u32 inst_id, void (*aen_cb_notify)(void *),
+               void (*gettimeofday)(struct bfa_timeval_s *));
+
+s32 bfa_aen_post(struct bfa_aen_s *aen, enum bfa_aen_category aen_category,
+                    int aen_type, union bfa_aen_data_u *aen_data);
+
+s32 bfa_aen_fetch(struct bfa_aen_s *aen, struct bfa_aen_entry_s *aen_entry,
+                     s32 entry_space, s32 rii, s32 *ri_arr,
+                     s32 ri_arr_cnt);
+
+s32 bfa_aen_get_inst(struct bfa_aen_s *aen);
+
+#endif /* __BFA_AEN_H__ */
diff --git a/drivers/scsi/bfa/include/aen/bfa_aen_adapter.h b/drivers/scsi/bfa/include/aen/bfa_aen_adapter.h
new file mode 100644 (file)
index 0000000..260d3ea
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) 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.
+ */
+
+/* messages define for BFA_AEN_CAT_ADAPTER Module */
+#ifndef        __bfa_aen_adapter_h__
+#define        __bfa_aen_adapter_h__
+
+#include  <cs/bfa_log.h>
+#include  <defs/bfa_defs_aen.h>
+
+#define BFA_AEN_ADAPTER_ADD \
+       BFA_LOG_CREATE_ID(BFA_AEN_CAT_ADAPTER, BFA_ADAPTER_AEN_ADD)
+#define BFA_AEN_ADAPTER_REMOVE \
+       BFA_LOG_CREATE_ID(BFA_AEN_CAT_ADAPTER, BFA_ADAPTER_AEN_REMOVE)
+
+#endif
+
diff --git a/drivers/scsi/bfa/include/aen/bfa_aen_audit.h b/drivers/scsi/bfa/include/aen/bfa_aen_audit.h
new file mode 100644 (file)
index 0000000..12cd7aa
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) 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.
+ */
+
+/* messages define for BFA_AEN_CAT_AUDIT Module */
+#ifndef        __bfa_aen_audit_h__
+#define        __bfa_aen_audit_h__
+
+#include  <cs/bfa_log.h>
+#include  <defs/bfa_defs_aen.h>
+
+#define BFA_AEN_AUDIT_AUTH_ENABLE \
+       BFA_LOG_CREATE_ID(BFA_AEN_CAT_AUDIT, BFA_AUDIT_AEN_AUTH_ENABLE)
+#define BFA_AEN_AUDIT_AUTH_DISABLE \
+       BFA_LOG_CREATE_ID(BFA_AEN_CAT_AUDIT, BFA_AUDIT_AEN_AUTH_DISABLE)
+
+#endif
+
diff --git a/drivers/scsi/bfa/include/aen/bfa_aen_ethport.h b/drivers/scsi/bfa/include/aen/bfa_aen_ethport.h
new file mode 100644 (file)
index 0000000..507d0b5
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) 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.
+ */
+
+/* messages define for BFA_AEN_CAT_ETHPORT Module */
+#ifndef        __bfa_aen_ethport_h__
+#define        __bfa_aen_ethport_h__
+
+#include  <cs/bfa_log.h>
+#include  <defs/bfa_defs_aen.h>
+
+#define BFA_AEN_ETHPORT_LINKUP \
+       BFA_LOG_CREATE_ID(BFA_AEN_CAT_ETHPORT, BFA_ETHPORT_AEN_LINKUP)
+#define BFA_AEN_ETHPORT_LINKDOWN \
+       BFA_LOG_CREATE_ID(BFA_AEN_CAT_ETHPORT, BFA_ETHPORT_AEN_LINKDOWN)
+#define BFA_AEN_ETHPORT_ENABLE \
+       BFA_LOG_CREATE_ID(BFA_AEN_CAT_ETHPORT, BFA_ETHPORT_AEN_ENABLE)
+#define BFA_AEN_ETHPORT_DISABLE \
+       BFA_LOG_CREATE_ID(BFA_AEN_CAT_ETHPORT, BFA_ETHPORT_AEN_DISABLE)
+
+#endif
+
diff --git a/drivers/scsi/bfa/include/aen/bfa_aen_ioc.h b/drivers/scsi/bfa/include/aen/bfa_aen_ioc.h
new file mode 100644 (file)
index 0000000..71378b4
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) 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.
+ */
+
+/* messages define for BFA_AEN_CAT_IOC Module */
+#ifndef        __bfa_aen_ioc_h__
+#define        __bfa_aen_ioc_h__
+
+#include  <cs/bfa_log.h>
+#include  <defs/bfa_defs_aen.h>
+
+#define BFA_AEN_IOC_HBGOOD \
+       BFA_LOG_CREATE_ID(BFA_AEN_CAT_IOC, BFA_IOC_AEN_HBGOOD)
+#define BFA_AEN_IOC_HBFAIL \
+       BFA_LOG_CREATE_ID(BFA_AEN_CAT_IOC, BFA_IOC_AEN_HBFAIL)
+#define BFA_AEN_IOC_ENABLE \
+       BFA_LOG_CREATE_ID(BFA_AEN_CAT_IOC, BFA_IOC_AEN_ENABLE)
+#define BFA_AEN_IOC_DISABLE \
+       BFA_LOG_CREATE_ID(BFA_AEN_CAT_IOC, BFA_IOC_AEN_DISABLE)
+#define BFA_AEN_IOC_FWMISMATCH \
+       BFA_LOG_CREATE_ID(BFA_AEN_CAT_IOC, BFA_IOC_AEN_FWMISMATCH)
+
+#endif
+
diff --git a/drivers/scsi/bfa/include/aen/bfa_aen_itnim.h b/drivers/scsi/bfa/include/aen/bfa_aen_itnim.h
new file mode 100644 (file)
index 0000000..a7d8ddc
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) 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.
+ */
+
+/* messages define for BFA_AEN_CAT_ITNIM Module */
+#ifndef        __bfa_aen_itnim_h__
+#define        __bfa_aen_itnim_h__
+
+#include  <cs/bfa_log.h>
+#include  <defs/bfa_defs_aen.h>
+
+#define BFA_AEN_ITNIM_ONLINE \
+       BFA_LOG_CREATE_ID(BFA_AEN_CAT_ITNIM, BFA_ITNIM_AEN_ONLINE)
+#define BFA_AEN_ITNIM_OFFLINE \
+       BFA_LOG_CREATE_ID(BFA_AEN_CAT_ITNIM, BFA_ITNIM_AEN_OFFLINE)
+#define BFA_AEN_ITNIM_DISCONNECT \
+       BFA_LOG_CREATE_ID(BFA_AEN_CAT_ITNIM, BFA_ITNIM_AEN_DISCONNECT)
+
+#endif
+
diff --git a/drivers/scsi/bfa/include/aen/bfa_aen_lport.h b/drivers/scsi/bfa/include/aen/bfa_aen_lport.h
new file mode 100644 (file)
index 0000000..5a8ebb6
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) 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.
+ */
+
+/* messages define for BFA_AEN_CAT_LPORT Module */
+#ifndef        __bfa_aen_lport_h__
+#define        __bfa_aen_lport_h__
+
+#include  <cs/bfa_log.h>
+#include  <defs/bfa_defs_aen.h>
+
+#define BFA_AEN_LPORT_NEW \
+       BFA_LOG_CREATE_ID(BFA_AEN_CAT_LPORT, BFA_LPORT_AEN_NEW)
+#define BFA_AEN_LPORT_DELETE \
+       BFA_LOG_CREATE_ID(BFA_AEN_CAT_LPORT, BFA_LPORT_AEN_DELETE)
+#define BFA_AEN_LPORT_ONLINE \
+       BFA_LOG_CREATE_ID(BFA_AEN_CAT_LPORT, BFA_LPORT_AEN_ONLINE)
+#define BFA_AEN_LPORT_OFFLINE \
+       BFA_LOG_CREATE_ID(BFA_AEN_CAT_LPORT, BFA_LPORT_AEN_OFFLINE)
+#define BFA_AEN_LPORT_DISCONNECT \
+       BFA_LOG_CREATE_ID(BFA_AEN_CAT_LPORT, BFA_LPORT_AEN_DISCONNECT)
+#define BFA_AEN_LPORT_NEW_PROP \
+       BFA_LOG_CREATE_ID(BFA_AEN_CAT_LPORT, BFA_LPORT_AEN_NEW_PROP)
+#define BFA_AEN_LPORT_DELETE_PROP \
+       BFA_LOG_CREATE_ID(BFA_AEN_CAT_LPORT, BFA_LPORT_AEN_DELETE_PROP)
+#define BFA_AEN_LPORT_NEW_STANDARD \
+       BFA_LOG_CREATE_ID(BFA_AEN_CAT_LPORT, BFA_LPORT_AEN_NEW_STANDARD)
+#define BFA_AEN_LPORT_DELETE_STANDARD \
+       BFA_LOG_CREATE_ID(BFA_AEN_CAT_LPORT, BFA_LPORT_AEN_DELETE_STANDARD)
+#define BFA_AEN_LPORT_NPIV_DUP_WWN \
+       BFA_LOG_CREATE_ID(BFA_AEN_CAT_LPORT, BFA_LPORT_AEN_NPIV_DUP_WWN)
+#define BFA_AEN_LPORT_NPIV_FABRIC_MAX \
+       BFA_LOG_CREATE_ID(BFA_AEN_CAT_LPORT, BFA_LPORT_AEN_NPIV_FABRIC_MAX)
+#define BFA_AEN_LPORT_NPIV_UNKNOWN \
+       BFA_LOG_CREATE_ID(BFA_AEN_CAT_LPORT, BFA_LPORT_AEN_NPIV_UNKNOWN)
+
+#endif
+
diff --git a/drivers/scsi/bfa/include/aen/bfa_aen_port.h b/drivers/scsi/bfa/include/aen/bfa_aen_port.h
new file mode 100644 (file)
index 0000000..9add905
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) 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.
+ */
+
+/* messages define for BFA_AEN_CAT_PORT Module */
+#ifndef        __bfa_aen_port_h__
+#define        __bfa_aen_port_h__
+
+#include  <cs/bfa_log.h>
+#include  <defs/bfa_defs_aen.h>
+
+#define BFA_AEN_PORT_ONLINE \
+       BFA_LOG_CREATE_ID(BFA_AEN_CAT_PORT, BFA_PORT_AEN_ONLINE)
+#define BFA_AEN_PORT_OFFLINE \
+       BFA_LOG_CREATE_ID(BFA_AEN_CAT_PORT, BFA_PORT_AEN_OFFLINE)
+#define BFA_AEN_PORT_RLIR \
+       BFA_LOG_CREATE_ID(BFA_AEN_CAT_PORT, BFA_PORT_AEN_RLIR)
+#define BFA_AEN_PORT_SFP_INSERT \
+       BFA_LOG_CREATE_ID(BFA_AEN_CAT_PORT, BFA_PORT_AEN_SFP_INSERT)
+#define BFA_AEN_PORT_SFP_REMOVE \
+       BFA_LOG_CREATE_ID(BFA_AEN_CAT_PORT, BFA_PORT_AEN_SFP_REMOVE)
+#define BFA_AEN_PORT_SFP_POM \
+       BFA_LOG_CREATE_ID(BFA_AEN_CAT_PORT, BFA_PORT_AEN_SFP_POM)
+#define BFA_AEN_PORT_ENABLE \
+       BFA_LOG_CREATE_ID(BFA_AEN_CAT_PORT, BFA_PORT_AEN_ENABLE)
+#define BFA_AEN_PORT_DISABLE \
+       BFA_LOG_CREATE_ID(BFA_AEN_CAT_PORT, BFA_PORT_AEN_DISABLE)
+#define BFA_AEN_PORT_AUTH_ON \
+       BFA_LOG_CREATE_ID(BFA_AEN_CAT_PORT, BFA_PORT_AEN_AUTH_ON)
+#define BFA_AEN_PORT_AUTH_OFF \
+       BFA_LOG_CREATE_ID(BFA_AEN_CAT_PORT, BFA_PORT_AEN_AUTH_OFF)
+#define BFA_AEN_PORT_DISCONNECT \
+       BFA_LOG_CREATE_ID(BFA_AEN_CAT_PORT, BFA_PORT_AEN_DISCONNECT)
+#define BFA_AEN_PORT_QOS_NEG \
+       BFA_LOG_CREATE_ID(BFA_AEN_CAT_PORT, BFA_PORT_AEN_QOS_NEG)
+#define BFA_AEN_PORT_FABRIC_NAME_CHANGE \
+       BFA_LOG_CREATE_ID(BFA_AEN_CAT_PORT, BFA_PORT_AEN_FABRIC_NAME_CHANGE)
+#define BFA_AEN_PORT_SFP_ACCESS_ERROR \
+       BFA_LOG_CREATE_ID(BFA_AEN_CAT_PORT, BFA_PORT_AEN_SFP_ACCESS_ERROR)
+#define BFA_AEN_PORT_SFP_UNSUPPORT \
+       BFA_LOG_CREATE_ID(BFA_AEN_CAT_PORT, BFA_PORT_AEN_SFP_UNSUPPORT)
+
+#endif
+
diff --git a/drivers/scsi/bfa/include/aen/bfa_aen_rport.h b/drivers/scsi/bfa/include/aen/bfa_aen_rport.h
new file mode 100644 (file)
index 0000000..7e4be1f
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) 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.
+ */
+
+/* messages define for BFA_AEN_CAT_RPORT Module */
+#ifndef        __bfa_aen_rport_h__
+#define        __bfa_aen_rport_h__
+
+#include  <cs/bfa_log.h>
+#include  <defs/bfa_defs_aen.h>
+
+#define BFA_AEN_RPORT_ONLINE \
+       BFA_LOG_CREATE_ID(BFA_AEN_CAT_RPORT, BFA_RPORT_AEN_ONLINE)
+#define BFA_AEN_RPORT_OFFLINE \
+       BFA_LOG_CREATE_ID(BFA_AEN_CAT_RPORT, BFA_RPORT_AEN_OFFLINE)
+#define BFA_AEN_RPORT_DISCONNECT \
+       BFA_LOG_CREATE_ID(BFA_AEN_CAT_RPORT, BFA_RPORT_AEN_DISCONNECT)
+#define BFA_AEN_RPORT_QOS_PRIO \
+       BFA_LOG_CREATE_ID(BFA_AEN_CAT_RPORT, BFA_RPORT_AEN_QOS_PRIO)
+#define BFA_AEN_RPORT_QOS_FLOWID \
+       BFA_LOG_CREATE_ID(BFA_AEN_CAT_RPORT, BFA_RPORT_AEN_QOS_FLOWID)
+
+#endif
+
diff --git a/drivers/scsi/bfa/include/bfa.h b/drivers/scsi/bfa/include/bfa.h
new file mode 100644 (file)
index 0000000..64c1412
--- /dev/null
@@ -0,0 +1,177 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ */
+#ifndef __BFA_H__
+#define __BFA_H__
+
+#include <bfa_os_inc.h>
+#include <cs/bfa_debug.h>
+#include <cs/bfa_q.h>
+#include <cs/bfa_trc.h>
+#include <cs/bfa_log.h>
+#include <cs/bfa_plog.h>
+#include <defs/bfa_defs_status.h>
+#include <defs/bfa_defs_ioc.h>
+#include <defs/bfa_defs_iocfc.h>
+#include <aen/bfa_aen.h>
+#include <bfi/bfi.h>
+
+struct bfa_s;
+#include <bfa_intr_priv.h>
+
+struct bfa_pcidev_s;
+
+/**
+ * PCI devices supported by the current BFA
+ */
+struct bfa_pciid_s {
+       u16        device_id;
+       u16        vendor_id;
+};
+
+extern char     bfa_version[];
+
+/**
+ * BFA Power Mgmt Commands
+ */
+enum bfa_pm_cmd {
+       BFA_PM_CTL_D0 = 0,
+       BFA_PM_CTL_D1 = 1,
+       BFA_PM_CTL_D2 = 2,
+       BFA_PM_CTL_D3 = 3,
+};
+
+/**
+ * BFA memory resources
+ */
+enum bfa_mem_type {
+       BFA_MEM_TYPE_KVA = 1,   /*! Kernel Virtual Memory *(non-dma-able) */
+       BFA_MEM_TYPE_DMA = 2,   /*! DMA-able memory */
+       BFA_MEM_TYPE_MAX = BFA_MEM_TYPE_DMA,
+};
+
+struct bfa_mem_elem_s {
+       enum bfa_mem_type mem_type;     /*  see enum bfa_mem_type       */
+       u32        mem_len;     /*  Total Length in Bytes       */
+       u8              *kva;           /*  kernel virtual address      */
+       u64        dma;         /*  dma address if DMA memory   */
+       u8              *kva_curp;      /*  kva allocation cursor       */
+       u64        dma_curp;    /*  dma allocation cursor       */
+};
+
+struct bfa_meminfo_s {
+       struct bfa_mem_elem_s meminfo[BFA_MEM_TYPE_MAX];
+};
+#define bfa_meminfo_kva(_m)    \
+       (_m)->meminfo[BFA_MEM_TYPE_KVA - 1].kva_curp
+#define bfa_meminfo_dma_virt(_m)       \
+       (_m)->meminfo[BFA_MEM_TYPE_DMA - 1].kva_curp
+#define bfa_meminfo_dma_phys(_m)       \
+       (_m)->meminfo[BFA_MEM_TYPE_DMA - 1].dma_curp
+
+/**
+ * Generic Scatter Gather Element used by driver
+ */
+struct bfa_sge_s {
+       u32        sg_len;
+       void           *sg_addr;
+};
+
+#define bfa_sge_to_be(__sge) do {                                          \
+       ((u32 *)(__sge))[0] = bfa_os_htonl(((u32 *)(__sge))[0]);      \
+       ((u32 *)(__sge))[1] = bfa_os_htonl(((u32 *)(__sge))[1]);      \
+       ((u32 *)(__sge))[2] = bfa_os_htonl(((u32 *)(__sge))[2]);      \
+} while (0)
+
+
+/*
+ * bfa stats interfaces
+ */
+#define bfa_stats(_mod, _stats)        (_mod)->stats._stats ++
+
+#define bfa_ioc_get_stats(__bfa, __ioc_stats)  \
+       bfa_ioc_fetch_stats(&(__bfa)->ioc, __ioc_stats)
+#define bfa_ioc_clear_stats(__bfa)     \
+       bfa_ioc_clr_stats(&(__bfa)->ioc)
+
+/*
+ * bfa API functions
+ */
+void bfa_get_pciids(struct bfa_pciid_s **pciids, int *npciids);
+void bfa_cfg_get_default(struct bfa_iocfc_cfg_s *cfg);
+void bfa_cfg_get_min(struct bfa_iocfc_cfg_s *cfg);
+void bfa_cfg_get_meminfo(struct bfa_iocfc_cfg_s *cfg,
+                       struct bfa_meminfo_s *meminfo);
+void bfa_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
+                       struct bfa_meminfo_s *meminfo,
+                       struct bfa_pcidev_s *pcidev);
+void bfa_init_trc(struct bfa_s *bfa, struct bfa_trc_mod_s *trcmod);
+void bfa_init_log(struct bfa_s *bfa, struct bfa_log_mod_s *logmod);
+void bfa_init_aen(struct bfa_s *bfa, struct bfa_aen_s *aen);
+void bfa_init_plog(struct bfa_s *bfa, struct bfa_plog_s *plog);
+void bfa_detach(struct bfa_s *bfa);
+void bfa_init(struct bfa_s *bfa);
+void bfa_start(struct bfa_s *bfa);
+void bfa_stop(struct bfa_s *bfa);
+void bfa_attach_fcs(struct bfa_s *bfa);
+void bfa_cb_init(void *bfad, bfa_status_t status);
+void bfa_cb_stop(void *bfad, bfa_status_t status);
+void bfa_cb_updateq(void *bfad, bfa_status_t status);
+
+bfa_boolean_t bfa_intx(struct bfa_s *bfa);
+void bfa_isr_enable(struct bfa_s *bfa);
+void bfa_isr_disable(struct bfa_s *bfa);
+void bfa_msix_getvecs(struct bfa_s *bfa, u32 *msix_vecs_bmap,
+                       u32 *num_vecs, u32 *max_vec_bit);
+#define bfa_msix(__bfa, __vec) (__bfa)->msix.handler[__vec](__bfa, __vec)
+
+void bfa_comp_deq(struct bfa_s *bfa, struct list_head *comp_q);
+void bfa_comp_process(struct bfa_s *bfa, struct list_head *comp_q);
+void bfa_comp_free(struct bfa_s *bfa, struct list_head *comp_q);
+
+typedef void (*bfa_cb_ioc_t) (void *cbarg, enum bfa_status status);
+void bfa_iocfc_get_attr(struct bfa_s *bfa, struct bfa_iocfc_attr_s *attr);
+bfa_status_t bfa_iocfc_get_stats(struct bfa_s *bfa,
+                       struct bfa_iocfc_stats_s *stats,
+                       bfa_cb_ioc_t cbfn, void *cbarg);
+bfa_status_t bfa_iocfc_clear_stats(struct bfa_s *bfa,
+                       bfa_cb_ioc_t cbfn, void *cbarg);
+void bfa_get_attr(struct bfa_s *bfa, struct bfa_ioc_attr_s *ioc_attr);
+
+void bfa_adapter_get_attr(struct bfa_s *bfa,
+                       struct bfa_adapter_attr_s *ad_attr);
+u64 bfa_adapter_get_id(struct bfa_s *bfa);
+
+bfa_status_t bfa_iocfc_israttr_set(struct bfa_s *bfa,
+                       struct bfa_iocfc_intr_attr_s *attr);
+
+void bfa_iocfc_enable(struct bfa_s *bfa);
+void bfa_iocfc_disable(struct bfa_s *bfa);
+void bfa_ioc_auto_recover(bfa_boolean_t auto_recover);
+void bfa_cb_ioc_disable(void *bfad);
+void bfa_timer_tick(struct bfa_s *bfa);
+#define bfa_timer_start(_bfa, _timer, _timercb, _arg, _timeout)        \
+       bfa_timer_begin(&(_bfa)->timer_mod, _timer, _timercb, _arg, _timeout)
+
+/*
+ * BFA debug API functions
+ */
+bfa_status_t bfa_debug_fwtrc(struct bfa_s *bfa, void *trcdata, int *trclen);
+bfa_status_t bfa_debug_fwsave(struct bfa_s *bfa, void *trcdata, int *trclen);
+
+#include "bfa_priv.h"
+
+#endif /* __BFA_H__ */
diff --git a/drivers/scsi/bfa/include/bfa_fcpim.h b/drivers/scsi/bfa/include/bfa_fcpim.h
new file mode 100644 (file)
index 0000000..0478979
--- /dev/null
@@ -0,0 +1,159 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ */
+
+#ifndef __BFA_FCPIM_H__
+#define __BFA_FCPIM_H__
+
+#include <bfa.h>
+#include <bfa_svc.h>
+#include <bfi/bfi_fcpim.h>
+#include <defs/bfa_defs_fcpim.h>
+
+/*
+ * forward declarations
+ */
+struct bfa_itnim_s;
+struct bfa_ioim_s;
+struct bfa_tskim_s;
+struct bfad_ioim_s;
+struct bfad_tskim_s;
+
+/*
+ * bfa fcpim module API functions
+ */
+void           bfa_fcpim_path_tov_set(struct bfa_s *bfa, u16 path_tov);
+u16    bfa_fcpim_path_tov_get(struct bfa_s *bfa);
+void           bfa_fcpim_qdepth_set(struct bfa_s *bfa, u16 q_depth);
+u16    bfa_fcpim_qdepth_get(struct bfa_s *bfa);
+bfa_status_t bfa_fcpim_get_modstats(struct bfa_s *bfa,
+                       struct bfa_fcpim_stats_s *modstats);
+bfa_status_t bfa_fcpim_clr_modstats(struct bfa_s *bfa);
+
+/*
+ * bfa itnim API functions
+ */
+struct bfa_itnim_s *bfa_itnim_create(struct bfa_s *bfa,
+                                       struct bfa_rport_s *rport, void *itnim);
+void           bfa_itnim_delete(struct bfa_itnim_s *itnim);
+void           bfa_itnim_online(struct bfa_itnim_s *itnim,
+                                bfa_boolean_t seq_rec);
+void           bfa_itnim_offline(struct bfa_itnim_s *itnim);
+void           bfa_itnim_get_stats(struct bfa_itnim_s *itnim,
+                       struct bfa_itnim_hal_stats_s *stats);
+void           bfa_itnim_clear_stats(struct bfa_itnim_s *itnim);
+
+
+/**
+ *             BFA completion callback for bfa_itnim_online().
+ *
+ * @param[in]          itnim           FCS or driver itnim instance
+ *
+ * return None
+ */
+void            bfa_cb_itnim_online(void *itnim);
+
+/**
+ *             BFA completion callback for bfa_itnim_offline().
+ *
+ * @param[in]          itnim           FCS or driver itnim instance
+ *
+ * return None
+ */
+void            bfa_cb_itnim_offline(void *itnim);
+void            bfa_cb_itnim_tov_begin(void *itnim);
+void            bfa_cb_itnim_tov(void *itnim);
+
+/**
+ *             BFA notification to FCS/driver for second level error recovery.
+ *
+ * Atleast one I/O request has timedout and target is unresponsive to
+ * repeated abort requests. Second level error recovery should be initiated
+ * by starting implicit logout and recovery procedures.
+ *
+ * @param[in]          itnim           FCS or driver itnim instance
+ *
+ * return None
+ */
+void            bfa_cb_itnim_sler(void *itnim);
+
+/*
+ * bfa ioim API functions
+ */
+struct bfa_ioim_s      *bfa_ioim_alloc(struct bfa_s *bfa,
+                                       struct bfad_ioim_s *dio,
+                                       struct bfa_itnim_s *itnim,
+                                       u16 nsgles);
+
+void           bfa_ioim_free(struct bfa_ioim_s *ioim);
+void           bfa_ioim_start(struct bfa_ioim_s *ioim);
+void           bfa_ioim_abort(struct bfa_ioim_s *ioim);
+void           bfa_ioim_delayed_comp(struct bfa_ioim_s *ioim,
+                                     bfa_boolean_t iotov);
+
+
+/**
+ *             I/O completion notification.
+ *
+ * @param[in]          dio                     driver IO structure
+ * @param[in]          io_status               IO completion status
+ * @param[in]          scsi_status             SCSI status returned by target
+ * @param[in]          sns_len                 SCSI sense length, 0 if none
+ * @param[in]          sns_info                SCSI sense data, if any
+ * @param[in]          residue                 Residual length
+ *
+ * @return None
+ */
+void            bfa_cb_ioim_done(void *bfad, struct bfad_ioim_s *dio,
+                                 enum bfi_ioim_status io_status,
+                                 u8 scsi_status, int sns_len,
+                                 u8 *sns_info, s32 residue);
+
+/**
+ *             I/O good completion notification.
+ *
+ * @param[in]          dio                     driver IO structure
+ *
+ * @return None
+ */
+void            bfa_cb_ioim_good_comp(void *bfad, struct bfad_ioim_s *dio);
+
+/**
+ *             I/O abort completion notification
+ *
+ * @param[in]          dio                     driver IO that was aborted
+ *
+ * @return None
+ */
+void            bfa_cb_ioim_abort(void *bfad, struct bfad_ioim_s *dio);
+void           bfa_cb_ioim_resfree(void *hcb_bfad);
+
+void                   bfa_cb_ioim_resfree(void *hcb_bfad);
+
+/*
+ * bfa tskim API functions
+ */
+struct bfa_tskim_s     *bfa_tskim_alloc(struct bfa_s *bfa,
+                                       struct bfad_tskim_s *dtsk);
+void           bfa_tskim_free(struct bfa_tskim_s *tskim);
+void           bfa_tskim_start(struct bfa_tskim_s *tskim,
+                               struct bfa_itnim_s *itnim, lun_t lun,
+                               enum fcp_tm_cmnd tm, u8 t_secs);
+void           bfa_cb_tskim_done(void *bfad, struct bfad_tskim_s *dtsk,
+                                 enum bfi_tskim_status tsk_status);
+
+#endif /* __BFA_FCPIM_H__ */
+
diff --git a/drivers/scsi/bfa/include/bfa_fcptm.h b/drivers/scsi/bfa/include/bfa_fcptm.h
new file mode 100644 (file)
index 0000000..5f5ffe0
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ */
+
+#ifndef __BFA_FCPTM_H__
+#define __BFA_FCPTM_H__
+
+#include <bfa.h>
+#include <bfa_svc.h>
+#include <bfi/bfi_fcptm.h>
+
+/*
+ * forward declarations
+ */
+struct bfa_tin_s;
+struct bfa_iotm_s;
+struct bfa_tsktm_s;
+
+/*
+ * bfa fcptm module API functions
+ */
+void bfa_fcptm_path_tov_set(struct bfa_s *bfa, u16 path_tov);
+u16 bfa_fcptm_path_tov_get(struct bfa_s *bfa);
+void bfa_fcptm_qdepth_set(struct bfa_s *bfa, u16 q_depth);
+u16 bfa_fcptm_qdepth_get(struct bfa_s *bfa);
+
+/*
+ * bfa tin API functions
+ */
+void bfa_tin_get_stats(struct bfa_tin_s *tin, struct bfa_tin_stats_s *stats);
+void bfa_tin_clear_stats(struct bfa_tin_s *tin);
+
+#endif /* __BFA_FCPTM_H__ */
+
diff --git a/drivers/scsi/bfa/include/bfa_svc.h b/drivers/scsi/bfa/include/bfa_svc.h
new file mode 100644 (file)
index 0000000..0c80b74
--- /dev/null
@@ -0,0 +1,324 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ */
+#ifndef __BFA_SVC_H__
+#define __BFA_SVC_H__
+
+/*
+ * forward declarations
+ */
+struct bfa_fcxp_s;
+
+#include <defs/bfa_defs_status.h>
+#include <defs/bfa_defs_pport.h>
+#include <defs/bfa_defs_rport.h>
+#include <defs/bfa_defs_qos.h>
+#include <cs/bfa_sm.h>
+#include <bfa.h>
+
+/**
+ *             BFA rport information.
+ */
+struct bfa_rport_info_s {
+       u16        max_frmsz;   /*  max rcv pdu size               */
+       u32        pid : 24,    /*  remote port ID                 */
+                       lp_tag : 8;
+       u32        local_pid : 24,      /*  local port ID                   */
+                       cisc : 8;       /*  CIRO supported                  */
+       u8         fc_class;    /*  supported FC classes. enum fc_cos */
+       u8         vf_en;               /*  virtual fabric enable          */
+       u16        vf_id;               /*  virtual fabric ID              */
+       enum bfa_pport_speed speed;     /*  Rport's current speed           */
+};
+
+/**
+ * BFA rport data structure
+ */
+struct bfa_rport_s {
+       struct list_head        qe;       /*  queue element */
+       bfa_sm_t              sm;         /*  state machine */
+       struct bfa_s          *bfa;       /*  backpointer to BFA */
+       void                  *rport_drv; /*  fcs/driver rport object */
+       u16              fw_handle; /*  firmware rport handle */
+       u16              rport_tag; /*  BFA rport tag */
+       struct bfa_rport_info_s rport_info; /*  rport info from *fcs/driver */
+       struct bfa_reqq_wait_s reqq_wait; /*  to wait for room in reqq */
+       struct bfa_cb_qe_s    hcb_qe;    /*  BFA callback qelem */
+       struct bfa_rport_hal_stats_s stats; /*  BFA rport statistics  */
+       struct bfa_rport_qos_attr_s  qos_attr;
+       union a {
+               bfa_status_t    status;  /*  f/w status */
+               void            *fw_msg; /*  QoS scn event */
+       } event_arg;
+};
+#define BFA_RPORT_FC_COS(_rport)       ((_rport)->rport_info.fc_class)
+
+/**
+ * Send completion callback.
+ */
+typedef void (*bfa_cb_fcxp_send_t) (void *bfad_fcxp, struct bfa_fcxp_s *fcxp,
+                       void *cbarg, enum bfa_status req_status,
+                       u32 rsp_len, u32 resid_len,
+                       struct fchs_s *rsp_fchs);
+
+/**
+ * BFA fcxp allocation (asynchronous)
+ */
+typedef void (*bfa_fcxp_alloc_cbfn_t) (void *cbarg, struct bfa_fcxp_s *fcxp);
+
+struct bfa_fcxp_wqe_s {
+       struct list_head         qe;
+       bfa_fcxp_alloc_cbfn_t  alloc_cbfn;
+       void           *alloc_cbarg;
+};
+
+typedef u64 (*bfa_fcxp_get_sgaddr_t) (void *bfad_fcxp, int sgeid);
+typedef u32 (*bfa_fcxp_get_sglen_t) (void *bfad_fcxp, int sgeid);
+
+#define BFA_UF_BUFSZ   (2 * 1024 + 256)
+
+/**
+ * @todo private
+ */
+struct bfa_uf_buf_s {
+       u8         d[BFA_UF_BUFSZ];
+};
+
+
+struct bfa_uf_s {
+       struct list_head        qe;             /*  queue element         */
+       struct bfa_s    *bfa;           /*  bfa instance          */
+       u16        uf_tag;              /*  identifying tag f/w messages */
+       u16        vf_id;
+       u16        src_rport_handle;
+       u16        rsvd;
+       u8              *data_ptr;
+       u16        data_len;    /*  actual receive length         */
+       u16        pb_len;              /*  posted buffer length          */
+       void            *buf_kva;       /*  buffer virtual address        */
+       u64        buf_pa;              /*  buffer physical address       */
+       struct bfa_cb_qe_s    hcb_qe;   /*  comp: BFA comp qelem          */
+       struct bfa_sge_s        sges[BFI_SGE_INLINE_MAX];
+};
+
+typedef void (*bfa_cb_pport_t) (void *cbarg, enum bfa_status status);
+
+/**
+ * bfa lport login/logout service interface
+ */
+struct bfa_lps_s {
+       struct list_head        qe;             /*  queue element */
+       struct bfa_s    *bfa;           /*  parent bfa instance */
+       bfa_sm_t        sm;             /*  finite state machine        */
+       u8              lp_tag;         /*  lport tag                   */
+       u8              reqq;           /*  lport request queue */
+       u8              alpa;           /*  ALPA for loop topologies    */
+       u32     lp_pid;         /*  lport port ID               */
+       bfa_boolean_t   fdisc;          /*  send FDISC instead of FLOGI*/
+       bfa_boolean_t   auth_en;        /*  enable authentication       */
+       bfa_boolean_t   auth_req;       /*  authentication required     */
+       bfa_boolean_t   npiv_en;        /*  NPIV is allowed by peer     */
+       bfa_boolean_t   fport;          /*  attached peer is F_PORT     */
+       bfa_boolean_t   brcd_switch;/*  attached peer is brcd switch    */
+       bfa_status_t    status;         /*  login status                */
+       u16     pdusz;          /*  max receive PDU size        */
+       u16     pr_bbcred;      /*  BB_CREDIT from peer         */
+       u8              lsrjt_rsn;      /*  LSRJT reason                */
+       u8              lsrjt_expl;     /*  LSRJT explanation           */
+       wwn_t           pwwn;           /*  port wwn of lport           */
+       wwn_t           nwwn;           /*  node wwn of lport           */
+       wwn_t           pr_pwwn;        /*  port wwn of lport peer      */
+       wwn_t           pr_nwwn;        /*  node wwn of lport peer      */
+       mac_t           lp_mac;         /*  fpma/spma MAC for lport     */
+       mac_t           fcf_mac;        /*  FCF MAC of lport            */
+       struct bfa_reqq_wait_s  wqe;    /*  request wait queue element  */
+       void            *uarg;          /*  user callback arg           */
+       struct bfa_cb_qe_s hcb_qe;      /*  comp: callback qelem        */
+       struct bfi_lps_login_rsp_s *loginrsp;
+       bfa_eproto_status_t     ext_status;
+};
+
+/*
+ * bfa pport API functions
+ */
+bfa_status_t bfa_pport_enable(struct bfa_s *bfa);
+bfa_status_t bfa_pport_disable(struct bfa_s *bfa);
+bfa_status_t bfa_pport_cfg_speed(struct bfa_s *bfa,
+                       enum bfa_pport_speed speed);
+enum bfa_pport_speed bfa_pport_get_speed(struct bfa_s *bfa);
+bfa_status_t bfa_pport_cfg_topology(struct bfa_s *bfa,
+                       enum bfa_pport_topology topo);
+enum bfa_pport_topology bfa_pport_get_topology(struct bfa_s *bfa);
+bfa_status_t bfa_pport_cfg_hardalpa(struct bfa_s *bfa, u8 alpa);
+bfa_boolean_t bfa_pport_get_hardalpa(struct bfa_s *bfa, u8 *alpa);
+u8 bfa_pport_get_myalpa(struct bfa_s *bfa);
+bfa_status_t bfa_pport_clr_hardalpa(struct bfa_s *bfa);
+bfa_status_t bfa_pport_cfg_maxfrsize(struct bfa_s *bfa, u16 maxsize);
+u16 bfa_pport_get_maxfrsize(struct bfa_s *bfa);
+u32 bfa_pport_mypid(struct bfa_s *bfa);
+u8 bfa_pport_get_rx_bbcredit(struct bfa_s *bfa);
+bfa_status_t bfa_pport_trunk_enable(struct bfa_s *bfa, u8 bitmap);
+bfa_status_t bfa_pport_trunk_disable(struct bfa_s *bfa);
+bfa_boolean_t bfa_pport_trunk_query(struct bfa_s *bfa, u32 *bitmap);
+void bfa_pport_get_attr(struct bfa_s *bfa, struct bfa_pport_attr_s *attr);
+wwn_t bfa_pport_get_wwn(struct bfa_s *bfa, bfa_boolean_t node);
+bfa_status_t bfa_pport_get_stats(struct bfa_s *bfa,
+                       union bfa_pport_stats_u *stats,
+                       bfa_cb_pport_t cbfn, void *cbarg);
+bfa_status_t bfa_pport_clear_stats(struct bfa_s *bfa, bfa_cb_pport_t cbfn,
+                       void *cbarg);
+void bfa_pport_event_register(struct bfa_s *bfa,
+                       void (*event_cbfn) (void *cbarg,
+                       bfa_pport_event_t event), void *event_cbarg);
+bfa_boolean_t bfa_pport_is_disabled(struct bfa_s *bfa);
+void bfa_pport_cfg_qos(struct bfa_s *bfa, bfa_boolean_t on_off);
+void bfa_pport_cfg_ratelim(struct bfa_s *bfa, bfa_boolean_t on_off);
+bfa_status_t bfa_pport_cfg_ratelim_speed(struct bfa_s *bfa,
+                       enum bfa_pport_speed speed);
+enum bfa_pport_speed bfa_pport_get_ratelim_speed(struct bfa_s *bfa);
+
+void bfa_pport_set_tx_bbcredit(struct bfa_s *bfa, u16 tx_bbcredit);
+void bfa_pport_busy(struct bfa_s *bfa, bfa_boolean_t status);
+void bfa_pport_beacon(struct bfa_s *bfa, bfa_boolean_t beacon,
+                       bfa_boolean_t link_e2e_beacon);
+void bfa_cb_pport_event(void *cbarg, bfa_pport_event_t event);
+void bfa_pport_qos_get_attr(struct bfa_s *bfa, struct bfa_qos_attr_s *qos_attr);
+void bfa_pport_qos_get_vc_attr(struct bfa_s *bfa,
+                       struct bfa_qos_vc_attr_s *qos_vc_attr);
+bfa_status_t bfa_pport_get_qos_stats(struct bfa_s *bfa,
+                       union bfa_pport_stats_u *stats,
+                       bfa_cb_pport_t cbfn, void *cbarg);
+bfa_status_t bfa_pport_clear_qos_stats(struct bfa_s *bfa, bfa_cb_pport_t cbfn,
+                       void *cbarg);
+bfa_boolean_t     bfa_pport_is_ratelim(struct bfa_s *bfa);
+bfa_boolean_t  bfa_pport_is_linkup(struct bfa_s *bfa);
+
+/*
+ * bfa rport API functions
+ */
+struct bfa_rport_s *bfa_rport_create(struct bfa_s *bfa, void *rport_drv);
+void bfa_rport_delete(struct bfa_rport_s *rport);
+void bfa_rport_online(struct bfa_rport_s *rport,
+                       struct bfa_rport_info_s *rport_info);
+void bfa_rport_offline(struct bfa_rport_s *rport);
+void bfa_rport_speed(struct bfa_rport_s *rport, enum bfa_pport_speed speed);
+void bfa_rport_get_stats(struct bfa_rport_s *rport,
+                       struct bfa_rport_hal_stats_s *stats);
+void bfa_rport_clear_stats(struct bfa_rport_s *rport);
+void bfa_cb_rport_online(void *rport);
+void bfa_cb_rport_offline(void *rport);
+void bfa_cb_rport_qos_scn_flowid(void *rport,
+                       struct bfa_rport_qos_attr_s old_qos_attr,
+                       struct bfa_rport_qos_attr_s new_qos_attr);
+void bfa_cb_rport_qos_scn_prio(void *rport,
+                       struct bfa_rport_qos_attr_s old_qos_attr,
+                       struct bfa_rport_qos_attr_s new_qos_attr);
+void bfa_rport_get_qos_attr(struct bfa_rport_s *rport,
+                       struct bfa_rport_qos_attr_s *qos_attr);
+
+/*
+ * bfa fcxp API functions
+ */
+struct bfa_fcxp_s *bfa_fcxp_alloc(void *bfad_fcxp, struct bfa_s *bfa,
+                       int nreq_sgles, int nrsp_sgles,
+                       bfa_fcxp_get_sgaddr_t get_req_sga,
+                       bfa_fcxp_get_sglen_t get_req_sglen,
+                       bfa_fcxp_get_sgaddr_t get_rsp_sga,
+                       bfa_fcxp_get_sglen_t get_rsp_sglen);
+void bfa_fcxp_alloc_wait(struct bfa_s *bfa, struct bfa_fcxp_wqe_s *wqe,
+                       bfa_fcxp_alloc_cbfn_t alloc_cbfn, void *cbarg);
+void bfa_fcxp_walloc_cancel(struct bfa_s *bfa,
+                       struct bfa_fcxp_wqe_s *wqe);
+void bfa_fcxp_discard(struct bfa_fcxp_s *fcxp);
+
+void *bfa_fcxp_get_reqbuf(struct bfa_fcxp_s *fcxp);
+void *bfa_fcxp_get_rspbuf(struct bfa_fcxp_s *fcxp);
+
+void bfa_fcxp_free(struct bfa_fcxp_s *fcxp);
+
+void bfa_fcxp_send(struct bfa_fcxp_s *fcxp,
+                       struct bfa_rport_s *rport, u16 vf_id, u8 lp_tag,
+                       bfa_boolean_t cts, enum fc_cos cos,
+                       u32 reqlen, struct fchs_s *fchs,
+                       bfa_cb_fcxp_send_t cbfn,
+                       void *cbarg,
+                       u32 rsp_maxlen, u8 rsp_timeout);
+bfa_status_t bfa_fcxp_abort(struct bfa_fcxp_s *fcxp);
+u32        bfa_fcxp_get_reqbufsz(struct bfa_fcxp_s *fcxp);
+u32    bfa_fcxp_get_maxrsp(struct bfa_s *bfa);
+
+static inline void *
+bfa_uf_get_frmbuf(struct bfa_uf_s *uf)
+{
+       return uf->data_ptr;
+}
+
+static inline   u16
+bfa_uf_get_frmlen(struct bfa_uf_s *uf)
+{
+       return uf->data_len;
+}
+
+/**
+ *      Callback prototype for unsolicited frame receive handler.
+ *
+ * @param[in]           cbarg           callback arg for receive handler
+ * @param[in]           uf              unsolicited frame descriptor
+ *
+ * @return None
+ */
+typedef void (*bfa_cb_uf_recv_t) (void *cbarg, struct bfa_uf_s *uf);
+
+/*
+ * bfa uf API functions
+ */
+void bfa_uf_recv_register(struct bfa_s *bfa, bfa_cb_uf_recv_t ufrecv,
+                       void *cbarg);
+void bfa_uf_free(struct bfa_uf_s *uf);
+
+/**
+ * bfa lport service api
+ */
+
+struct bfa_lps_s *bfa_lps_alloc(struct bfa_s *bfa);
+void bfa_lps_delete(struct bfa_lps_s *lps);
+void bfa_lps_discard(struct bfa_lps_s *lps);
+void bfa_lps_flogi(struct bfa_lps_s *lps, void *uarg, u8 alpa, u16 pdusz,
+                  wwn_t pwwn, wwn_t nwwn, bfa_boolean_t auth_en);
+void bfa_lps_fdisc(struct bfa_lps_s *lps, void *uarg, u16 pdusz, wwn_t pwwn,
+                  wwn_t nwwn);
+void bfa_lps_flogo(struct bfa_lps_s *lps);
+void bfa_lps_fdisclogo(struct bfa_lps_s *lps);
+u8 bfa_lps_get_tag(struct bfa_lps_s *lps);
+bfa_boolean_t bfa_lps_is_npiv_en(struct bfa_lps_s *lps);
+bfa_boolean_t bfa_lps_is_fport(struct bfa_lps_s *lps);
+bfa_boolean_t bfa_lps_is_brcd_fabric(struct bfa_lps_s *lps);
+bfa_boolean_t bfa_lps_is_authreq(struct bfa_lps_s *lps);
+bfa_eproto_status_t bfa_lps_get_extstatus(struct bfa_lps_s *lps);
+u32 bfa_lps_get_pid(struct bfa_lps_s *lps);
+u8 bfa_lps_get_tag_from_pid(struct bfa_s *bfa, u32 pid);
+u16 bfa_lps_get_peer_bbcredit(struct bfa_lps_s *lps);
+wwn_t bfa_lps_get_peer_pwwn(struct bfa_lps_s *lps);
+wwn_t bfa_lps_get_peer_nwwn(struct bfa_lps_s *lps);
+u8 bfa_lps_get_lsrjt_rsn(struct bfa_lps_s *lps);
+u8 bfa_lps_get_lsrjt_expl(struct bfa_lps_s *lps);
+void bfa_cb_lps_flogi_comp(void *bfad, void *uarg, bfa_status_t status);
+void bfa_cb_lps_flogo_comp(void *bfad, void *uarg);
+void bfa_cb_lps_fdisc_comp(void *bfad, void *uarg, bfa_status_t status);
+void bfa_cb_lps_fdisclogo_comp(void *bfad, void *uarg);
+
+#endif /* __BFA_SVC_H__ */
+
diff --git a/drivers/scsi/bfa/include/bfa_timer.h b/drivers/scsi/bfa/include/bfa_timer.h
new file mode 100644 (file)
index 0000000..e407103
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ */
+#ifndef __BFA_TIMER_H__
+#define __BFA_TIMER_H__
+
+#include <bfa_os_inc.h>
+#include <cs/bfa_q.h>
+
+struct bfa_s;
+
+typedef void (*bfa_timer_cbfn_t)(void *);
+
+/**
+ * BFA timer data structure
+ */
+struct bfa_timer_s {
+       struct list_head        qe;
+       bfa_timer_cbfn_t timercb;
+       void            *arg;
+       int             timeout;        /**< in millisecs. */
+};
+
+/**
+ * Timer module structure
+ */
+struct bfa_timer_mod_s {
+       struct list_head timer_q;
+};
+
+#define BFA_TIMER_FREQ 500 /**< specified in millisecs */
+
+void bfa_timer_beat(struct bfa_timer_mod_s *mod);
+void bfa_timer_init(struct bfa_timer_mod_s *mod);
+void bfa_timer_begin(struct bfa_timer_mod_s *mod, struct bfa_timer_s *timer,
+                       bfa_timer_cbfn_t timercb, void *arg,
+                       unsigned int timeout);
+void bfa_timer_stop(struct bfa_timer_s *timer);
+
+#endif /* __BFA_TIMER_H__ */
diff --git a/drivers/scsi/bfa/include/bfi/bfi.h b/drivers/scsi/bfa/include/bfi/bfi.h
new file mode 100644 (file)
index 0000000..6cadfe0
--- /dev/null
@@ -0,0 +1,174 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ */
+
+#ifndef __BFI_H__
+#define __BFI_H__
+
+#include <bfa_os_inc.h>
+#include <defs/bfa_defs_status.h>
+
+#pragma pack(1)
+
+/**
+ * Msg header common to all msgs
+ */
+struct bfi_mhdr_s {
+       u8         msg_class;   /*  @ref bfi_mclass_t       */
+       u8         msg_id;              /*  msg opcode with in the class   */
+       union {
+               struct {
+                       u8         rsvd;
+                       u8         lpu_id;      /*  msg destination         */
+               } h2i;
+               u16        i2htok;      /*  token in msgs to host           */
+       } mtag;
+};
+
+#define bfi_h2i_set(_mh, _mc, _op, _lpuid) do {                \
+       (_mh).msg_class                 = (_mc);      \
+       (_mh).msg_id                    = (_op);      \
+       (_mh).mtag.h2i.lpu_id   = (_lpuid);      \
+} while (0)
+
+#define bfi_i2h_set(_mh, _mc, _op, _i2htok) do {               \
+       (_mh).msg_class                 = (_mc);      \
+       (_mh).msg_id                    = (_op);      \
+       (_mh).mtag.i2htok               = (_i2htok);      \
+} while (0)
+
+/*
+ * Message opcodes: 0-127 to firmware, 128-255 to host
+ */
+#define BFI_I2H_OPCODE_BASE    128
+#define BFA_I2HM(_x)                   ((_x) + BFI_I2H_OPCODE_BASE)
+
+/**
+ ****************************************************************************
+ *
+ * Scatter Gather Element and Page definition
+ *
+ ****************************************************************************
+ */
+
+#define BFI_SGE_INLINE 1
+#define BFI_SGE_INLINE_MAX     (BFI_SGE_INLINE + 1)
+
+/**
+ * SG Flags
+ */
+enum {
+       BFI_SGE_DATA    = 0,    /*  data address, not last           */
+       BFI_SGE_DATA_CPL        = 1,    /*  data addr, last in current page */
+       BFI_SGE_DATA_LAST       = 3,    /*  data address, last               */
+       BFI_SGE_LINK    = 2,    /*  link address                     */
+       BFI_SGE_PGDLEN  = 2,    /*  cumulative data length for page */
+};
+
+/**
+ * DMA addresses
+ */
+union bfi_addr_u {
+       struct {
+               u32        addr_lo;
+               u32        addr_hi;
+       } a32;
+};
+
+/**
+ * Scatter Gather Element
+ */
+struct bfi_sge_s {
+#ifdef __BIGENDIAN
+       u32        flags        : 2,
+                       rsvd    : 2,
+                       sg_len  : 28;
+#else
+       u32        sg_len       : 28,
+                       rsvd    : 2,
+                       flags   : 2;
+#endif
+       union bfi_addr_u sga;
+};
+
+/**
+ * Scatter Gather Page
+ */
+#define BFI_SGPG_DATA_SGES             7
+#define BFI_SGPG_SGES_MAX              (BFI_SGPG_DATA_SGES + 1)
+#define BFI_SGPG_RSVD_WD_LEN   8
+struct bfi_sgpg_s {
+       struct bfi_sge_s sges[BFI_SGPG_SGES_MAX];
+       u32     rsvd[BFI_SGPG_RSVD_WD_LEN];
+};
+
+/*
+ * Large Message structure - 128 Bytes size Msgs
+ */
+#define BFI_LMSG_SZ            128
+#define BFI_LMSG_PL_WSZ        \
+                       ((BFI_LMSG_SZ - sizeof(struct bfi_mhdr_s)) / 4)
+
+struct bfi_msg_s {
+       struct bfi_mhdr_s mhdr;
+       u32     pl[BFI_LMSG_PL_WSZ];
+};
+
+/**
+ * Mailbox message structure
+ */
+#define BFI_MBMSG_SZ           7
+struct bfi_mbmsg_s {
+       struct bfi_mhdr_s       mh;
+       u32             pl[BFI_MBMSG_SZ];
+};
+
+/**
+ * Message Classes
+ */
+enum bfi_mclass {
+       BFI_MC_IOC              = 1,    /*  IO Controller (IOC)     */
+       BFI_MC_DIAG             = 2,    /*  Diagnostic Msgs                 */
+       BFI_MC_FLASH            = 3,    /*  Flash message class     */
+       BFI_MC_CEE              = 4,
+       BFI_MC_FC_PORT          = 5,    /*  FC port                         */
+       BFI_MC_IOCFC            = 6,    /*  FC - IO Controller (IOC)        */
+       BFI_MC_LL               = 7,    /*  Link Layer                      */
+       BFI_MC_UF               = 8,    /*  Unsolicited frame receive       */
+       BFI_MC_FCXP             = 9,    /*  FC Transport                    */
+       BFI_MC_LPS              = 10,   /*  lport fc login services         */
+       BFI_MC_RPORT            = 11,   /*  Remote port             */
+       BFI_MC_ITNIM            = 12,   /*  I-T nexus (Initiator mode)      */
+       BFI_MC_IOIM_READ        = 13,   /*  read IO (Initiator mode)        */
+       BFI_MC_IOIM_WRITE       = 14,   /*  write IO (Initiator mode)       */
+       BFI_MC_IOIM_IO          = 15,   /*  IO (Initiator mode)     */
+       BFI_MC_IOIM             = 16,   /*  IO (Initiator mode)     */
+       BFI_MC_IOIM_IOCOM       = 17,   /*  good IO completion              */
+       BFI_MC_TSKIM            = 18,   /*  Initiator Task management       */
+       BFI_MC_SBOOT            = 19,   /*  SAN boot services               */
+       BFI_MC_IPFC             = 20,   /*  IP over FC Msgs                 */
+       BFI_MC_PORT             = 21,   /*  Physical port                   */
+       BFI_MC_MAX              = 32
+};
+
+#define BFI_IOC_MAX_CQS                4
+#define BFI_IOC_MAX_CQS_ASIC   8
+#define BFI_IOC_MSGLEN_MAX     32      /* 32 bytes */
+
+#pragma pack()
+
+#endif /* __BFI_H__ */
+
diff --git a/drivers/scsi/bfa/include/bfi/bfi_boot.h b/drivers/scsi/bfa/include/bfi/bfi_boot.h
new file mode 100644 (file)
index 0000000..5955afe
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) 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.
+ */
+/*
+ * bfi_boot.h
+ */
+
+#ifndef __BFI_BOOT_H__
+#define __BFI_BOOT_H__
+
+#define BFI_BOOT_TYPE_OFF              8
+#define BFI_BOOT_PARAM_OFF             12
+
+#define BFI_BOOT_TYPE_NORMAL           0       /* param is device id */
+#define        BFI_BOOT_TYPE_FLASH             1
+#define        BFI_BOOT_TYPE_MEMTEST           2
+
+#define BFI_BOOT_MEMTEST_RES_ADDR   0x900
+#define BFI_BOOT_MEMTEST_RES_SIG    0xA0A1A2A3
+
+#endif
diff --git a/drivers/scsi/bfa/include/bfi/bfi_cbreg.h b/drivers/scsi/bfa/include/bfi/bfi_cbreg.h
new file mode 100644 (file)
index 0000000..b3bb52b
--- /dev/null
@@ -0,0 +1,305 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) 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.
+ */
+
+/*
+ * bfi_cbreg.h crossbow host block register definitions
+ *
+ * !!! Do not edit. Auto generated. !!!
+ */
+
+#ifndef __BFI_CBREG_H__
+#define __BFI_CBREG_H__
+
+
+#define HOSTFN0_INT_STATUS               0x00014000
+#define __HOSTFN0_INT_STATUS_LVL_MK      0x00f00000
+#define __HOSTFN0_INT_STATUS_LVL_SH      20
+#define __HOSTFN0_INT_STATUS_LVL(_v)     ((_v) << __HOSTFN0_INT_STATUS_LVL_SH)
+#define __HOSTFN0_INT_STATUS_P           0x000fffff
+#define HOSTFN0_INT_MSK                  0x00014004
+#define HOST_PAGE_NUM_FN0                0x00014008
+#define __HOST_PAGE_NUM_FN               0x000001ff
+#define HOSTFN1_INT_STATUS               0x00014100
+#define __HOSTFN1_INT_STAT_LVL_MK        0x00f00000
+#define __HOSTFN1_INT_STAT_LVL_SH        20
+#define __HOSTFN1_INT_STAT_LVL(_v)       ((_v) << __HOSTFN1_INT_STAT_LVL_SH)
+#define __HOSTFN1_INT_STAT_P             0x000fffff
+#define HOSTFN1_INT_MSK                  0x00014104
+#define HOST_PAGE_NUM_FN1                0x00014108
+#define APP_PLL_400_CTL_REG              0x00014204
+#define __P_400_PLL_LOCK                 0x80000000
+#define __APP_PLL_400_SRAM_USE_100MHZ    0x00100000
+#define __APP_PLL_400_RESET_TIMER_MK     0x000e0000
+#define __APP_PLL_400_RESET_TIMER_SH     17
+#define __APP_PLL_400_RESET_TIMER(_v)    ((_v) << __APP_PLL_400_RESET_TIMER_SH)
+#define __APP_PLL_400_LOGIC_SOFT_RESET   0x00010000
+#define __APP_PLL_400_CNTLMT0_1_MK       0x0000c000
+#define __APP_PLL_400_CNTLMT0_1_SH       14
+#define __APP_PLL_400_CNTLMT0_1(_v)      ((_v) << __APP_PLL_400_CNTLMT0_1_SH)
+#define __APP_PLL_400_JITLMT0_1_MK       0x00003000
+#define __APP_PLL_400_JITLMT0_1_SH       12
+#define __APP_PLL_400_JITLMT0_1(_v)      ((_v) << __APP_PLL_400_JITLMT0_1_SH)
+#define __APP_PLL_400_HREF               0x00000800
+#define __APP_PLL_400_HDIV               0x00000400
+#define __APP_PLL_400_P0_1_MK            0x00000300
+#define __APP_PLL_400_P0_1_SH            8
+#define __APP_PLL_400_P0_1(_v)           ((_v) << __APP_PLL_400_P0_1_SH)
+#define __APP_PLL_400_Z0_2_MK            0x000000e0
+#define __APP_PLL_400_Z0_2_SH            5
+#define __APP_PLL_400_Z0_2(_v)           ((_v) << __APP_PLL_400_Z0_2_SH)
+#define __APP_PLL_400_RSEL200500         0x00000010
+#define __APP_PLL_400_ENARST             0x00000008
+#define __APP_PLL_400_BYPASS             0x00000004
+#define __APP_PLL_400_LRESETN            0x00000002
+#define __APP_PLL_400_ENABLE             0x00000001
+#define APP_PLL_212_CTL_REG              0x00014208
+#define __P_212_PLL_LOCK                 0x80000000
+#define __APP_PLL_212_RESET_TIMER_MK     0x000e0000
+#define __APP_PLL_212_RESET_TIMER_SH     17
+#define __APP_PLL_212_RESET_TIMER(_v)    ((_v) << __APP_PLL_212_RESET_TIMER_SH)
+#define __APP_PLL_212_LOGIC_SOFT_RESET   0x00010000
+#define __APP_PLL_212_CNTLMT0_1_MK       0x0000c000
+#define __APP_PLL_212_CNTLMT0_1_SH       14
+#define __APP_PLL_212_CNTLMT0_1(_v)      ((_v) << __APP_PLL_212_CNTLMT0_1_SH)
+#define __APP_PLL_212_JITLMT0_1_MK       0x00003000
+#define __APP_PLL_212_JITLMT0_1_SH       12
+#define __APP_PLL_212_JITLMT0_1(_v)      ((_v) << __APP_PLL_212_JITLMT0_1_SH)
+#define __APP_PLL_212_HREF               0x00000800
+#define __APP_PLL_212_HDIV               0x00000400
+#define __APP_PLL_212_P0_1_MK            0x00000300
+#define __APP_PLL_212_P0_1_SH            8
+#define __APP_PLL_212_P0_1(_v)           ((_v) << __APP_PLL_212_P0_1_SH)
+#define __APP_PLL_212_Z0_2_MK            0x000000e0
+#define __APP_PLL_212_Z0_2_SH            5
+#define __APP_PLL_212_Z0_2(_v)           ((_v) << __APP_PLL_212_Z0_2_SH)
+#define __APP_PLL_212_RSEL200500         0x00000010
+#define __APP_PLL_212_ENARST             0x00000008
+#define __APP_PLL_212_BYPASS             0x00000004
+#define __APP_PLL_212_LRESETN            0x00000002
+#define __APP_PLL_212_ENABLE             0x00000001
+#define HOST_SEM0_REG                    0x00014230
+#define __HOST_SEMAPHORE                 0x00000001
+#define HOST_SEM1_REG                    0x00014234
+#define HOST_SEM2_REG                    0x00014238
+#define HOST_SEM3_REG                    0x0001423c
+#define HOST_SEM0_INFO_REG               0x00014240
+#define HOST_SEM1_INFO_REG               0x00014244
+#define HOST_SEM2_INFO_REG               0x00014248
+#define HOST_SEM3_INFO_REG               0x0001424c
+#define HOSTFN0_LPU0_CMD_STAT            0x00019000
+#define __HOSTFN0_LPU0_MBOX_INFO_MK      0xfffffffe
+#define __HOSTFN0_LPU0_MBOX_INFO_SH      1
+#define __HOSTFN0_LPU0_MBOX_INFO(_v)     ((_v) << __HOSTFN0_LPU0_MBOX_INFO_SH)
+#define __HOSTFN0_LPU0_MBOX_CMD_STATUS   0x00000001
+#define LPU0_HOSTFN0_CMD_STAT            0x00019008
+#define __LPU0_HOSTFN0_MBOX_INFO_MK      0xfffffffe
+#define __LPU0_HOSTFN0_MBOX_INFO_SH      1
+#define __LPU0_HOSTFN0_MBOX_INFO(_v)     ((_v) << __LPU0_HOSTFN0_MBOX_INFO_SH)
+#define __LPU0_HOSTFN0_MBOX_CMD_STATUS   0x00000001
+#define HOSTFN1_LPU1_CMD_STAT            0x00019014
+#define __HOSTFN1_LPU1_MBOX_INFO_MK      0xfffffffe
+#define __HOSTFN1_LPU1_MBOX_INFO_SH      1
+#define __HOSTFN1_LPU1_MBOX_INFO(_v)     ((_v) << __HOSTFN1_LPU1_MBOX_INFO_SH)
+#define __HOSTFN1_LPU1_MBOX_CMD_STATUS   0x00000001
+#define LPU1_HOSTFN1_CMD_STAT            0x0001901c
+#define __LPU1_HOSTFN1_MBOX_INFO_MK      0xfffffffe
+#define __LPU1_HOSTFN1_MBOX_INFO_SH      1
+#define __LPU1_HOSTFN1_MBOX_INFO(_v)     ((_v) << __LPU1_HOSTFN1_MBOX_INFO_SH)
+#define __LPU1_HOSTFN1_MBOX_CMD_STATUS   0x00000001
+#define CPE_Q0_DEPTH                     0x00010014
+#define CPE_Q0_PI                        0x0001001c
+#define CPE_Q0_CI                        0x00010020
+#define CPE_Q1_DEPTH                     0x00010034
+#define CPE_Q1_PI                        0x0001003c
+#define CPE_Q1_CI                        0x00010040
+#define CPE_Q2_DEPTH                     0x00010054
+#define CPE_Q2_PI                        0x0001005c
+#define CPE_Q2_CI                        0x00010060
+#define CPE_Q3_DEPTH                     0x00010074
+#define CPE_Q3_PI                        0x0001007c
+#define CPE_Q3_CI                        0x00010080
+#define CPE_Q4_DEPTH                     0x00010094
+#define CPE_Q4_PI                        0x0001009c
+#define CPE_Q4_CI                        0x000100a0
+#define CPE_Q5_DEPTH                     0x000100b4
+#define CPE_Q5_PI                        0x000100bc
+#define CPE_Q5_CI                        0x000100c0
+#define CPE_Q6_DEPTH                     0x000100d4
+#define CPE_Q6_PI                        0x000100dc
+#define CPE_Q6_CI                        0x000100e0
+#define CPE_Q7_DEPTH                     0x000100f4
+#define CPE_Q7_PI                        0x000100fc
+#define CPE_Q7_CI                        0x00010100
+#define RME_Q0_DEPTH                     0x00011014
+#define RME_Q0_PI                        0x0001101c
+#define RME_Q0_CI                        0x00011020
+#define RME_Q1_DEPTH                     0x00011034
+#define RME_Q1_PI                        0x0001103c
+#define RME_Q1_CI                        0x00011040
+#define RME_Q2_DEPTH                     0x00011054
+#define RME_Q2_PI                        0x0001105c
+#define RME_Q2_CI                        0x00011060
+#define RME_Q3_DEPTH                     0x00011074
+#define RME_Q3_PI                        0x0001107c
+#define RME_Q3_CI                        0x00011080
+#define RME_Q4_DEPTH                     0x00011094
+#define RME_Q4_PI                        0x0001109c
+#define RME_Q4_CI                        0x000110a0
+#define RME_Q5_DEPTH                     0x000110b4
+#define RME_Q5_PI                        0x000110bc
+#define RME_Q5_CI                        0x000110c0
+#define RME_Q6_DEPTH                     0x000110d4
+#define RME_Q6_PI                        0x000110dc
+#define RME_Q6_CI                        0x000110e0
+#define RME_Q7_DEPTH                     0x000110f4
+#define RME_Q7_PI                        0x000110fc
+#define RME_Q7_CI                        0x00011100
+#define PSS_CTL_REG                      0x00018800
+#define __PSS_I2C_CLK_DIV_MK             0x00030000
+#define __PSS_I2C_CLK_DIV_SH             16
+#define __PSS_I2C_CLK_DIV(_v)            ((_v) << __PSS_I2C_CLK_DIV_SH)
+#define __PSS_LMEM_INIT_DONE             0x00001000
+#define __PSS_LMEM_RESET                 0x00000200
+#define __PSS_LMEM_INIT_EN               0x00000100
+#define __PSS_LPU1_RESET                 0x00000002
+#define __PSS_LPU0_RESET                 0x00000001
+
+
+/*
+ * These definitions are either in error/missing in spec. Its auto-generated
+ * from hard coded values in regparse.pl.
+ */
+#define __EMPHPOST_AT_4G_MK_FIX          0x0000001c
+#define __EMPHPOST_AT_4G_SH_FIX          0x00000002
+#define __EMPHPRE_AT_4G_FIX              0x00000003
+#define __SFP_TXRATE_EN_FIX              0x00000100
+#define __SFP_RXRATE_EN_FIX              0x00000080
+
+
+/*
+ * These register definitions are auto-generated from hard coded values
+ * in regparse.pl.
+ */
+#define HOSTFN0_LPU_MBOX0_0              0x00019200
+#define HOSTFN1_LPU_MBOX0_8              0x00019260
+#define LPU_HOSTFN0_MBOX0_0              0x00019280
+#define LPU_HOSTFN1_MBOX0_8              0x000192e0
+
+
+/*
+ * These register mapping definitions are auto-generated from mapping tables
+ * in regparse.pl.
+ */
+#define BFA_IOC0_HBEAT_REG               HOST_SEM0_INFO_REG
+#define BFA_IOC0_STATE_REG               HOST_SEM1_INFO_REG
+#define BFA_IOC1_HBEAT_REG               HOST_SEM2_INFO_REG
+#define BFA_IOC1_STATE_REG               HOST_SEM3_INFO_REG
+#define BFA_FW_USE_COUNT                 HOST_SEM4_INFO_REG
+
+#define CPE_Q_DEPTH(__n) \
+       (CPE_Q0_DEPTH + (__n) * (CPE_Q1_DEPTH - CPE_Q0_DEPTH))
+#define CPE_Q_PI(__n) \
+       (CPE_Q0_PI + (__n) * (CPE_Q1_PI - CPE_Q0_PI))
+#define CPE_Q_CI(__n) \
+       (CPE_Q0_CI + (__n) * (CPE_Q1_CI - CPE_Q0_CI))
+#define RME_Q_DEPTH(__n) \
+       (RME_Q0_DEPTH + (__n) * (RME_Q1_DEPTH - RME_Q0_DEPTH))
+#define RME_Q_PI(__n) \
+       (RME_Q0_PI + (__n) * (RME_Q1_PI - RME_Q0_PI))
+#define RME_Q_CI(__n) \
+       (RME_Q0_CI + (__n) * (RME_Q1_CI - RME_Q0_CI))
+
+#define CPE_Q_NUM(__fn, __q)  (((__fn) << 2) + (__q))
+#define RME_Q_NUM(__fn, __q)  (((__fn) << 2) + (__q))
+#define CPE_Q_MASK(__q)  ((__q) & 0x3)
+#define RME_Q_MASK(__q)  ((__q) & 0x3)
+
+
+/*
+ * PCI MSI-X vector defines
+ */
+enum {
+    BFA_MSIX_CPE_Q0 = 0,
+    BFA_MSIX_CPE_Q1 = 1,
+    BFA_MSIX_CPE_Q2 = 2,
+    BFA_MSIX_CPE_Q3 = 3,
+    BFA_MSIX_CPE_Q4 = 4,
+    BFA_MSIX_CPE_Q5 = 5,
+    BFA_MSIX_CPE_Q6 = 6,
+    BFA_MSIX_CPE_Q7 = 7,
+    BFA_MSIX_RME_Q0 = 8,
+    BFA_MSIX_RME_Q1 = 9,
+    BFA_MSIX_RME_Q2 = 10,
+    BFA_MSIX_RME_Q3 = 11,
+    BFA_MSIX_RME_Q4 = 12,
+    BFA_MSIX_RME_Q5 = 13,
+    BFA_MSIX_RME_Q6 = 14,
+    BFA_MSIX_RME_Q7 = 15,
+    BFA_MSIX_ERR_EMC = 16,
+    BFA_MSIX_ERR_LPU0 = 17,
+    BFA_MSIX_ERR_LPU1 = 18,
+    BFA_MSIX_ERR_PSS = 19,
+    BFA_MSIX_MBOX_LPU0 = 20,
+    BFA_MSIX_MBOX_LPU1 = 21,
+    BFA_MSIX_CB_MAX = 22,
+};
+
+/*
+ * And corresponding host interrupt status bit field defines
+ */
+#define __HFN_INT_CPE_Q0                   0x00000001U
+#define __HFN_INT_CPE_Q1                   0x00000002U
+#define __HFN_INT_CPE_Q2                   0x00000004U
+#define __HFN_INT_CPE_Q3                   0x00000008U
+#define __HFN_INT_CPE_Q4                   0x00000010U
+#define __HFN_INT_CPE_Q5                   0x00000020U
+#define __HFN_INT_CPE_Q6                   0x00000040U
+#define __HFN_INT_CPE_Q7                   0x00000080U
+#define __HFN_INT_RME_Q0                   0x00000100U
+#define __HFN_INT_RME_Q1                   0x00000200U
+#define __HFN_INT_RME_Q2                   0x00000400U
+#define __HFN_INT_RME_Q3                   0x00000800U
+#define __HFN_INT_RME_Q4                   0x00001000U
+#define __HFN_INT_RME_Q5                   0x00002000U
+#define __HFN_INT_RME_Q6                   0x00004000U
+#define __HFN_INT_RME_Q7                   0x00008000U
+#define __HFN_INT_ERR_EMC                  0x00010000U
+#define __HFN_INT_ERR_LPU0                 0x00020000U
+#define __HFN_INT_ERR_LPU1                 0x00040000U
+#define __HFN_INT_ERR_PSS                  0x00080000U
+#define __HFN_INT_MBOX_LPU0                0x00100000U
+#define __HFN_INT_MBOX_LPU1                0x00200000U
+#define __HFN_INT_MBOX1_LPU0               0x00400000U
+#define __HFN_INT_MBOX1_LPU1               0x00800000U
+#define __HFN_INT_CPE_MASK                 0x000000ffU
+#define __HFN_INT_RME_MASK                 0x0000ff00U
+
+
+/*
+ * crossbow memory map.
+ */
+#define PSS_SMEM_PAGE_START    0x8000
+#define PSS_SMEM_PGNUM(_pg0, _ma)      ((_pg0) + ((_ma) >> 15))
+#define PSS_SMEM_PGOFF(_ma)    ((_ma) & 0x7fff)
+
+/*
+ * End of crossbow memory map
+ */
+
+
+#endif /* __BFI_CBREG_H__ */
+
diff --git a/drivers/scsi/bfa/include/bfi/bfi_cee.h b/drivers/scsi/bfa/include/bfi/bfi_cee.h
new file mode 100644 (file)
index 0000000..0970596
--- /dev/null
@@ -0,0 +1,119 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) 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.
+ */
+/**
+ *  Copyright (c) 2006-2009 Brocade Communications Systems, Inc.
+ *  All rights reserved.
+ *
+ *  bfi_dcbx.h BFI Interface (Mailbox commands and related structures)
+ * between host driver and DCBX/LLDP firmware module.
+ *
+**/
+
+#ifndef __BFI_CEE_H__
+#define __BFI_CEE_H__
+
+#include <bfi/bfi.h>
+
+#pragma pack(1)
+
+
+enum bfi_cee_h2i_msgs_e {
+       BFI_CEE_H2I_GET_CFG_REQ = 1,
+       BFI_CEE_H2I_RESET_STATS = 2,
+       BFI_CEE_H2I_GET_STATS_REQ = 3,
+};
+
+
+enum bfi_cee_i2h_msgs_e {
+       BFI_CEE_I2H_GET_CFG_RSP = BFA_I2HM(1),
+       BFI_CEE_I2H_RESET_STATS_RSP = BFA_I2HM(2),
+       BFI_CEE_I2H_GET_STATS_RSP = BFA_I2HM(3),
+};
+
+
+/* Data structures */
+
+/*
+ * BFI_CEE_H2I_RESET_STATS
+ */
+struct bfi_lldp_reset_stats_s {
+       struct bfi_mhdr_s  mh;
+};
+
+/*
+ * BFI_CEE_H2I_RESET_STATS
+ */
+struct bfi_cee_reset_stats_s {
+       struct bfi_mhdr_s  mh;
+};
+
+/*
+ * BFI_CEE_H2I_GET_CFG_REQ
+ */
+struct bfi_cee_get_req_s {
+       struct bfi_mhdr_s  mh;
+       union bfi_addr_u   dma_addr;
+};
+
+
+/*
+ * BFI_CEE_I2H_GET_CFG_RSP
+ */
+struct bfi_cee_get_rsp_s {
+       struct bfi_mhdr_s  mh;
+       u8            cmd_status;
+       u8            rsvd[3];
+};
+
+/*
+ * BFI_CEE_H2I_GET_STATS_REQ
+ */
+struct bfi_cee_stats_req_s {
+       struct bfi_mhdr_s  mh;
+       union bfi_addr_u   dma_addr;
+};
+
+
+/*
+ * BFI_CEE_I2H_GET_STATS_RSP
+ */
+struct bfi_cee_stats_rsp_s {
+       struct bfi_mhdr_s  mh;
+       u8                 cmd_status;
+       u8                 rsvd[3];
+};
+
+
+
+union bfi_cee_h2i_msg_u {
+       struct bfi_mhdr_s           mh;
+       struct bfi_cee_get_req_s   get_req;
+       struct bfi_cee_stats_req_s stats_req;
+};
+
+
+union bfi_cee_i2h_msg_u {
+       struct bfi_mhdr_s         mh;
+       struct bfi_cee_get_rsp_s  get_rsp;
+       struct bfi_cee_stats_rsp_s stats_rsp;
+};
+
+#pragma pack()
+
+
+#endif /* __BFI_CEE_H__ */
+
diff --git a/drivers/scsi/bfa/include/bfi/bfi_ctreg.h b/drivers/scsi/bfa/include/bfi/bfi_ctreg.h
new file mode 100644 (file)
index 0000000..d3caa58
--- /dev/null
@@ -0,0 +1,611 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) 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.
+ */
+
+/*
+ * bfi_ctreg.h catapult host block register definitions
+ *
+ * !!! Do not edit. Auto generated. !!!
+ */
+
+#ifndef __BFI_CTREG_H__
+#define __BFI_CTREG_H__
+
+
+#define HOSTFN0_LPU_MBOX0_0              0x00019200
+#define HOSTFN1_LPU_MBOX0_8              0x00019260
+#define LPU_HOSTFN0_MBOX0_0              0x00019280
+#define LPU_HOSTFN1_MBOX0_8              0x000192e0
+#define HOSTFN2_LPU_MBOX0_0              0x00019400
+#define HOSTFN3_LPU_MBOX0_8              0x00019460
+#define LPU_HOSTFN2_MBOX0_0              0x00019480
+#define LPU_HOSTFN3_MBOX0_8              0x000194e0
+#define HOSTFN0_INT_STATUS               0x00014000
+#define __HOSTFN0_HALT_OCCURRED          0x01000000
+#define __HOSTFN0_INT_STATUS_LVL_MK      0x00f00000
+#define __HOSTFN0_INT_STATUS_LVL_SH      20
+#define __HOSTFN0_INT_STATUS_LVL(_v)     ((_v) << __HOSTFN0_INT_STATUS_LVL_SH)
+#define __HOSTFN0_INT_STATUS_P_MK        0x000f0000
+#define __HOSTFN0_INT_STATUS_P_SH        16
+#define __HOSTFN0_INT_STATUS_P(_v)       ((_v) << __HOSTFN0_INT_STATUS_P_SH)
+#define __HOSTFN0_INT_STATUS_F           0x0000ffff
+#define HOSTFN0_INT_MSK                  0x00014004
+#define HOST_PAGE_NUM_FN0                0x00014008
+#define __HOST_PAGE_NUM_FN               0x000001ff
+#define HOST_MSIX_ERR_INDEX_FN0          0x0001400c
+#define __MSIX_ERR_INDEX_FN              0x000001ff
+#define HOSTFN1_INT_STATUS               0x00014100
+#define __HOSTFN1_HALT_OCCURRED          0x01000000
+#define __HOSTFN1_INT_STATUS_LVL_MK      0x00f00000
+#define __HOSTFN1_INT_STATUS_LVL_SH      20
+#define __HOSTFN1_INT_STATUS_LVL(_v)     ((_v) << __HOSTFN1_INT_STATUS_LVL_SH)
+#define __HOSTFN1_INT_STATUS_P_MK        0x000f0000
+#define __HOSTFN1_INT_STATUS_P_SH        16
+#define __HOSTFN1_INT_STATUS_P(_v)       ((_v) << __HOSTFN1_INT_STATUS_P_SH)
+#define __HOSTFN1_INT_STATUS_F           0x0000ffff
+#define HOSTFN1_INT_MSK                  0x00014104
+#define HOST_PAGE_NUM_FN1                0x00014108
+#define HOST_MSIX_ERR_INDEX_FN1          0x0001410c
+#define APP_PLL_425_CTL_REG              0x00014204
+#define __P_425_PLL_LOCK                 0x80000000
+#define __APP_PLL_425_SRAM_USE_100MHZ    0x00100000
+#define __APP_PLL_425_RESET_TIMER_MK     0x000e0000
+#define __APP_PLL_425_RESET_TIMER_SH     17
+#define __APP_PLL_425_RESET_TIMER(_v)    ((_v) << __APP_PLL_425_RESET_TIMER_SH)
+#define __APP_PLL_425_LOGIC_SOFT_RESET   0x00010000
+#define __APP_PLL_425_CNTLMT0_1_MK       0x0000c000
+#define __APP_PLL_425_CNTLMT0_1_SH       14
+#define __APP_PLL_425_CNTLMT0_1(_v)      ((_v) << __APP_PLL_425_CNTLMT0_1_SH)
+#define __APP_PLL_425_JITLMT0_1_MK       0x00003000
+#define __APP_PLL_425_JITLMT0_1_SH       12
+#define __APP_PLL_425_JITLMT0_1(_v)      ((_v) << __APP_PLL_425_JITLMT0_1_SH)
+#define __APP_PLL_425_HREF               0x00000800
+#define __APP_PLL_425_HDIV               0x00000400
+#define __APP_PLL_425_P0_1_MK            0x00000300
+#define __APP_PLL_425_P0_1_SH            8
+#define __APP_PLL_425_P0_1(_v)           ((_v) << __APP_PLL_425_P0_1_SH)
+#define __APP_PLL_425_Z0_2_MK            0x000000e0
+#define __APP_PLL_425_Z0_2_SH            5
+#define __APP_PLL_425_Z0_2(_v)           ((_v) << __APP_PLL_425_Z0_2_SH)
+#define __APP_PLL_425_RSEL200500         0x00000010
+#define __APP_PLL_425_ENARST             0x00000008
+#define __APP_PLL_425_BYPASS             0x00000004
+#define __APP_PLL_425_LRESETN            0x00000002
+#define __APP_PLL_425_ENABLE             0x00000001
+#define APP_PLL_312_CTL_REG              0x00014208
+#define __P_312_PLL_LOCK                 0x80000000
+#define __ENABLE_MAC_AHB_1               0x00800000
+#define __ENABLE_MAC_AHB_0               0x00400000
+#define __ENABLE_MAC_1                   0x00200000
+#define __ENABLE_MAC_0                   0x00100000
+#define __APP_PLL_312_RESET_TIMER_MK     0x000e0000
+#define __APP_PLL_312_RESET_TIMER_SH     17
+#define __APP_PLL_312_RESET_TIMER(_v)    ((_v) << __APP_PLL_312_RESET_TIMER_SH)
+#define __APP_PLL_312_LOGIC_SOFT_RESET   0x00010000
+#define __APP_PLL_312_CNTLMT0_1_MK       0x0000c000
+#define __APP_PLL_312_CNTLMT0_1_SH       14
+#define __APP_PLL_312_CNTLMT0_1(_v)      ((_v) << __APP_PLL_312_CNTLMT0_1_SH)
+#define __APP_PLL_312_JITLMT0_1_MK       0x00003000
+#define __APP_PLL_312_JITLMT0_1_SH       12
+#define __APP_PLL_312_JITLMT0_1(_v)      ((_v) << __APP_PLL_312_JITLMT0_1_SH)
+#define __APP_PLL_312_HREF               0x00000800
+#define __APP_PLL_312_HDIV               0x00000400
+#define __APP_PLL_312_P0_1_MK            0x00000300
+#define __APP_PLL_312_P0_1_SH            8
+#define __APP_PLL_312_P0_1(_v)           ((_v) << __APP_PLL_312_P0_1_SH)
+#define __APP_PLL_312_Z0_2_MK            0x000000e0
+#define __APP_PLL_312_Z0_2_SH            5
+#define __APP_PLL_312_Z0_2(_v)           ((_v) << __APP_PLL_312_Z0_2_SH)
+#define __APP_PLL_312_RSEL200500         0x00000010
+#define __APP_PLL_312_ENARST             0x00000008
+#define __APP_PLL_312_BYPASS             0x00000004
+#define __APP_PLL_312_LRESETN            0x00000002
+#define __APP_PLL_312_ENABLE             0x00000001
+#define MBIST_CTL_REG                    0x00014220
+#define __EDRAM_BISTR_START              0x00000004
+#define __MBIST_RESET                    0x00000002
+#define __MBIST_START                    0x00000001
+#define MBIST_STAT_REG                   0x00014224
+#define __EDRAM_BISTR_STATUS             0x00000008
+#define __EDRAM_BISTR_DONE               0x00000004
+#define __MEM_BIT_STATUS                 0x00000002
+#define __MBIST_DONE                     0x00000001
+#define HOST_SEM0_REG                    0x00014230
+#define __HOST_SEMAPHORE                 0x00000001
+#define HOST_SEM1_REG                    0x00014234
+#define HOST_SEM2_REG                    0x00014238
+#define HOST_SEM3_REG                    0x0001423c
+#define HOST_SEM0_INFO_REG               0x00014240
+#define HOST_SEM1_INFO_REG               0x00014244
+#define HOST_SEM2_INFO_REG               0x00014248
+#define HOST_SEM3_INFO_REG               0x0001424c
+#define ETH_MAC_SER_REG                  0x00014288
+#define __APP_EMS_CKBUFAMPIN             0x00000020
+#define __APP_EMS_REFCLKSEL              0x00000010
+#define __APP_EMS_CMLCKSEL               0x00000008
+#define __APP_EMS_REFCKBUFEN2            0x00000004
+#define __APP_EMS_REFCKBUFEN1            0x00000002
+#define __APP_EMS_CHANNEL_SEL            0x00000001
+#define HOSTFN2_INT_STATUS               0x00014300
+#define __HOSTFN2_HALT_OCCURRED          0x01000000
+#define __HOSTFN2_INT_STATUS_LVL_MK      0x00f00000
+#define __HOSTFN2_INT_STATUS_LVL_SH      20
+#define __HOSTFN2_INT_STATUS_LVL(_v)     ((_v) << __HOSTFN2_INT_STATUS_LVL_SH)
+#define __HOSTFN2_INT_STATUS_P_MK        0x000f0000
+#define __HOSTFN2_INT_STATUS_P_SH        16
+#define __HOSTFN2_INT_STATUS_P(_v)       ((_v) << __HOSTFN2_INT_STATUS_P_SH)
+#define __HOSTFN2_INT_STATUS_F           0x0000ffff
+#define HOSTFN2_INT_MSK                  0x00014304
+#define HOST_PAGE_NUM_FN2                0x00014308
+#define HOST_MSIX_ERR_INDEX_FN2          0x0001430c
+#define HOSTFN3_INT_STATUS               0x00014400
+#define __HALT_OCCURRED                  0x01000000
+#define __HOSTFN3_INT_STATUS_LVL_MK      0x00f00000
+#define __HOSTFN3_INT_STATUS_LVL_SH      20
+#define __HOSTFN3_INT_STATUS_LVL(_v)     ((_v) << __HOSTFN3_INT_STATUS_LVL_SH)
+#define __HOSTFN3_INT_STATUS_P_MK        0x000f0000
+#define __HOSTFN3_INT_STATUS_P_SH        16
+#define __HOSTFN3_INT_STATUS_P(_v)       ((_v) << __HOSTFN3_INT_STATUS_P_SH)
+#define __HOSTFN3_INT_STATUS_F           0x0000ffff
+#define HOSTFN3_INT_MSK                  0x00014404
+#define HOST_PAGE_NUM_FN3                0x00014408
+#define HOST_MSIX_ERR_INDEX_FN3          0x0001440c
+#define FNC_ID_REG                       0x00014600
+#define __FUNCTION_NUMBER                0x00000007
+#define FNC_PERS_REG                     0x00014604
+#define __F3_FUNCTION_ACTIVE             0x80000000
+#define __F3_FUNCTION_MODE               0x40000000
+#define __F3_PORT_MAP_MK                 0x30000000
+#define __F3_PORT_MAP_SH                 28
+#define __F3_PORT_MAP(_v)                ((_v) << __F3_PORT_MAP_SH)
+#define __F3_VM_MODE                     0x08000000
+#define __F3_INTX_STATUS_MK              0x07000000
+#define __F3_INTX_STATUS_SH              24
+#define __F3_INTX_STATUS(_v)             ((_v) << __F3_INTX_STATUS_SH)
+#define __F2_FUNCTION_ACTIVE             0x00800000
+#define __F2_FUNCTION_MODE               0x00400000
+#define __F2_PORT_MAP_MK                 0x00300000
+#define __F2_PORT_MAP_SH                 20
+#define __F2_PORT_MAP(_v)                ((_v) << __F2_PORT_MAP_SH)
+#define __F2_VM_MODE                     0x00080000
+#define __F2_INTX_STATUS_MK              0x00070000
+#define __F2_INTX_STATUS_SH              16
+#define __F2_INTX_STATUS(_v)             ((_v) << __F2_INTX_STATUS_SH)
+#define __F1_FUNCTION_ACTIVE             0x00008000
+#define __F1_FUNCTION_MODE               0x00004000
+#define __F1_PORT_MAP_MK                 0x00003000
+#define __F1_PORT_MAP_SH                 12
+#define __F1_PORT_MAP(_v)                ((_v) << __F1_PORT_MAP_SH)
+#define __F1_VM_MODE                     0x00000800
+#define __F1_INTX_STATUS_MK              0x00000700
+#define __F1_INTX_STATUS_SH              8
+#define __F1_INTX_STATUS(_v)             ((_v) << __F1_INTX_STATUS_SH)
+#define __F0_FUNCTION_ACTIVE             0x00000080
+#define __F0_FUNCTION_MODE               0x00000040
+#define __F0_PORT_MAP_MK                 0x00000030
+#define __F0_PORT_MAP_SH                 4
+#define __F0_PORT_MAP(_v)                ((_v) << __F0_PORT_MAP_SH)
+#define __F0_VM_MODE                     0x00000008
+#define __F0_INTX_STATUS                 0x00000007
+enum {
+    __F0_INTX_STATUS_MSIX            = 0x0,
+    __F0_INTX_STATUS_INTA            = 0x1,
+    __F0_INTX_STATUS_INTB            = 0x2,
+    __F0_INTX_STATUS_INTC            = 0x3,
+    __F0_INTX_STATUS_INTD            = 0x4,
+};
+#define OP_MODE                          0x0001460c
+#define __APP_ETH_CLK_LOWSPEED           0x00000004
+#define __GLOBAL_CORECLK_HALFSPEED       0x00000002
+#define __GLOBAL_FCOE_MODE               0x00000001
+#define HOST_SEM4_REG                    0x00014610
+#define HOST_SEM5_REG                    0x00014614
+#define HOST_SEM6_REG                    0x00014618
+#define HOST_SEM7_REG                    0x0001461c
+#define HOST_SEM4_INFO_REG               0x00014620
+#define HOST_SEM5_INFO_REG               0x00014624
+#define HOST_SEM6_INFO_REG               0x00014628
+#define HOST_SEM7_INFO_REG               0x0001462c
+#define HOSTFN0_LPU0_MBOX0_CMD_STAT      0x00019000
+#define __HOSTFN0_LPU0_MBOX0_INFO_MK     0xfffffffe
+#define __HOSTFN0_LPU0_MBOX0_INFO_SH     1
+#define __HOSTFN0_LPU0_MBOX0_INFO(_v)    ((_v) << __HOSTFN0_LPU0_MBOX0_INFO_SH)
+#define __HOSTFN0_LPU0_MBOX0_CMD_STATUS  0x00000001
+#define HOSTFN0_LPU1_MBOX0_CMD_STAT      0x00019004
+#define __HOSTFN0_LPU1_MBOX0_INFO_MK     0xfffffffe
+#define __HOSTFN0_LPU1_MBOX0_INFO_SH     1
+#define __HOSTFN0_LPU1_MBOX0_INFO(_v)    ((_v) << __HOSTFN0_LPU1_MBOX0_INFO_SH)
+#define __HOSTFN0_LPU1_MBOX0_CMD_STATUS  0x00000001
+#define LPU0_HOSTFN0_MBOX0_CMD_STAT      0x00019008
+#define __LPU0_HOSTFN0_MBOX0_INFO_MK     0xfffffffe
+#define __LPU0_HOSTFN0_MBOX0_INFO_SH     1
+#define __LPU0_HOSTFN0_MBOX0_INFO(_v)    ((_v) << __LPU0_HOSTFN0_MBOX0_INFO_SH)
+#define __LPU0_HOSTFN0_MBOX0_CMD_STATUS  0x00000001
+#define LPU1_HOSTFN0_MBOX0_CMD_STAT      0x0001900c
+#define __LPU1_HOSTFN0_MBOX0_INFO_MK     0xfffffffe
+#define __LPU1_HOSTFN0_MBOX0_INFO_SH     1
+#define __LPU1_HOSTFN0_MBOX0_INFO(_v)    ((_v) << __LPU1_HOSTFN0_MBOX0_INFO_SH)
+#define __LPU1_HOSTFN0_MBOX0_CMD_STATUS  0x00000001
+#define HOSTFN1_LPU0_MBOX0_CMD_STAT      0x00019010
+#define __HOSTFN1_LPU0_MBOX0_INFO_MK     0xfffffffe
+#define __HOSTFN1_LPU0_MBOX0_INFO_SH     1
+#define __HOSTFN1_LPU0_MBOX0_INFO(_v)    ((_v) << __HOSTFN1_LPU0_MBOX0_INFO_SH)
+#define __HOSTFN1_LPU0_MBOX0_CMD_STATUS  0x00000001
+#define HOSTFN1_LPU1_MBOX0_CMD_STAT      0x00019014
+#define __HOSTFN1_LPU1_MBOX0_INFO_MK     0xfffffffe
+#define __HOSTFN1_LPU1_MBOX0_INFO_SH     1
+#define __HOSTFN1_LPU1_MBOX0_INFO(_v)    ((_v) << __HOSTFN1_LPU1_MBOX0_INFO_SH)
+#define __HOSTFN1_LPU1_MBOX0_CMD_STATUS  0x00000001
+#define LPU0_HOSTFN1_MBOX0_CMD_STAT      0x00019018
+#define __LPU0_HOSTFN1_MBOX0_INFO_MK     0xfffffffe
+#define __LPU0_HOSTFN1_MBOX0_INFO_SH     1
+#define __LPU0_HOSTFN1_MBOX0_INFO(_v)    ((_v) << __LPU0_HOSTFN1_MBOX0_INFO_SH)
+#define __LPU0_HOSTFN1_MBOX0_CMD_STATUS  0x00000001
+#define LPU1_HOSTFN1_MBOX0_CMD_STAT      0x0001901c
+#define __LPU1_HOSTFN1_MBOX0_INFO_MK     0xfffffffe
+#define __LPU1_HOSTFN1_MBOX0_INFO_SH     1
+#define __LPU1_HOSTFN1_MBOX0_INFO(_v)    ((_v) << __LPU1_HOSTFN1_MBOX0_INFO_SH)
+#define __LPU1_HOSTFN1_MBOX0_CMD_STATUS  0x00000001
+#define HOSTFN2_LPU0_MBOX0_CMD_STAT      0x00019150
+#define __HOSTFN2_LPU0_MBOX0_INFO_MK     0xfffffffe
+#define __HOSTFN2_LPU0_MBOX0_INFO_SH     1
+#define __HOSTFN2_LPU0_MBOX0_INFO(_v)    ((_v) << __HOSTFN2_LPU0_MBOX0_INFO_SH)
+#define __HOSTFN2_LPU0_MBOX0_CMD_STATUS  0x00000001
+#define HOSTFN2_LPU1_MBOX0_CMD_STAT      0x00019154
+#define __HOSTFN2_LPU1_MBOX0_INFO_MK     0xfffffffe
+#define __HOSTFN2_LPU1_MBOX0_INFO_SH     1
+#define __HOSTFN2_LPU1_MBOX0_INFO(_v)    ((_v) << __HOSTFN2_LPU1_MBOX0_INFO_SH)
+#define __HOSTFN2_LPU1_MBOX0BOX0_CMD_STATUS 0x00000001
+#define LPU0_HOSTFN2_MBOX0_CMD_STAT      0x00019158
+#define __LPU0_HOSTFN2_MBOX0_INFO_MK     0xfffffffe
+#define __LPU0_HOSTFN2_MBOX0_INFO_SH     1
+#define __LPU0_HOSTFN2_MBOX0_INFO(_v)    ((_v) << __LPU0_HOSTFN2_MBOX0_INFO_SH)
+#define __LPU0_HOSTFN2_MBOX0_CMD_STATUS  0x00000001
+#define LPU1_HOSTFN2_MBOX0_CMD_STAT      0x0001915c
+#define __LPU1_HOSTFN2_MBOX0_INFO_MK     0xfffffffe
+#define __LPU1_HOSTFN2_MBOX0_INFO_SH     1
+#define __LPU1_HOSTFN2_MBOX0_INFO(_v)    ((_v) << __LPU1_HOSTFN2_MBOX0_INFO_SH)
+#define __LPU1_HOSTFN2_MBOX0_CMD_STATUS  0x00000001
+#define HOSTFN3_LPU0_MBOX0_CMD_STAT      0x00019160
+#define __HOSTFN3_LPU0_MBOX0_INFO_MK     0xfffffffe
+#define __HOSTFN3_LPU0_MBOX0_INFO_SH     1
+#define __HOSTFN3_LPU0_MBOX0_INFO(_v)    ((_v) << __HOSTFN3_LPU0_MBOX0_INFO_SH)
+#define __HOSTFN3_LPU0_MBOX0_CMD_STATUS  0x00000001
+#define HOSTFN3_LPU1_MBOX0_CMD_STAT      0x00019164
+#define __HOSTFN3_LPU1_MBOX0_INFO_MK     0xfffffffe
+#define __HOSTFN3_LPU1_MBOX0_INFO_SH     1
+#define __HOSTFN3_LPU1_MBOX0_INFO(_v)    ((_v) << __HOSTFN3_LPU1_MBOX0_INFO_SH)
+#define __HOSTFN3_LPU1_MBOX0_CMD_STATUS  0x00000001
+#define LPU0_HOSTFN3_MBOX0_CMD_STAT      0x00019168
+#define __LPU0_HOSTFN3_MBOX0_INFO_MK     0xfffffffe
+#define __LPU0_HOSTFN3_MBOX0_INFO_SH     1
+#define __LPU0_HOSTFN3_MBOX0_INFO(_v)    ((_v) << __LPU0_HOSTFN3_MBOX0_INFO_SH)
+#define __LPU0_HOSTFN3_MBOX0_CMD_STATUS  0x00000001
+#define LPU1_HOSTFN3_MBOX0_CMD_STAT      0x0001916c
+#define __LPU1_HOSTFN3_MBOX0_INFO_MK     0xfffffffe
+#define __LPU1_HOSTFN3_MBOX0_INFO_SH     1
+#define __LPU1_HOSTFN3_MBOX0_INFO(_v)    ((_v) << __LPU1_HOSTFN3_MBOX0_INFO_SH)
+#define __LPU1_HOSTFN3_MBOX0_CMD_STATUS  0x00000001
+#define FW_INIT_HALT_P0                  0x000191ac
+#define __FW_INIT_HALT_P                 0x00000001
+#define FW_INIT_HALT_P1                  0x000191bc
+#define CPE_PI_PTR_Q0                    0x00038000
+#define __CPE_PI_UNUSED_MK               0xffff0000
+#define __CPE_PI_UNUSED_SH               16
+#define __CPE_PI_UNUSED(_v)              ((_v) << __CPE_PI_UNUSED_SH)
+#define __CPE_PI_PTR                     0x0000ffff
+#define CPE_PI_PTR_Q1                    0x00038040
+#define CPE_CI_PTR_Q0                    0x00038004
+#define __CPE_CI_UNUSED_MK               0xffff0000
+#define __CPE_CI_UNUSED_SH               16
+#define __CPE_CI_UNUSED(_v)              ((_v) << __CPE_CI_UNUSED_SH)
+#define __CPE_CI_PTR                     0x0000ffff
+#define CPE_CI_PTR_Q1                    0x00038044
+#define CPE_DEPTH_Q0                     0x00038008
+#define __CPE_DEPTH_UNUSED_MK            0xf8000000
+#define __CPE_DEPTH_UNUSED_SH            27
+#define __CPE_DEPTH_UNUSED(_v)           ((_v) << __CPE_DEPTH_UNUSED_SH)
+#define __CPE_MSIX_VEC_INDEX_MK          0x07ff0000
+#define __CPE_MSIX_VEC_INDEX_SH          16
+#define __CPE_MSIX_VEC_INDEX(_v)         ((_v) << __CPE_MSIX_VEC_INDEX_SH)
+#define __CPE_DEPTH                      0x0000ffff
+#define CPE_DEPTH_Q1                     0x00038048
+#define CPE_QCTRL_Q0                     0x0003800c
+#define __CPE_CTRL_UNUSED30_MK           0xfc000000
+#define __CPE_CTRL_UNUSED30_SH           26
+#define __CPE_CTRL_UNUSED30(_v)          ((_v) << __CPE_CTRL_UNUSED30_SH)
+#define __CPE_FUNC_INT_CTRL_MK           0x03000000
+#define __CPE_FUNC_INT_CTRL_SH           24
+#define __CPE_FUNC_INT_CTRL(_v)          ((_v) << __CPE_FUNC_INT_CTRL_SH)
+enum {
+    __CPE_FUNC_INT_CTRL_DISABLE      = 0x0,
+    __CPE_FUNC_INT_CTRL_F2NF         = 0x1,
+    __CPE_FUNC_INT_CTRL_3QUART       = 0x2,
+    __CPE_FUNC_INT_CTRL_HALF         = 0x3,
+};
+#define __CPE_CTRL_UNUSED20_MK           0x00f00000
+#define __CPE_CTRL_UNUSED20_SH           20
+#define __CPE_CTRL_UNUSED20(_v)          ((_v) << __CPE_CTRL_UNUSED20_SH)
+#define __CPE_SCI_TH_MK                  0x000f0000
+#define __CPE_SCI_TH_SH                  16
+#define __CPE_SCI_TH(_v)                 ((_v) << __CPE_SCI_TH_SH)
+#define __CPE_CTRL_UNUSED10_MK           0x0000c000
+#define __CPE_CTRL_UNUSED10_SH           14
+#define __CPE_CTRL_UNUSED10(_v)          ((_v) << __CPE_CTRL_UNUSED10_SH)
+#define __CPE_ACK_PENDING                0x00002000
+#define __CPE_CTRL_UNUSED40_MK           0x00001c00
+#define __CPE_CTRL_UNUSED40_SH           10
+#define __CPE_CTRL_UNUSED40(_v)          ((_v) << __CPE_CTRL_UNUSED40_SH)
+#define __CPE_PCIEID_MK                  0x00000300
+#define __CPE_PCIEID_SH                  8
+#define __CPE_PCIEID(_v)                 ((_v) << __CPE_PCIEID_SH)
+#define __CPE_CTRL_UNUSED00_MK           0x000000fe
+#define __CPE_CTRL_UNUSED00_SH           1
+#define __CPE_CTRL_UNUSED00(_v)          ((_v) << __CPE_CTRL_UNUSED00_SH)
+#define __CPE_ESIZE                      0x00000001
+#define CPE_QCTRL_Q1                     0x0003804c
+#define __CPE_CTRL_UNUSED31_MK           0xfc000000
+#define __CPE_CTRL_UNUSED31_SH           26
+#define __CPE_CTRL_UNUSED31(_v)          ((_v) << __CPE_CTRL_UNUSED31_SH)
+#define __CPE_CTRL_UNUSED21_MK           0x00f00000
+#define __CPE_CTRL_UNUSED21_SH           20
+#define __CPE_CTRL_UNUSED21(_v)          ((_v) << __CPE_CTRL_UNUSED21_SH)
+#define __CPE_CTRL_UNUSED11_MK           0x0000c000
+#define __CPE_CTRL_UNUSED11_SH           14
+#define __CPE_CTRL_UNUSED11(_v)          ((_v) << __CPE_CTRL_UNUSED11_SH)
+#define __CPE_CTRL_UNUSED41_MK           0x00001c00
+#define __CPE_CTRL_UNUSED41_SH           10
+#define __CPE_CTRL_UNUSED41(_v)          ((_v) << __CPE_CTRL_UNUSED41_SH)
+#define __CPE_CTRL_UNUSED01_MK           0x000000fe
+#define __CPE_CTRL_UNUSED01_SH           1
+#define __CPE_CTRL_UNUSED01(_v)          ((_v) << __CPE_CTRL_UNUSED01_SH)
+#define RME_PI_PTR_Q0                    0x00038020
+#define __LATENCY_TIME_STAMP_MK          0xffff0000
+#define __LATENCY_TIME_STAMP_SH          16
+#define __LATENCY_TIME_STAMP(_v)         ((_v) << __LATENCY_TIME_STAMP_SH)
+#define __RME_PI_PTR                     0x0000ffff
+#define RME_PI_PTR_Q1                    0x00038060
+#define RME_CI_PTR_Q0                    0x00038024
+#define __DELAY_TIME_STAMP_MK            0xffff0000
+#define __DELAY_TIME_STAMP_SH            16
+#define __DELAY_TIME_STAMP(_v)           ((_v) << __DELAY_TIME_STAMP_SH)
+#define __RME_CI_PTR                     0x0000ffff
+#define RME_CI_PTR_Q1                    0x00038064
+#define RME_DEPTH_Q0                     0x00038028
+#define __RME_DEPTH_UNUSED_MK            0xf8000000
+#define __RME_DEPTH_UNUSED_SH            27
+#define __RME_DEPTH_UNUSED(_v)           ((_v) << __RME_DEPTH_UNUSED_SH)
+#define __RME_MSIX_VEC_INDEX_MK          0x07ff0000
+#define __RME_MSIX_VEC_INDEX_SH          16
+#define __RME_MSIX_VEC_INDEX(_v)         ((_v) << __RME_MSIX_VEC_INDEX_SH)
+#define __RME_DEPTH                      0x0000ffff
+#define RME_DEPTH_Q1                     0x00038068
+#define RME_QCTRL_Q0                     0x0003802c
+#define __RME_INT_LATENCY_TIMER_MK       0xff000000
+#define __RME_INT_LATENCY_TIMER_SH       24
+#define __RME_INT_LATENCY_TIMER(_v)      ((_v) << __RME_INT_LATENCY_TIMER_SH)
+#define __RME_INT_DELAY_TIMER_MK         0x00ff0000
+#define __RME_INT_DELAY_TIMER_SH         16
+#define __RME_INT_DELAY_TIMER(_v)        ((_v) << __RME_INT_DELAY_TIMER_SH)
+#define __RME_INT_DELAY_DISABLE          0x00008000
+#define __RME_DLY_DELAY_DISABLE          0x00004000
+#define __RME_ACK_PENDING                0x00002000
+#define __RME_FULL_INTERRUPT_DISABLE     0x00001000
+#define __RME_CTRL_UNUSED10_MK           0x00000c00
+#define __RME_CTRL_UNUSED10_SH           10
+#define __RME_CTRL_UNUSED10(_v)          ((_v) << __RME_CTRL_UNUSED10_SH)
+#define __RME_PCIEID_MK                  0x00000300
+#define __RME_PCIEID_SH                  8
+#define __RME_PCIEID(_v)                 ((_v) << __RME_PCIEID_SH)
+#define __RME_CTRL_UNUSED00_MK           0x000000fe
+#define __RME_CTRL_UNUSED00_SH           1
+#define __RME_CTRL_UNUSED00(_v)          ((_v) << __RME_CTRL_UNUSED00_SH)
+#define __RME_ESIZE                      0x00000001
+#define RME_QCTRL_Q1                     0x0003806c
+#define __RME_CTRL_UNUSED11_MK           0x00000c00
+#define __RME_CTRL_UNUSED11_SH           10
+#define __RME_CTRL_UNUSED11(_v)          ((_v) << __RME_CTRL_UNUSED11_SH)
+#define __RME_CTRL_UNUSED01_MK           0x000000fe
+#define __RME_CTRL_UNUSED01_SH           1
+#define __RME_CTRL_UNUSED01(_v)          ((_v) << __RME_CTRL_UNUSED01_SH)
+#define PSS_CTL_REG                      0x00018800
+#define __PSS_I2C_CLK_DIV_MK             0x007f0000
+#define __PSS_I2C_CLK_DIV_SH             16
+#define __PSS_I2C_CLK_DIV(_v)            ((_v) << __PSS_I2C_CLK_DIV_SH)
+#define __PSS_LMEM_INIT_DONE             0x00001000
+#define __PSS_LMEM_RESET                 0x00000200
+#define __PSS_LMEM_INIT_EN               0x00000100
+#define __PSS_LPU1_RESET                 0x00000002
+#define __PSS_LPU0_RESET                 0x00000001
+#define HQM_QSET0_RXQ_DRBL_P0            0x00038000
+#define __RXQ0_ADD_VECTORS_P             0x80000000
+#define __RXQ0_STOP_P                    0x40000000
+#define __RXQ0_PRD_PTR_P                 0x0000ffff
+#define HQM_QSET1_RXQ_DRBL_P0            0x00038080
+#define __RXQ1_ADD_VECTORS_P             0x80000000
+#define __RXQ1_STOP_P                    0x40000000
+#define __RXQ1_PRD_PTR_P                 0x0000ffff
+#define HQM_QSET0_RXQ_DRBL_P1            0x0003c000
+#define HQM_QSET1_RXQ_DRBL_P1            0x0003c080
+#define HQM_QSET0_TXQ_DRBL_P0            0x00038020
+#define __TXQ0_ADD_VECTORS_P             0x80000000
+#define __TXQ0_STOP_P                    0x40000000
+#define __TXQ0_PRD_PTR_P                 0x0000ffff
+#define HQM_QSET1_TXQ_DRBL_P0            0x000380a0
+#define __TXQ1_ADD_VECTORS_P             0x80000000
+#define __TXQ1_STOP_P                    0x40000000
+#define __TXQ1_PRD_PTR_P                 0x0000ffff
+#define HQM_QSET0_TXQ_DRBL_P1            0x0003c020
+#define HQM_QSET1_TXQ_DRBL_P1            0x0003c0a0
+#define HQM_QSET0_IB_DRBL_1_P0           0x00038040
+#define __IB1_0_ACK_P                    0x80000000
+#define __IB1_0_DISABLE_P                0x40000000
+#define __IB1_0_NUM_OF_ACKED_EVENTS_P    0x0000ffff
+#define HQM_QSET1_IB_DRBL_1_P0           0x000380c0
+#define __IB1_1_ACK_P                    0x80000000
+#define __IB1_1_DISABLE_P                0x40000000
+#define __IB1_1_NUM_OF_ACKED_EVENTS_P    0x0000ffff
+#define HQM_QSET0_IB_DRBL_1_P1           0x0003c040
+#define HQM_QSET1_IB_DRBL_1_P1           0x0003c0c0
+#define HQM_QSET0_IB_DRBL_2_P0           0x00038060
+#define __IB2_0_ACK_P                    0x80000000
+#define __IB2_0_DISABLE_P                0x40000000
+#define __IB2_0_NUM_OF_ACKED_EVENTS_P    0x0000ffff
+#define HQM_QSET1_IB_DRBL_2_P0           0x000380e0
+#define __IB2_1_ACK_P                    0x80000000
+#define __IB2_1_DISABLE_P                0x40000000
+#define __IB2_1_NUM_OF_ACKED_EVENTS_P    0x0000ffff
+#define HQM_QSET0_IB_DRBL_2_P1           0x0003c060
+#define HQM_QSET1_IB_DRBL_2_P1           0x0003c0e0
+
+
+/*
+ * These definitions are either in error/missing in spec. Its auto-generated
+ * from hard coded values in regparse.pl.
+ */
+#define __EMPHPOST_AT_4G_MK_FIX          0x0000001c
+#define __EMPHPOST_AT_4G_SH_FIX          0x00000002
+#define __EMPHPRE_AT_4G_FIX              0x00000003
+#define __SFP_TXRATE_EN_FIX              0x00000100
+#define __SFP_RXRATE_EN_FIX              0x00000080
+
+
+/*
+ * These register definitions are auto-generated from hard coded values
+ * in regparse.pl.
+ */
+
+
+/*
+ * These register mapping definitions are auto-generated from mapping tables
+ * in regparse.pl.
+ */
+#define BFA_IOC0_HBEAT_REG               HOST_SEM0_INFO_REG
+#define BFA_IOC0_STATE_REG               HOST_SEM1_INFO_REG
+#define BFA_IOC1_HBEAT_REG               HOST_SEM2_INFO_REG
+#define BFA_IOC1_STATE_REG               HOST_SEM3_INFO_REG
+#define BFA_FW_USE_COUNT                 HOST_SEM4_INFO_REG
+
+#define CPE_DEPTH_Q(__n) \
+       (CPE_DEPTH_Q0 + (__n) * (CPE_DEPTH_Q1 - CPE_DEPTH_Q0))
+#define CPE_QCTRL_Q(__n) \
+       (CPE_QCTRL_Q0 + (__n) * (CPE_QCTRL_Q1 - CPE_QCTRL_Q0))
+#define CPE_PI_PTR_Q(__n) \
+       (CPE_PI_PTR_Q0 + (__n) * (CPE_PI_PTR_Q1 - CPE_PI_PTR_Q0))
+#define CPE_CI_PTR_Q(__n) \
+       (CPE_CI_PTR_Q0 + (__n) * (CPE_CI_PTR_Q1 - CPE_CI_PTR_Q0))
+#define RME_DEPTH_Q(__n) \
+       (RME_DEPTH_Q0 + (__n) * (RME_DEPTH_Q1 - RME_DEPTH_Q0))
+#define RME_QCTRL_Q(__n) \
+       (RME_QCTRL_Q0 + (__n) * (RME_QCTRL_Q1 - RME_QCTRL_Q0))
+#define RME_PI_PTR_Q(__n) \
+       (RME_PI_PTR_Q0 + (__n) * (RME_PI_PTR_Q1 - RME_PI_PTR_Q0))
+#define RME_CI_PTR_Q(__n) \
+       (RME_CI_PTR_Q0 + (__n) * (RME_CI_PTR_Q1 - RME_CI_PTR_Q0))
+#define HQM_QSET_RXQ_DRBL_P0(__n) \
+       (HQM_QSET0_RXQ_DRBL_P0 + (__n) * (HQM_QSET1_RXQ_DRBL_P0 - \
+       HQM_QSET0_RXQ_DRBL_P0))
+#define HQM_QSET_TXQ_DRBL_P0(__n) \
+       (HQM_QSET0_TXQ_DRBL_P0 + (__n) * (HQM_QSET1_TXQ_DRBL_P0 - \
+       HQM_QSET0_TXQ_DRBL_P0))
+#define HQM_QSET_IB_DRBL_1_P0(__n) \
+       (HQM_QSET0_IB_DRBL_1_P0 + (__n) * (HQM_QSET1_IB_DRBL_1_P0 - \
+       HQM_QSET0_IB_DRBL_1_P0))
+#define HQM_QSET_IB_DRBL_2_P0(__n) \
+       (HQM_QSET0_IB_DRBL_2_P0 + (__n) * (HQM_QSET1_IB_DRBL_2_P0 - \
+       HQM_QSET0_IB_DRBL_2_P0))
+#define HQM_QSET_RXQ_DRBL_P1(__n) \
+       (HQM_QSET0_RXQ_DRBL_P1 + (__n) * (HQM_QSET1_RXQ_DRBL_P1 - \
+       HQM_QSET0_RXQ_DRBL_P1))
+#define HQM_QSET_TXQ_DRBL_P1(__n) \
+       (HQM_QSET0_TXQ_DRBL_P1 + (__n) * (HQM_QSET1_TXQ_DRBL_P1 - \
+       HQM_QSET0_TXQ_DRBL_P1))
+#define HQM_QSET_IB_DRBL_1_P1(__n) \
+       (HQM_QSET0_IB_DRBL_1_P1 + (__n) * (HQM_QSET1_IB_DRBL_1_P1 - \
+       HQM_QSET0_IB_DRBL_1_P1))
+#define HQM_QSET_IB_DRBL_2_P1(__n) \
+       (HQM_QSET0_IB_DRBL_2_P1 + (__n) * (HQM_QSET1_IB_DRBL_2_P1 - \
+       HQM_QSET0_IB_DRBL_2_P1))
+
+#define CPE_Q_NUM(__fn, __q)  (((__fn) << 2) + (__q))
+#define RME_Q_NUM(__fn, __q)  (((__fn) << 2) + (__q))
+#define CPE_Q_MASK(__q)  ((__q) & 0x3)
+#define RME_Q_MASK(__q)  ((__q) & 0x3)
+
+
+/*
+ * PCI MSI-X vector defines
+ */
+enum {
+    BFA_MSIX_CPE_Q0 = 0,
+    BFA_MSIX_CPE_Q1 = 1,
+    BFA_MSIX_CPE_Q2 = 2,
+    BFA_MSIX_CPE_Q3 = 3,
+    BFA_MSIX_RME_Q0 = 4,
+    BFA_MSIX_RME_Q1 = 5,
+    BFA_MSIX_RME_Q2 = 6,
+    BFA_MSIX_RME_Q3 = 7,
+    BFA_MSIX_LPU_ERR = 8,
+    BFA_MSIX_CT_MAX = 9,
+};
+
+/*
+ * And corresponding host interrupt status bit field defines
+ */
+#define __HFN_INT_CPE_Q0                   0x00000001U
+#define __HFN_INT_CPE_Q1                   0x00000002U
+#define __HFN_INT_CPE_Q2                   0x00000004U
+#define __HFN_INT_CPE_Q3                   0x00000008U
+#define __HFN_INT_CPE_Q4                   0x00000010U
+#define __HFN_INT_CPE_Q5                   0x00000020U
+#define __HFN_INT_CPE_Q6                   0x00000040U
+#define __HFN_INT_CPE_Q7                   0x00000080U
+#define __HFN_INT_RME_Q0                   0x00000100U
+#define __HFN_INT_RME_Q1                   0x00000200U
+#define __HFN_INT_RME_Q2                   0x00000400U
+#define __HFN_INT_RME_Q3                   0x00000800U
+#define __HFN_INT_RME_Q4                   0x00001000U
+#define __HFN_INT_RME_Q5                   0x00002000U
+#define __HFN_INT_RME_Q6                   0x00004000U
+#define __HFN_INT_RME_Q7                   0x00008000U
+#define __HFN_INT_ERR_EMC                  0x00010000U
+#define __HFN_INT_ERR_LPU0                 0x00020000U
+#define __HFN_INT_ERR_LPU1                 0x00040000U
+#define __HFN_INT_ERR_PSS                  0x00080000U
+#define __HFN_INT_MBOX_LPU0                0x00100000U
+#define __HFN_INT_MBOX_LPU1                0x00200000U
+#define __HFN_INT_MBOX1_LPU0               0x00400000U
+#define __HFN_INT_MBOX1_LPU1               0x00800000U
+#define __HFN_INT_CPE_MASK                 0x000000ffU
+#define __HFN_INT_RME_MASK                 0x0000ff00U
+
+
+/*
+ * catapult memory map.
+ */
+#define LL_PGN_HQM0                      0x0096
+#define LL_PGN_HQM1                      0x0097
+#define PSS_SMEM_PAGE_START    0x8000
+#define PSS_SMEM_PGNUM(_pg0, _ma)      ((_pg0) + ((_ma) >> 15))
+#define PSS_SMEM_PGOFF(_ma)    ((_ma) & 0x7fff)
+
+/*
+ * End of catapult memory map
+ */
+
+
+#endif /* __BFI_CTREG_H__ */
+
diff --git a/drivers/scsi/bfa/include/bfi/bfi_fabric.h b/drivers/scsi/bfa/include/bfi/bfi_fabric.h
new file mode 100644 (file)
index 0000000..c0669ed
--- /dev/null
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ */
+
+#ifndef __BFI_FABRIC_H__
+#define __BFI_FABRIC_H__
+
+#include <bfi/bfi.h>
+
+#pragma pack(1)
+
+enum bfi_fabric_h2i_msgs {
+       BFI_FABRIC_H2I_CREATE_REQ       = 1,
+       BFI_FABRIC_H2I_DELETE_REQ       = 2,
+       BFI_FABRIC_H2I_SETAUTH          = 3,
+};
+
+enum bfi_fabric_i2h_msgs {
+       BFI_FABRIC_I2H_CREATE_RSP       = BFA_I2HM(1),
+       BFI_FABRIC_I2H_DELETE_RSP       = BFA_I2HM(2),
+       BFI_FABRIC_I2H_SETAUTH_RSP      = BFA_I2HM(3),
+       BFI_FABRIC_I2H_ONLINE           = BFA_I2HM(4),
+       BFI_FABRIC_I2H_OFFLINE          = BFA_I2HM(5),
+};
+
+struct bfi_fabric_create_req_s {
+       bfi_mhdr_t      mh;             /*  common msg header           */
+       u8         vf_en;               /*  virtual fabric enable       */
+       u8         rsvd;
+       u16        vf_id;               /*  virtual fabric ID           */
+       wwn_t           pwwn;           /*  port name                   */
+       wwn_t           nwwn;           /*  node name                   */
+};
+
+struct bfi_fabric_create_rsp_s {
+       bfi_mhdr_t      mh;             /*  common msg header           */
+       u16        bfa_handle;  /*  host fabric handle          */
+       u8         status;              /*  fabric create status        */
+       u8         rsvd;
+};
+
+struct bfi_fabric_delete_req_s {
+       bfi_mhdr_t      mh;             /*  common msg header           */
+       u16        fw_handle;   /*  firmware fabric handle      */
+       u16        rsvd;
+};
+
+struct bfi_fabric_delete_rsp_s {
+       bfi_mhdr_t      mh;             /*  common msg header           */
+       u16        bfa_handle;  /*  host fabric handle          */
+       u8         status;              /*  fabric deletion status      */
+       u8         rsvd;
+};
+
+#define BFI_FABRIC_AUTHSECRET_LEN      64
+struct bfi_fabric_setauth_req_s {
+       bfi_mhdr_t      mh;             /*  common msg header           */
+       u16        fw_handle;   /*  f/w handle of fabric        */
+       u8              algorithm;
+       u8              group;
+       u8              secret[BFI_FABRIC_AUTHSECRET_LEN];
+};
+
+union bfi_fabric_h2i_msg_u {
+       bfi_msg_t               *msg;
+       struct bfi_fabric_create_req_s  *create_req;
+       struct bfi_fabric_delete_req_s  *delete_req;
+};
+
+union bfi_fabric_i2h_msg_u {
+       bfi_msg_t               *msg;
+       struct bfi_fabric_create_rsp_s  *create_rsp;
+       struct bfi_fabric_delete_rsp_s  *delete_rsp;
+};
+
+#pragma pack()
+
+#endif /* __BFI_FABRIC_H__ */
+
diff --git a/drivers/scsi/bfa/include/bfi/bfi_fcpim.h b/drivers/scsi/bfa/include/bfi/bfi_fcpim.h
new file mode 100644 (file)
index 0000000..52c059f
--- /dev/null
@@ -0,0 +1,301 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ */
+
+#ifndef __BFI_FCPIM_H__
+#define __BFI_FCPIM_H__
+
+#include "bfi.h"
+#include <protocol/fcp.h>
+
+#pragma pack(1)
+
+/*
+ * Initiator mode I-T nexus interface defines.
+ */
+
+enum bfi_itnim_h2i {
+       BFI_ITNIM_H2I_CREATE_REQ = 1,   /*  i-t nexus creation */
+       BFI_ITNIM_H2I_DELETE_REQ = 2,   /*  i-t nexus deletion */
+};
+
+enum bfi_itnim_i2h {
+       BFI_ITNIM_I2H_CREATE_RSP = BFA_I2HM(1),
+       BFI_ITNIM_I2H_DELETE_RSP = BFA_I2HM(2),
+       BFI_ITNIM_I2H_SLER_EVENT = BFA_I2HM(3),
+};
+
+struct bfi_itnim_create_req_s {
+       struct bfi_mhdr_s  mh;          /*  common msg header            */
+       u16        fw_handle;   /*  f/w handle for itnim         */
+       u8         class;               /*  FC class for IO              */
+       u8         seq_rec;     /*  sequence recovery support    */
+       u8         msg_no;              /*  seq id of the msg            */
+};
+
+struct bfi_itnim_create_rsp_s {
+       struct bfi_mhdr_s  mh;          /*  common msg header            */
+       u16        bfa_handle;  /*  bfa handle for itnim         */
+       u8         status;              /*  fcp request status           */
+       u8         seq_id;              /*  seq id of the msg            */
+};
+
+struct bfi_itnim_delete_req_s {
+       struct bfi_mhdr_s  mh;          /*  common msg header            */
+       u16        fw_handle;   /*  f/w itnim handle             */
+       u8         seq_id;              /*  seq id of the msg            */
+       u8         rsvd;
+};
+
+struct bfi_itnim_delete_rsp_s {
+       struct bfi_mhdr_s  mh;          /*  common msg header            */
+       u16        bfa_handle;  /*  bfa handle for itnim         */
+       u8         status;              /*  fcp request status           */
+       u8         seq_id;              /*  seq id of the msg            */
+};
+
+struct bfi_itnim_sler_event_s {
+       struct bfi_mhdr_s  mh;          /*  common msg header            */
+       u16        bfa_handle;  /*  bfa handle for itnim         */
+       u16        rsvd;
+};
+
+union bfi_itnim_h2i_msg_u {
+       struct bfi_itnim_create_req_s *create_req;
+       struct bfi_itnim_delete_req_s *delete_req;
+       struct bfi_msg_s      *msg;
+};
+
+union bfi_itnim_i2h_msg_u {
+       struct bfi_itnim_create_rsp_s *create_rsp;
+       struct bfi_itnim_delete_rsp_s *delete_rsp;
+       struct bfi_itnim_sler_event_s *sler_event;
+       struct bfi_msg_s      *msg;
+};
+
+/*
+ * Initiator mode IO interface defines.
+ */
+
+enum bfi_ioim_h2i {
+       BFI_IOIM_H2I_IOABORT_REQ = 1,   /*  IO abort request     */
+       BFI_IOIM_H2I_IOCLEANUP_REQ = 2, /*  IO cleanup request   */
+};
+
+enum bfi_ioim_i2h {
+       BFI_IOIM_I2H_IO_RSP = BFA_I2HM(1),      /*  non-fp IO response   */
+       BFI_IOIM_I2H_IOABORT_RSP = BFA_I2HM(2),/*  ABORT rsp     */
+};
+
+/**
+ * IO command DIF info
+ */
+struct bfi_ioim_dif_s {
+       u32     dif_info[4];
+};
+
+/**
+ * FCP IO messages overview
+ *
+ * @note
+ * - Max CDB length supported is 64 bytes.
+ * - SCSI Linked commands and SCSI bi-directional Commands not
+ *      supported.
+ *
+ */
+struct bfi_ioim_req_s {
+       struct bfi_mhdr_s  mh;          /*  Common msg header            */
+       u16        io_tag;              /*  I/O tag                      */
+       u16        rport_hdl;   /*  itnim/rport firmware handle */
+       struct fcp_cmnd_s cmnd;         /*  IO request info              */
+
+       /**
+        * SG elements array within the IO request must be double word
+        * aligned. This aligment is required to optimize SGM setup for the IO.
+        */
+       struct bfi_sge_s   sges[BFI_SGE_INLINE_MAX];
+       u8         io_timeout;
+       u8         dif_en;
+       u8         rsvd_a[2];
+       struct bfi_ioim_dif_s  dif;
+};
+
+/**
+ *     This table shows various IO status codes from firmware and their
+ *     meaning. Host driver can use these status codes to further process
+ *     IO completions.
+ *
+ *     BFI_IOIM_STS_OK         : IO completed with error free SCSI &
+ *                                        transport status.
+ *                                        - io-tag can be reused.
+ *
+ *     BFA_IOIM_STS_SCSI_ERR           : IO completed with scsi error.
+ *                                       - io-tag can be reused.
+ *
+ *     BFI_IOIM_STS_HOST_ABORTED       : IO was aborted successfully due to
+ *                                        host request.
+ *                                        - io-tag cannot be reused yet.
+ *
+ *     BFI_IOIM_STS_ABORTED            : IO was aborted successfully
+ *                                        internally by f/w.
+ *                                        - io-tag cannot be reused yet.
+ *
+ *     BFI_IOIM_STS_TIMEDOUT   : IO timedout and ABTS/RRQ is happening
+ *                                        in the firmware and
+ *                                        - io-tag cannot be reused yet.
+ *
+ *     BFI_IOIM_STS_SQER_NEEDED        : Firmware could not recover the IO
+ *                                       with sequence level error
+ *                                       logic and hence host needs to retry
+ *                                       this IO with a different IO tag
+ *                                       - io-tag cannot be used yet.
+ *
+ *     BFI_IOIM_STS_NEXUS_ABORT        : Second Level Error Recovery from host
+ *                                       is required because 2 consecutive ABTS
+ *                                       timedout and host needs logout and
+ *                                       re-login with the target
+ *                                       - io-tag cannot be used yet.
+ *
+ *     BFI_IOIM_STS_UNDERRUN   : IO completed with SCSI status good,
+ *                                       but the data tranferred is less than
+ *                                       the fcp data length in the command.
+ *                                       ex. SCSI INQUIRY where transferred
+ *                                       data length and residue count in FCP
+ *                                       response accounts for total fcp-dl
+ *                                       - io-tag can be reused.
+ *
+ *     BFI_IOIM_STS_OVERRUN    : IO completed with SCSI status good,
+ *                                       but the data transerred is more than
+ *                                       fcp data length in the command. ex.
+ *                                       TAPE IOs where blocks can of unequal
+ *                                       lengths.
+ *                                       - io-tag can be reused.
+ *
+ *     BFI_IOIM_STS_RES_FREE   : Firmware has completed using io-tag
+ *                                       during abort process
+ *                                       - io-tag can be reused.
+ *
+ *     BFI_IOIM_STS_PROTO_ERR  : Firmware detected a protocol error.
+ *                                       ex target sent more data than
+ *                                       requested, or there was data frame
+ *                                       loss and other reasons
+ *                                       - io-tag cannot be used yet.
+ *
+ *     BFI_IOIM_STS_DIF_ERR    : Firwmare detected DIF error. ex: DIF
+ *                                       CRC err or Ref Tag err or App tag err.
+ *                                       - io-tag can be reused.
+ *
+ *     BFA_IOIM_STS_TSK_MGT_ABORT      : IO was aborted because of Task
+ *                                       Management command from the host
+ *                                       - io-tag can be reused.
+ *
+ *     BFI_IOIM_STS_UTAG               : Firmware does not know about this
+ *                                       io_tag.
+ *                                       - io-tag can be reused.
+ */
+enum bfi_ioim_status {
+       BFI_IOIM_STS_OK = 0,
+       BFI_IOIM_STS_HOST_ABORTED = 1,
+       BFI_IOIM_STS_ABORTED = 2,
+       BFI_IOIM_STS_TIMEDOUT = 3,
+       BFI_IOIM_STS_RES_FREE = 4,
+       BFI_IOIM_STS_SQER_NEEDED = 5,
+       BFI_IOIM_STS_PROTO_ERR = 6,
+       BFI_IOIM_STS_UTAG = 7,
+       BFI_IOIM_STS_PATHTOV = 8,
+};
+
+#define BFI_IOIM_SNSLEN        (256)
+/**
+ * I/O response message
+ */
+struct bfi_ioim_rsp_s {
+       struct bfi_mhdr_s  mh;          /*  common msg header            */
+       u16        io_tag;              /*  completed IO tag             */
+       u16        bfa_rport_hndl;      /*  releated rport handle        */
+       u8         io_status;   /*  IO completion status         */
+       u8         reuse_io_tag;        /*  IO tag can be reused        */
+       u16     abort_tag;      /*  host abort request tag      */
+       u8              scsi_status;    /*  scsi status from target      */
+       u8              sns_len;        /*  scsi sense length            */
+       u8              resid_flags;    /*  IO residue flags             */
+       u8              rsvd_a;
+       u32     residue;        /*  IO residual length in bytes */
+       u32     rsvd_b[3];
+};
+
+struct bfi_ioim_abort_req_s {
+       struct bfi_mhdr_s  mh;          /*  Common msg header  */
+       u16        io_tag;         /*  I/O tag            */
+       u16        abort_tag;      /*  unique request tag */
+};
+
+/*
+ * Initiator mode task management command interface defines.
+ */
+
+enum bfi_tskim_h2i {
+       BFI_TSKIM_H2I_TM_REQ    = 1, /*  task-mgmt command         */
+       BFI_TSKIM_H2I_ABORT_REQ = 2, /*  task-mgmt command         */
+};
+
+enum bfi_tskim_i2h {
+       BFI_TSKIM_I2H_TM_RSP = BFA_I2HM(1),
+};
+
+struct bfi_tskim_req_s {
+       struct bfi_mhdr_s  mh;             /*  Common msg header          */
+       u16        tsk_tag;        /*  task management tag        */
+       u16        itn_fhdl;       /*  itn firmware handle        */
+       lun_t           lun;            /*  LU number                  */
+       u8         tm_flags;       /*  see fcp_tm_cmnd_t          */
+       u8         t_secs;         /*  Timeout value in seconds   */
+       u8         rsvd[2];
+};
+
+struct bfi_tskim_abortreq_s {
+       struct bfi_mhdr_s  mh;             /*  Common msg header          */
+       u16        tsk_tag;        /*  task management tag        */
+       u16        rsvd;
+};
+
+enum bfi_tskim_status {
+       /*
+        * Following are FCP-4 spec defined status codes,
+        * **DO NOT CHANGE THEM **
+        */
+       BFI_TSKIM_STS_OK       = 0,
+       BFI_TSKIM_STS_NOT_SUPP = 4,
+       BFI_TSKIM_STS_FAILED   = 5,
+
+       /**
+        * Defined by BFA
+        */
+       BFI_TSKIM_STS_TIMEOUT  = 10,    /*  TM request timedout     */
+       BFI_TSKIM_STS_ABORTED  = 11,    /*  Aborted on host request */
+};
+
+struct bfi_tskim_rsp_s {
+       struct bfi_mhdr_s  mh;          /*  Common msg header            */
+       u16        tsk_tag;     /*  task mgmt cmnd tag           */
+       u8         tsk_status;  /*  @ref bfi_tskim_status */
+       u8         rsvd;
+};
+
+#pragma pack()
+
+#endif /* __BFI_FCPIM_H__ */
+
diff --git a/drivers/scsi/bfa/include/bfi/bfi_fcxp.h b/drivers/scsi/bfa/include/bfi/bfi_fcxp.h
new file mode 100644 (file)
index 0000000..e0e995a
--- /dev/null
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ */
+
+#ifndef __BFI_FCXP_H__
+#define __BFI_FCXP_H__
+
+#include "bfi.h"
+
+#pragma pack(1)
+
+enum bfi_fcxp_h2i {
+       BFI_FCXP_H2I_SEND_REQ = 1,
+};
+
+enum bfi_fcxp_i2h {
+       BFI_FCXP_I2H_SEND_RSP = BFA_I2HM(1),
+};
+
+#define BFA_FCXP_MAX_SGES      2
+
+/**
+ * FCXP send request structure
+ */
+struct bfi_fcxp_send_req_s {
+       struct bfi_mhdr_s  mh;          /*  Common msg header               */
+       u16        fcxp_tag;    /*  driver request tag              */
+       u16        max_frmsz;   /*  max send frame size     */
+       u16        vf_id;               /*  vsan tag if applicable          */
+       u16        rport_fw_hndl;       /*  FW Handle for the remote port  */
+       u8         class;               /*  FC class used for req/rsp       */
+       u8         rsp_timeout; /*  timeout in secs, 0-no response */
+       u8         cts;         /*  continue sequence               */
+       u8         lp_tag;              /*  lport tag                       */
+       struct fchs_s   fchs;           /*  request FC header structure    */
+       u32        req_len;     /*  request payload length          */
+       u32        rsp_maxlen;  /*  max response length expected   */
+       struct bfi_sge_s   req_sge[BFA_FCXP_MAX_SGES];  /*  request buf    */
+       struct bfi_sge_s   rsp_sge[BFA_FCXP_MAX_SGES];  /*  response buf   */
+};
+
+/**
+ * FCXP send response structure
+ */
+struct bfi_fcxp_send_rsp_s {
+       struct bfi_mhdr_s  mh;          /*  Common msg header               */
+       u16        fcxp_tag;    /*  send request tag                */
+       u8         req_status;  /*  request status                  */
+       u8         rsvd;
+       u32        rsp_len;     /*  actual response length          */
+       u32        residue_len; /*  residual response length        */
+       struct fchs_s   fchs;           /*  response FC header structure   */
+};
+
+#pragma pack()
+
+#endif /* __BFI_FCXP_H__ */
+
diff --git a/drivers/scsi/bfa/include/bfi/bfi_ioc.h b/drivers/scsi/bfa/include/bfi/bfi_ioc.h
new file mode 100644 (file)
index 0000000..026e9c0
--- /dev/null
@@ -0,0 +1,202 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ */
+
+#ifndef __BFI_IOC_H__
+#define __BFI_IOC_H__
+
+#include "bfi.h"
+#include <defs/bfa_defs_ioc.h>
+
+#pragma pack(1)
+
+enum bfi_ioc_h2i_msgs {
+       BFI_IOC_H2I_ENABLE_REQ          = 1,
+       BFI_IOC_H2I_DISABLE_REQ         = 2,
+       BFI_IOC_H2I_GETATTR_REQ         = 3,
+       BFI_IOC_H2I_DBG_SYNC            = 4,
+       BFI_IOC_H2I_DBG_DUMP            = 5,
+};
+
+enum bfi_ioc_i2h_msgs {
+       BFI_IOC_I2H_ENABLE_REPLY        = BFA_I2HM(1),
+       BFI_IOC_I2H_DISABLE_REPLY       = BFA_I2HM(2),
+       BFI_IOC_I2H_GETATTR_REPLY       = BFA_I2HM(3),
+       BFI_IOC_I2H_READY_EVENT         = BFA_I2HM(4),
+       BFI_IOC_I2H_HBEAT               = BFA_I2HM(5),
+};
+
+/**
+ * BFI_IOC_H2I_GETATTR_REQ message
+ */
+struct bfi_ioc_getattr_req_s {
+       struct bfi_mhdr_s       mh;
+       union bfi_addr_u        attr_addr;
+};
+
+struct bfi_ioc_attr_s {
+       wwn_t           mfg_wwn;
+       mac_t           mfg_mac;
+       u16     rsvd_a;
+       char            brcd_serialnum[STRSZ(BFA_MFG_SERIALNUM_SIZE)];
+       u8         pcie_gen;
+       u8         pcie_lanes_orig;
+       u8         pcie_lanes;
+       u8         rx_bbcredit; /*  receive buffer credits */
+       u32        adapter_prop;        /*  adapter properties     */
+       u16        maxfrsize;   /*  max receive frame size */
+       char            asic_rev;
+       u8         rsvd_b;
+       char            fw_version[BFA_VERSION_LEN];
+       char            optrom_version[BFA_VERSION_LEN];
+       struct bfa_mfg_vpd_s    vpd;
+};
+
+/**
+ * BFI_IOC_I2H_GETATTR_REPLY message
+ */
+struct bfi_ioc_getattr_reply_s {
+       struct bfi_mhdr_s  mh;          /*  Common msg header          */
+       u8              status; /*  cfg reply status           */
+       u8              rsvd[3];
+};
+
+/**
+ * Firmware memory page offsets
+ */
+#define BFI_IOC_SMEM_PG0_CB    (0x40)
+#define BFI_IOC_SMEM_PG0_CT    (0x180)
+
+/**
+ * Firmware trace offset
+ */
+#define BFI_IOC_TRC_OFF                (0x4b00)
+#define BFI_IOC_TRC_ENTS       256
+
+#define BFI_IOC_FW_SIGNATURE   (0xbfadbfad)
+#define BFI_IOC_MD5SUM_SZ      4
+struct bfi_ioc_image_hdr_s {
+       u32        signature;   /*  constant signature */
+       u32        rsvd_a;
+       u32        exec;                /*  exec vector        */
+       u32        param;               /*  parameters         */
+       u32        rsvd_b[4];
+       u32        md5sum[BFI_IOC_MD5SUM_SZ];
+};
+
+/**
+ *  BFI_IOC_I2H_READY_EVENT message
+ */
+struct bfi_ioc_rdy_event_s {
+       struct bfi_mhdr_s  mh;                  /*  common msg header */
+       u8         init_status; /*  init event status */
+       u8         rsvd[3];
+};
+
+struct bfi_ioc_hbeat_s {
+       struct bfi_mhdr_s  mh;          /*  common msg header           */
+       u32        hb_count;    /*  current heart beat count    */
+};
+
+/**
+ * IOC hardware/firmware state
+ */
+enum bfi_ioc_state {
+       BFI_IOC_UNINIT   = 0,           /*  not initialized                 */
+       BFI_IOC_INITING          = 1,   /*  h/w is being initialized        */
+       BFI_IOC_HWINIT   = 2,           /*  h/w is initialized              */
+       BFI_IOC_CFG      = 3,           /*  IOC configuration in progress   */
+       BFI_IOC_OP               = 4,   /*  IOC is operational              */
+       BFI_IOC_DISABLING        = 5,   /*  IOC is being disabled           */
+       BFI_IOC_DISABLED         = 6,   /*  IOC is disabled                 */
+       BFI_IOC_CFG_DISABLED = 7,       /*  IOC is being disabled;transient */
+       BFI_IOC_HBFAIL       = 8,       /*  IOC heart-beat failure          */
+       BFI_IOC_MEMTEST      = 9,       /*  IOC is doing memtest            */
+};
+
+#define BFI_IOC_ENDIAN_SIG  0x12345678
+
+enum {
+       BFI_ADAPTER_TYPE_FC   = 0x01,           /*  FC adapters           */
+       BFI_ADAPTER_TYPE_MK   = 0x0f0000,       /*  adapter type mask     */
+       BFI_ADAPTER_TYPE_SH   = 16,             /*  adapter type shift    */
+       BFI_ADAPTER_NPORTS_MK = 0xff00,         /*  number of ports mask  */
+       BFI_ADAPTER_NPORTS_SH = 8,              /*  number of ports shift */
+       BFI_ADAPTER_SPEED_MK  = 0xff,           /*  adapter speed mask    */
+       BFI_ADAPTER_SPEED_SH  = 0,              /*  adapter speed shift   */
+       BFI_ADAPTER_PROTO     = 0x100000,       /*  prototype adapaters   */
+       BFI_ADAPTER_TTV       = 0x200000,       /*  TTV debug capable     */
+       BFI_ADAPTER_UNSUPP    = 0x400000,       /*  unknown adapter type  */
+};
+
+#define BFI_ADAPTER_GETP(__prop,__adap_prop)                   \
+    (((__adap_prop) & BFI_ADAPTER_ ## __prop ## _MK) >>         \
+     BFI_ADAPTER_ ## __prop ## _SH)
+#define BFI_ADAPTER_SETP(__prop, __val)                        \
+    ((__val) << BFI_ADAPTER_ ## __prop ## _SH)
+#define BFI_ADAPTER_IS_PROTO(__adap_type)                      \
+    ((__adap_type) & BFI_ADAPTER_PROTO)
+#define BFI_ADAPTER_IS_TTV(__adap_type)                        \
+    ((__adap_type) & BFI_ADAPTER_TTV)
+#define BFI_ADAPTER_IS_UNSUPP(__adap_type)                     \
+    ((__adap_type) & BFI_ADAPTER_UNSUPP)
+#define BFI_ADAPTER_IS_SPECIAL(__adap_type)                     \
+    ((__adap_type) & (BFI_ADAPTER_TTV | BFI_ADAPTER_PROTO |     \
+                       BFI_ADAPTER_UNSUPP))
+
+/**
+ * BFI_IOC_H2I_ENABLE_REQ & BFI_IOC_H2I_DISABLE_REQ messages
+ */
+struct bfi_ioc_ctrl_req_s {
+       struct bfi_mhdr_s       mh;
+       u8                      ioc_class;
+       u8              rsvd[3];
+};
+
+/**
+ * BFI_IOC_I2H_ENABLE_REPLY & BFI_IOC_I2H_DISABLE_REPLY messages
+ */
+struct bfi_ioc_ctrl_reply_s {
+       struct bfi_mhdr_s  mh;          /*  Common msg header     */
+       u8         status;              /*  enable/disable status */
+       u8         rsvd[3];
+};
+
+#define BFI_IOC_MSGSZ   8
+/**
+ * H2I Messages
+ */
+union bfi_ioc_h2i_msg_u {
+       struct bfi_mhdr_s       mh;
+       struct bfi_ioc_ctrl_req_s enable_req;
+       struct bfi_ioc_ctrl_req_s disable_req;
+       struct bfi_ioc_getattr_req_s getattr_req;
+       u32                     mboxmsg[BFI_IOC_MSGSZ];
+};
+
+/**
+ * I2H Messages
+ */
+union bfi_ioc_i2h_msg_u {
+       struct bfi_mhdr_s       mh;
+       struct bfi_ioc_rdy_event_s      rdy_event;
+       u32                     mboxmsg[BFI_IOC_MSGSZ];
+};
+
+#pragma pack()
+
+#endif /* __BFI_IOC_H__ */
+
diff --git a/drivers/scsi/bfa/include/bfi/bfi_iocfc.h b/drivers/scsi/bfa/include/bfi/bfi_iocfc.h
new file mode 100644 (file)
index 0000000..c3760df
--- /dev/null
@@ -0,0 +1,177 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ */
+
+#ifndef __BFI_IOCFC_H__
+#define __BFI_IOCFC_H__
+
+#include "bfi.h"
+#include <defs/bfa_defs_ioc.h>
+#include <defs/bfa_defs_iocfc.h>
+#include <defs/bfa_defs_boot.h>
+
+#pragma pack(1)
+
+enum bfi_iocfc_h2i_msgs {
+       BFI_IOCFC_H2I_CFG_REQ           = 1,
+       BFI_IOCFC_H2I_GET_STATS_REQ     = 2,
+       BFI_IOCFC_H2I_CLEAR_STATS_REQ   = 3,
+       BFI_IOCFC_H2I_SET_INTR_REQ      = 4,
+       BFI_IOCFC_H2I_UPDATEQ_REQ = 5,
+};
+
+enum bfi_iocfc_i2h_msgs {
+       BFI_IOCFC_I2H_CFG_REPLY         = BFA_I2HM(1),
+       BFI_IOCFC_I2H_GET_STATS_RSP     = BFA_I2HM(2),
+       BFI_IOCFC_I2H_CLEAR_STATS_RSP   = BFA_I2HM(3),
+       BFI_IOCFC_I2H_UPDATEQ_RSP = BFA_I2HM(5),
+};
+
+struct bfi_iocfc_cfg_s {
+       u8         num_cqs;     /*  Number of CQs to be used     */
+       u8         sense_buf_len;       /*  SCSI sense length            */
+       u8         trunk_enabled;       /*  port trunking enabled        */
+       u8         trunk_ports; /*  trunk ports bit map          */
+       u32        endian_sig;  /*  endian signature of host     */
+
+       /**
+        * Request and response circular queue base addresses, size and
+        * shadow index pointers.
+        */
+       union bfi_addr_u  req_cq_ba[BFI_IOC_MAX_CQS];
+       union bfi_addr_u  req_shadow_ci[BFI_IOC_MAX_CQS];
+       u16    req_cq_elems[BFI_IOC_MAX_CQS];
+       union bfi_addr_u  rsp_cq_ba[BFI_IOC_MAX_CQS];
+       union bfi_addr_u  rsp_shadow_pi[BFI_IOC_MAX_CQS];
+       u16    rsp_cq_elems[BFI_IOC_MAX_CQS];
+
+       union bfi_addr_u  stats_addr;   /*  DMA-able address for stats    */
+       union bfi_addr_u  cfgrsp_addr;  /*  config response dma address  */
+       union bfi_addr_u  ioim_snsbase;  /*  IO sense buffer base address */
+       struct bfa_iocfc_intr_attr_s intr_attr; /*  IOC interrupt attributes */
+};
+
+/**
+ * Boot target wwn information for this port. This contains either the stored
+ * or discovered boot target port wwns for the port.
+ */
+struct bfi_iocfc_bootwwns {
+       wwn_t           wwn[BFA_BOOT_BOOTLUN_MAX];
+       u8              nwwns;
+       u8              rsvd[7];
+};
+
+struct bfi_iocfc_cfgrsp_s {
+       struct bfa_iocfc_fwcfg_s        fwcfg;
+       struct bfa_iocfc_intr_attr_s    intr_attr;
+       struct bfi_iocfc_bootwwns       bootwwns;
+};
+
+/**
+ * BFI_IOCFC_H2I_CFG_REQ message
+ */
+struct bfi_iocfc_cfg_req_s {
+       struct bfi_mhdr_s      mh;
+       union bfi_addr_u      ioc_cfg_dma_addr;
+};
+
+/**
+ * BFI_IOCFC_I2H_CFG_REPLY message
+ */
+struct bfi_iocfc_cfg_reply_s {
+       struct bfi_mhdr_s  mh;          /*  Common msg header          */
+       u8         cfg_success; /*  cfg reply status           */
+       u8         lpu_bm;              /*  LPUs assigned for this IOC */
+       u8         rsvd[2];
+};
+
+/**
+ *  BFI_IOCFC_H2I_GET_STATS_REQ & BFI_IOCFC_H2I_CLEAR_STATS_REQ messages
+ */
+struct bfi_iocfc_stats_req_s {
+       struct bfi_mhdr_s mh;           /*  msg header            */
+       u32        msgtag;              /*  msgtag for reply      */
+};
+
+/**
+ * BFI_IOCFC_I2H_GET_STATS_RSP & BFI_IOCFC_I2H_CLEAR_STATS_RSP messages
+ */
+struct bfi_iocfc_stats_rsp_s {
+       struct bfi_mhdr_s mh;           /*  common msg header     */
+       u8         status;              /*  reply status          */
+       u8         rsvd[3];
+       u32        msgtag;              /*  msgtag for reply      */
+};
+
+/**
+ * BFI_IOCFC_H2I_SET_INTR_REQ message
+ */
+struct bfi_iocfc_set_intr_req_s {
+       struct bfi_mhdr_s mh;           /*  common msg header     */
+       u8              coalesce;       /*  enable intr coalescing*/
+       u8         rsvd[3];
+       u16     delay;          /*  delay timer 0..1125us  */
+       u16     latency;        /*  latency timer 0..225us */
+};
+
+/**
+ * BFI_IOCFC_H2I_UPDATEQ_REQ message
+ */
+struct bfi_iocfc_updateq_req_s {
+       struct bfi_mhdr_s mh;           /*  common msg header     */
+       u32 reqq_ba;                    /*  reqq base addr        */
+       u32 rspq_ba;                    /*  rspq base addr        */
+       u32 reqq_sci;                   /*  reqq shadow ci        */
+       u32 rspq_spi;                   /*  rspq shadow pi        */
+};
+
+/**
+ * BFI_IOCFC_I2H_UPDATEQ_RSP message
+ */
+struct bfi_iocfc_updateq_rsp_s {
+       struct bfi_mhdr_s mh;           /*  common msg header     */
+       u8         status;              /*  updateq  status       */
+       u8         rsvd[3];
+};
+
+/**
+ * H2I Messages
+ */
+union bfi_iocfc_h2i_msg_u {
+       struct bfi_mhdr_s               mh;
+       struct bfi_iocfc_cfg_req_s      cfg_req;
+       struct bfi_iocfc_stats_req_s stats_get;
+       struct bfi_iocfc_stats_req_s stats_clr;
+       struct bfi_iocfc_updateq_req_s updateq_req;
+       u32                             mboxmsg[BFI_IOC_MSGSZ];
+};
+
+/**
+ * I2H Messages
+ */
+union bfi_iocfc_i2h_msg_u {
+       struct bfi_mhdr_s               mh;
+       struct bfi_iocfc_cfg_reply_s            cfg_reply;
+       struct bfi_iocfc_stats_rsp_s stats_get_rsp;
+       struct bfi_iocfc_stats_rsp_s stats_clr_rsp;
+       struct bfi_iocfc_updateq_rsp_s updateq_rsp;
+       u32                             mboxmsg[BFI_IOC_MSGSZ];
+};
+
+#pragma pack()
+
+#endif /* __BFI_IOCFC_H__ */
+
diff --git a/drivers/scsi/bfa/include/bfi/bfi_lport.h b/drivers/scsi/bfa/include/bfi/bfi_lport.h
new file mode 100644 (file)
index 0000000..2901061
--- /dev/null
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ */
+
+#ifndef __BFI_LPORT_H__
+#define __BFI_LPORT_H__
+
+#include <bfi/bfi.h>
+
+#pragma pack(1)
+
+enum bfi_lport_h2i_msgs {
+       BFI_LPORT_H2I_CREATE_REQ = 1,
+       BFI_LPORT_H2I_DELETE_REQ = 2,
+};
+
+enum bfi_lport_i2h_msgs {
+       BFI_LPORT_I2H_CREATE_RSP = BFA_I2HM(1),
+       BFI_LPORT_I2H_DELETE_RSP = BFA_I2HM(2),
+       BFI_LPORT_I2H_ONLINE      = BFA_I2HM(3),
+       BFI_LPORT_I2H_OFFLINE     = BFA_I2HM(4),
+};
+
+#define BFI_LPORT_MAX_SYNNAME  64
+
+enum bfi_lport_role_e {
+       BFI_LPORT_ROLE_FCPIM    = 1,
+       BFI_LPORT_ROLE_FCPTM    = 2,
+       BFI_LPORT_ROLE_IPFC     = 4,
+};
+
+struct bfi_lport_create_req_s {
+       bfi_mhdr_t      mh;             /*  common msg header           */
+       u16     fabric_fwhdl;   /*  parent fabric instance      */
+       u8              roles;          /*  lport FC-4 roles            */
+       u8              rsvd;
+       wwn_t           pwwn;           /*  port name                   */
+       wwn_t           nwwn;           /*  node name                   */
+       u8              symname[BFI_LPORT_MAX_SYNNAME];
+};
+
+struct bfi_lport_create_rsp_s {
+       bfi_mhdr_t      mh;             /*  common msg header           */
+       u8         status;              /*  lport creation status       */
+       u8         rsvd[3];
+};
+
+struct bfi_lport_delete_req_s {
+       bfi_mhdr_t      mh;             /*  common msg header           */
+       u16        fw_handle;   /*  firmware lport handle       */
+       u16        rsvd;
+};
+
+struct bfi_lport_delete_rsp_s {
+       bfi_mhdr_t      mh;             /*  common msg header           */
+       u16        bfa_handle;  /*  host lport handle           */
+       u8         status;              /*  lport deletion status       */
+       u8         rsvd;
+};
+
+union bfi_lport_h2i_msg_u {
+       bfi_msg_t               *msg;
+       struct bfi_lport_create_req_s   *create_req;
+       struct bfi_lport_delete_req_s   *delete_req;
+};
+
+union bfi_lport_i2h_msg_u {
+       bfi_msg_t               *msg;
+       struct bfi_lport_create_rsp_s   *create_rsp;
+       struct bfi_lport_delete_rsp_s   *delete_rsp;
+};
+
+#pragma pack()
+
+#endif /* __BFI_LPORT_H__ */
+
diff --git a/drivers/scsi/bfa/include/bfi/bfi_lps.h b/drivers/scsi/bfa/include/bfi/bfi_lps.h
new file mode 100644 (file)
index 0000000..414b0e3
--- /dev/null
@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ */
+
+#ifndef __BFI_LPS_H__
+#define __BFI_LPS_H__
+
+#include <bfi/bfi.h>
+
+#pragma pack(1)
+
+enum bfi_lps_h2i_msgs {
+       BFI_LPS_H2I_LOGIN_REQ   = 1,
+       BFI_LPS_H2I_LOGOUT_REQ  = 2,
+};
+
+enum bfi_lps_i2h_msgs {
+       BFI_LPS_H2I_LOGIN_RSP   = BFA_I2HM(1),
+       BFI_LPS_H2I_LOGOUT_RSP  = BFA_I2HM(2),
+};
+
+struct bfi_lps_login_req_s {
+       struct bfi_mhdr_s  mh;          /*  common msg header           */
+       u8              lp_tag;
+       u8              alpa;
+       u16     pdu_size;
+       wwn_t           pwwn;
+       wwn_t           nwwn;
+       u8              fdisc;
+       u8              auth_en;
+       u8              rsvd[2];
+};
+
+struct bfi_lps_login_rsp_s {
+       struct bfi_mhdr_s  mh;          /*  common msg header           */
+       u8              lp_tag;
+       u8              status;
+       u8              lsrjt_rsn;
+       u8              lsrjt_expl;
+       wwn_t           port_name;
+       wwn_t           node_name;
+       u16     bb_credit;
+       u8              f_port;
+       u8              npiv_en;
+       u32     lp_pid : 24;
+       u32     auth_req : 8;
+       mac_t           lp_mac;
+       mac_t           fcf_mac;
+       u8              ext_status;
+       u8      brcd_switch;/*  attached peer is brcd switch    */
+};
+
+struct bfi_lps_logout_req_s {
+       struct bfi_mhdr_s  mh;          /*  common msg header           */
+       u8              lp_tag;
+       u8              rsvd[3];
+       wwn_t           port_name;
+};
+
+struct bfi_lps_logout_rsp_s {
+       struct bfi_mhdr_s  mh;          /*  common msg header           */
+       u8              lp_tag;
+       u8              status;
+       u8              rsvd[2];
+};
+
+union bfi_lps_h2i_msg_u {
+       struct bfi_mhdr_s               *msg;
+       struct bfi_lps_login_req_s      *login_req;
+       struct bfi_lps_logout_req_s     *logout_req;
+};
+
+union bfi_lps_i2h_msg_u {
+       struct bfi_msg_s                *msg;
+       struct bfi_lps_login_rsp_s      *login_rsp;
+       struct bfi_lps_logout_rsp_s     *logout_rsp;
+};
+
+#pragma pack()
+
+#endif /* __BFI_LPS_H__ */
+
+
diff --git a/drivers/scsi/bfa/include/bfi/bfi_port.h b/drivers/scsi/bfa/include/bfi/bfi_port.h
new file mode 100644 (file)
index 0000000..3ec3bea
--- /dev/null
@@ -0,0 +1,115 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ */
+#ifndef __BFI_PORT_H__
+#define __BFI_PORT_H__
+
+#include <bfi/bfi.h>
+#include <defs/bfa_defs_pport.h>
+
+#pragma pack(1)
+
+enum bfi_port_h2i {
+       BFI_PORT_H2I_ENABLE_REQ         = (1),
+       BFI_PORT_H2I_DISABLE_REQ        = (2),
+       BFI_PORT_H2I_GET_STATS_REQ      = (3),
+       BFI_PORT_H2I_CLEAR_STATS_REQ    = (4),
+};
+
+enum bfi_port_i2h {
+       BFI_PORT_I2H_ENABLE_RSP         = BFA_I2HM(1),
+       BFI_PORT_I2H_DISABLE_RSP        = BFA_I2HM(2),
+       BFI_PORT_I2H_GET_STATS_RSP      = BFA_I2HM(3),
+       BFI_PORT_I2H_CLEAR_STATS_RSP    = BFA_I2HM(4),
+};
+
+/**
+ * Generic REQ type
+ */
+struct bfi_port_generic_req_s {
+       struct bfi_mhdr_s  mh;          /*  msg header                      */
+       u32        msgtag;              /*  msgtag for reply                */
+       u32     rsvd;
+};
+
+/**
+ * Generic RSP type
+ */
+struct bfi_port_generic_rsp_s {
+       struct bfi_mhdr_s  mh;          /*  common msg header               */
+       u8         status;              /*  port enable status              */
+       u8         rsvd[3];
+       u32        msgtag;              /*  msgtag for reply                */
+};
+
+/**
+ * @todo
+ * BFI_PORT_H2I_ENABLE_REQ
+ */
+
+/**
+ * @todo
+ * BFI_PORT_I2H_ENABLE_RSP
+ */
+
+/**
+ * BFI_PORT_H2I_DISABLE_REQ
+ */
+
+/**
+ * BFI_PORT_I2H_DISABLE_RSP
+ */
+
+/**
+ * BFI_PORT_H2I_GET_STATS_REQ
+ */
+struct bfi_port_get_stats_req_s {
+       struct bfi_mhdr_s  mh;          /*  common msg header               */
+       union bfi_addr_u   dma_addr;
+};
+
+/**
+ * BFI_PORT_I2H_GET_STATS_RSP
+ */
+
+/**
+ * BFI_PORT_H2I_CLEAR_STATS_REQ
+ */
+
+/**
+ * BFI_PORT_I2H_CLEAR_STATS_RSP
+ */
+
+union bfi_port_h2i_msg_u {
+       struct bfi_mhdr_s               mh;
+       struct bfi_port_generic_req_s   enable_req;
+       struct bfi_port_generic_req_s   disable_req;
+       struct bfi_port_get_stats_req_s getstats_req;
+       struct bfi_port_generic_req_s   clearstats_req;
+};
+
+union bfi_port_i2h_msg_u {
+       struct bfi_mhdr_s               mh;
+       struct bfi_port_generic_rsp_s   enable_rsp;
+       struct bfi_port_generic_rsp_s   disable_rsp;
+       struct bfi_port_generic_rsp_s   getstats_rsp;
+       struct bfi_port_generic_rsp_s   clearstats_rsp;
+};
+
+#pragma pack()
+
+#endif /* __BFI_PORT_H__ */
+
diff --git a/drivers/scsi/bfa/include/bfi/bfi_pport.h b/drivers/scsi/bfa/include/bfi/bfi_pport.h
new file mode 100644 (file)
index 0000000..c96d246
--- /dev/null
@@ -0,0 +1,184 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ */
+#ifndef __BFI_PPORT_H__
+#define __BFI_PPORT_H__
+
+#include <bfi/bfi.h>
+#include <defs/bfa_defs_pport.h>
+
+#pragma pack(1)
+
+enum bfi_pport_h2i {
+       BFI_PPORT_H2I_ENABLE_REQ                = (1),
+       BFI_PPORT_H2I_DISABLE_REQ               = (2),
+       BFI_PPORT_H2I_GET_STATS_REQ             = (3),
+       BFI_PPORT_H2I_CLEAR_STATS_REQ   = (4),
+       BFI_PPORT_H2I_SET_SVC_PARAMS_REQ        = (5),
+       BFI_PPORT_H2I_ENABLE_RX_VF_TAG_REQ      = (6),
+       BFI_PPORT_H2I_ENABLE_TX_VF_TAG_REQ      = (7),
+       BFI_PPORT_H2I_GET_QOS_STATS_REQ         = (8),
+       BFI_PPORT_H2I_CLEAR_QOS_STATS_REQ       = (9),
+};
+
+enum bfi_pport_i2h {
+       BFI_PPORT_I2H_ENABLE_RSP                = BFA_I2HM(1),
+       BFI_PPORT_I2H_DISABLE_RSP               = BFA_I2HM(2),
+       BFI_PPORT_I2H_GET_STATS_RSP             = BFA_I2HM(3),
+       BFI_PPORT_I2H_CLEAR_STATS_RSP   = BFA_I2HM(4),
+       BFI_PPORT_I2H_SET_SVC_PARAMS_RSP        = BFA_I2HM(5),
+       BFI_PPORT_I2H_ENABLE_RX_VF_TAG_RSP      = BFA_I2HM(6),
+       BFI_PPORT_I2H_ENABLE_TX_VF_TAG_RSP      = BFA_I2HM(7),
+       BFI_PPORT_I2H_EVENT                     = BFA_I2HM(8),
+       BFI_PPORT_I2H_GET_QOS_STATS_RSP         = BFA_I2HM(9),
+       BFI_PPORT_I2H_CLEAR_QOS_STATS_RSP       = BFA_I2HM(10),
+};
+
+/**
+ * Generic REQ type
+ */
+struct bfi_pport_generic_req_s {
+       struct bfi_mhdr_s  mh;          /*  msg header                      */
+       u32        msgtag;              /*  msgtag for reply                */
+};
+
+/**
+ * Generic RSP type
+ */
+struct bfi_pport_generic_rsp_s {
+       struct bfi_mhdr_s  mh;          /*  common msg header               */
+       u8         status;              /*  port enable status              */
+       u8         rsvd[3];
+       u32        msgtag;              /*  msgtag for reply                */
+};
+
+/**
+ * BFI_PPORT_H2I_ENABLE_REQ
+ */
+struct bfi_pport_enable_req_s {
+       struct bfi_mhdr_s  mh;          /*  msg header                      */
+       u32        rsvd1;
+       wwn_t           nwwn;           /*  node wwn of physical port       */
+       wwn_t           pwwn;           /*  port wwn of physical port       */
+       struct bfa_pport_cfg_s port_cfg;        /*  port configuration      */
+       union bfi_addr_u  stats_dma_addr;       /*  DMA address for stats  */
+       u32        msgtag;              /*  msgtag for reply                */
+       u32        rsvd2;
+};
+
+/**
+ * BFI_PPORT_I2H_ENABLE_RSP
+ */
+#define bfi_pport_enable_rsp_t struct bfi_pport_generic_rsp_s
+
+/**
+ * BFI_PPORT_H2I_DISABLE_REQ
+ */
+#define bfi_pport_disable_req_t struct bfi_pport_generic_req_s
+
+/**
+ * BFI_PPORT_I2H_DISABLE_RSP
+ */
+#define bfi_pport_disable_rsp_t struct bfi_pport_generic_rsp_s
+
+/**
+ * BFI_PPORT_H2I_GET_STATS_REQ
+ */
+#define bfi_pport_get_stats_req_t struct bfi_pport_generic_req_s
+
+/**
+ * BFI_PPORT_I2H_GET_STATS_RSP
+ */
+#define bfi_pport_get_stats_rsp_t struct bfi_pport_generic_rsp_s
+
+/**
+ * BFI_PPORT_H2I_CLEAR_STATS_REQ
+ */
+#define bfi_pport_clear_stats_req_t struct bfi_pport_generic_req_s
+
+/**
+ * BFI_PPORT_I2H_CLEAR_STATS_RSP
+ */
+#define bfi_pport_clear_stats_rsp_t struct bfi_pport_generic_rsp_s
+
+/**
+ * BFI_PPORT_H2I_GET_QOS_STATS_REQ
+ */
+#define bfi_pport_get_qos_stats_req_t struct bfi_pport_generic_req_s
+
+/**
+ * BFI_PPORT_H2I_GET_QOS_STATS_RSP
+ */
+#define bfi_pport_get_qos_stats_rsp_t struct bfi_pport_generic_rsp_s
+
+/**
+ * BFI_PPORT_H2I_CLEAR_QOS_STATS_REQ
+ */
+#define bfi_pport_clear_qos_stats_req_t struct bfi_pport_generic_req_s
+
+/**
+ * BFI_PPORT_H2I_CLEAR_QOS_STATS_RSP
+ */
+#define bfi_pport_clear_qos_stats_rsp_t struct bfi_pport_generic_rsp_s
+
+/**
+ * BFI_PPORT_H2I_SET_SVC_PARAMS_REQ
+ */
+struct bfi_pport_set_svc_params_req_s {
+       struct bfi_mhdr_s  mh;          /*  msg header */
+       u16        tx_bbcredit; /*  Tx credits */
+       u16        rsvd;
+};
+
+/**
+ * BFI_PPORT_I2H_SET_SVC_PARAMS_RSP
+ */
+
+/**
+ * BFI_PPORT_I2H_EVENT
+ */
+struct bfi_pport_event_s {
+       struct bfi_mhdr_s       mh;     /*  common msg header */
+       struct bfa_pport_link_s link_state;
+};
+
+union bfi_pport_h2i_msg_u {
+       struct bfi_mhdr_s                       *mhdr;
+       struct bfi_pport_enable_req_s           *penable;
+       struct bfi_pport_generic_req_s          *pdisable;
+       struct bfi_pport_generic_req_s          *pgetstats;
+       struct bfi_pport_generic_req_s          *pclearstats;
+       struct bfi_pport_set_svc_params_req_s   *psetsvcparams;
+       struct bfi_pport_get_qos_stats_req_s    *pgetqosstats;
+       struct bfi_pport_generic_req_s          *pclearqosstats;
+};
+
+union bfi_pport_i2h_msg_u {
+       struct bfi_msg_s                        *msg;
+       struct bfi_pport_generic_rsp_s          *enable_rsp;
+       struct bfi_pport_disable_rsp_s          *disable_rsp;
+       struct bfi_pport_generic_rsp_s          *getstats_rsp;
+       struct bfi_pport_clear_stats_rsp_s      *clearstats_rsp;
+       struct bfi_pport_set_svc_params_rsp_s   *setsvcparasm_rsp;
+       struct bfi_pport_get_qos_stats_rsp_s    *getqosstats_rsp;
+       struct bfi_pport_clear_qos_stats_rsp_s  *clearqosstats_rsp;
+       struct bfi_pport_event_s                *event;
+};
+
+#pragma pack()
+
+#endif /* __BFI_PPORT_H__ */
+
diff --git a/drivers/scsi/bfa/include/bfi/bfi_rport.h b/drivers/scsi/bfa/include/bfi/bfi_rport.h
new file mode 100644 (file)
index 0000000..3520f55
--- /dev/null
@@ -0,0 +1,104 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ */
+
+#ifndef __BFI_RPORT_H__
+#define __BFI_RPORT_H__
+
+#include <bfi/bfi.h>
+
+#pragma pack(1)
+
+enum bfi_rport_h2i_msgs {
+       BFI_RPORT_H2I_CREATE_REQ = 1,
+       BFI_RPORT_H2I_DELETE_REQ = 2,
+       BFI_RPORT_H2I_SET_SPEED_REQ  = 3,
+};
+
+enum bfi_rport_i2h_msgs {
+       BFI_RPORT_I2H_CREATE_RSP = BFA_I2HM(1),
+       BFI_RPORT_I2H_DELETE_RSP = BFA_I2HM(2),
+       BFI_RPORT_I2H_QOS_SCN    = BFA_I2HM(3),
+};
+
+struct bfi_rport_create_req_s {
+       struct bfi_mhdr_s  mh;          /*  common msg header           */
+       u16        bfa_handle;  /*  host rport handle           */
+       u16        max_frmsz;   /*  max rcv pdu size            */
+       u32        pid       : 24,      /*  remote port ID              */
+                       lp_tag    : 8;  /*  local port tag              */
+       u32        local_pid : 24,      /*  local port ID               */
+                       cisc      : 8;
+       u8         fc_class;    /*  supported FC classes        */
+       u8         vf_en;               /*  virtual fabric enable       */
+       u16        vf_id;               /*  virtual fabric ID           */
+};
+
+struct bfi_rport_create_rsp_s {
+       struct bfi_mhdr_s  mh;          /*  common msg header           */
+       u8         status;              /*  rport creation status       */
+       u8         rsvd[3];
+       u16        bfa_handle;  /*  host rport handle           */
+       u16        fw_handle;   /*  firmware rport handle       */
+       struct bfa_rport_qos_attr_s qos_attr;  /* QoS Attributes */
+};
+
+struct bfa_rport_speed_req_s {
+       struct bfi_mhdr_s  mh;          /*  common msg header           */
+       u16        fw_handle;   /*  firmware rport handle       */
+       u8              speed;          /*! rport's speed via RPSC  */
+       u8              rsvd;
+};
+
+struct bfi_rport_delete_req_s {
+       struct bfi_mhdr_s  mh;          /*  common msg header           */
+       u16        fw_handle;   /*  firmware rport handle       */
+       u16        rsvd;
+};
+
+struct bfi_rport_delete_rsp_s {
+       struct bfi_mhdr_s  mh;          /*  common msg header           */
+       u16        bfa_handle;  /*  host rport handle           */
+       u8         status;              /*  rport deletion status       */
+       u8         rsvd;
+};
+
+struct bfi_rport_qos_scn_s {
+       struct bfi_mhdr_s  mh;          /*  common msg header           */
+       u16        bfa_handle;  /*  host rport handle           */
+       u16        rsvd;
+       struct bfa_rport_qos_attr_s old_qos_attr;  /* Old QoS Attributes */
+       struct bfa_rport_qos_attr_s new_qos_attr;  /* New QoS Attributes */
+};
+
+union bfi_rport_h2i_msg_u {
+       struct bfi_msg_s                *msg;
+       struct bfi_rport_create_req_s   *create_req;
+       struct bfi_rport_delete_req_s   *delete_req;
+       struct bfi_rport_speed_req_s    *speed_req;
+};
+
+union bfi_rport_i2h_msg_u {
+       struct bfi_msg_s                *msg;
+       struct bfi_rport_create_rsp_s   *create_rsp;
+       struct bfi_rport_delete_rsp_s   *delete_rsp;
+       struct bfi_rport_qos_scn_s      *qos_scn_evt;
+};
+
+#pragma pack()
+
+#endif /* __BFI_RPORT_H__ */
+
diff --git a/drivers/scsi/bfa/include/bfi/bfi_uf.h b/drivers/scsi/bfa/include/bfi/bfi_uf.h
new file mode 100644 (file)
index 0000000..f328a9e
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ */
+
+#ifndef __BFI_UF_H__
+#define __BFI_UF_H__
+
+#include "bfi.h"
+
+#pragma pack(1)
+
+enum bfi_uf_h2i {
+       BFI_UF_H2I_BUF_POST = 1,
+};
+
+enum bfi_uf_i2h {
+       BFI_UF_I2H_FRM_RCVD = BFA_I2HM(1),
+};
+
+#define BFA_UF_MAX_SGES        2
+
+struct bfi_uf_buf_post_s {
+       struct bfi_mhdr_s  mh;          /*  Common msg header           */
+       u16        buf_tag;     /*  buffer tag                  */
+       u16        buf_len;     /*  total buffer length */
+       struct bfi_sge_s   sge[BFA_UF_MAX_SGES]; /*  buffer DMA SGEs    */
+};
+
+struct bfi_uf_frm_rcvd_s {
+       struct bfi_mhdr_s  mh;          /*  Common msg header           */
+       u16        buf_tag;     /*  buffer tag                  */
+       u16        rsvd;
+       u16        frm_len;     /*  received frame length       */
+       u16        xfr_len;     /*  tranferred length           */
+};
+
+#pragma pack()
+
+#endif /* __BFI_UF_H__ */
diff --git a/drivers/scsi/bfa/include/cna/bfa_cna_trcmod.h b/drivers/scsi/bfa/include/cna/bfa_cna_trcmod.h
new file mode 100644 (file)
index 0000000..43ba706
--- /dev/null
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) 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.
+ */
+
+/**
+ *  bfa_cna_trcmod.h CNA trace modules
+ */
+
+#ifndef __BFA_CNA_TRCMOD_H__
+#define __BFA_CNA_TRCMOD_H__
+
+#include <cs/bfa_trc.h>
+
+/*
+ * !!! Only append to the enums defined here to avoid any versioning
+ * !!! needed between trace utility and driver version
+ */
+enum {
+       BFA_TRC_CNA_CEE         = 1,
+       BFA_TRC_CNA_PORT        = 2,
+};
+
+#endif /* __BFA_CNA_TRCMOD_H__ */
diff --git a/drivers/scsi/bfa/include/cna/cee/bfa_cee.h b/drivers/scsi/bfa/include/cna/cee/bfa_cee.h
new file mode 100644 (file)
index 0000000..77f297f
--- /dev/null
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ */
+
+#ifndef __BFA_CEE_H__
+#define __BFA_CEE_H__
+
+#include <defs/bfa_defs_cee.h>
+#include <bfa_ioc.h>
+#include <cs/bfa_trc.h>
+#include <cs/bfa_log.h>
+
+typedef void (*bfa_cee_get_attr_cbfn_t) (void *dev, bfa_status_t status);
+typedef void (*bfa_cee_get_stats_cbfn_t) (void *dev, bfa_status_t status);
+typedef void (*bfa_cee_reset_stats_cbfn_t) (void *dev, bfa_status_t status);
+typedef void (*bfa_cee_hbfail_cbfn_t) (void *dev, bfa_status_t status);
+
+struct bfa_cee_cbfn_s {
+       bfa_cee_get_attr_cbfn_t    get_attr_cbfn;
+       void *get_attr_cbarg;
+       bfa_cee_get_stats_cbfn_t   get_stats_cbfn;
+       void *get_stats_cbarg;
+       bfa_cee_reset_stats_cbfn_t reset_stats_cbfn;
+       void *reset_stats_cbarg;
+};
+
+struct bfa_cee_s {
+       void *dev;
+       bfa_boolean_t get_attr_pending;
+       bfa_boolean_t get_stats_pending;
+       bfa_boolean_t reset_stats_pending;
+       bfa_status_t get_attr_status;
+       bfa_status_t get_stats_status;
+       bfa_status_t reset_stats_status;
+       struct bfa_cee_cbfn_s cbfn;
+       struct bfa_ioc_hbfail_notify_s hbfail;
+       struct bfa_trc_mod_s *trcmod;
+       struct bfa_log_mod_s *logmod;
+       struct bfa_cee_attr_s *attr;
+       struct bfa_cee_stats_s *stats;
+       struct bfa_dma_s attr_dma;
+       struct bfa_dma_s stats_dma;
+       struct bfa_ioc_s *ioc;
+       struct bfa_mbox_cmd_s get_cfg_mb;
+       struct bfa_mbox_cmd_s get_stats_mb;
+       struct bfa_mbox_cmd_s reset_stats_mb;
+};
+
+u32 bfa_cee_meminfo(void);
+void bfa_cee_mem_claim(struct bfa_cee_s *cee, u8 *dma_kva,
+                        u64 dma_pa);
+void bfa_cee_attach(struct bfa_cee_s *cee, struct bfa_ioc_s *ioc, void *dev,
+                       struct bfa_trc_mod_s *trcmod,
+                       struct bfa_log_mod_s *logmod);
+void bfa_cee_detach(struct bfa_cee_s *cee);
+bfa_status_t bfa_cee_get_attr(struct bfa_cee_s *cee,
+                        struct bfa_cee_attr_s *attr,
+                       bfa_cee_get_attr_cbfn_t cbfn, void *cbarg);
+bfa_status_t bfa_cee_get_stats(struct bfa_cee_s *cee,
+                       struct bfa_cee_stats_s *stats,
+                       bfa_cee_get_stats_cbfn_t cbfn, void *cbarg);
+bfa_status_t bfa_cee_reset_stats(struct bfa_cee_s *cee,
+                       bfa_cee_reset_stats_cbfn_t cbfn, void *cbarg);
+#endif /* __BFA_CEE_H__ */
diff --git a/drivers/scsi/bfa/include/cna/port/bfa_port.h b/drivers/scsi/bfa/include/cna/port/bfa_port.h
new file mode 100644 (file)
index 0000000..7cbf17d
--- /dev/null
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ */
+
+#ifndef __BFA_PORT_H__
+#define __BFA_PORT_H__
+
+#include <defs/bfa_defs_port.h>
+#include <bfa_ioc.h>
+#include <cs/bfa_trc.h>
+#include <cs/bfa_log.h>
+
+typedef void    (*bfa_port_stats_cbfn_t) (void *dev, bfa_status_t status);
+typedef void    (*bfa_port_endis_cbfn_t) (void *dev, bfa_status_t status);
+
+struct bfa_port_s {
+       void           *dev;
+       struct bfa_ioc_s *ioc;
+       struct bfa_trc_mod_s *trcmod;
+       struct bfa_log_mod_s *logmod;
+       u32        msgtag;
+       bfa_boolean_t   stats_busy;
+       struct bfa_mbox_cmd_s stats_mb;
+       bfa_port_stats_cbfn_t stats_cbfn;
+       void           *stats_cbarg;
+       bfa_status_t    stats_status;
+       union bfa_pport_stats_u *stats;
+       struct bfa_dma_s stats_dma;
+       bfa_boolean_t   endis_pending;
+       struct bfa_mbox_cmd_s endis_mb;
+       bfa_port_endis_cbfn_t endis_cbfn;
+       void           *endis_cbarg;
+       bfa_status_t    endis_status;
+       struct bfa_ioc_hbfail_notify_s hbfail;
+};
+
+void            bfa_port_attach(struct bfa_port_s *port, struct bfa_ioc_s *ioc,
+                               void *dev, struct bfa_trc_mod_s *trcmod,
+                               struct bfa_log_mod_s *logmod);
+void            bfa_port_detach(struct bfa_port_s *port);
+void            bfa_port_hbfail(void *arg);
+
+bfa_status_t    bfa_port_get_stats(struct bfa_port_s *port,
+                                  union bfa_pport_stats_u *stats,
+                                  bfa_port_stats_cbfn_t cbfn, void *cbarg);
+bfa_status_t    bfa_port_clear_stats(struct bfa_port_s *port,
+                                    bfa_port_stats_cbfn_t cbfn, void *cbarg);
+bfa_status_t    bfa_port_enable(struct bfa_port_s *port,
+                               bfa_port_endis_cbfn_t cbfn, void *cbarg);
+bfa_status_t    bfa_port_disable(struct bfa_port_s *port,
+                                bfa_port_endis_cbfn_t cbfn, void *cbarg);
+u32        bfa_port_meminfo(void);
+void            bfa_port_mem_claim(struct bfa_port_s *port, u8 *dma_kva,
+                                  u64 dma_pa);
+
+#endif /* __BFA_PORT_H__ */
diff --git a/drivers/scsi/bfa/include/cna/pstats/ethport_defs.h b/drivers/scsi/bfa/include/cna/pstats/ethport_defs.h
new file mode 100644 (file)
index 0000000..1563ee5
--- /dev/null
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved.
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ */
+
+#ifndef __ETHPORT_DEFS_H__
+#define __ETHPORT_DEFS_H__
+
+struct bnad_drv_stats {
+       u64 netif_queue_stop;
+       u64 netif_queue_wakeup;
+       u64 tso4;
+       u64 tso6;
+       u64 tso_err;
+       u64 tcpcsum_offload;
+       u64 udpcsum_offload;
+       u64 csum_help;
+       u64 csum_help_err;
+
+       u64 hw_stats_updates;
+       u64 netif_rx_schedule;
+       u64 netif_rx_complete;
+       u64 netif_rx_dropped;
+};
+#endif
diff --git a/drivers/scsi/bfa/include/cna/pstats/phyport_defs.h b/drivers/scsi/bfa/include/cna/pstats/phyport_defs.h
new file mode 100644 (file)
index 0000000..eb75480
--- /dev/null
@@ -0,0 +1,218 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved.
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ */
+
+#ifndef __PHYPORT_DEFS_H__
+#define __PHYPORT_DEFS_H__
+
+#define BNA_TXF_ID_MAX         64
+#define BNA_RXF_ID_MAX         64
+
+/*
+ * Statistics
+ */
+
+/*
+ * TxF Frame Statistics
+ */
+struct bna_stats_txf {
+       u64        ucast_octets;
+       u64        ucast;
+       u64        ucast_vlan;
+
+       u64        mcast_octets;
+       u64        mcast;
+       u64        mcast_vlan;
+
+       u64        bcast_octets;
+       u64        bcast;
+       u64        bcast_vlan;
+
+       u64        errors;
+       u64        filter_vlan; /* frames filtered due to VLAN */
+       u64        filter_mac_sa;       /* frames filtered due to SA check */
+};
+
+/*
+ * RxF Frame Statistics
+ */
+struct bna_stats_rxf {
+       u64        ucast_octets;
+       u64        ucast;
+       u64        ucast_vlan;
+
+       u64        mcast_octets;
+       u64        mcast;
+       u64        mcast_vlan;
+
+       u64        bcast_octets;
+       u64        bcast;
+       u64        bcast_vlan;
+       u64        frame_drops;
+};
+
+/*
+ * FC Tx Frame Statistics
+ */
+struct bna_stats_fc_tx {
+       u64        txf_ucast_octets;
+       u64        txf_ucast;
+       u64        txf_ucast_vlan;
+
+       u64        txf_mcast_octets;
+       u64        txf_mcast;
+       u64        txf_mcast_vlan;
+
+       u64        txf_bcast_octets;
+       u64        txf_bcast;
+       u64        txf_bcast_vlan;
+
+       u64        txf_parity_errors;
+       u64        txf_timeout;
+       u64        txf_fid_parity_errors;
+};
+
+/*
+ * FC Rx Frame Statistics
+ */
+struct bna_stats_fc_rx {
+       u64        rxf_ucast_octets;
+       u64        rxf_ucast;
+       u64        rxf_ucast_vlan;
+
+       u64        rxf_mcast_octets;
+       u64        rxf_mcast;
+       u64        rxf_mcast_vlan;
+
+       u64        rxf_bcast_octets;
+       u64        rxf_bcast;
+       u64        rxf_bcast_vlan;
+};
+
+/*
+ * RAD Frame Statistics
+ */
+struct cna_stats_rad {
+       u64        rx_frames;
+       u64        rx_octets;
+       u64        rx_vlan_frames;
+
+       u64        rx_ucast;
+       u64        rx_ucast_octets;
+       u64        rx_ucast_vlan;
+
+       u64        rx_mcast;
+       u64        rx_mcast_octets;
+       u64        rx_mcast_vlan;
+
+       u64        rx_bcast;
+       u64        rx_bcast_octets;
+       u64        rx_bcast_vlan;
+
+       u64        rx_drops;
+};
+
+/*
+ * BPC Tx Registers
+ */
+struct cna_stats_bpc_tx {
+       u64        tx_pause[8];
+       u64        tx_zero_pause[8];    /*  Pause cancellation */
+       u64        tx_first_pause[8];   /*  Pause initiation rather
+                                                *than retention */
+};
+
+/*
+ * BPC Rx Registers
+ */
+struct cna_stats_bpc_rx {
+       u64        rx_pause[8];
+       u64        rx_zero_pause[8];    /*  Pause cancellation */
+       u64        rx_first_pause[8];   /*  Pause initiation rather
+                                                *than retention */
+};
+
+/*
+ * MAC Rx Statistics
+ */
+struct cna_stats_mac_rx {
+       u64        frame_64;    /* both rx and tx counter */
+       u64        frame_65_127;        /* both rx and tx counter */
+       u64        frame_128_255;       /* both rx and tx counter */
+       u64        frame_256_511;       /* both rx and tx counter */
+       u64        frame_512_1023;      /* both rx and tx counter */
+       u64        frame_1024_1518;     /* both rx and tx counter */
+       u64        frame_1518_1522;     /* both rx and tx counter */
+       u64        rx_bytes;
+       u64        rx_packets;
+       u64        rx_fcs_error;
+       u64        rx_multicast;
+       u64        rx_broadcast;
+       u64        rx_control_frames;
+       u64        rx_pause;
+       u64        rx_unknown_opcode;
+       u64        rx_alignment_error;
+       u64        rx_frame_length_error;
+       u64        rx_code_error;
+       u64        rx_carrier_sense_error;
+       u64        rx_undersize;
+       u64        rx_oversize;
+       u64        rx_fragments;
+       u64        rx_jabber;
+       u64        rx_drop;
+};
+
+/*
+ * MAC Tx Statistics
+ */
+struct cna_stats_mac_tx {
+       u64        tx_bytes;
+       u64        tx_packets;
+       u64        tx_multicast;
+       u64        tx_broadcast;
+       u64        tx_pause;
+       u64        tx_deferral;
+       u64        tx_excessive_deferral;
+       u64        tx_single_collision;
+       u64        tx_muliple_collision;
+       u64        tx_late_collision;
+       u64        tx_excessive_collision;
+       u64        tx_total_collision;
+       u64        tx_pause_honored;
+       u64        tx_drop;
+       u64        tx_jabber;
+       u64        tx_fcs_error;
+       u64        tx_control_frame;
+       u64        tx_oversize;
+       u64        tx_undersize;
+       u64        tx_fragments;
+};
+
+/*
+ * Complete statistics
+ */
+struct bna_stats {
+       struct cna_stats_mac_rx mac_rx_stats;
+       struct cna_stats_bpc_rx bpc_rx_stats;
+       struct cna_stats_rad rad_stats;
+       struct bna_stats_fc_rx fc_rx_stats;
+       struct cna_stats_mac_tx mac_tx_stats;
+       struct cna_stats_bpc_tx bpc_tx_stats;
+       struct bna_stats_fc_tx fc_tx_stats;
+       struct bna_stats_rxf rxf_stats[BNA_TXF_ID_MAX];
+       struct bna_stats_txf txf_stats[BNA_RXF_ID_MAX];
+};
+
+#endif
diff --git a/drivers/scsi/bfa/include/cs/bfa_checksum.h b/drivers/scsi/bfa/include/cs/bfa_checksum.h
new file mode 100644 (file)
index 0000000..af8c1d5
--- /dev/null
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) 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.
+ */
+
+/**
+ *  bfa_checksum.h BFA checksum utilities
+ */
+
+#ifndef __BFA_CHECKSUM_H__
+#define __BFA_CHECKSUM_H__
+
+static inline u32
+bfa_checksum_u32(u32 *buf, int sz)
+{
+       int             i, m = sz >> 2;
+       u32     sum = 0;
+
+       for (i = 0; i < m; i++)
+               sum ^= buf[i];
+
+       return (sum);
+}
+
+static inline u16
+bfa_checksum_u16(u16 *buf, int sz)
+{
+       int             i, m = sz >> 1;
+       u16        sum = 0;
+
+       for (i = 0; i < m; i++)
+               sum ^= buf[i];
+
+       return (sum);
+}
+
+static inline u8
+bfa_checksum_u8(u8 *buf, int sz)
+{
+       int             i;
+       u8         sum = 0;
+
+       for (i = 0; i < sz; i++)
+               sum ^= buf[i];
+
+       return (sum);
+}
+#endif
diff --git a/drivers/scsi/bfa/include/cs/bfa_debug.h b/drivers/scsi/bfa/include/cs/bfa_debug.h
new file mode 100644 (file)
index 0000000..441be86
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) 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.
+ */
+
+/**
+ *  bfa_debug.h BFA debug interfaces
+ */
+
+#ifndef __BFA_DEBUG_H__
+#define __BFA_DEBUG_H__
+
+#define bfa_assert(__cond)     do {                                    \
+       if (!(__cond))                                                  \
+               bfa_panic(__LINE__, __FILE__, #__cond);      \
+} while (0)
+
+#define bfa_sm_fault(__mod, __event)   do {                            \
+       bfa_sm_panic((__mod)->logm, __LINE__, __FILE__, __event);      \
+} while (0)
+
+#ifndef BFA_PERF_BUILD
+#define bfa_assert_fp(__cond)  bfa_assert(__cond)
+#else
+#define bfa_assert_fp(__cond)
+#endif
+
+struct bfa_log_mod_s;
+void bfa_panic(int line, char *file, char *panicstr);
+void bfa_sm_panic(struct bfa_log_mod_s *logm, int line, char *file, int event);
+
+#endif /* __BFA_DEBUG_H__ */
diff --git a/drivers/scsi/bfa/include/cs/bfa_log.h b/drivers/scsi/bfa/include/cs/bfa_log.h
new file mode 100644 (file)
index 0000000..761cbe2
--- /dev/null
@@ -0,0 +1,184 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) 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.
+ */
+
+/**
+ *  bfa_log.h BFA log library data structure and function definition
+ */
+
+#ifndef __BFA_LOG_H__
+#define __BFA_LOG_H__
+
+#include <bfa_os_inc.h>
+#include <defs/bfa_defs_status.h>
+#include <defs/bfa_defs_aen.h>
+
+/*
+ * BFA log module definition
+ *
+ * To create a new module id:
+ * Add a #define at the end of the list below. Select a value for your
+ * definition so that it is one (1) greater than the previous
+ * definition. Modify the definition of BFA_LOG_MODULE_ID_MAX to become
+ * your new definition.
+ * Should have no gaps in between the values because this is used in arrays.
+ * IMPORTANT: AEN_IDs must be at the begining, otherwise update bfa_defs_aen.h
+ */
+
+enum bfa_log_module_id {
+       BFA_LOG_UNUSED_ID       = 0,
+
+       /* AEN defs begin */
+       BFA_LOG_AEN_MIN         = BFA_LOG_UNUSED_ID,
+
+       BFA_LOG_AEN_ID_ADAPTER  = BFA_LOG_AEN_MIN + BFA_AEN_CAT_ADAPTER,/* 1 */
+       BFA_LOG_AEN_ID_PORT     = BFA_LOG_AEN_MIN + BFA_AEN_CAT_PORT,   /* 2 */
+       BFA_LOG_AEN_ID_LPORT    = BFA_LOG_AEN_MIN + BFA_AEN_CAT_LPORT,  /* 3 */
+       BFA_LOG_AEN_ID_RPORT    = BFA_LOG_AEN_MIN + BFA_AEN_CAT_RPORT,  /* 4 */
+       BFA_LOG_AEN_ID_ITNIM    = BFA_LOG_AEN_MIN + BFA_AEN_CAT_ITNIM,  /* 5 */
+       BFA_LOG_AEN_ID_TIN      = BFA_LOG_AEN_MIN + BFA_AEN_CAT_TIN,    /* 6 */
+       BFA_LOG_AEN_ID_IPFC     = BFA_LOG_AEN_MIN + BFA_AEN_CAT_IPFC,   /* 7 */
+       BFA_LOG_AEN_ID_AUDIT    = BFA_LOG_AEN_MIN + BFA_AEN_CAT_AUDIT,  /* 8 */
+       BFA_LOG_AEN_ID_IOC      = BFA_LOG_AEN_MIN + BFA_AEN_CAT_IOC,    /* 9 */
+       BFA_LOG_AEN_ID_ETHPORT  = BFA_LOG_AEN_MIN + BFA_AEN_CAT_ETHPORT,/* 10 */
+
+       BFA_LOG_AEN_MAX         = BFA_LOG_AEN_ID_ETHPORT,
+       /* AEN defs end */
+
+       BFA_LOG_MODULE_ID_MIN   = BFA_LOG_AEN_MAX,
+
+       BFA_LOG_FW_ID           = BFA_LOG_MODULE_ID_MIN + 1,
+       BFA_LOG_HAL_ID          = BFA_LOG_MODULE_ID_MIN + 2,
+       BFA_LOG_FCS_ID          = BFA_LOG_MODULE_ID_MIN + 3,
+       BFA_LOG_WDRV_ID         = BFA_LOG_MODULE_ID_MIN + 4,
+       BFA_LOG_LINUX_ID        = BFA_LOG_MODULE_ID_MIN + 5,
+       BFA_LOG_SOLARIS_ID      = BFA_LOG_MODULE_ID_MIN + 6,
+
+       BFA_LOG_MODULE_ID_MAX   = BFA_LOG_SOLARIS_ID,
+
+       /* Not part of any arrays */
+       BFA_LOG_MODULE_ID_ALL   = BFA_LOG_MODULE_ID_MAX + 1,
+       BFA_LOG_AEN_ALL         = BFA_LOG_MODULE_ID_MAX + 2,
+       BFA_LOG_DRV_ALL         = BFA_LOG_MODULE_ID_MAX + 3,
+};
+
+/*
+ * BFA log catalog name
+ */
+#define BFA_LOG_CAT_NAME       "BFA"
+
+/*
+ * bfa log severity values
+ */
+enum bfa_log_severity {
+       BFA_LOG_INVALID = 0,
+       BFA_LOG_CRITICAL = 1,
+       BFA_LOG_ERROR = 2,
+       BFA_LOG_WARNING = 3,
+       BFA_LOG_INFO = 4,
+       BFA_LOG_NONE = 5,
+       BFA_LOG_LEVEL_MAX = BFA_LOG_NONE
+};
+
+#define BFA_LOG_MODID_OFFSET           16
+
+
+struct bfa_log_msgdef_s {
+       u32     msg_id;         /*  message id */
+       int             attributes;     /*  attributes */
+       int             severity;       /*  severity level */
+       char            *msg_value;
+                                       /*  msg string */
+       char            *message;
+                                       /*  msg format string */
+       int             arg_type;       /*  argument type */
+       int             arg_num;        /*  number of argument */
+};
+
+/*
+ * supported argument type
+ */
+enum bfa_log_arg_type {
+       BFA_LOG_S = 0,          /*  string */
+       BFA_LOG_D,              /*  decimal */
+       BFA_LOG_I,              /*  integer */
+       BFA_LOG_O,              /*  oct number */
+       BFA_LOG_U,              /*  unsigned integer */
+       BFA_LOG_X,              /*  hex number */
+       BFA_LOG_F,              /*  floating */
+       BFA_LOG_C,              /*  character */
+       BFA_LOG_L,              /*  double */
+       BFA_LOG_P               /*  pointer */
+};
+
+#define BFA_LOG_ARG_TYPE       2
+#define BFA_LOG_ARG0           (0 * BFA_LOG_ARG_TYPE)
+#define BFA_LOG_ARG1           (1 * BFA_LOG_ARG_TYPE)
+#define BFA_LOG_ARG2           (2 * BFA_LOG_ARG_TYPE)
+#define BFA_LOG_ARG3           (3 * BFA_LOG_ARG_TYPE)
+
+#define BFA_LOG_GET_MOD_ID(msgid) ((msgid >> BFA_LOG_MODID_OFFSET) & 0xff)
+#define BFA_LOG_GET_MSG_IDX(msgid) (msgid & 0xffff)
+#define BFA_LOG_GET_MSG_ID(msgdef) ((msgdef)->msg_id)
+#define BFA_LOG_GET_MSG_FMT_STRING(msgdef) ((msgdef)->message)
+#define BFA_LOG_GET_SEVERITY(msgdef) ((msgdef)->severity)
+
+/*
+ * Event attributes
+ */
+#define BFA_LOG_ATTR_NONE      0
+#define BFA_LOG_ATTR_AUDIT     1
+#define BFA_LOG_ATTR_LOG       2
+#define BFA_LOG_ATTR_FFDC      4
+
+#define BFA_LOG_CREATE_ID(msw, lsw) \
+       (((u32)msw << BFA_LOG_MODID_OFFSET) | lsw)
+
+struct bfa_log_mod_s;
+
+/**
+ * callback function
+ */
+typedef void (*bfa_log_cb_t)(struct bfa_log_mod_s *log_mod, u32 msg_id,
+                       const char *format, ...);
+
+
+struct bfa_log_mod_s {
+       char            instance_info[16];      /*  instance info */
+       int             log_level[BFA_LOG_MODULE_ID_MAX + 1];
+                                               /*  log level for modules */
+       bfa_log_cb_t    cbfn;                   /*  callback function */
+};
+
+extern int bfa_log_init(struct bfa_log_mod_s *log_mod,
+                       char *instance_name, bfa_log_cb_t cbfn);
+extern int bfa_log(struct bfa_log_mod_s *log_mod, u32 msg_id, ...);
+extern bfa_status_t bfa_log_set_level(struct bfa_log_mod_s *log_mod,
+                       int mod_id, enum bfa_log_severity log_level);
+extern bfa_status_t bfa_log_set_level_all(struct bfa_log_mod_s *log_mod,
+                       enum bfa_log_severity log_level);
+extern bfa_status_t bfa_log_set_level_aen(struct bfa_log_mod_s *log_mod,
+                       enum bfa_log_severity log_level);
+extern enum bfa_log_severity bfa_log_get_level(struct bfa_log_mod_s *log_mod,
+                       int mod_id);
+extern enum bfa_log_severity bfa_log_get_msg_level(
+                       struct bfa_log_mod_s *log_mod, u32 msg_id);
+/*
+ * array of messages generated from xml files
+ */
+extern struct bfa_log_msgdef_s bfa_log_msg_array[];
+
+#endif
diff --git a/drivers/scsi/bfa/include/cs/bfa_perf.h b/drivers/scsi/bfa/include/cs/bfa_perf.h
new file mode 100644 (file)
index 0000000..45aa5f9
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ */
+#ifndef __BFAD_PERF_H__
+#define __BFAD_PERF_H__
+
+#ifdef BFAD_PERF_BUILD
+
+#undef bfa_trc
+#undef bfa_trc32
+#undef bfa_assert
+#undef BFA_TRC_FILE
+
+#define bfa_trc(_trcp, _data)
+#define bfa_trc32(_trcp, _data)
+#define bfa_assert(__cond)
+#define BFA_TRC_FILE(__mod, __submod)
+
+#endif
+
+#endif /* __BFAD_PERF_H__ */
diff --git a/drivers/scsi/bfa/include/cs/bfa_plog.h b/drivers/scsi/bfa/include/cs/bfa_plog.h
new file mode 100644 (file)
index 0000000..670f86e
--- /dev/null
@@ -0,0 +1,162 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ */
+#ifndef __BFA_PORTLOG_H__
+#define __BFA_PORTLOG_H__
+
+#include "protocol/fc.h"
+#include <defs/bfa_defs_types.h>
+
+#define BFA_PL_NLOG_ENTS 256
+#define BFA_PL_LOG_REC_INCR(_x) ((_x)++, (_x) %= BFA_PL_NLOG_ENTS)
+
+#define BFA_PL_STRING_LOG_SZ   32   /* number of chars in string log */
+#define BFA_PL_INT_LOG_SZ      8    /* number of integers in the integer log */
+
+enum bfa_plog_log_type {
+       BFA_PL_LOG_TYPE_INVALID = 0,
+       BFA_PL_LOG_TYPE_INT     = 1,
+       BFA_PL_LOG_TYPE_STRING  = 2,
+};
+
+/*
+ * the (fixed size) record format for each entry in the portlog
+ */
+struct bfa_plog_rec_s {
+       u32        tv;  /* Filled by the portlog driver when the *
+                                * entry is added to the circular log.   */
+       u8         port;        /* Source port that logged this entry. CM
+                                * entities will use 0xFF */
+       u8         mid; /* Integer value to be used by all entities *
+                                * while logging. The module id to string   *
+                                * conversion will be done by BFAL. See
+                                * enum bfa_plog_mid */
+       u8         eid; /* indicates Rx, Tx, IOCTL, etc. See
+                                * enum bfa_plog_eid */
+       u8         log_type; /* indicates string log or integer log.
+                                  * see bfa_plog_log_type_t */
+       u8         log_num_ints;
+       /*
+        * interpreted only if log_type is INT_LOG. indicates number of
+        * integers in the int_log[] (0-PL_INT_LOG_SZ).
+        */
+       u8         rsvd;
+       u16        misc;        /* can be used to indicate fc frame length,
+                                *etc.. */
+       union {
+               char            string_log[BFA_PL_STRING_LOG_SZ];
+               u32        int_log[BFA_PL_INT_LOG_SZ];
+       } log_entry;
+
+};
+
+/*
+ * the following #defines will be used by the logging entities to indicate
+ * their module id. BFAL will convert the integer value to string format
+ *
+* process to be used while changing the following #defines:
+ *  - Always add new entries at the end
+ *  - define corresponding string in BFAL
+ *  - Do not remove any entry or rearrange the order.
+ */
+enum bfa_plog_mid {
+       BFA_PL_MID_INVALID      = 0,
+       BFA_PL_MID_DEBUG        = 1,
+       BFA_PL_MID_DRVR         = 2,
+       BFA_PL_MID_HAL          = 3,
+       BFA_PL_MID_HAL_FCXP     = 4,
+       BFA_PL_MID_HAL_UF       = 5,
+       BFA_PL_MID_FCS          = 6,
+       BFA_PL_MID_MAX          = 7
+};
+
+#define BFA_PL_MID_STRLEN    8
+struct bfa_plog_mid_strings_s {
+       char            m_str[BFA_PL_MID_STRLEN];
+};
+
+/*
+ * the following #defines will be used by the logging entities to indicate
+ * their event type. BFAL will convert the integer value to string format
+ *
+* process to be used while changing the following #defines:
+ *  - Always add new entries at the end
+ *  - define corresponding string in BFAL
+ *  - Do not remove any entry or rearrange the order.
+ */
+enum bfa_plog_eid {
+       BFA_PL_EID_INVALID              = 0,
+       BFA_PL_EID_IOC_DISABLE          = 1,
+       BFA_PL_EID_IOC_ENABLE           = 2,
+       BFA_PL_EID_PORT_DISABLE         = 3,
+       BFA_PL_EID_PORT_ENABLE          = 4,
+       BFA_PL_EID_PORT_ST_CHANGE       = 5,
+       BFA_PL_EID_TX                   = 6,
+       BFA_PL_EID_TX_ACK1              = 7,
+       BFA_PL_EID_TX_RJT               = 8,
+       BFA_PL_EID_TX_BSY               = 9,
+       BFA_PL_EID_RX                   = 10,
+       BFA_PL_EID_RX_ACK1              = 11,
+       BFA_PL_EID_RX_RJT               = 12,
+       BFA_PL_EID_RX_BSY               = 13,
+       BFA_PL_EID_CT_IN                = 14,
+       BFA_PL_EID_CT_OUT               = 15,
+       BFA_PL_EID_DRIVER_START         = 16,
+       BFA_PL_EID_RSCN                 = 17,
+       BFA_PL_EID_DEBUG                = 18,
+       BFA_PL_EID_MISC                 = 19,
+       BFA_PL_EID_MAX                  = 20
+};
+
+#define BFA_PL_ENAME_STRLEN            8
+struct bfa_plog_eid_strings_s {
+       char            e_str[BFA_PL_ENAME_STRLEN];
+};
+
+#define BFA_PL_SIG_LEN 8
+#define BFA_PL_SIG_STR  "12pl123"
+
+/*
+ * per port circular log buffer
+ */
+struct bfa_plog_s {
+       char            plog_sig[BFA_PL_SIG_LEN];       /* Start signature */
+       u8         plog_enabled;
+       u8         rsvd[7];
+       u32        ticks;
+       u16        head;
+       u16        tail;
+       struct bfa_plog_rec_s  plog_recs[BFA_PL_NLOG_ENTS];
+};
+
+void bfa_plog_init(struct bfa_plog_s *plog);
+void bfa_plog_str(struct bfa_plog_s *plog, enum bfa_plog_mid mid,
+                       enum bfa_plog_eid event, u16 misc, char *log_str);
+void bfa_plog_intarr(struct bfa_plog_s *plog, enum bfa_plog_mid mid,
+                       enum bfa_plog_eid event, u16 misc,
+                       u32 *intarr, u32 num_ints);
+void bfa_plog_fchdr(struct bfa_plog_s *plog, enum bfa_plog_mid mid,
+                       enum bfa_plog_eid event, u16 misc,
+                       struct fchs_s *fchdr);
+void bfa_plog_fchdr_and_pl(struct bfa_plog_s *plog, enum bfa_plog_mid mid,
+                       enum bfa_plog_eid event, u16 misc,
+                       struct fchs_s *fchdr, u32 pld_w0);
+void bfa_plog_clear(struct bfa_plog_s *plog);
+void bfa_plog_enable(struct bfa_plog_s *plog);
+void bfa_plog_disable(struct bfa_plog_s *plog);
+bfa_boolean_t  bfa_plog_get_setting(struct bfa_plog_s *plog);
+
+#endif /* __BFA_PORTLOG_H__ */
diff --git a/drivers/scsi/bfa/include/cs/bfa_q.h b/drivers/scsi/bfa/include/cs/bfa_q.h
new file mode 100644 (file)
index 0000000..ea895fa
--- /dev/null
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) 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.
+ */
+
+/**
+ *  bfa_q.h Circular queue definitions.
+ */
+
+#ifndef __BFA_Q_H__
+#define __BFA_Q_H__
+
+#define bfa_q_first(_q) ((void *)(((struct list_head *) (_q))->next))
+#define bfa_q_next(_qe)        (((struct list_head *) (_qe))->next)
+#define bfa_q_prev(_qe) (((struct list_head *) (_qe))->prev)
+
+/*
+ * bfa_q_qe_init - to initialize a queue element
+ */
+#define bfa_q_qe_init(_qe) {                                           \
+       bfa_q_next(_qe) = (struct list_head *) NULL;                    \
+       bfa_q_prev(_qe) = (struct list_head *) NULL;                    \
+}
+
+/*
+ * bfa_q_deq - dequeue an element from head of the queue
+ */
+#define bfa_q_deq(_q, _qe) {                                           \
+       if (!list_empty(_q)) {                                  \
+               (*((struct list_head **) (_qe))) = bfa_q_next(_q);      \
+               bfa_q_prev(bfa_q_next(*((struct list_head **) _qe))) =  \
+                                               (struct list_head *) (_q); \
+               bfa_q_next(_q) = bfa_q_next(*((struct list_head **) _qe)); \
+               BFA_Q_DBG_INIT(*((struct list_head **) _qe));           \
+       } else {                                                        \
+               *((struct list_head **) (_qe)) = (struct list_head *) NULL; \
+       }                                                               \
+}
+
+/*
+ * bfa_q_deq_tail - dequeue an element from tail of the queue
+ */
+#define bfa_q_deq_tail(_q, _qe) {                                          \
+       if (!list_empty(_q)) {                                              \
+               *((struct list_head **) (_qe)) = bfa_q_prev(_q);            \
+               bfa_q_next(bfa_q_prev(*((struct list_head **) _qe))) =      \
+                                               (struct list_head *) (_q);  \
+               bfa_q_prev(_q) = bfa_q_prev(*(struct list_head **) _qe);    \
+               BFA_Q_DBG_INIT(*((struct list_head **) _qe));               \
+       } else {                                                            \
+               *((struct list_head **) (_qe)) = (struct list_head *) NULL; \
+       }                                                                   \
+}
+
+/*
+ * #ifdef BFA_DEBUG (Using bfa_assert to check for debug_build is not
+ * consistent across modules)
+ */
+#ifndef BFA_PERF_BUILD
+#define BFA_Q_DBG_INIT(_qe)    bfa_q_qe_init(_qe)
+#else
+#define BFA_Q_DBG_INIT(_qe)
+#endif
+
+#define bfa_q_is_on_q(_q, _qe)         \
+       bfa_q_is_on_q_func(_q, (struct list_head *)(_qe))
+extern int bfa_q_is_on_q_func(struct list_head *q, struct list_head *qe);
+
+#endif
diff --git a/drivers/scsi/bfa/include/cs/bfa_sm.h b/drivers/scsi/bfa/include/cs/bfa_sm.h
new file mode 100644 (file)
index 0000000..9877066
--- /dev/null
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) 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.
+ */
+
+/**
+ *  bfasm.h State machine defines
+ */
+
+#ifndef __BFA_SM_H__
+#define __BFA_SM_H__
+
+typedef void (*bfa_sm_t)(void *sm, int event);
+
+#define bfa_sm_set_state(_sm, _state)  (_sm)->sm = (bfa_sm_t)(_state)
+#define bfa_sm_send_event(_sm, _event) (_sm)->sm((_sm), (_event))
+#define bfa_sm_get_state(_sm)          ((_sm)->sm)
+#define bfa_sm_cmp_state(_sm, _state)  ((_sm)->sm == (bfa_sm_t)(_state))
+
+/**
+ * For converting from state machine function to state encoding.
+ */
+struct bfa_sm_table_s {
+       bfa_sm_t        sm;     /*  state machine function      */
+       int             state;  /*  state machine encoding      */
+       char            *name;  /*  state name for display      */
+};
+#define BFA_SM(_sm)    ((bfa_sm_t)(_sm))
+
+int bfa_sm_to_state(struct bfa_sm_table_s *smt, bfa_sm_t sm);
+
+/**
+ * State machine with entry actions.
+ */
+typedef void (*bfa_fsm_t)(void *fsm, int event);
+
+/**
+ * oc - object class eg. bfa_ioc
+ * st - state, eg. reset
+ * otype - object type, eg. struct bfa_ioc_s
+ * etype - object type, eg. enum ioc_event
+ */
+#define bfa_fsm_state_decl(oc, st, otype, etype)               \
+       static void oc ## _sm_ ## st(otype * fsm, etype event);      \
+       static void oc ## _sm_ ## st ## _entry(otype * fsm)
+
+#define bfa_fsm_set_state(_fsm, _state) do {   \
+       (_fsm)->fsm = (bfa_fsm_t)(_state);      \
+       _state ## _entry(_fsm);      \
+} while (0)
+
+#define bfa_fsm_send_event(_fsm, _event)       \
+       (_fsm)->fsm((_fsm), (_event))
+#define bfa_fsm_cmp_state(_fsm, _state)                \
+       ((_fsm)->fsm == (bfa_fsm_t)(_state))
+
+#endif
diff --git a/drivers/scsi/bfa/include/cs/bfa_trc.h b/drivers/scsi/bfa/include/cs/bfa_trc.h
new file mode 100644 (file)
index 0000000..3e74392
--- /dev/null
@@ -0,0 +1,176 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ */
+#ifndef __BFA_TRC_H__
+#define __BFA_TRC_H__
+
+#include <bfa_os_inc.h>
+
+#ifndef BFA_TRC_MAX
+#define BFA_TRC_MAX    (4 * 1024)
+#endif
+
+#ifndef BFA_TRC_TS
+#define BFA_TRC_TS(_trcm)      ((_trcm)->ticks ++)
+#endif
+
+struct bfa_trc_s {
+#ifdef __BIGENDIAN
+       u16     fileno;
+       u16     line;
+#else
+       u16     line;
+       u16     fileno;
+#endif
+       u32     timestamp;
+       union {
+               struct {
+                       u32     rsvd;
+                       u32     u32;
+               } u32;
+               u64     u64;
+       } data;
+};
+
+
+struct bfa_trc_mod_s {
+       u32     head;
+       u32     tail;
+       u32     ntrc;
+       u32     stopped;
+       u32     ticks;
+       u32     rsvd[3];
+       struct bfa_trc_s trc[BFA_TRC_MAX];
+};
+
+
+enum {
+       BFA_TRC_FW   = 1,       /*  firmware modules */
+       BFA_TRC_HAL  = 2,       /*  BFA modules */
+       BFA_TRC_FCS  = 3,       /*  BFA FCS modules */
+       BFA_TRC_LDRV = 4,       /*  Linux driver modules */
+       BFA_TRC_SDRV = 5,       /*  Solaris driver modules */
+       BFA_TRC_VDRV = 6,       /*  vmware driver modules */
+       BFA_TRC_WDRV = 7,       /*  windows driver modules */
+       BFA_TRC_AEN  = 8,       /*  AEN module */
+       BFA_TRC_BIOS = 9,       /*  bios driver modules */
+       BFA_TRC_EFI  = 10,      /*  EFI driver modules */
+       BNA_TRC_WDRV = 11,      /*  BNA windows driver modules */
+       BNA_TRC_VDRV = 12,      /*  BNA vmware driver modules */
+       BNA_TRC_SDRV = 13,      /*  BNA Solaris driver modules */
+       BNA_TRC_LDRV = 14,      /*  BNA Linux driver modules */
+       BNA_TRC_HAL  = 15,      /*  BNA modules */
+       BFA_TRC_CNA  = 16,      /*  Common modules */
+       BNA_TRC_IMDRV = 17      /*  BNA windows intermediate driver modules */
+};
+#define BFA_TRC_MOD_SH 10
+#define BFA_TRC_MOD(__mod)     ((BFA_TRC_ ## __mod) << BFA_TRC_MOD_SH)
+
+/**
+ * Define a new tracing file (module). Module should match one defined above.
+ */
+#define BFA_TRC_FILE(__mod, __submod)                                  \
+       static int __trc_fileno = ((BFA_TRC_ ## __mod ## _ ## __submod) | \
+                                                BFA_TRC_MOD(__mod))
+
+
+#define bfa_trc32(_trcp, _data)        \
+       __bfa_trc((_trcp)->trcmod, __trc_fileno, __LINE__, (u32)_data)
+
+
+#ifndef BFA_BOOT_BUILD
+#define bfa_trc(_trcp, _data)  \
+       __bfa_trc((_trcp)->trcmod, __trc_fileno, __LINE__, (u64)_data)
+#else
+void bfa_boot_trc(struct bfa_trc_mod_s *trcmod, u16 fileno,
+                       u16 line, u32 data);
+#define bfa_trc(_trcp, _data)  \
+       bfa_boot_trc((_trcp)->trcmod, __trc_fileno, __LINE__, (u32)_data)
+#endif
+
+
+static inline void
+bfa_trc_init(struct bfa_trc_mod_s *trcm)
+{
+       trcm->head = trcm->tail = trcm->stopped = 0;
+       trcm->ntrc = BFA_TRC_MAX;
+}
+
+
+static inline void
+bfa_trc_stop(struct bfa_trc_mod_s *trcm)
+{
+       trcm->stopped = 1;
+}
+
+#ifdef FWTRC
+extern void dc_flush(void *data);
+#else
+#define dc_flush(data)
+#endif
+
+
+static inline void
+__bfa_trc(struct bfa_trc_mod_s *trcm, int fileno, int line, u64 data)
+{
+       int             tail = trcm->tail;
+       struct bfa_trc_s        *trc = &trcm->trc[tail];
+
+       if (trcm->stopped)
+               return;
+
+       trc->fileno = (u16) fileno;
+       trc->line = (u16) line;
+       trc->data.u64 = data;
+       trc->timestamp = BFA_TRC_TS(trcm);
+       dc_flush(trc);
+
+       trcm->tail = (trcm->tail + 1) & (BFA_TRC_MAX - 1);
+       if (trcm->tail == trcm->head)
+               trcm->head = (trcm->head + 1) & (BFA_TRC_MAX - 1);
+       dc_flush(trcm);
+}
+
+
+static inline void
+__bfa_trc32(struct bfa_trc_mod_s *trcm, int fileno, int line, u32 data)
+{
+       int             tail = trcm->tail;
+       struct bfa_trc_s *trc = &trcm->trc[tail];
+
+       if (trcm->stopped)
+               return;
+
+       trc->fileno = (u16) fileno;
+       trc->line = (u16) line;
+       trc->data.u32.u32 = data;
+       trc->timestamp = BFA_TRC_TS(trcm);
+       dc_flush(trc);
+
+       trcm->tail = (trcm->tail + 1) & (BFA_TRC_MAX - 1);
+       if (trcm->tail == trcm->head)
+               trcm->head = (trcm->head + 1) & (BFA_TRC_MAX - 1);
+       dc_flush(trcm);
+}
+
+#ifndef BFA_PERF_BUILD
+#define bfa_trc_fp(_trcp, _data)       bfa_trc(_trcp, _data)
+#else
+#define bfa_trc_fp(_trcp, _data)
+#endif
+
+#endif /* __BFA_TRC_H__ */
+
diff --git a/drivers/scsi/bfa/include/cs/bfa_wc.h b/drivers/scsi/bfa/include/cs/bfa_wc.h
new file mode 100644 (file)
index 0000000..0460bd4
--- /dev/null
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) 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.
+ */
+
+/**
+ *  bfa_wc.h Generic wait counter.
+ */
+
+#ifndef __BFA_WC_H__
+#define __BFA_WC_H__
+
+typedef void (*bfa_wc_resume_t) (void *cbarg);
+
+struct bfa_wc_s {
+       bfa_wc_resume_t wc_resume;
+       void            *wc_cbarg;
+       int             wc_count;
+};
+
+static inline void
+bfa_wc_up(struct bfa_wc_s *wc)
+{
+       wc->wc_count++;
+}
+
+static inline void
+bfa_wc_down(struct bfa_wc_s *wc)
+{
+       wc->wc_count--;
+       if (wc->wc_count == 0)
+               wc->wc_resume(wc->wc_cbarg);
+}
+
+/**
+ * Initialize a waiting counter.
+ */
+static inline void
+bfa_wc_init(struct bfa_wc_s *wc, bfa_wc_resume_t wc_resume, void *wc_cbarg)
+{
+       wc->wc_resume = wc_resume;
+       wc->wc_cbarg = wc_cbarg;
+       wc->wc_count = 0;
+       bfa_wc_up(wc);
+}
+
+/**
+ * Wait for counter to reach zero
+ */
+static inline void
+bfa_wc_wait(struct bfa_wc_s *wc)
+{
+       bfa_wc_down(wc);
+}
+
+#endif
diff --git a/drivers/scsi/bfa/include/defs/bfa_defs_adapter.h b/drivers/scsi/bfa/include/defs/bfa_defs_adapter.h
new file mode 100644 (file)
index 0000000..8c208fc
--- /dev/null
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ */
+#ifndef __BFA_DEFS_ADAPTER_H__
+#define __BFA_DEFS_ADAPTER_H__
+
+#include <protocol/types.h>
+#include <defs/bfa_defs_version.h>
+#include <defs/bfa_defs_mfg.h>
+
+/**
+ * BFA adapter level attributes.
+ */
+enum {
+       BFA_ADAPTER_SERIAL_NUM_LEN = STRSZ(BFA_MFG_SERIALNUM_SIZE),
+                                       /*
+                                        *!< adapter serial num length
+                                        */
+       BFA_ADAPTER_MODEL_NAME_LEN  = 16,  /*  model name length */
+       BFA_ADAPTER_MODEL_DESCR_LEN = 128, /*  model description length */
+       BFA_ADAPTER_MFG_NAME_LEN    = 8,   /*  manufacturer name length */
+       BFA_ADAPTER_SYM_NAME_LEN    = 64,  /*  adapter symbolic name length */
+       BFA_ADAPTER_OS_TYPE_LEN     = 64,  /*  adapter os type length */
+};
+
+struct bfa_adapter_attr_s {
+       char            manufacturer[BFA_ADAPTER_MFG_NAME_LEN];
+       char            serial_num[BFA_ADAPTER_SERIAL_NUM_LEN];
+       u32     rsvd1;
+       char            model[BFA_ADAPTER_MODEL_NAME_LEN];
+       char            model_descr[BFA_ADAPTER_MODEL_DESCR_LEN];
+       wwn_t           pwwn;
+       char            node_symname[FC_SYMNAME_MAX];
+       char            hw_ver[BFA_VERSION_LEN];
+       char            fw_ver[BFA_VERSION_LEN];
+       char            optrom_ver[BFA_VERSION_LEN];
+       char            os_type[BFA_ADAPTER_OS_TYPE_LEN];
+       struct bfa_mfg_vpd_s    vpd;
+       struct mac_s    mac;
+
+       u8              nports;
+       u8              max_speed;
+       u8              prototype;
+       char            asic_rev;
+
+       u8         pcie_gen;
+       u8         pcie_lanes_orig;
+       u8         pcie_lanes;
+       u8              cna_capable;
+};
+
+/**
+ * BFA adapter level events
+ * Arguments below are in BFAL context from Mgmt
+ * BFA_PORT_AEN_ADD:        [in]: None     [out]: serial_num, pwwn, nports
+ * BFA_PORT_AEN_REMOVE:     [in]: pwwn     [out]: serial_num, pwwn, nports
+ */
+enum bfa_adapter_aen_event {
+       BFA_ADAPTER_AEN_ADD     = 1,    /*  New Adapter found event */
+       BFA_ADAPTER_AEN_REMOVE  = 2,    /*  Adapter removed event */
+};
+
+struct bfa_adapter_aen_data_s {
+       char            serial_num[BFA_ADAPTER_SERIAL_NUM_LEN];
+       u32        nports;      /*  Number of NPorts */
+       wwn_t           pwwn;   /*  WWN of one of its physical port */
+};
+
+#endif /* __BFA_DEFS_ADAPTER_H__ */
diff --git a/drivers/scsi/bfa/include/defs/bfa_defs_aen.h b/drivers/scsi/bfa/include/defs/bfa_defs_aen.h
new file mode 100644 (file)
index 0000000..4c81a61
--- /dev/null
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ */
+
+#ifndef __BFA_DEFS_AEN_H__
+#define __BFA_DEFS_AEN_H__
+
+#include <defs/bfa_defs_types.h>
+#include <defs/bfa_defs_ioc.h>
+#include <defs/bfa_defs_adapter.h>
+#include <defs/bfa_defs_port.h>
+#include <defs/bfa_defs_lport.h>
+#include <defs/bfa_defs_rport.h>
+#include <defs/bfa_defs_itnim.h>
+#include <defs/bfa_defs_tin.h>
+#include <defs/bfa_defs_ipfc.h>
+#include <defs/bfa_defs_audit.h>
+#include <defs/bfa_defs_ethport.h>
+
+enum bfa_aen_category {
+       BFA_AEN_CAT_ADAPTER     = 1,
+       BFA_AEN_CAT_PORT        = 2,
+       BFA_AEN_CAT_LPORT       = 3,
+       BFA_AEN_CAT_RPORT       = 4,
+       BFA_AEN_CAT_ITNIM       = 5,
+       BFA_AEN_CAT_TIN         = 6,
+       BFA_AEN_CAT_IPFC        = 7,
+       BFA_AEN_CAT_AUDIT       = 8,
+       BFA_AEN_CAT_IOC         = 9,
+       BFA_AEN_CAT_ETHPORT     = 10,
+       BFA_AEN_MAX_CAT         = 10
+};
+
+#pragma pack(1)
+union bfa_aen_data_u {
+       struct bfa_adapter_aen_data_s   adapter;
+       struct bfa_port_aen_data_s      port;
+       struct bfa_lport_aen_data_s     lport;
+       struct bfa_rport_aen_data_s     rport;
+       struct bfa_itnim_aen_data_s     itnim;
+       struct bfa_audit_aen_data_s     audit;
+       struct bfa_ioc_aen_data_s       ioc;
+       struct bfa_ethport_aen_data_s   ethport;
+};
+
+struct bfa_aen_entry_s {
+       enum bfa_aen_category   aen_category;
+       int                     aen_type;
+       union bfa_aen_data_u    aen_data;
+       struct bfa_timeval_s    aen_tv;
+       s32             seq_num;
+       s32             bfad_num;
+       s32             rsvd[1];
+};
+
+#pragma pack()
+
+#define bfa_aen_event_t int
+
+#endif /* __BFA_DEFS_AEN_H__ */
diff --git a/drivers/scsi/bfa/include/defs/bfa_defs_audit.h b/drivers/scsi/bfa/include/defs/bfa_defs_audit.h
new file mode 100644 (file)
index 0000000..8e3a962
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ */
+
+#ifndef __BFA_DEFS_AUDIT_H__
+#define __BFA_DEFS_AUDIT_H__
+
+#include <bfa_os_inc.h>
+
+/**
+ * BFA audit events
+ */
+enum bfa_audit_aen_event {
+       BFA_AUDIT_AEN_AUTH_ENABLE       = 1,
+       BFA_AUDIT_AEN_AUTH_DISABLE      = 2,
+};
+
+/**
+ * audit event data
+ */
+struct bfa_audit_aen_data_s {
+       wwn_t           pwwn;
+};
+
+#endif /* __BFA_DEFS_AUDIT_H__ */
diff --git a/drivers/scsi/bfa/include/defs/bfa_defs_auth.h b/drivers/scsi/bfa/include/defs/bfa_defs_auth.h
new file mode 100644 (file)
index 0000000..dd19c83
--- /dev/null
@@ -0,0 +1,112 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ */
+#ifndef __BFA_DEFS_AUTH_H__
+#define __BFA_DEFS_AUTH_H__
+
+#include <defs/bfa_defs_types.h>
+
+#define PUBLIC_KEY                     15409
+#define PRIVATE_KEY                    19009
+#define KEY_LEN                                32399
+#define BFA_AUTH_SECRET_STRING_LEN     256
+#define BFA_AUTH_FAIL_TIMEOUT          0xFF
+
+/**
+ * Authentication status
+ */
+enum bfa_auth_status {
+       BFA_AUTH_STATUS_NONE    = 0,    /*  no authentication */
+       BFA_AUTH_UNINIT         = 1,    /*  state - uninit */
+       BFA_AUTH_NEG_SEND       = 2,    /*  state - negotiate send */
+       BFA_AUTH_CHAL_WAIT      = 3,    /*  state - challenge wait */
+       BFA_AUTH_NEG_RETRY      = 4,    /*  state - negotiate retry */
+       BFA_AUTH_REPLY_SEND     = 5,    /*  state - reply send */
+       BFA_AUTH_STATUS_WAIT    = 6,    /*  state - status wait */
+       BFA_AUTH_SUCCESS        = 7,    /*  state - success */
+       BFA_AUTH_FAILED         = 8,    /*  state - failed */
+       BFA_AUTH_STATUS_UNKNOWN = 9,    /*  authentication status unknown */
+};
+
+struct auth_proto_stats_s {
+       u32        auth_rjts;
+       u32        auth_negs;
+       u32        auth_dones;
+
+       u32        dhchap_challenges;
+       u32        dhchap_replies;
+       u32        dhchap_successes;
+};
+
+/**
+ * Authentication related statistics
+ */
+struct bfa_auth_stats_s {
+       u32           auth_failures;    /*  authentication failures */
+       u32           auth_successes;   /*  authentication successes*/
+       struct auth_proto_stats_s auth_rx_stats; /*  Rx protocol stats */
+       struct auth_proto_stats_s auth_tx_stats; /*  Tx protocol stats */
+};
+
+/**
+ * Authentication hash function algorithms
+ */
+enum bfa_auth_algo {
+       BFA_AUTH_ALGO_MD5       = 1,    /*  Message-Digest algorithm 5 */
+       BFA_AUTH_ALGO_SHA1      = 2,    /*  Secure Hash Algorithm 1 */
+       BFA_AUTH_ALGO_MS        = 3,    /*  MD5, then SHA-1 */
+       BFA_AUTH_ALGO_SM        = 4,    /*  SHA-1, then MD5 */
+};
+
+/**
+ * DH Groups
+ *
+ * Current value could be combination of one or more of the following values
+ */
+enum bfa_auth_group {
+       BFA_AUTH_GROUP_DHNULL   = 0,    /*  DH NULL (value == 0) */
+       BFA_AUTH_GROUP_DH768    = 1,    /*  DH group 768 (value == 1) */
+       BFA_AUTH_GROUP_DH1024   = 2,    /*  DH group 1024 (value == 2) */
+       BFA_AUTH_GROUP_DH1280   = 4,    /*  DH group 1280 (value == 3) */
+       BFA_AUTH_GROUP_DH1536   = 8,    /*  DH group 1536 (value == 4) */
+
+       BFA_AUTH_GROUP_ALL      = 256   /*  Use default DH group order
+                                        *    0, 1, 2, 3, 4 */
+};
+
+/**
+ * Authentication secret sources
+ */
+enum bfa_auth_secretsource {
+       BFA_AUTH_SECSRC_LOCAL   = 1,    /*  locally configured */
+       BFA_AUTH_SECSRC_RADIUS  = 2,    /*  use radius server */
+       BFA_AUTH_SECSRC_TACACS  = 3,    /*  TACACS server */
+};
+
+/**
+ * Authentication attributes
+ */
+struct bfa_auth_attr_s {
+       enum bfa_auth_status    status;
+       enum bfa_auth_algo      algo;
+       enum bfa_auth_group     dh_grp;
+       u16             rjt_code;
+       u16             rjt_code_exp;
+       u8                      secret_set;
+       u8                      resv[7];
+};
+
+#endif /* __BFA_DEFS_AUTH_H__ */
diff --git a/drivers/scsi/bfa/include/defs/bfa_defs_boot.h b/drivers/scsi/bfa/include/defs/bfa_defs_boot.h
new file mode 100644 (file)
index 0000000..6f4aa52
--- /dev/null
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ */
+
+#ifndef __BFA_DEFS_BOOT_H__
+#define __BFA_DEFS_BOOT_H__
+
+#include <protocol/types.h>
+#include <defs/bfa_defs_types.h>
+#include <defs/bfa_defs_pport.h>
+
+enum {
+       BFA_BOOT_BOOTLUN_MAX = 4,       /*  maximum boot lun per IOC */
+};
+
+#define BOOT_CFG_REV1  1
+
+/**
+ *      Boot options setting. Boot options setting determines from where
+ *      to get the boot lun information
+ */
+enum bfa_boot_bootopt {
+    BFA_BOOT_AUTO_DISCOVER = 0,    /*  Boot from blun provided by fabric */
+    BFA_BOOT_STORED_BLUN   = 1,    /*  Boot from bluns stored in flash   */
+    BFA_BOOT_FIRST_LUN     = 2,    /*  Boot from first discovered blun   */
+};
+
+/**
+ * Boot lun information.
+ */
+struct bfa_boot_bootlun_s {
+       wwn_t           pwwn;   /*  port wwn of target */
+       lun_t           lun;    /*  64-bit lun */
+};
+
+/**
+ * BOOT boot configuraton
+ */
+struct bfa_boot_cfg_s {
+       u8         version;
+       u8         rsvd1;
+       u16        chksum;
+
+       u8         enable;              /*  enable/disable SAN boot */
+       u8         speed;               /*  boot speed settings */
+       u8         topology;    /*  boot topology setting */
+       u8         bootopt;     /*  bfa_boot_bootopt_t */
+
+       u32        nbluns;              /*  number of boot luns */
+
+       u32        rsvd2;
+
+       struct bfa_boot_bootlun_s blun[BFA_BOOT_BOOTLUN_MAX];
+       struct bfa_boot_bootlun_s blun_disc[BFA_BOOT_BOOTLUN_MAX];
+};
+
+
+#endif /* __BFA_DEFS_BOOT_H__ */
diff --git a/drivers/scsi/bfa/include/defs/bfa_defs_cee.h b/drivers/scsi/bfa/include/defs/bfa_defs_cee.h
new file mode 100644 (file)
index 0000000..520a22f
--- /dev/null
@@ -0,0 +1,159 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ *  bfa_defs_cee.h Interface declarations between host based
+ *     BFAL and DCBX/LLDP module in Firmware
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ */
+#ifndef __BFA_DEFS_CEE_H__
+#define __BFA_DEFS_CEE_H__
+
+#include <defs/bfa_defs_types.h>
+#include <defs/bfa_defs_pport.h>
+#include <protocol/types.h>
+
+#pragma pack(1)
+
+#define BFA_CEE_LLDP_MAX_STRING_LEN (128)
+
+
+/* FIXME: this is coming from the protocol spec. Can the host & apps share the
+   protocol .h files ?
+ */
+#define BFA_CEE_LLDP_SYS_CAP_OTHER       0x0001
+#define BFA_CEE_LLDP_SYS_CAP_REPEATER    0x0002
+#define BFA_CEE_LLDP_SYS_CAP_MAC_BRIDGE  0x0004
+#define BFA_CEE_LLDP_SYS_CAP_WLAN_AP     0x0008
+#define BFA_CEE_LLDP_SYS_CAP_ROUTER      0x0010
+#define BFA_CEE_LLDP_SYS_CAP_TELEPHONE          0x0020
+#define BFA_CEE_LLDP_SYS_CAP_DOCSIS_CD   0x0040
+#define BFA_CEE_LLDP_SYS_CAP_STATION     0x0080
+#define BFA_CEE_LLDP_SYS_CAP_CVLAN          0x0100
+#define BFA_CEE_LLDP_SYS_CAP_SVLAN          0x0200
+#define BFA_CEE_LLDP_SYS_CAP_TPMR               0x0400
+
+
+/* LLDP string type */
+struct bfa_cee_lldp_str_s {
+       u8 sub_type;
+       u8 len;
+       u8 rsvd[2];
+       u8 value[BFA_CEE_LLDP_MAX_STRING_LEN];
+};
+
+
+/* LLDP paramters */
+struct bfa_cee_lldp_cfg_s {
+       struct bfa_cee_lldp_str_s chassis_id;
+       struct bfa_cee_lldp_str_s port_id;
+       struct bfa_cee_lldp_str_s port_desc;
+       struct bfa_cee_lldp_str_s sys_name;
+       struct bfa_cee_lldp_str_s sys_desc;
+       struct bfa_cee_lldp_str_s mgmt_addr;
+       u16    time_to_interval;
+       u16    enabled_system_cap;
+};
+
+enum bfa_cee_dcbx_version_e {
+       DCBX_PROTOCOL_PRECEE = 1,
+       DCBX_PROTOCOL_CEE    = 2,
+};
+
+enum bfa_cee_lls_e {
+       CEE_LLS_DOWN_NO_TLV = 0, /* LLS is down because the TLV not sent by
+                                 * the peer */
+       CEE_LLS_DOWN        = 1, /* LLS is down as advertised by the peer */
+       CEE_LLS_UP          = 2,
+};
+
+/* CEE/DCBX parameters */
+struct bfa_cee_dcbx_cfg_s {
+       u8 pgid[8];
+       u8 pg_percentage[8];
+       u8 pfc_enabled;          /* bitmap of priorties with PFC enabled */
+       u8 fcoe_user_priority;   /* bitmap of priorities used for FcoE
+                                      * traffic */
+       u8 dcbx_version;        /* operating version:CEE or preCEE */
+       u8 lls_fcoe;    /* FCoE Logical Link Status */
+       u8 lls_lan;     /* LAN Logical Link Status */
+       u8 rsvd[3];
+};
+
+/* CEE status */
+/* Making this to tri-state for the benefit of port list command */
+enum bfa_cee_status_e {
+    CEE_PHY_DOWN = 0,
+    CEE_PHY_UP = 1,
+    CEE_UP = 2,
+};
+
+/* CEE Query */
+struct bfa_cee_attr_s {
+       u8                   cee_status;
+       u8                   error_reason;
+       struct bfa_cee_lldp_cfg_s lldp_remote;
+       struct bfa_cee_dcbx_cfg_s dcbx_remote;
+       mac_t src_mac;
+       u8 link_speed;
+       u8 filler[3];
+};
+
+
+
+
+/* LLDP/DCBX/CEE Statistics */
+
+struct bfa_cee_lldp_stats_s {
+       u32 frames_transmitted;
+       u32 frames_aged_out;
+       u32 frames_discarded;
+       u32 frames_in_error;
+       u32 frames_rcvd;
+       u32 tlvs_discarded;
+       u32 tlvs_unrecognized;
+};
+
+struct bfa_cee_dcbx_stats_s {
+       u32 subtlvs_unrecognized;
+       u32 negotiation_failed;
+       u32 remote_cfg_changed;
+       u32 tlvs_received;
+       u32 tlvs_invalid;
+       u32 seqno;
+       u32 ackno;
+       u32 recvd_seqno;
+       u32 recvd_ackno;
+};
+
+struct bfa_cee_cfg_stats_s {
+       u32 cee_status_down;
+       u32 cee_status_up;
+       u32 cee_hw_cfg_changed;
+       u32 recvd_invalid_cfg;
+};
+
+
+struct bfa_cee_stats_s {
+       struct bfa_cee_lldp_stats_s lldp_stats;
+       struct bfa_cee_dcbx_stats_s dcbx_stats;
+       struct bfa_cee_cfg_stats_s  cfg_stats;
+};
+
+#pragma pack()
+
+
+#endif /* __BFA_DEFS_CEE_H__ */
+
+
diff --git a/drivers/scsi/bfa/include/defs/bfa_defs_driver.h b/drivers/scsi/bfa/include/defs/bfa_defs_driver.h
new file mode 100644 (file)
index 0000000..5704980
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ */
+
+#ifndef __BFA_DEFS_DRIVER_H__
+#define __BFA_DEFS_DRIVER_H__
+
+/**
+ * Driver statistics
+ */
+       u16    tm_io_abort;
+    u16    tm_io_abort_comp;
+    u16    tm_lun_reset;
+    u16    tm_lun_reset_comp;
+    u16    tm_target_reset;
+    u16    tm_bus_reset;
+    u16    ioc_restart;        /*  IOC restart count */
+    u16    io_pending;         /*  outstanding io count per-IOC */
+    u64    control_req;
+    u64    input_req;
+    u64    output_req;
+    u64    input_words;
+    u64    output_words;
+} bfa_driver_stats_t;
+
+
+#endif /* __BFA_DEFS_DRIVER_H__ */
diff --git a/drivers/scsi/bfa/include/defs/bfa_defs_ethport.h b/drivers/scsi/bfa/include/defs/bfa_defs_ethport.h
new file mode 100644 (file)
index 0000000..79f9b3e
--- /dev/null
@@ -0,0 +1,98 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ */
+
+#ifndef __BFA_DEFS_ETHPORT_H__
+#define __BFA_DEFS_ETHPORT_H__
+
+#include <defs/bfa_defs_status.h>
+#include <protocol/types.h>
+#include <cna/pstats/phyport_defs.h>
+#include <cna/pstats/ethport_defs.h>
+
+struct bna_tx_info_s {
+       u32    miniport_state;
+       u32    adapter_state;
+       u64    tx_count;
+       u64    tx_wi;
+       u64    tx_sg;
+       u64    tx_tcp_chksum;
+       u64    tx_udp_chksum;
+       u64    tx_ip_chksum;
+       u64    tx_lsov1;
+       u64    tx_lsov2;
+       u64    tx_max_sg_len ;
+};
+
+struct bna_rx_queue_info_s {
+       u16    q_id ;
+       u16    buf_size ;
+       u16    buf_count ;
+       u16    rsvd ;
+       u64    rx_count ;
+       u64    rx_dropped ;
+       u64    rx_unsupported ;
+       u64    rx_internal_err ;
+       u64    rss_count ;
+       u64    vlan_count ;
+       u64    rx_tcp_chksum ;
+       u64    rx_udp_chksum ;
+       u64    rx_ip_chksum ;
+       u64    rx_hds ;
+};
+
+struct bna_rx_q_set_s {
+       u16    q_set_type;
+       u32    miniport_state;
+       u32    adapter_state;
+       struct bna_rx_queue_info_s    rx_queue[2];
+};
+
+struct bna_port_stats_s {
+       struct bna_tx_info_s   tx_stats;
+       u16        qset_count ;
+       struct bna_rx_q_set_s  rx_qset[8];
+};
+
+struct bfa_ethport_stats_s {
+       struct bna_stats_txf    txf_stats[1];
+       struct bna_stats_rxf    rxf_stats[1];
+       struct bnad_drv_stats drv_stats;
+};
+
+/**
+ * Ethernet port events
+ * Arguments below are in BFAL context from Mgmt
+ * BFA_PORT_AEN_ETH_LINKUP:    [in]: mac [out]: mac
+ * BFA_PORT_AEN_ETH_LINKDOWN:  [in]: mac [out]: mac
+ * BFA_PORT_AEN_ETH_ENABLE:  [in]: mac [out]: mac
+ * BFA_PORT_AEN_ETH_DISABLE:  [in]: mac [out]: mac
+ *
+ */
+enum bfa_ethport_aen_event {
+       BFA_ETHPORT_AEN_LINKUP = 1, /*  Base Port Ethernet link up event */
+       BFA_ETHPORT_AEN_LINKDOWN = 2, /*  Base Port Ethernet link down event */
+       BFA_ETHPORT_AEN_ENABLE = 3, /*  Base Port Ethernet link enable event */
+       BFA_ETHPORT_AEN_DISABLE = 4, /*  Base Port Ethernet link disable
+                                     * event */
+};
+
+struct bfa_ethport_aen_data_s {
+       mac_t mac;      /*  MAC address of the physical port */
+};
+
+
+#endif /* __BFA_DEFS_ETHPORT_H__ */
diff --git a/drivers/scsi/bfa/include/defs/bfa_defs_fcpim.h b/drivers/scsi/bfa/include/defs/bfa_defs_fcpim.h
new file mode 100644 (file)
index 0000000..c08f4f5
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ */
+#ifndef __BFA_DEFS_FCPIM_H__
+#define __BFA_DEFS_FCPIM_H__
+
+struct bfa_fcpim_stats_s {
+       u32        total_ios;   /*  Total IO count */
+       u32        qresumes;    /*  IO waiting for CQ space */
+       u32        no_iotags;   /*  NO IO contexts */
+       u32        io_aborts;   /*  IO abort requests */
+       u32        no_tskims;   /*  NO task management contexts */
+       u32        iocomp_ok;   /*  IO completions with OK status */
+       u32        iocomp_underrun;     /*  IO underrun (good) */
+       u32        iocomp_overrun;      /*  IO overrun (good) */
+       u32        iocomp_aborted;      /*  Aborted IO requests */
+       u32        iocomp_timedout;     /*  IO timeouts */
+       u32        iocom_nexus_abort;   /*  IO selection timeouts */
+       u32        iocom_proto_err;     /*  IO protocol errors */
+       u32        iocom_dif_err;       /*  IO SBC-3 protection errors */
+       u32        iocom_tm_abort;      /*  IO aborted by TM requests */
+       u32        iocom_sqer_needed;   /*  IO retry for SQ error
+                                                *recovery */
+       u32        iocom_res_free;      /*  Delayed freeing of IO resources */
+       u32        iocomp_scsierr;      /*  IO with non-good SCSI status */
+       u32        iocom_hostabrts;     /*  Host IO abort requests */
+       u32        iocom_utags; /*  IO comp with unknown tags */
+       u32        io_cleanups; /*  IO implicitly aborted */
+       u32        io_tmaborts; /*  IO aborted due to TM commands */
+       u32        rsvd;
+};
+#endif /*__BFA_DEFS_FCPIM_H__*/
diff --git a/drivers/scsi/bfa/include/defs/bfa_defs_im_common.h b/drivers/scsi/bfa/include/defs/bfa_defs_im_common.h
new file mode 100644 (file)
index 0000000..9ccf53b
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ */
+
+#ifndef __BFA_DEFS_IM_COMMON_H__
+#define __BFA_DEFS_IM_COMMON_H__
+
+#define        BFA_ADAPTER_NAME_LEN    256
+#define BFA_ADAPTER_GUID_LEN    256
+#define RESERVED_VLAN_NAME      L"PORT VLAN"
+#define PASSTHRU_VLAN_NAME      L"PASSTHRU VLAN"
+
+       u64     tx_pkt_cnt;
+       u64     rx_pkt_cnt;
+       u32     duration;
+       u8              status;
+} bfa_im_stats_t, *pbfa_im_stats_t;
+
+#endif /* __BFA_DEFS_IM_COMMON_H__ */
diff --git a/drivers/scsi/bfa/include/defs/bfa_defs_im_team.h b/drivers/scsi/bfa/include/defs/bfa_defs_im_team.h
new file mode 100644 (file)
index 0000000..a486a7e
--- /dev/null
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ */
+
+#ifndef __BFA_DEFS_IM_TEAM_H__
+#define __BFA_DEFS_IM_TEAM_H__
+
+#include <protocol/types.h>
+
+#define        BFA_TEAM_MAX_PORTS      8
+#define        BFA_TEAM_NAME_LEN       256
+#define BFA_MAX_NUM_TEAMS      16
+#define BFA_TEAM_INVALID_DELAY -1
+
+       BFA_LACP_RATE_SLOW = 1,
+       BFA_LACP_RATE_FAST
+} bfa_im_lacp_rate_t;
+
+       BFA_TEAM_MODE_FAIL_OVER = 1,
+       BFA_TEAM_MODE_FAIL_BACK,
+       BFA_TEAM_MODE_LACP,
+       BFA_TEAM_MODE_NONE
+} bfa_im_team_mode_t;
+
+       BFA_XMIT_POLICY_L2 = 1,
+       BFA_XMIT_POLICY_L3_L4
+} bfa_im_xmit_policy_t;
+
+       bfa_im_team_mode_t     team_mode;
+       bfa_im_lacp_rate_t     lacp_rate;
+       bfa_im_xmit_policy_t   xmit_policy;
+       int               delay;
+       wchar_t           primary[BFA_ADAPTER_NAME_LEN];
+       wchar_t           preferred_primary[BFA_ADAPTER_NAME_LEN];
+       mac_t             mac;
+       u16               num_ports;
+       u16          num_vlans;
+       u16 vlan_list[BFA_MAX_VLANS_PER_PORT];
+       wchar_t  team_guid_list[BFA_TEAM_MAX_PORTS][BFA_ADAPTER_GUID_LEN];
+       wchar_t  ioc_name_list[BFA_TEAM_MAX_PORTS][BFA_ADAPTER_NAME_LEN];
+} bfa_im_team_attr_t;
+
+       wchar_t                      team_name[BFA_TEAM_NAME_LEN];
+       bfa_im_xmit_policy_t     xmit_policy;
+       int                      delay;
+       wchar_t                  primary[BFA_ADAPTER_NAME_LEN];
+       wchar_t                  preferred_primary[BFA_ADAPTER_NAME_LEN];
+} bfa_im_team_edit_t, *pbfa_im_team_edit_t;
+
+       wchar_t                                 team_name[BFA_TEAM_NAME_LEN];
+       bfa_im_team_mode_t      team_mode;
+       mac_t                   mac;
+} bfa_im_team_info_t;
+
+       bfa_im_team_info_t              team_info[BFA_MAX_NUM_TEAMS];
+       u16                             num_teams;
+} bfa_im_team_list_t, *pbfa_im_team_list_t;
+
+#endif /* __BFA_DEFS_IM_TEAM_H__ */
diff --git a/drivers/scsi/bfa/include/defs/bfa_defs_ioc.h b/drivers/scsi/bfa/include/defs/bfa_defs_ioc.h
new file mode 100644 (file)
index 0000000..b1d532d
--- /dev/null
@@ -0,0 +1,152 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ */
+
+#ifndef __BFA_DEFS_IOC_H__
+#define __BFA_DEFS_IOC_H__
+
+#include <protocol/types.h>
+#include <defs/bfa_defs_types.h>
+#include <defs/bfa_defs_version.h>
+#include <defs/bfa_defs_adapter.h>
+#include <defs/bfa_defs_pm.h>
+
+enum {
+       BFA_IOC_DRIVER_LEN      = 16,
+       BFA_IOC_CHIP_REV_LEN    = 8,
+};
+
+/**
+ * Driver and firmware versions.
+ */
+struct bfa_ioc_driver_attr_s {
+       char            driver[BFA_IOC_DRIVER_LEN];     /*  driver name */
+       char            driver_ver[BFA_VERSION_LEN];    /*  driver version */
+       char            fw_ver[BFA_VERSION_LEN];        /*  firmware version*/
+       char            bios_ver[BFA_VERSION_LEN];      /*  bios version */
+       char            efi_ver[BFA_VERSION_LEN];       /*  EFI version */
+       char            ob_ver[BFA_VERSION_LEN];        /*  openboot version*/
+};
+
+/**
+ * IOC PCI device attributes
+ */
+struct bfa_ioc_pci_attr_s {
+       u16        vendor_id;   /*  PCI vendor ID */
+       u16        device_id;   /*  PCI device ID */
+       u16        ssid;                /*  subsystem ID */
+       u16        ssvid;               /*  subsystem vendor ID */
+       u32        pcifn;               /*  PCI device function */
+       u32        rsvd;                /* padding */
+       u8         chip_rev[BFA_IOC_CHIP_REV_LEN];       /*  chip revision */
+};
+
+/**
+ * IOC states
+ */
+enum bfa_ioc_state {
+       BFA_IOC_RESET       = 1,  /*  IOC is in reset state */
+       BFA_IOC_SEMWAIT     = 2,  /*  Waiting for IOC hardware semaphore */
+       BFA_IOC_HWINIT      = 3,  /*  IOC hardware is being initialized */
+       BFA_IOC_GETATTR     = 4,  /*  IOC is being configured */
+       BFA_IOC_OPERATIONAL = 5,  /*  IOC is operational */
+       BFA_IOC_INITFAIL    = 6,  /*  IOC hardware failure */
+       BFA_IOC_HBFAIL      = 7,  /*  IOC heart-beat failure */
+       BFA_IOC_DISABLING   = 8,  /*  IOC is being disabled */
+       BFA_IOC_DISABLED    = 9,  /*  IOC is disabled */
+       BFA_IOC_FWMISMATCH  = 10, /*  IOC firmware different from drivers */
+};
+
+/**
+ * IOC firmware stats
+ */
+struct bfa_fw_ioc_stats_s {
+       u32        hb_count;
+       u32        cfg_reqs;
+       u32        enable_reqs;
+       u32        disable_reqs;
+       u32        stats_reqs;
+       u32        clrstats_reqs;
+       u32        unknown_reqs;
+       u32        ic_reqs;             /*  interrupt coalesce reqs */
+};
+
+/**
+ * IOC driver stats
+ */
+struct bfa_ioc_drv_stats_s {
+       u32     ioc_isrs;
+       u32     ioc_enables;
+       u32     ioc_disables;
+       u32     ioc_hbfails;
+       u32     ioc_boots;
+       u32     stats_tmos;
+       u32        hb_count;
+       u32        disable_reqs;
+       u32        enable_reqs;
+       u32        disable_replies;
+       u32        enable_replies;
+};
+
+/**
+ * IOC statistics
+ */
+struct bfa_ioc_stats_s {
+       struct bfa_ioc_drv_stats_s      drv_stats; /*  driver IOC stats */
+       struct bfa_fw_ioc_stats_s       fw_stats;  /*  firmware IOC stats */
+};
+
+
+enum bfa_ioc_type_e {
+       BFA_IOC_TYPE_FC   = 1,
+       BFA_IOC_TYPE_FCoE = 2,
+       BFA_IOC_TYPE_LL   = 3,
+};
+
+/**
+ * IOC attributes returned in queries
+ */
+struct bfa_ioc_attr_s {
+       enum bfa_ioc_type_e             ioc_type;
+       enum bfa_ioc_state              state;          /*  IOC state      */
+       struct bfa_adapter_attr_s       adapter_attr;   /*  HBA attributes */
+       struct bfa_ioc_driver_attr_s    driver_attr;    /*  driver attr    */
+       struct bfa_ioc_pci_attr_s       pci_attr;
+       u8                              port_id;        /*  port number    */
+};
+
+/**
+ * BFA IOC level events
+ */
+enum bfa_ioc_aen_event {
+       BFA_IOC_AEN_HBGOOD      = 1,    /*  Heart Beat restore event    */
+       BFA_IOC_AEN_HBFAIL      = 2,    /*  Heart Beat failure event    */
+       BFA_IOC_AEN_ENABLE      = 3,    /*  IOC enabled event           */
+       BFA_IOC_AEN_DISABLE     = 4,    /*  IOC disabled event          */
+       BFA_IOC_AEN_FWMISMATCH  = 5,    /*  IOC firmware mismatch       */
+};
+
+/**
+ * BFA IOC level event data, now just a place holder
+ */
+struct bfa_ioc_aen_data_s {
+       enum bfa_ioc_type_e ioc_type;
+       wwn_t   pwwn;
+       mac_t   mac;
+};
+
+#endif /* __BFA_DEFS_IOC_H__ */
+
diff --git a/drivers/scsi/bfa/include/defs/bfa_defs_iocfc.h b/drivers/scsi/bfa/include/defs/bfa_defs_iocfc.h
new file mode 100644 (file)
index 0000000..d76bcbd
--- /dev/null
@@ -0,0 +1,310 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ */
+
+#ifndef __BFA_DEFS_IOCFC_H__
+#define __BFA_DEFS_IOCFC_H__
+
+#include <protocol/types.h>
+#include <defs/bfa_defs_types.h>
+#include <defs/bfa_defs_version.h>
+#include <defs/bfa_defs_adapter.h>
+#include <defs/bfa_defs_pm.h>
+
+#define BFA_IOCFC_INTR_DELAY   1125
+#define BFA_IOCFC_INTR_LATENCY 225
+
+/**
+ * Interrupt coalescing configuration.
+ */
+struct bfa_iocfc_intr_attr_s {
+       bfa_boolean_t   coalesce;       /*  enable/disable coalescing */
+       u16     latency;        /*  latency in microseconds   */
+       u16     delay;          /*  delay in microseconds     */
+};
+
+/**
+ * IOC firmware configuraton
+ */
+struct bfa_iocfc_fwcfg_s {
+       u16        num_fabrics; /*  number of fabrics           */
+       u16        num_lports;  /*  number of local lports      */
+       u16        num_rports;  /*  number of remote ports      */
+       u16        num_ioim_reqs;       /*  number of IO reqs           */
+       u16        num_tskim_reqs;      /*  task management requests    */
+       u16        num_iotm_reqs;       /*  number of TM IO reqs        */
+       u16        num_tsktm_reqs;      /*  TM task management requests*/
+       u16        num_fcxp_reqs;       /*  unassisted FC exchanges     */
+       u16        num_uf_bufs; /*  unsolicited recv buffers    */
+       u8              num_cqs;
+       u8              rsvd;
+};
+
+struct bfa_iocfc_drvcfg_s {
+       u16        num_reqq_elems;      /*  number of req queue elements */
+       u16        num_rspq_elems;      /*  number of rsp queue elements */
+       u16        num_sgpgs;   /*  number of total SG pages      */
+       u16        num_sboot_tgts;      /*  number of SAN boot targets    */
+       u16        num_sboot_luns;      /*  number of SAN boot luns       */
+       u16         ioc_recover;        /*  IOC recovery mode             */
+       u16         min_cfg;    /*  minimum configuration         */
+       u16        path_tov;    /*  device path timeout   */
+       bfa_boolean_t   delay_comp; /*  delay completion of
+                                                       failed inflight IOs */
+       u32             rsvd;
+};
+/**
+ * IOC configuration
+ */
+struct bfa_iocfc_cfg_s {
+       struct bfa_iocfc_fwcfg_s        fwcfg;  /*  firmware side config */
+       struct bfa_iocfc_drvcfg_s       drvcfg; /*  driver side config    */
+};
+
+/**
+ * IOC firmware IO stats
+ */
+struct bfa_fw_io_stats_s {
+       u32     host_abort;             /*  IO aborted by host driver*/
+       u32     host_cleanup;           /*  IO clean up by host driver */
+
+       u32     fw_io_timeout;          /*  IOs timedout */
+       u32     fw_frm_parse;           /*  frame parsed by f/w */
+       u32     fw_frm_data;            /*  fcp_data frame parsed by f/w */
+       u32     fw_frm_rsp;             /*  fcp_rsp frame parsed by f/w */
+       u32     fw_frm_xfer_rdy;        /*  xfer_rdy frame parsed by f/w */
+       u32     fw_frm_bls_acc;         /*  BLS ACC  frame parsed by f/w */
+       u32     fw_frm_tgt_abort;       /*  target ABTS parsed by f/w */
+       u32     fw_frm_unknown;         /*  unknown parsed by f/w */
+       u32     fw_data_dma;            /*  f/w DMA'ed the data frame */
+       u32     fw_frm_drop;            /*  f/w drop the frame */
+
+       u32     rec_timeout;            /*  FW rec timed out */
+       u32     error_rec;                      /*  FW sending rec on
+                                                       * an error condition*/
+       u32     wait_for_si;            /*  FW wait for SI */
+       u32     rec_rsp_inval;          /*  REC rsp invalid */
+       u32     seqr_io_abort;          /*  target does not know cmd so abort */
+       u32     seqr_io_retry;          /*  SEQR failed so retry IO */
+
+       u32     itn_cisc_upd_rsp;       /*  ITN cisc updated on fcp_rsp */
+       u32     itn_cisc_upd_data;      /*  ITN cisc updated on fcp_data */
+       u32     itn_cisc_upd_xfer_rdy;  /*  ITN cisc updated on fcp_data */
+
+       u32     fcp_data_lost;          /*  fcp data lost */
+
+       u32     ro_set_in_xfer_rdy;     /*  Target set RO in Xfer_rdy frame */
+       u32     xfer_rdy_ooo_err;       /*  Out of order Xfer_rdy received */
+       u32     xfer_rdy_unknown_err;   /*  unknown error in xfer_rdy frame */
+
+       u32     io_abort_timeout;       /*  ABTS timedout  */
+       u32     sler_initiated;         /*  SLER initiated */
+
+       u32     unexp_fcp_rsp;          /*  fcp response in wrong state */
+
+       u32     fcp_rsp_under_run;      /*  fcp rsp IO underrun */
+       u32        fcp_rsp_under_run_wr;   /*  fcp rsp IO underrun for write */
+       u32     fcp_rsp_under_run_err;  /*  fcp rsp IO underrun error */
+       u32        fcp_rsp_resid_inval;    /*  invalid residue */
+       u32     fcp_rsp_over_run;       /*  fcp rsp IO overrun */
+       u32     fcp_rsp_over_run_err;   /*  fcp rsp IO overrun error */
+       u32     fcp_rsp_proto_err;      /*  protocol error in fcp rsp */
+       u32     fcp_rsp_sense_err;      /*  error in sense info in fcp rsp */
+       u32     fcp_conf_req;           /*  FCP conf requested */
+
+       u32     tgt_aborted_io;         /*  target initiated abort */
+
+       u32     ioh_edtov_timeout_event;/*  IOH edtov timer popped */
+       u32     ioh_fcp_rsp_excp_event; /*  IOH FCP_RSP exception */
+       u32     ioh_fcp_conf_event;     /*  IOH FCP_CONF */
+       u32     ioh_mult_frm_rsp_event; /*  IOH multi_frame FCP_RSP */
+       u32     ioh_hit_class2_event;   /*  IOH hit class2 */
+       u32     ioh_miss_other_event;   /*  IOH miss other */
+       u32     ioh_seq_cnt_err_event;  /*  IOH seq cnt error */
+       u32     ioh_len_err_event;              /*  IOH len error - fcp_dl !=
+                                                       * bytes xfered */
+       u32     ioh_seq_len_err_event;  /*  IOH seq len error */
+       u32     ioh_data_oor_event;     /*  Data out of range */
+       u32     ioh_ro_ooo_event;       /*  Relative offset out of range */
+       u32     ioh_cpu_owned_event;    /*  IOH hit -iost owned by f/w */
+       u32     ioh_unexp_frame_event;  /*  unexpected frame recieved
+                                                *   count */
+       u32     ioh_err_int;            /*  IOH error int during data-phase
+                                                *   for scsi write
+                                                */
+};
+
+/**
+ * IOC port firmware stats
+ */
+
+struct bfa_fw_port_fpg_stats_s {
+    u32    intr_evt;
+    u32    intr;
+    u32    intr_excess;
+    u32    intr_cause0;
+    u32    intr_other;
+    u32    intr_other_ign;
+    u32    sig_lost;
+    u32    sig_regained;
+    u32    sync_lost;
+    u32    sync_to;
+    u32    sync_regained;
+    u32    div2_overflow;
+    u32    div2_underflow;
+    u32    efifo_overflow;
+    u32    efifo_underflow;
+    u32    idle_rx;
+    u32    lrr_rx;
+    u32    lr_rx;
+    u32    ols_rx;
+    u32    nos_rx;
+    u32    lip_rx;
+    u32    arbf0_rx;
+    u32    mrk_rx;
+    u32    const_mrk_rx;
+    u32    prim_unknown;
+    u32    rsvd;
+};
+
+
+struct bfa_fw_port_lksm_stats_s {
+    u32    hwsm_success;       /*  hwsm state machine success          */
+    u32    hwsm_fails;         /*  hwsm fails                          */
+    u32    hwsm_wdtov;         /*  hwsm timed out                      */
+    u32    swsm_success;       /*  swsm success                        */
+    u32    swsm_fails;         /*  swsm fails                          */
+    u32    swsm_wdtov;         /*  swsm timed out                      */
+    u32    busybufs;           /*  link init failed due to busybuf     */
+    u32    buf_waits;          /*  bufwait state entries               */
+    u32    link_fails;         /*  link failures                       */
+    u32    psp_errors;         /*  primitive sequence protocol errors  */
+    u32    lr_unexp;           /*  No. of times LR rx-ed unexpectedly  */
+    u32    lrr_unexp;          /*  No. of times LRR rx-ed unexpectedly */
+    u32    lr_tx;              /*  No. of times LR tx started          */
+    u32    lrr_tx;             /*  No. of times LRR tx started         */
+    u32    ols_tx;             /*  No. of times OLS tx started         */
+    u32    nos_tx;             /*  No. of times NOS tx started         */
+};
+
+
+struct bfa_fw_port_snsm_stats_s {
+    u32    hwsm_success;       /*  Successful hwsm terminations        */
+    u32    hwsm_fails;         /*  hwsm fail count                     */
+    u32    hwsm_wdtov;         /*  hwsm timed out                      */
+    u32    swsm_success;       /*  swsm success                        */
+    u32    swsm_wdtov;         /*  swsm timed out                      */
+    u32    error_resets;       /*  error resets initiated by upsm      */
+    u32    sync_lost;          /*  Sync loss count                     */
+    u32    sig_lost;           /*  Signal loss count                   */
+};
+
+
+struct bfa_fw_port_physm_stats_s {
+    u32    module_inserts;     /*  Module insert count                 */
+    u32    module_xtracts;     /*  Module extracts count               */
+    u32    module_invalids;    /*  Invalid module inserted count       */
+    u32    module_read_ign;    /*  Module validation status ignored    */
+    u32    laser_faults;       /*  Laser fault count                   */
+    u32    rsvd;
+};
+
+
+struct bfa_fw_fip_stats_s {
+    u32    disc_req;           /*  Discovery solicit requests          */
+    u32    disc_rsp;           /*  Discovery solicit response          */
+    u32    disc_err;           /*  Discovery advt. parse errors        */
+    u32    disc_unsol;         /*  Discovery unsolicited               */
+    u32    disc_timeouts;      /*  Discovery timeouts                  */
+    u32    linksvc_unsupp;     /*  Unsupported link service req        */
+    u32    linksvc_err;        /*  Parse error in link service req     */
+    u32    logo_req;           /*  Number of FIP logos received        */
+    u32    clrvlink_req;       /*  Clear virtual link req              */
+    u32    op_unsupp;          /*  Unsupported FIP operation           */
+    u32    untagged;           /*  Untagged frames (ignored)           */
+    u32    rsvd;
+};
+
+
+struct bfa_fw_lps_stats_s {
+    u32    mac_invalids;       /*  Invalid mac assigned                */
+    u32    rsvd;
+};
+
+
+struct bfa_fw_fcoe_stats_s {
+    u32    cee_linkups;        /*  CEE link up count                   */
+    u32    cee_linkdns;        /*  CEE link down count                 */
+    u32    fip_linkups;        /*  FIP link up count                   */
+    u32    fip_linkdns;        /*  FIP link up count                   */
+    u32    fip_fails;          /*  FIP fail count                      */
+    u32    mac_invalids;       /*  Invalid mac assigned                */
+};
+
+/**
+ * IOC firmware FCoE port stats
+ */
+struct bfa_fw_fcoe_port_stats_s {
+    struct bfa_fw_fcoe_stats_s  fcoe_stats;
+    struct bfa_fw_fip_stats_s   fip_stats;
+};
+
+/**
+ * IOC firmware FC port stats
+ */
+struct bfa_fw_fc_port_stats_s {
+       struct bfa_fw_port_fpg_stats_s          fpg_stats;
+       struct bfa_fw_port_physm_stats_s        physm_stats;
+       struct bfa_fw_port_snsm_stats_s         snsm_stats;
+       struct bfa_fw_port_lksm_stats_s         lksm_stats;
+};
+
+/**
+ * IOC firmware FC port stats
+ */
+union bfa_fw_port_stats_s {
+       struct bfa_fw_fc_port_stats_s   fc_stats;
+       struct bfa_fw_fcoe_port_stats_s fcoe_stats;
+};
+
+/**
+ * IOC firmware stats
+ */
+struct bfa_fw_stats_s {
+       struct bfa_fw_ioc_stats_s       ioc_stats;
+       struct bfa_fw_io_stats_s        io_stats;
+       union  bfa_fw_port_stats_s      port_stats;
+};
+
+/**
+ * IOC statistics
+ */
+struct bfa_iocfc_stats_s {
+       struct bfa_fw_stats_s   fw_stats;       /*  firmware IOC stats      */
+};
+
+/**
+ * IOC attributes returned in queries
+ */
+struct bfa_iocfc_attr_s {
+       struct bfa_iocfc_cfg_s          config;         /*  IOCFC config   */
+       struct bfa_iocfc_intr_attr_s    intr_attr;      /*  interrupt attr */
+};
+
+#define BFA_IOCFC_PATHTOV_MAX  60
+#define BFA_IOCFC_QDEPTH_MAX   2000
+
+#endif /* __BFA_DEFS_IOC_H__ */
diff --git a/drivers/scsi/bfa/include/defs/bfa_defs_ipfc.h b/drivers/scsi/bfa/include/defs/bfa_defs_ipfc.h
new file mode 100644 (file)
index 0000000..7cb63ea
--- /dev/null
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ */
+#ifndef __BFA_DEFS_IPFC_H__
+#define __BFA_DEFS_IPFC_H__
+
+#include <bfa_os_inc.h>
+#include <protocol/types.h>
+#include <defs/bfa_defs_types.h>
+
+/**
+ * FCS ip remote port states
+ */
+enum bfa_iprp_state {
+       BFA_IPRP_UNINIT  = 0,   /*  PORT is not yet initialized */
+       BFA_IPRP_ONLINE  = 1,   /*  process login is complete */
+       BFA_IPRP_OFFLINE = 2,   /*  iprp is offline */
+};
+
+/**
+ * FCS remote port statistics
+ */
+struct bfa_iprp_stats_s {
+       u32        offlines;
+       u32        onlines;
+       u32        rscns;
+       u32        plogis;
+       u32        logos;
+       u32        plogi_timeouts;
+       u32        plogi_rejects;
+};
+
+/**
+ * FCS iprp attribute returned in queries
+ */
+struct bfa_iprp_attr_s {
+       enum bfa_iprp_state state;
+};
+
+struct bfa_ipfc_stats_s {
+       u32 arp_sent;
+       u32 arp_recv;
+       u32 arp_reply_sent;
+       u32 arp_reply_recv;
+       u32 farp_sent;
+       u32 farp_recv;
+       u32 farp_reply_sent;
+       u32 farp_reply_recv;
+       u32 farp_reject_sent;
+       u32 farp_reject_recv;
+};
+
+struct bfa_ipfc_attr_s {
+       bfa_boolean_t enabled;
+};
+
+#endif /* __BFA_DEFS_IPFC_H__ */
diff --git a/drivers/scsi/bfa/include/defs/bfa_defs_itnim.h b/drivers/scsi/bfa/include/defs/bfa_defs_itnim.h
new file mode 100644 (file)
index 0000000..2ec7699
--- /dev/null
@@ -0,0 +1,126 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ */
+#ifndef __BFA_DEFS_ITNIM_H__
+#define __BFA_DEFS_ITNIM_H__
+
+#include <bfa_os_inc.h>
+#include <protocol/types.h>
+
+/**
+ * FCS itnim states
+ */
+enum bfa_itnim_state {
+       BFA_ITNIM_OFFLINE       = 0,    /*  offline */
+       BFA_ITNIM_PRLI_SEND     = 1,    /*  prli send */
+       BFA_ITNIM_PRLI_SENT     = 2,    /*  prli sent */
+       BFA_ITNIM_PRLI_RETRY    = 3,    /*  prli retry */
+       BFA_ITNIM_HCB_ONLINE    = 4,    /*  online callback */
+       BFA_ITNIM_ONLINE        = 5,    /*  online */
+       BFA_ITNIM_HCB_OFFLINE   = 6,    /*  offline callback */
+       BFA_ITNIM_INITIATIOR    = 7,    /*  initiator */
+};
+
+struct bfa_itnim_hal_stats_s {
+       u32     onlines;        /*  ITN nexus onlines (PRLI done) */
+       u32     offlines;       /*  ITN Nexus offlines  */
+       u32     creates;        /*  ITN create requests         */
+       u32     deletes;        /*  ITN delete requests         */
+       u32     create_comps;   /*  ITN create completions      */
+       u32     delete_comps;   /*  ITN delete completions      */
+       u32     sler_events;    /*  SLER (sequence level error
+                                        * recovery) events */
+       u32     ioc_disabled;   /*  Num IOC disables            */
+       u32     cleanup_comps;  /*  ITN cleanup completions */
+       u32     tm_cmnds;       /*  task management(TM) cmnds sent */
+       u32     tm_fw_rsps;     /*  TM cmds firmware responses */
+       u32     tm_success;     /*  TM successes */
+       u32     tm_failures;    /*  TM failures */
+       u32     tm_io_comps;    /*  TM IO completions */
+       u32     tm_qresumes;    /*  TM queue resumes (after waiting
+                                        * for resources)
+                                        */
+       u32     tm_iocdowns;    /*  TM cmnds affected by IOC down */
+       u32     tm_cleanups;    /*  TM cleanups */
+       u32     tm_cleanup_comps;
+                                       /*  TM cleanup completions */
+       u32     ios;            /*  IO requests */
+       u32     io_comps;       /*  IO completions */
+       u64     input_reqs;     /*  INPUT requests */
+       u64     output_reqs;    /*  OUTPUT requests */
+};
+
+/**
+ * FCS remote port statistics
+ */
+struct bfa_itnim_stats_s {
+       u32        onlines;     /*  num rport online */
+       u32        offlines;    /*  num rport offline */
+       u32        prli_sent;   /*  num prli sent out */
+       u32        fcxp_alloc_wait;/*  num fcxp alloc waits */
+       u32        prli_rsp_err;        /*  num prli rsp errors */
+       u32        prli_rsp_acc;        /*  num prli rsp accepts */
+       u32        initiator;   /*  rport is an initiator */
+       u32        prli_rsp_parse_err;  /*  prli rsp parsing errors */
+       u32        prli_rsp_rjt;        /*  num prli rsp rejects */
+       u32        timeout;     /*  num timeouts detected */
+       u32        sler;                /*  num sler notification from BFA */
+       u32     rsvd;
+       struct bfa_itnim_hal_stats_s    hal_stats;
+};
+
+/**
+ * FCS itnim attributes returned in queries
+ */
+struct bfa_itnim_attr_s {
+       enum bfa_itnim_state state; /*  FCS itnim state        */
+       u8 retry;               /*  data retransmision support */
+       u8      task_retry_id;  /*  task retry ident support   */
+       u8 rec_support;    /*  REC supported              */
+       u8 conf_comp;      /*  confirmed completion supp  */
+};
+
+/**
+ * BFA ITNIM events.
+ * Arguments below are in BFAL context from Mgmt
+ * BFA_ITNIM_AEN_NEW:       [in]: None  [out]: vf_id, lpwwn
+ * BFA_ITNIM_AEN_DELETE:    [in]: vf_id, lpwwn, rpwwn (0 = all fcp4 targets),
+ *                               [out]: vf_id, ppwwn, lpwwn, rpwwn
+ * BFA_ITNIM_AEN_ONLINE:    [in]: vf_id, lpwwn, rpwwn (0 = all fcp4 targets),
+ *                               [out]: vf_id, ppwwn, lpwwn, rpwwn
+ * BFA_ITNIM_AEN_OFFLINE:   [in]: vf_id, lpwwn, rpwwn (0 = all fcp4 targets),
+ *                               [out]: vf_id, ppwwn, lpwwn, rpwwn
+ * BFA_ITNIM_AEN_DISCONNECT:[in]: vf_id, lpwwn, rpwwn (0 = all fcp4 targets),
+ *                               [out]: vf_id, ppwwn, lpwwn, rpwwn
+ */
+enum bfa_itnim_aen_event {
+       BFA_ITNIM_AEN_ONLINE    = 1,    /*  Target online */
+       BFA_ITNIM_AEN_OFFLINE   = 2,    /*  Target offline */
+       BFA_ITNIM_AEN_DISCONNECT = 3,   /*  Target disconnected */
+};
+
+/**
+ * BFA ITNIM event data structure.
+ */
+struct bfa_itnim_aen_data_s {
+       u16        vf_id;       /*  vf_id of the IT nexus */
+       u16        rsvd[3];
+       wwn_t           ppwwn;  /*  WWN of its physical port */
+       wwn_t           lpwwn;  /*  WWN of logical port */
+       wwn_t           rpwwn;  /*  WWN of remote(target) port */
+};
+
+#endif /* __BFA_DEFS_ITNIM_H__ */
diff --git a/drivers/scsi/bfa/include/defs/bfa_defs_led.h b/drivers/scsi/bfa/include/defs/bfa_defs_led.h
new file mode 100644 (file)
index 0000000..6203927
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ */
+
+#ifndef __BFA_DEFS_LED_H__
+#define __BFA_DEFS_LED_H__
+
+#define        BFA_LED_MAX_NUM         3
+
+enum bfa_led_op {
+       BFA_LED_OFF   = 0,
+       BFA_LED_ON    = 1,
+       BFA_LED_FLICK = 2,
+       BFA_LED_BLINK = 3,
+};
+
+enum bfa_led_color {
+       BFA_LED_GREEN = 0,
+       BFA_LED_AMBER = 1,
+};
+
+#endif /* __BFA_DEFS_LED_H__ */
diff --git a/drivers/scsi/bfa/include/defs/bfa_defs_lport.h b/drivers/scsi/bfa/include/defs/bfa_defs_lport.h
new file mode 100644 (file)
index 0000000..7359f82
--- /dev/null
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ */
+
+#ifndef __BFA_DEFS_LPORT_H__
+#define __BFA_DEFS_LPORT_H__
+
+#include <defs/bfa_defs_types.h>
+#include <defs/bfa_defs_port.h>
+
+/**
+ * BFA AEN logical port events.
+ * Arguments below are in BFAL context from Mgmt
+ * BFA_LPORT_AEN_NEW:       [in]: None         [out]: vf_id, ppwwn, lpwwn, roles
+ * BFA_LPORT_AEN_DELETE:    [in]: lpwwn        [out]: vf_id, ppwwn. lpwwn, roles
+ * BFA_LPORT_AEN_ONLINE:    [in]: lpwwn        [out]: vf_id, ppwwn. lpwwn, roles
+ * BFA_LPORT_AEN_OFFLINE:   [in]: lpwwn        [out]: vf_id, ppwwn. lpwwn, roles
+ * BFA_LPORT_AEN_DISCONNECT:[in]: lpwwn        [out]: vf_id, ppwwn. lpwwn, roles
+ * BFA_LPORT_AEN_NEW_PROP:  [in]: None         [out]: vf_id, ppwwn. lpwwn, roles
+ * BFA_LPORT_AEN_DELETE_PROP:     [in]: lpwwn  [out]: vf_id, ppwwn. lpwwn, roles
+ * BFA_LPORT_AEN_NEW_STANDARD:    [in]: None   [out]: vf_id, ppwwn. lpwwn, roles
+ * BFA_LPORT_AEN_DELETE_STANDARD: [in]: lpwwn  [out]: vf_id, ppwwn. lpwwn, roles
+ * BFA_LPORT_AEN_NPIV_DUP_WWN:    [in]: lpwwn  [out]: vf_id, ppwwn. lpwwn, roles
+ * BFA_LPORT_AEN_NPIV_FABRIC_MAX: [in]: lpwwn  [out]: vf_id, ppwwn. lpwwn, roles
+ * BFA_LPORT_AEN_NPIV_UNKNOWN:    [in]: lpwwn  [out]: vf_id, ppwwn. lpwwn, roles
+ */
+enum bfa_lport_aen_event {
+       BFA_LPORT_AEN_NEW       = 1,    /*  LPort created event */
+       BFA_LPORT_AEN_DELETE    = 2,    /*  LPort deleted event */
+       BFA_LPORT_AEN_ONLINE    = 3,    /*  LPort online event */
+       BFA_LPORT_AEN_OFFLINE   = 4,    /*  LPort offline event */
+       BFA_LPORT_AEN_DISCONNECT = 5,   /*  LPort disconnect event */
+       BFA_LPORT_AEN_NEW_PROP  = 6,    /*  VPort created event */
+       BFA_LPORT_AEN_DELETE_PROP = 7,  /*  VPort deleted event */
+       BFA_LPORT_AEN_NEW_STANDARD = 8, /*  VPort created event */
+       BFA_LPORT_AEN_DELETE_STANDARD = 9,  /*  VPort deleted event */
+       BFA_LPORT_AEN_NPIV_DUP_WWN = 10,    /*  VPort configured with
+                                            *   duplicate WWN event
+                                                */
+       BFA_LPORT_AEN_NPIV_FABRIC_MAX = 11, /*  Max NPIV in fabric/fport */
+       BFA_LPORT_AEN_NPIV_UNKNOWN = 12, /*  Unknown NPIV Error code event */
+};
+
+/**
+ * BFA AEN event data structure
+ */
+struct bfa_lport_aen_data_s {
+       u16        vf_id;       /*  vf_id of this logical port */
+       u16        rsvd;
+       enum bfa_port_role roles;       /*  Logical port mode,IM/TM/IP etc */
+       wwn_t           ppwwn;  /*  WWN of its physical port */
+       wwn_t           lpwwn;  /*  WWN of this logical port */
+};
+
+#endif /* __BFA_DEFS_LPORT_H__ */
diff --git a/drivers/scsi/bfa/include/defs/bfa_defs_mfg.h b/drivers/scsi/bfa/include/defs/bfa_defs_mfg.h
new file mode 100644 (file)
index 0000000..13fd4ab
--- /dev/null
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ */
+#ifndef __BFA_DEFS_MFG_H__
+#define __BFA_DEFS_MFG_H__
+
+#include <bfa_os_inc.h>
+
+/**
+ * Manufacturing block version
+ */
+#define BFA_MFG_VERSION                                1
+
+/**
+ * Manufacturing block format
+ */
+#define BFA_MFG_SERIALNUM_SIZE                 11
+#define BFA_MFG_PARTNUM_SIZE                   14
+#define BFA_MFG_SUPPLIER_ID_SIZE               10
+#define BFA_MFG_SUPPLIER_PARTNUM_SIZE  20
+#define BFA_MFG_SUPPLIER_SERIALNUM_SIZE        20
+#define BFA_MFG_SUPPLIER_REVISION_SIZE 4
+#define STRSZ(_n)      (((_n) + 4) & ~3)
+
+/**
+ * VPD data length
+ */
+#define BFA_MFG_VPD_LEN     256
+
+/**
+ * All numerical fields are in big-endian format.
+ */
+struct bfa_mfg_vpd_s {
+    u8     version;    /*  vpd data version */
+    u8     vpd_sig[3]; /*  characters 'V', 'P', 'D' */
+    u8     chksum;     /*  u8 checksum */
+    u8     vendor;     /*  vendor */
+    u8     len;        /*  vpd data length excluding header */
+    u8     rsv;
+    u8     data[BFA_MFG_VPD_LEN];  /*  vpd data */
+};
+
+#pragma pack(1)
+
+#endif /* __BFA_DEFS_MFG_H__ */
diff --git a/drivers/scsi/bfa/include/defs/bfa_defs_pci.h b/drivers/scsi/bfa/include/defs/bfa_defs_pci.h
new file mode 100644 (file)
index 0000000..c9b8332
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ */
+
+#ifndef __BFA_DEFS_PCI_H__
+#define __BFA_DEFS_PCI_H__
+
+/**
+ * PCI device and vendor ID information
+ */
+enum {
+       BFA_PCI_VENDOR_ID_BROCADE       = 0x1657,
+       BFA_PCI_DEVICE_ID_FC_8G2P       = 0x13,
+       BFA_PCI_DEVICE_ID_FC_8G1P       = 0x17,
+       BFA_PCI_DEVICE_ID_CT            = 0x14,
+};
+
+/**
+ * PCI sub-system device and vendor ID information
+ */
+enum {
+       BFA_PCI_FCOE_SSDEVICE_ID        = 0x14,
+};
+
+#define BFA_PCI_ACCESS_RANGES 1        /* Maximum number of device address ranges
+                                * mapped through different BAR(s). */
+
+#endif /* __BFA_DEFS_PCI_H__ */
diff --git a/drivers/scsi/bfa/include/defs/bfa_defs_pm.h b/drivers/scsi/bfa/include/defs/bfa_defs_pm.h
new file mode 100644 (file)
index 0000000..e8d6d95
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ */
+
+#ifndef __BFA_DEFS_PM_H__
+#define __BFA_DEFS_PM_H__
+
+#include <bfa_os_inc.h>
+
+/**
+ * BFA power management device states
+ */
+enum bfa_pm_ds {
+       BFA_PM_DS_D0 = 0,       /*  full power mode */
+       BFA_PM_DS_D1 = 1,       /*  power save state 1 */
+       BFA_PM_DS_D2 = 2,       /*  power save state 2 */
+       BFA_PM_DS_D3 = 3,       /*  power off state */
+};
+
+#endif /* __BFA_DEFS_PM_H__ */
diff --git a/drivers/scsi/bfa/include/defs/bfa_defs_pom.h b/drivers/scsi/bfa/include/defs/bfa_defs_pom.h
new file mode 100644 (file)
index 0000000..d9fa278
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ */
+#ifndef __BFA_DEFS_POM_H__
+#define __BFA_DEFS_POM_H__
+
+#include <bfa_os_inc.h>
+#include <defs/bfa_defs_types.h>
+
+/**
+ * POM health status levels for each attributes.
+ */
+enum bfa_pom_entry_health {
+       BFA_POM_HEALTH_NOINFO  = 1,     /*  no information */
+       BFA_POM_HEALTH_NORMAL  = 2,     /*  health is normal */
+       BFA_POM_HEALTH_WARNING = 3,     /*  warning level */
+       BFA_POM_HEALTH_ALARM   = 4,     /*  alarming level */
+};
+
+/**
+ * Reading of temperature/voltage/current/power
+ */
+struct bfa_pom_entry_s {
+       enum bfa_pom_entry_health health;       /*  POM entry health */
+       u32        curr_value;  /*  current value */
+       u32        thr_warn_high;       /*  threshold warning high */
+       u32        thr_warn_low;        /*  threshold warning low */
+       u32        thr_alarm_low;       /*  threshold alaram low */
+       u32        thr_alarm_high;      /*  threshold alarm high */
+};
+
+/**
+ * POM attributes
+ */
+struct bfa_pom_attr_s {
+       struct bfa_pom_entry_s temperature;     /*  centigrade */
+       struct bfa_pom_entry_s voltage; /*  volts */
+       struct bfa_pom_entry_s curr;    /*  milli amps */
+       struct bfa_pom_entry_s txpower; /*  micro watts */
+       struct bfa_pom_entry_s rxpower; /*  micro watts */
+};
+
+#endif /* __BFA_DEFS_POM_H__ */
diff --git a/drivers/scsi/bfa/include/defs/bfa_defs_port.h b/drivers/scsi/bfa/include/defs/bfa_defs_port.h
new file mode 100644 (file)
index 0000000..de0696c
--- /dev/null
@@ -0,0 +1,245 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ */
+
+#ifndef __BFA_DEFS_PORT_H__
+#define __BFA_DEFS_PORT_H__
+
+#include <bfa_os_inc.h>
+#include <protocol/types.h>
+#include <defs/bfa_defs_pport.h>
+#include <defs/bfa_defs_ioc.h>
+
+#define BFA_FCS_FABRIC_IPADDR_SZ  16
+
+/**
+ * symbolic names for base port/virtual port
+ */
+#define BFA_SYMNAME_MAXLEN     128     /* vmware/windows uses 128 bytes */
+struct bfa_port_symname_s {
+       char            symname[BFA_SYMNAME_MAXLEN];
+};
+
+/**
+* Roles of FCS port:
+ *     - FCP IM and FCP TM roles cannot be enabled together for a FCS port
+ *     - Create multiple ports if both IM and TM functions required.
+ *     - Atleast one role must be specified.
+ */
+enum bfa_port_role {
+       BFA_PORT_ROLE_FCP_IM    = 0x01, /*  FCP initiator role */
+       BFA_PORT_ROLE_FCP_TM    = 0x02, /*  FCP target role */
+       BFA_PORT_ROLE_FCP_IPFC  = 0x04, /*  IP over FC role */
+       BFA_PORT_ROLE_FCP_MAX   = BFA_PORT_ROLE_FCP_IPFC | BFA_PORT_ROLE_FCP_IM
+};
+
+/**
+ * FCS port configuration.
+ */
+struct bfa_port_cfg_s {
+    wwn_t               pwwn;       /*  port wwn */
+    wwn_t               nwwn;       /*  node wwn */
+    struct bfa_port_symname_s  sym_name;   /*  vm port symbolic name */
+    enum bfa_port_role     roles;      /*  FCS port roles */
+       u32                     rsvd;
+    u8             tag[16];    /*  opaque tag from application */
+};
+
+/**
+ * FCS port states
+ */
+enum bfa_port_state {
+       BFA_PORT_UNINIT  = 0,   /*  PORT is not yet initialized */
+       BFA_PORT_FDISC   = 1,   /*  FDISC is in progress */
+       BFA_PORT_ONLINE  = 2,   /*  login to fabric is complete */
+       BFA_PORT_OFFLINE = 3,   /*  No login to fabric */
+};
+
+/**
+ * FCS port type. Required for VmWare.
+ */
+enum bfa_port_type {
+       BFA_PORT_TYPE_PHYSICAL = 0,
+       BFA_PORT_TYPE_VIRTUAL,
+};
+
+/**
+ * FCS port offline reason. Required for VmWare.
+ */
+enum bfa_port_offline_reason {
+       BFA_PORT_OFFLINE_UNKNOWN = 0,
+       BFA_PORT_OFFLINE_LINKDOWN,
+       BFA_PORT_OFFLINE_FAB_UNSUPPORTED,       /*  NPIV not supported by the
+                                                *    fabric */
+       BFA_PORT_OFFLINE_FAB_NORESOURCES,
+       BFA_PORT_OFFLINE_FAB_LOGOUT,
+};
+
+/**
+ * FCS lport info. Required for VmWare.
+ */
+struct bfa_port_info_s {
+       u8         port_type;   /* bfa_port_type_t : physical or
+                                        * virtual */
+       u8         port_state;  /* one of bfa_port_state values */
+       u8         offline_reason;      /* one of bfa_port_offline_reason_t
+                                        * values */
+       wwn_t           port_wwn;
+       wwn_t           node_wwn;
+
+       /*
+        * following 4 feilds are valid for Physical Ports only
+        */
+       u32        max_vports_supp;     /* Max supported vports */
+       u32        num_vports_inuse;    /* Num of in use vports */
+       u32        max_rports_supp;     /* Max supported rports */
+       u32        num_rports_inuse;    /* Num of doscovered rports */
+
+};
+
+/**
+ * FCS port statistics
+ */
+struct bfa_port_stats_s {
+       u32        ns_plogi_sent;
+       u32        ns_plogi_rsp_err;
+       u32        ns_plogi_acc_err;
+       u32        ns_plogi_accepts;
+       u32        ns_rejects;  /* NS command rejects */
+       u32        ns_plogi_unknown_rsp;
+       u32        ns_plogi_alloc_wait;
+
+       u32        ns_retries;  /* NS command retries */
+       u32        ns_timeouts; /* NS command timeouts */
+
+       u32        ns_rspnid_sent;
+       u32        ns_rspnid_accepts;
+       u32        ns_rspnid_rsp_err;
+       u32        ns_rspnid_rejects;
+       u32        ns_rspnid_alloc_wait;
+
+       u32        ns_rftid_sent;
+       u32        ns_rftid_accepts;
+       u32        ns_rftid_rsp_err;
+       u32        ns_rftid_rejects;
+       u32        ns_rftid_alloc_wait;
+
+       u32     ns_rffid_sent;
+       u32     ns_rffid_accepts;
+       u32     ns_rffid_rsp_err;
+       u32     ns_rffid_rejects;
+       u32     ns_rffid_alloc_wait;
+
+       u32        ns_gidft_sent;
+       u32        ns_gidft_accepts;
+       u32        ns_gidft_rsp_err;
+       u32        ns_gidft_rejects;
+       u32        ns_gidft_unknown_rsp;
+       u32        ns_gidft_alloc_wait;
+
+       /*
+        * Mgmt Server stats
+        */
+       u32        ms_retries;  /* MS command retries */
+       u32        ms_timeouts; /* MS command timeouts */
+       u32        ms_plogi_sent;
+       u32        ms_plogi_rsp_err;
+       u32        ms_plogi_acc_err;
+       u32        ms_plogi_accepts;
+       u32        ms_rejects;  /* NS command rejects */
+       u32        ms_plogi_unknown_rsp;
+       u32        ms_plogi_alloc_wait;
+
+       u32        num_rscn;    /* Num of RSCN received */
+       u32        num_portid_rscn;/* Num portid format RSCN
+                                                               * received */
+
+       u32     uf_recvs;       /* unsolicited recv frames      */
+       u32     uf_recv_drops;  /* dropped received frames      */
+
+       u32     rsvd;           /* padding for 64 bit alignment */
+};
+
+/**
+ * BFA port attribute returned in queries
+ */
+struct bfa_port_attr_s {
+       enum bfa_port_state state;              /*  port state */
+       u32         pid;                /*  port ID */
+       struct bfa_port_cfg_s   port_cfg;       /*  port configuration */
+       enum bfa_pport_type port_type;  /*  current topology */
+       u32         loopback;   /*  cable is externally looped back */
+       wwn_t           fabric_name; /*  attached switch's nwwn */
+       u8              fabric_ip_addr[BFA_FCS_FABRIC_IPADDR_SZ]; /*  attached
+                                                       * fabric's ip addr */
+};
+
+/**
+ * BFA physical port Level events
+ * Arguments below are in BFAL context from Mgmt
+ * BFA_PORT_AEN_ONLINE:     [in]: pwwn [out]: pwwn
+ * BFA_PORT_AEN_OFFLINE:    [in]: pwwn [out]: pwwn
+ * BFA_PORT_AEN_RLIR:       [in]: None [out]: pwwn, rlir_data, rlir_len
+ * BFA_PORT_AEN_SFP_INSERT: [in]: pwwn [out]: port_id, pwwn
+ * BFA_PORT_AEN_SFP_REMOVE: [in]: pwwn [out]: port_id, pwwn
+ * BFA_PORT_AEN_SFP_POM:    [in]: pwwn [out]: level, port_id, pwwn
+ * BFA_PORT_AEN_ENABLE:     [in]: pwwn [out]: pwwn
+ * BFA_PORT_AEN_DISABLE:    [in]: pwwn [out]: pwwn
+ * BFA_PORT_AEN_AUTH_ON:    [in]: pwwn [out]: pwwn
+ * BFA_PORT_AEN_AUTH_OFF:   [in]: pwwn [out]: pwwn
+ * BFA_PORT_AEN_DISCONNECT: [in]: pwwn [out]: pwwn
+ * BFA_PORT_AEN_QOS_NEG:    [in]: pwwn [out]: pwwn
+ * BFA_PORT_AEN_FABRIC_NAME_CHANGE: [in]: pwwn, [out]: pwwn, fwwn
+ *
+ */
+enum bfa_port_aen_event {
+       BFA_PORT_AEN_ONLINE     = 1,    /*  Physical Port online event */
+       BFA_PORT_AEN_OFFLINE    = 2,    /*  Physical Port offline event */
+       BFA_PORT_AEN_RLIR       = 3,    /*  RLIR event, not supported */
+       BFA_PORT_AEN_SFP_INSERT = 4,    /*  SFP inserted event */
+       BFA_PORT_AEN_SFP_REMOVE = 5,    /*  SFP removed event */
+       BFA_PORT_AEN_SFP_POM    = 6,    /*  SFP POM event */
+       BFA_PORT_AEN_ENABLE     = 7,    /*  Physical Port enable event */
+       BFA_PORT_AEN_DISABLE    = 8,    /*  Physical Port disable event */
+       BFA_PORT_AEN_AUTH_ON    = 9,    /*  Physical Port auth success event */
+       BFA_PORT_AEN_AUTH_OFF   = 10,   /*  Physical Port auth fail event */
+       BFA_PORT_AEN_DISCONNECT = 11,   /*  Physical Port disconnect event */
+       BFA_PORT_AEN_QOS_NEG    = 12,   /*  Base Port QOS negotiation event */
+       BFA_PORT_AEN_FABRIC_NAME_CHANGE = 13, /*  Fabric Name/WWN change
+                                              * event */
+       BFA_PORT_AEN_SFP_ACCESS_ERROR = 14, /*  SFP read error event */
+       BFA_PORT_AEN_SFP_UNSUPPORT = 15, /*  Unsupported SFP event */
+};
+
+enum bfa_port_aen_sfp_pom {
+       BFA_PORT_AEN_SFP_POM_GREEN = 1, /*  Normal */
+       BFA_PORT_AEN_SFP_POM_AMBER = 2, /*  Warning */
+       BFA_PORT_AEN_SFP_POM_RED   = 3, /*  Critical */
+       BFA_PORT_AEN_SFP_POM_MAX   = BFA_PORT_AEN_SFP_POM_RED
+};
+
+struct bfa_port_aen_data_s {
+       enum bfa_ioc_type_e ioc_type;
+       wwn_t           pwwn;         /*  WWN of the physical port */
+       wwn_t           fwwn;         /*  WWN of the fabric port */
+       mac_t           mac;          /*  MAC addres of the ethernet port,
+                                      * applicable to CNA port only */
+       int             phy_port_num; /*! For SFP related events */
+       enum bfa_port_aen_sfp_pom level; /*  Only transitions will
+                                         * be informed */
+};
+
+#endif /* __BFA_DEFS_PORT_H__ */
diff --git a/drivers/scsi/bfa/include/defs/bfa_defs_pport.h b/drivers/scsi/bfa/include/defs/bfa_defs_pport.h
new file mode 100644 (file)
index 0000000..a000bc4
--- /dev/null
@@ -0,0 +1,383 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ */
+
+#ifndef __BFA_DEFS_PPORT_H__
+#define __BFA_DEFS_PPORT_H__
+
+#include <bfa_os_inc.h>
+#include <protocol/fc.h>
+#include <defs/bfa_defs_types.h>
+#include <defs/bfa_defs_qos.h>
+#include <cna/pstats/phyport_defs.h>
+
+/* Modify char* port_stt[] in bfal_port.c if a new state was added */
+enum bfa_pport_states {
+       BFA_PPORT_ST_UNINIT             = 1,
+       BFA_PPORT_ST_ENABLING_QWAIT     = 2,
+       BFA_PPORT_ST_ENABLING           = 3,
+       BFA_PPORT_ST_LINKDOWN           = 4,
+       BFA_PPORT_ST_LINKUP             = 5,
+       BFA_PPORT_ST_DISABLING_QWAIT    = 6,
+       BFA_PPORT_ST_DISABLING          = 7,
+       BFA_PPORT_ST_DISABLED           = 8,
+       BFA_PPORT_ST_STOPPED            = 9,
+       BFA_PPORT_ST_IOCDOWN            = 10,
+       BFA_PPORT_ST_IOCDIS             = 11,
+       BFA_PPORT_ST_FWMISMATCH         = 12,
+       BFA_PPORT_ST_MAX_STATE,
+};
+
+/**
+ *     Port speed settings. Each specific speed is a bit field. Use multiple
+ *      bits to specify speeds to be selected for auto-negotiation.
+ */
+enum bfa_pport_speed {
+       BFA_PPORT_SPEED_UNKNOWN = 0,
+       BFA_PPORT_SPEED_1GBPS   = 1,
+       BFA_PPORT_SPEED_2GBPS   = 2,
+       BFA_PPORT_SPEED_4GBPS   = 4,
+       BFA_PPORT_SPEED_8GBPS   = 8,
+       BFA_PPORT_SPEED_10GBPS  = 10,
+       BFA_PPORT_SPEED_AUTO =
+               (BFA_PPORT_SPEED_1GBPS | BFA_PPORT_SPEED_2GBPS |
+                BFA_PPORT_SPEED_4GBPS | BFA_PPORT_SPEED_8GBPS),
+};
+
+/**
+ *             Port operational type (in sync with SNIA port type).
+ */
+enum bfa_pport_type {
+       BFA_PPORT_TYPE_UNKNOWN = 1,     /*  port type is unkown */
+       BFA_PPORT_TYPE_TRUNKED = 2,     /*  Trunked mode */
+       BFA_PPORT_TYPE_NPORT   = 5,     /*  P2P with switched fabric */
+       BFA_PPORT_TYPE_NLPORT  = 6,     /*  public loop */
+       BFA_PPORT_TYPE_LPORT   = 20,    /*  private loop */
+       BFA_PPORT_TYPE_P2P     = 21,    /*  P2P with no switched fabric */
+       BFA_PPORT_TYPE_VPORT   = 22,    /*  NPIV - virtual port */
+};
+
+/**
+ *             Port topology setting. A port's topology and fabric login status
+ *             determine its operational type.
+ */
+enum bfa_pport_topology {
+       BFA_PPORT_TOPOLOGY_NONE = 0,    /*  No valid topology */
+       BFA_PPORT_TOPOLOGY_P2P  = 1,    /*  P2P only */
+       BFA_PPORT_TOPOLOGY_LOOP = 2,    /*  LOOP topology */
+       BFA_PPORT_TOPOLOGY_AUTO = 3,    /*  auto topology selection */
+};
+
+/**
+ *             Physical port loopback types.
+ */
+enum bfa_pport_opmode {
+       BFA_PPORT_OPMODE_NORMAL   = 0x00, /*  normal non-loopback mode */
+       BFA_PPORT_OPMODE_LB_INT   = 0x01, /*  internal loop back */
+       BFA_PPORT_OPMODE_LB_SLW   = 0x02, /*  serial link wrapback (serdes) */
+       BFA_PPORT_OPMODE_LB_EXT   = 0x04, /*  external loop back (serdes) */
+       BFA_PPORT_OPMODE_LB_CBL   = 0x08, /*  cabled loop back */
+       BFA_PPORT_OPMODE_LB_NLINT = 0x20, /*  NL_Port internal loopback */
+};
+
+#define BFA_PPORT_OPMODE_LB_HARD(_mode)                        \
+       ((_mode == BFA_PPORT_OPMODE_LB_INT) ||          \
+     (_mode == BFA_PPORT_OPMODE_LB_SLW) ||             \
+     (_mode == BFA_PPORT_OPMODE_LB_EXT))
+
+/**
+               Port State (in sync with SNIA port state).
+ */
+enum bfa_pport_snia_state {
+       BFA_PPORT_STATE_UNKNOWN  = 1,   /*  port is not initialized */
+       BFA_PPORT_STATE_ONLINE   = 2,   /*  port is ONLINE */
+       BFA_PPORT_STATE_DISABLED = 3,   /*  port is disabled by user */
+       BFA_PPORT_STATE_BYPASSED = 4,   /*  port is bypassed (in LOOP) */
+       BFA_PPORT_STATE_DIAG     = 5,   /*  port diagnostics is active */
+       BFA_PPORT_STATE_LINKDOWN = 6,   /*  link is down */
+       BFA_PPORT_STATE_LOOPBACK = 8,   /*  port is looped back */
+};
+
+/**
+ *             Port link state
+ */
+enum bfa_pport_linkstate {
+       BFA_PPORT_LINKUP         = 1,   /*  Physical port/Trunk link up */
+       BFA_PPORT_LINKDOWN       = 2,   /*  Physical port/Trunk link down */
+       BFA_PPORT_TRUNK_LINKDOWN = 3,   /*  Trunk link down (new tmaster) */
+};
+
+/**
+ *             Port link state event
+ */
+#define bfa_pport_event_t enum bfa_pport_linkstate
+
+/**
+ *             Port link state reason code
+ */
+enum bfa_pport_linkstate_rsn {
+       BFA_PPORT_LINKSTATE_RSN_NONE            = 0,
+       BFA_PPORT_LINKSTATE_RSN_DISABLED        = 1,
+       BFA_PPORT_LINKSTATE_RSN_RX_NOS          = 2,
+       BFA_PPORT_LINKSTATE_RSN_RX_OLS          = 3,
+       BFA_PPORT_LINKSTATE_RSN_RX_LIP          = 4,
+       BFA_PPORT_LINKSTATE_RSN_RX_LIPF7        = 5,
+       BFA_PPORT_LINKSTATE_RSN_SFP_REMOVED     = 6,
+       BFA_PPORT_LINKSTATE_RSN_PORT_FAULT      = 7,
+       BFA_PPORT_LINKSTATE_RSN_RX_LOS          = 8,
+       BFA_PPORT_LINKSTATE_RSN_LOCAL_FAULT     = 9,
+       BFA_PPORT_LINKSTATE_RSN_REMOTE_FAULT    = 10,
+       BFA_PPORT_LINKSTATE_RSN_TIMEOUT         = 11,
+
+
+
+       /* CEE related reason codes/errors */
+       CEE_LLDP_INFO_AGED_OUT       = 20,
+       CEE_LLDP_SHUTDOWN_TLV_RCVD   = 21,
+       CEE_PEER_NOT_ADVERTISE_DCBX  = 22,
+       CEE_PEER_NOT_ADVERTISE_PG    = 23,
+       CEE_PEER_NOT_ADVERTISE_PFC   = 24,
+       CEE_PEER_NOT_ADVERTISE_FCOE  = 25,
+       CEE_PG_NOT_COMPATIBLE        = 26,
+       CEE_PFC_NOT_COMPATIBLE       = 27,
+       CEE_FCOE_NOT_COMPATIBLE      = 28,
+       CEE_BAD_PG_RCVD              = 29,
+       CEE_BAD_BW_RCVD              = 30,
+       CEE_BAD_PFC_RCVD             = 31,
+       CEE_BAD_FCOE_PRI_RCVD        = 32,
+       CEE_FCOE_PRI_PFC_OFF         = 33,
+       CEE_DUP_CONTROL_TLV_RCVD     = 34,
+       CEE_DUP_FEAT_TLV_RCVD        = 35,
+       CEE_APPLY_NEW_CFG            = 36,      /* reason, not an error */
+       CEE_PROTOCOL_INIT            = 37,  /* reason, not an error */
+       CEE_PHY_LINK_DOWN            = 38,
+       CEE_LLS_FCOE_ABSENT          = 39,
+       CEE_LLS_FCOE_DOWN            = 40
+};
+
+/**
+ *      Default Target Rate Limiting Speed.
+ */
+#define BFA_PPORT_DEF_TRL_SPEED  BFA_PPORT_SPEED_1GBPS
+
+/**
+ *      Physical port configuration
+ */
+struct bfa_pport_cfg_s {
+       u8         topology;    /*  bfa_pport_topology          */
+       u8         speed;               /*  enum bfa_pport_speed        */
+       u8         trunked;     /*  trunked or not              */
+       u8         qos_enabled; /*  qos enabled or not          */
+       u8         trunk_ports; /*  bitmap of trunked ports     */
+       u8         cfg_hardalpa;        /*  is hard alpa configured     */
+       u16        maxfrsize;   /*  maximum frame size          */
+       u8         hardalpa;    /*  configured hard alpa        */
+       u8         rx_bbcredit; /*  receive buffer credits      */
+       u8         tx_bbcredit; /*  transmit buffer credits     */
+       u8         ratelimit;   /*  ratelimit enabled or not    */
+       u8         trl_def_speed;       /*  ratelimit default speed     */
+       u8              rsvd[3];
+       u16     path_tov;       /*  device path timeout */
+       u16     q_depth;        /*  SCSI Queue depth            */
+};
+
+/**
+ *             Port attribute values.
+ */
+struct bfa_pport_attr_s {
+       /*
+        * Static fields
+        */
+       wwn_t           nwwn;           /*  node wwn */
+       wwn_t           pwwn;           /*  port wwn */
+       enum fc_cos     cos_supported;  /*  supported class of services */
+       u32        rsvd;
+       struct fc_symname_s    port_symname;    /*  port symbolic name */
+       enum bfa_pport_speed speed_supported; /*  supported speeds */
+       bfa_boolean_t   pbind_enabled;  /*  Will be set if Persistent binding
+                                        *   enabled. Relevant only in Windows
+                                        */
+
+       /*
+        * Configured values
+        */
+       struct bfa_pport_cfg_s pport_cfg;       /*  pport cfg */
+
+       /*
+        * Dynamic field - info from BFA
+        */
+       enum bfa_pport_states   port_state;     /*  current port state */
+       enum bfa_pport_speed    speed;          /*  current speed */
+       enum bfa_pport_topology         topology;       /*  current topology */
+       bfa_boolean_t           beacon;         /*  current beacon status */
+       bfa_boolean_t           link_e2e_beacon;/*  set if link beacon on */
+       bfa_boolean_t           plog_enabled;   /*  set if portlog is enabled*/
+
+       /*
+        * Dynamic field - info from FCS
+        */
+       u32             pid;            /*  port ID */
+       enum bfa_pport_type     port_type;      /*  current topology */
+       u32             loopback;       /*  external loopback */
+       u32             rsvd1;
+       u32             rsvd2;          /*  padding for 64 bit */
+};
+
+/**
+ *             FC Port statistics.
+ */
+struct bfa_pport_fc_stats_s {
+       u64        secs_reset;  /*  seconds since stats is reset */
+       u64        tx_frames;   /*  transmitted frames */
+       u64        tx_words;    /*  transmitted words */
+       u64        rx_frames;   /*  received frames */
+       u64        rx_words;    /*  received words */
+       u64        lip_count;   /*  LIPs seen */
+       u64        nos_count;   /*  NOS count */
+       u64        error_frames;        /*  errored frames (sent?) */
+       u64        dropped_frames;      /*  dropped frames */
+       u64        link_failures;       /*  link failure count */
+       u64        loss_of_syncs;       /*  loss of sync count */
+       u64        loss_of_signals;/*  loss of signal count */
+       u64        primseq_errs;        /*  primitive sequence protocol */
+       u64        bad_os_count;        /*  invalid ordered set */
+       u64        err_enc_out; /*  Encoding error outside frame */
+       u64        invalid_crcs;        /*  frames received with invalid CRC*/
+       u64     undersized_frm; /*  undersized frames */
+       u64     oversized_frm;  /*  oversized frames */
+       u64     bad_eof_frm;    /*  frames with bad EOF */
+       struct bfa_qos_stats_s  qos_stats;      /*  QoS statistics */
+};
+
+/**
+ *             Eth Port statistics.
+ */
+struct bfa_pport_eth_stats_s {
+       u64     secs_reset;     /*  seconds since stats is reset */
+       u64     frame_64;      /*  both rx and tx counter */
+       u64     frame_65_127;      /* both rx and tx counter */
+       u64     frame_128_255;     /* both rx and tx counter */
+       u64     frame_256_511;     /* both rx and tx counter */
+       u64     frame_512_1023;    /* both rx and tx counter */
+       u64     frame_1024_1518;   /* both rx and tx counter */
+       u64     frame_1519_1522;   /* both rx and tx counter */
+
+       u64     tx_bytes;
+       u64     tx_packets;
+       u64     tx_mcast_packets;
+       u64     tx_bcast_packets;
+       u64     tx_control_frame;
+       u64     tx_drop;
+       u64     tx_jabber;
+       u64     tx_fcs_error;
+       u64     tx_fragments;
+
+       u64     rx_bytes;
+       u64     rx_packets;
+       u64     rx_mcast_packets;
+       u64     rx_bcast_packets;
+       u64     rx_control_frames;
+       u64     rx_unknown_opcode;
+       u64     rx_drop;
+       u64     rx_jabber;
+       u64     rx_fcs_error;
+       u64     rx_alignment_error;
+       u64     rx_frame_length_error;
+       u64     rx_code_error;
+       u64     rx_fragments;
+
+       u64     rx_pause; /* BPC */
+       u64     rx_zero_pause; /*  BPC Pause cancellation */
+       u64     tx_pause;      /* BPC */
+       u64     tx_zero_pause; /*  BPC Pause cancellation */
+       u64     rx_fcoe_pause; /* BPC */
+       u64     rx_fcoe_zero_pause; /*  BPC Pause cancellation */
+       u64     tx_fcoe_pause;      /* BPC */
+       u64     tx_fcoe_zero_pause; /*  BPC Pause cancellation */
+};
+
+/**
+ *             Port statistics.
+ */
+union bfa_pport_stats_u {
+       struct bfa_pport_fc_stats_s     fc;
+       struct bfa_pport_eth_stats_s    eth;
+};
+
+/**
+ *              Port FCP mappings.
+ */
+struct bfa_pport_fcpmap_s {
+       char            osdevname[256];
+       u32     bus;
+       u32        target;
+       u32        oslun;
+       u32        fcid;
+       wwn_t           nwwn;
+       wwn_t           pwwn;
+       u64        fcplun;
+       char            luid[256];
+};
+
+/**
+ *              Port RNID info.
+ */
+struct bfa_pport_rnid_s {
+       wwn_t             wwn;
+       u32          unittype;
+       u32          portid;
+       u32          attached_nodes_num;
+       u16          ip_version;
+       u16          udp_port;
+       u8           ipaddr[16];
+       u16          rsvd;
+       u16          topologydiscoveryflags;
+};
+
+/**
+ *             Link state information
+ */
+struct bfa_pport_link_s {
+       u8         linkstate;   /*  Link state bfa_pport_linkstate */
+       u8         linkstate_rsn;       /*  bfa_pport_linkstate_rsn_t */
+       u8         topology;    /*  P2P/LOOP bfa_pport_topology */
+       u8         speed;               /*  Link speed (1/2/4/8 G) */
+       u32        linkstate_opt;       /*  Linkstate optional data (debug) */
+       u8         trunked;     /*  Trunked or not (1 or 0) */
+       u8         resvd[3];
+       struct bfa_qos_attr_s  qos_attr;   /* QoS Attributes */
+       struct bfa_qos_vc_attr_s qos_vc_attr;  /*  VC info from ELP */
+       union {
+               struct {
+                       u8         tmaster;/*  Trunk Master or
+                                                *    not (1 or 0) */
+                       u8         tlinks;      /*  Trunk links bitmap
+                                                *    (linkup) */
+                       u8         resv1;       /*  Reserved */
+               } trunk_info;
+
+               struct {
+                       u8         myalpa;         /*  alpa claimed */
+                       u8         login_req; /*  Login required or
+                                                   *    not (1 or 0) */
+                       u8         alpabm_val;/*  alpa bitmap valid
+                                                   *    or not (1 or 0) */
+                       struct fc_alpabm_s     alpabm;     /*  alpa bitmap */
+               } loop_info;
+       } tl;
+};
+
+#endif /* __BFA_DEFS_PPORT_H__ */
diff --git a/drivers/scsi/bfa/include/defs/bfa_defs_qos.h b/drivers/scsi/bfa/include/defs/bfa_defs_qos.h
new file mode 100644 (file)
index 0000000..aadbacd
--- /dev/null
@@ -0,0 +1,99 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ */
+
+#ifndef __BFA_DEFS_QOS_H__
+#define __BFA_DEFS_QOS_H__
+
+/**
+ * QoS states
+ */
+enum bfa_qos_state {
+       BFA_QOS_ONLINE = 1,             /*  QoS is online */
+       BFA_QOS_OFFLINE = 2,            /*  QoS is offline */
+};
+
+
+/**
+ * QoS  Priority levels.
+ */
+enum bfa_qos_priority {
+       BFA_QOS_UNKNOWN = 0,
+       BFA_QOS_HIGH  = 1,      /*  QoS Priority Level High */
+       BFA_QOS_MED  =  2,      /*  QoS Priority Level Medium */
+       BFA_QOS_LOW  =  3,      /*  QoS Priority Level Low */
+};
+
+
+/**
+ * QoS  bandwidth allocation for each priority level
+ */
+enum bfa_qos_bw_alloc {
+       BFA_QOS_BW_HIGH  = 60,  /*  bandwidth allocation for High */
+       BFA_QOS_BW_MED  =  30,  /*  bandwidth allocation for Medium */
+       BFA_QOS_BW_LOW  =  10,  /*  bandwidth allocation for Low */
+};
+
+/**
+ * QoS attribute returned in QoS Query
+ */
+struct bfa_qos_attr_s {
+       enum bfa_qos_state state;               /*  QoS current state */
+       u32  total_bb_cr;               /*  Total BB Credits */
+};
+
+/**
+ * These fields should be displayed only from the CLI.
+ * There will be a separate BFAL API (get_qos_vc_attr ?)
+ * to retrieve this.
+ *
+ */
+#define  BFA_QOS_MAX_VC  16
+
+struct bfa_qos_vc_info_s {
+       u8 vc_credit;
+       u8 borrow_credit;
+       u8 priority;
+       u8 resvd;
+};
+
+struct bfa_qos_vc_attr_s {
+       u16  total_vc_count;                    /*  Total VC Count */
+       u16  shared_credit;
+       u32  elp_opmode_flags;
+       struct bfa_qos_vc_info_s vc_info[BFA_QOS_MAX_VC];  /*   as many as
+                                                           * total_vc_count */
+};
+
+/**
+ * QoS statistics
+ */
+struct bfa_qos_stats_s {
+       u32     flogi_sent;             /*  QoS Flogi sent */
+       u32     flogi_acc_recvd;        /*  QoS Flogi Acc received */
+       u32     flogi_rjt_recvd; /*  QoS Flogi rejects received */
+       u32     flogi_retries;          /*  QoS Flogi retries */
+
+       u32     elp_recvd;              /*  QoS ELP received */
+       u32     elp_accepted;       /*  QoS ELP Accepted */
+       u32     elp_rejected;       /*  QoS ELP rejected */
+       u32     elp_dropped;        /*  QoS ELP dropped  */
+
+       u32     qos_rscn_recvd;     /*  QoS RSCN received */
+       u32     rsvd;           /* padding for 64 bit alignment */
+};
+
+#endif /* __BFA_DEFS_QOS_H__ */
diff --git a/drivers/scsi/bfa/include/defs/bfa_defs_rport.h b/drivers/scsi/bfa/include/defs/bfa_defs_rport.h
new file mode 100644 (file)
index 0000000..e0af59d
--- /dev/null
@@ -0,0 +1,199 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ */
+
+#ifndef __BFA_DEFS_RPORT_H__
+#define __BFA_DEFS_RPORT_H__
+
+#include <bfa_os_inc.h>
+#include <protocol/types.h>
+#include <defs/bfa_defs_pport.h>
+#include <defs/bfa_defs_port.h>
+#include <defs/bfa_defs_qos.h>
+
+/**
+ * FCS remote port states
+ */
+enum bfa_rport_state {
+       BFA_RPORT_UNINIT        = 0,    /*  PORT is not yet initialized */
+       BFA_RPORT_OFFLINE       = 1,    /*  rport is offline */
+       BFA_RPORT_PLOGI         = 2,    /*  PLOGI to rport is in progress */
+       BFA_RPORT_ONLINE        = 3,    /*  login to rport is complete */
+       BFA_RPORT_PLOGI_RETRY   = 4,    /*  retrying login to rport */
+       BFA_RPORT_NSQUERY       = 5,    /*  nameserver query */
+       BFA_RPORT_ADISC         = 6,    /*  ADISC authentication */
+       BFA_RPORT_LOGO          = 7,    /*  logging out with rport */
+       BFA_RPORT_LOGORCV       = 8,    /*  handling LOGO from rport */
+       BFA_RPORT_NSDISC        = 9,    /*  re-discover rport */
+};
+
+/**
+ *  Rport Scsi Function : Initiator/Target.
+ */
+enum bfa_rport_function {
+       BFA_RPORT_INITIATOR     = 0x01, /*  SCSI Initiator      */
+       BFA_RPORT_TARGET        = 0x02, /*  SCSI Target */
+};
+
+/**
+ * port/node symbolic names for rport
+ */
+#define BFA_RPORT_SYMNAME_MAXLEN       255
+struct bfa_rport_symname_s {
+       char            symname[BFA_RPORT_SYMNAME_MAXLEN];
+};
+
+struct bfa_rport_hal_stats_s {
+       u32        sm_un_cr;        /*  uninit: create events      */
+       u32        sm_un_unexp;     /*  uninit: exception events   */
+       u32        sm_cr_on;        /*  created: online events     */
+       u32        sm_cr_del;       /*  created: delete events     */
+       u32        sm_cr_hwf;       /*  created: IOC down          */
+       u32        sm_cr_unexp;     /*  created: exception events  */
+       u32        sm_fwc_rsp;      /*  fw create: f/w responses   */
+       u32        sm_fwc_del;      /*  fw create: delete events   */
+       u32        sm_fwc_off;      /*  fw create: offline events  */
+       u32        sm_fwc_hwf;      /*  fw create: IOC down        */
+       u32        sm_fwc_unexp;            /*  fw create: exception events*/
+       u32        sm_on_off;       /*  online: offline events     */
+       u32        sm_on_del;       /*  online: delete events      */
+       u32        sm_on_hwf;       /*  online: IOC down events    */
+       u32        sm_on_unexp;     /*  online: exception events   */
+       u32        sm_fwd_rsp;      /*  fw delete: fw responses    */
+       u32        sm_fwd_del;      /*  fw delete: delete events   */
+       u32        sm_fwd_hwf;      /*  fw delete: IOC down events */
+       u32        sm_fwd_unexp;            /*  fw delete: exception events*/
+       u32        sm_off_del;      /*  offline: delete events     */
+       u32        sm_off_on;       /*  offline: online events     */
+       u32        sm_off_hwf;      /*  offline: IOC down events   */
+       u32        sm_off_unexp;            /*  offline: exception events  */
+       u32        sm_del_fwrsp;            /*  delete: fw responses       */
+       u32        sm_del_hwf;      /*  delete: IOC down events    */
+       u32        sm_del_unexp;            /*  delete: exception events   */
+       u32        sm_delp_fwrsp;           /*  delete pend: fw responses  */
+       u32        sm_delp_hwf;     /*  delete pend: IOC downs     */
+       u32        sm_delp_unexp;           /*  delete pend: exceptions    */
+       u32        sm_offp_fwrsp;           /*  off-pending: fw responses  */
+       u32        sm_offp_del;     /*  off-pending: deletes       */
+       u32        sm_offp_hwf;     /*  off-pending: IOC downs     */
+       u32        sm_offp_unexp;           /*  off-pending: exceptions    */
+       u32        sm_iocd_off;     /*  IOC down: offline events   */
+       u32        sm_iocd_del;     /*  IOC down: delete events    */
+       u32        sm_iocd_on;      /*  IOC down: online events    */
+       u32        sm_iocd_unexp;           /*  IOC down: exceptions       */
+       u32        rsvd;
+};
+
+/**
+ * FCS remote port statistics
+ */
+struct bfa_rport_stats_s {
+       u32        offlines;           /*  remote port offline count  */
+       u32        onlines;            /*  remote port online count   */
+       u32        rscns;              /*  RSCN affecting rport       */
+       u32        plogis;                  /*  plogis sent                */
+       u32        plogi_accs;      /*  plogi accepts              */
+       u32        plogi_timeouts;          /*  plogi timeouts             */
+       u32        plogi_rejects;           /*  rcvd plogi rejects         */
+       u32        plogi_failed;            /*  local failure              */
+       u32        plogi_rcvd;      /*  plogis rcvd                */
+       u32        prli_rcvd;          /*  inbound PRLIs              */
+       u32        adisc_rcvd;         /*  ADISCs received            */
+       u32        adisc_rejects;      /*  recvd  ADISC rejects       */
+       u32        adisc_sent;         /*  ADISC requests sent        */
+       u32        adisc_accs;         /*  ADISC accepted by rport    */
+       u32        adisc_failed;       /*  ADISC failed (no response) */
+       u32        adisc_rejected;     /*  ADISC rejected by us    */
+       u32        logos;              /*  logos sent                 */
+       u32        logo_accs;          /*  LOGO accepts from rport    */
+       u32        logo_failed;        /*  LOGO failures              */
+       u32        logo_rejected;      /*  LOGO rejects from rport    */
+       u32        logo_rcvd;          /*  LOGO from remote port      */
+
+       u32        rpsc_rcvd;         /*  RPSC received            */
+       u32        rpsc_rejects;      /*  recvd  RPSC rejects       */
+       u32        rpsc_sent;         /*  RPSC requests sent        */
+       u32        rpsc_accs;         /*  RPSC accepted by rport    */
+       u32        rpsc_failed;       /*  RPSC failed (no response) */
+       u32        rpsc_rejected;     /*  RPSC rejected by us    */
+
+       u32        rsvd;
+       struct bfa_rport_hal_stats_s    hal_stats;  /*  BFA rport stats    */
+};
+
+/**
+ *  Rport's QoS attributes
+ */
+struct bfa_rport_qos_attr_s {
+       enum bfa_qos_priority qos_priority;  /*  rport's QoS priority   */
+       u32            qos_flow_id;       /*  QoS flow Id        */
+};
+
+/**
+ * FCS remote port attributes returned in queries
+ */
+struct bfa_rport_attr_s {
+       wwn_t                   nwwn;   /*  node wwn */
+       wwn_t                   pwwn;   /*  port wwn */
+       enum fc_cos cos_supported;      /*  supported class of services */
+       u32             pid;    /*  port ID */
+       u32             df_sz;  /*  Max payload size */
+       enum bfa_rport_state    state;  /*  Rport State machine state */
+       enum fc_cos             fc_cos; /*  FC classes of services */
+       bfa_boolean_t           cisc;   /*  CISC capable device */
+       struct bfa_rport_symname_s symname; /*  Symbolic Name */
+       enum bfa_rport_function scsi_function; /*  Initiator/Target */
+       struct bfa_rport_qos_attr_s qos_attr; /*  qos attributes  */
+       enum bfa_pport_speed curr_speed;   /*  operating speed got from
+                                           * RPSC ELS. UNKNOWN, if RPSC
+                                           * is not supported */
+       bfa_boolean_t   trl_enforced;   /*  TRL enforced ? TRUE/FALSE */
+       enum bfa_pport_speed    assigned_speed; /* Speed assigned by the user.
+                                                * will be used if RPSC is not
+                                                * supported by the rport */
+};
+
+#define bfa_rport_aen_qos_data_t struct bfa_rport_qos_attr_s
+
+/**
+ * BFA remote port events
+ * Arguments below are in BFAL context from Mgmt
+ * BFA_RPORT_AEN_ONLINE:    [in]: lpwwn        [out]: vf_id, lpwwn, rpwwn
+ * BFA_RPORT_AEN_OFFLINE:   [in]: lpwwn [out]: vf_id, lpwwn, rpwwn
+ * BFA_RPORT_AEN_DISCONNECT:[in]: lpwwn [out]: vf_id, lpwwn, rpwwn
+ * BFA_RPORT_AEN_QOS_PRIO:  [in]: lpwwn [out]: vf_id, lpwwn, rpwwn, prio
+ * BFA_RPORT_AEN_QOS_FLOWID:[in]: lpwwn [out]: vf_id, lpwwn, rpwwn, flow_id
+ */
+enum bfa_rport_aen_event {
+       BFA_RPORT_AEN_ONLINE      = 1,  /*  RPort online event */
+       BFA_RPORT_AEN_OFFLINE     = 2,  /*  RPort offline event */
+       BFA_RPORT_AEN_DISCONNECT  = 3,  /*  RPort disconnect event */
+       BFA_RPORT_AEN_QOS_PRIO    = 4,  /*  QOS priority change event */
+       BFA_RPORT_AEN_QOS_FLOWID  = 5,  /*  QOS flow Id change event */
+};
+
+struct bfa_rport_aen_data_s {
+       u16        vf_id;       /*  vf_id of this logical port */
+       u16        rsvd[3];
+       wwn_t           ppwwn;  /*  WWN of its physical port */
+       wwn_t           lpwwn;  /*  WWN of this logical port */
+       wwn_t           rpwwn;  /*  WWN of this remote port */
+       union {
+               bfa_rport_aen_qos_data_t qos;
+       } priv;
+};
+
+#endif /* __BFA_DEFS_RPORT_H__ */
diff --git a/drivers/scsi/bfa/include/defs/bfa_defs_status.h b/drivers/scsi/bfa/include/defs/bfa_defs_status.h
new file mode 100644 (file)
index 0000000..cdceaeb
--- /dev/null
@@ -0,0 +1,255 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ */
+#ifndef __BFA_DEFS_STATUS_H__
+#define __BFA_DEFS_STATUS_H__
+
+/**
+ * API status return values
+ *
+ * NOTE: The error msgs are auto generated from the comments. Only singe line
+ * comments are supported
+ */
+enum bfa_status {
+       BFA_STATUS_OK           = 0,    /*  Success */
+       BFA_STATUS_FAILED       = 1,    /*  Operation failed */
+       BFA_STATUS_EINVAL       = 2,    /*  Invalid params Check input
+                                        * parameters */
+       BFA_STATUS_ENOMEM       = 3,    /*  Out of resources */
+       BFA_STATUS_ENOSYS       = 4,    /*  Function not implemented */
+       BFA_STATUS_ETIMER       = 5,    /*  Timer expired - Retry, if
+                                        * persists, contact support */
+       BFA_STATUS_EPROTOCOL    = 6,    /*  Protocol error */
+       BFA_STATUS_ENOFCPORTS   = 7,    /*  No FC ports resources */
+       BFA_STATUS_NOFLASH      = 8,    /*  Flash not present */
+       BFA_STATUS_BADFLASH     = 9,    /*  Flash is corrupted or bad */
+       BFA_STATUS_SFP_UNSUPP   = 10,   /*  Unsupported SFP - Replace SFP */
+       BFA_STATUS_UNKNOWN_VFID = 11,   /*  VF_ID not found */
+       BFA_STATUS_DATACORRUPTED = 12,  /*  Diag returned data corrupted
+                                        * contact support */
+       BFA_STATUS_DEVBUSY      = 13,   /*  Device busy - Retry operation */
+       BFA_STATUS_ABORTED      = 14,   /*  Operation aborted */
+       BFA_STATUS_NODEV        = 15,   /*  Dev is not present */
+       BFA_STATUS_HDMA_FAILED  = 16,   /*  Host dma failed contact support */
+       BFA_STATUS_FLASH_BAD_LEN = 17,  /*  Flash bad length */
+       BFA_STATUS_UNKNOWN_LWWN = 18,   /*  LPORT PWWN not found */
+       BFA_STATUS_UNKNOWN_RWWN = 19,   /*  RPORT PWWN not found */
+       BFA_STATUS_FCPT_LS_RJT  = 20,   /*  Got LS_RJT for FC Pass
+                                        * through Req */
+       BFA_STATUS_VPORT_EXISTS = 21,   /*  VPORT already exists */
+       BFA_STATUS_VPORT_MAX    = 22,   /*  Reached max VPORT supported
+                                        * limit */
+       BFA_STATUS_UNSUPP_SPEED = 23,   /*  Invalid Speed Check speed
+                                        * setting */
+       BFA_STATUS_INVLD_DFSZ   = 24,   /*  Invalid Max data field size */
+       BFA_STATUS_CNFG_FAILED  = 25,   /*  Setting can not be persisted */
+       BFA_STATUS_CMD_NOTSUPP  = 26,   /*  Command/API not supported */
+       BFA_STATUS_NO_ADAPTER   = 27,   /*  No Brocade Adapter Found */
+       BFA_STATUS_LINKDOWN     = 28,   /*  Link is down - Check or replace
+                                        * SFP/cable */
+       BFA_STATUS_FABRIC_RJT   = 29,   /*  Reject from attached fabric */
+       BFA_STATUS_UNKNOWN_VWWN = 30,   /*  VPORT PWWN not found */
+       BFA_STATUS_NSLOGIN_FAILED = 31, /*  Nameserver login failed */
+       BFA_STATUS_NO_RPORTS    = 32,   /*  No remote ports found */
+       BFA_STATUS_NSQUERY_FAILED = 33, /*  Nameserver query failed */
+       BFA_STATUS_PORT_OFFLINE = 34,   /*  Port is not online */
+       BFA_STATUS_RPORT_OFFLINE = 35,  /*  RPORT is not online */
+       BFA_STATUS_TGTOPEN_FAILED = 36, /*  Remote SCSI target open failed */
+       BFA_STATUS_BAD_LUNS     = 37,   /*  No valid LUNs found */
+       BFA_STATUS_IO_FAILURE   = 38,   /*  SCSI target IO failure */
+       BFA_STATUS_NO_FABRIC    = 39,   /*  No switched fabric present */
+       BFA_STATUS_EBADF        = 40,   /*  Bad file descriptor */
+       BFA_STATUS_EINTR        = 41,   /*  A signal was caught during ioctl */
+       BFA_STATUS_EIO          = 42,   /*  I/O error */
+       BFA_STATUS_ENOTTY       = 43,   /*  Inappropriate I/O control
+                                        * operation */
+       BFA_STATUS_ENXIO        = 44,   /*  No such device or address */
+       BFA_STATUS_EFOPEN       = 45,   /*  Failed to open file */
+       BFA_STATUS_VPORT_WWN_BP = 46,   /*  WWN is same as base port's WWN */
+       BFA_STATUS_PORT_NOT_DISABLED = 47, /*  Port not disabled disable port
+                                           * first */
+       BFA_STATUS_BADFRMHDR    = 48,   /*  Bad frame header */
+       BFA_STATUS_BADFRMSZ     = 49,   /*  Bad frame size check and replace
+                                        * SFP/cable */
+       BFA_STATUS_MISSINGFRM   = 50,   /*  Missing frame check and replace
+                                        * SFP/cable */
+       BFA_STATUS_LINKTIMEOUT  = 51,   /*  Link timeout check and replace
+                                        * SFP/cable */
+       BFA_STATUS_NO_FCPIM_NEXUS = 52, /*  No FCP Nexus exists with the
+                                        * rport */
+       BFA_STATUS_CHECKSUM_FAIL = 53,  /*  checksum failure */
+       BFA_STATUS_GZME_FAILED  = 54,   /*  Get zone member query failed */
+       BFA_STATUS_SCSISTART_REQD = 55, /*  SCSI disk require START command */
+       BFA_STATUS_IOC_FAILURE  = 56,   /*  IOC failure - Retry, if persists
+                                        * contact support */
+       BFA_STATUS_INVALID_WWN  = 57,   /*  Invalid WWN */
+       BFA_STATUS_MISMATCH     = 58,   /*  Version mismatch */
+       BFA_STATUS_IOC_ENABLED  = 59,   /*  IOC is already enabled */
+       BFA_STATUS_ADAPTER_ENABLED = 60, /*  Adapter is not disabled disable
+                                         * adapter first */
+       BFA_STATUS_IOC_NON_OP   = 61,   /*  IOC is not operational. Enable IOC
+                                        * and if it still fails,
+                                        * contact support */
+       BFA_STATUS_ADDR_MAP_FAILURE = 62, /*  PCI base address not mapped
+                                          * in OS */
+       BFA_STATUS_SAME_NAME    = 63,   /*  Name exists! use a different
+                                        * name */
+       BFA_STATUS_PENDING      = 64,   /*  API completes asynchronously */
+       BFA_STATUS_8G_SPD       = 65,   /*  Speed setting not valid for
+                                        * 8G HBA */
+       BFA_STATUS_4G_SPD       = 66,   /*  Speed setting not valid for
+                                        * 4G HBA */
+       BFA_STATUS_AD_IS_ENABLE = 67,   /*  Adapter is already enabled */
+       BFA_STATUS_EINVAL_TOV   = 68,   /*  Invalid path failover TOV */
+       BFA_STATUS_EINVAL_QDEPTH = 69,  /*  Invalid queue depth value */
+       BFA_STATUS_VERSION_FAIL = 70,   /*  Application/Driver version
+                                        * mismatch */
+       BFA_STATUS_DIAG_BUSY    = 71,   /*  diag busy */
+       BFA_STATUS_BEACON_ON    = 72,   /*  Port Beacon already on */
+       BFA_STATUS_BEACON_OFF   = 73,   /*  Port Beacon already off */
+       BFA_STATUS_LBEACON_ON   = 74,   /*  Link End-to-End Beacon already
+                                        * on */
+       BFA_STATUS_LBEACON_OFF  = 75,   /*  Link End-to-End Beacon already
+                                        * off */
+       BFA_STATUS_PORT_NOT_INITED = 76, /*  Port not initialized */
+       BFA_STATUS_RPSC_ENABLED = 77, /*  Target has a valid speed */
+       BFA_STATUS_ENOFSAVE = 78,       /*  No saved firmware trace */
+       BFA_STATUS_BAD_FILE = 79,       /*  Not a valid Brocade Boot Code
+                                        * file */
+       BFA_STATUS_RLIM_EN = 80,        /*  Target rate limiting is already
+                                        * enabled */
+       BFA_STATUS_RLIM_DIS = 81,  /*  Target rate limiting is already
+                                   * disabled */
+       BFA_STATUS_IOC_DISABLED = 82,   /*  IOC is already disabled */
+       BFA_STATUS_ADAPTER_DISABLED = 83,   /*  Adapter is already disabled */
+       BFA_STATUS_BIOS_DISABLED = 84,   /*  Bios is already disabled */
+       BFA_STATUS_AUTH_ENABLED = 85,   /*  Authentication is already
+                                        * enabled */
+       BFA_STATUS_AUTH_DISABLED = 86,   /*  Authentication is already
+                                        * disabled */
+       BFA_STATUS_ERROR_TRL_ENABLED = 87,   /*  Target rate limiting is
+                                             * enabled */
+       BFA_STATUS_ERROR_QOS_ENABLED = 88,   /*  QoS is enabled */
+       BFA_STATUS_NO_SFP_DEV = 89, /*  No SFP device check or replace SFP */
+       BFA_STATUS_MEMTEST_FAILED = 90, /*  Memory test failed contact
+                                        * support */
+       BFA_STATUS_INVALID_DEVID = 91,  /*  Invalid device id provided */
+       BFA_STATUS_QOS_ENABLED = 92, /*  QOS is already enabled */
+       BFA_STATUS_QOS_DISABLED = 93, /*  QOS is already disabled */
+       BFA_STATUS_INCORRECT_DRV_CONFIG = 94, /*  Check configuration
+                                              * key/value pair */
+       BFA_STATUS_REG_FAIL = 95, /*  Can't read windows registry */
+       BFA_STATUS_IM_INV_CODE = 96, /*  Invalid IOCTL code */
+       BFA_STATUS_IM_INV_VLAN = 97, /*  Invalid VLAN ID */
+       BFA_STATUS_IM_INV_ADAPT_NAME = 98, /*  Invalid adapter name */
+       BFA_STATUS_IM_LOW_RESOURCES = 99, /*  Memory allocation failure in
+                                          * driver */
+       BFA_STATUS_IM_VLANID_IS_PVID = 100, /*  Given VLAN id same as PVID */
+       BFA_STATUS_IM_VLANID_EXISTS = 101, /*  Given VLAN id already exists */
+       BFA_STATUS_IM_FW_UPDATE_FAIL = 102, /*  Updating firmware with new
+                                            * VLAN ID failed */
+       BFA_STATUS_PORTLOG_ENABLED = 103, /*  Port Log is already enabled */
+       BFA_STATUS_PORTLOG_DISABLED = 104, /*  Port Log is already disabled */
+       BFA_STATUS_FILE_NOT_FOUND = 105, /*  Specified file could not be
+                                         * found */
+       BFA_STATUS_QOS_FC_ONLY = 106, /*  QOS can be enabled for FC mode
+                                      * only */
+       BFA_STATUS_RLIM_FC_ONLY = 107, /*  RATELIM can be enabled for FC mode
+                                       * only */
+       BFA_STATUS_CT_SPD = 108, /*  Invalid speed selection for Catapult. */
+       BFA_STATUS_LEDTEST_OP = 109, /*  LED test is operating */
+       BFA_STATUS_CEE_NOT_DN = 110, /*  eth port is not at down state, please
+                                     * bring down first */
+       BFA_STATUS_10G_SPD = 111, /*  Speed setting not valid for 10G HBA */
+       BFA_STATUS_IM_INV_TEAM_NAME = 112, /*  Invalid team name */
+       BFA_STATUS_IM_DUP_TEAM_NAME = 113, /*  Given team name already
+                                           * exists */
+       BFA_STATUS_IM_ADAPT_ALREADY_IN_TEAM = 114, /*  Given adapter is part
+                                                   * of another team */
+       BFA_STATUS_IM_ADAPT_HAS_VLANS = 115, /*  Adapter has VLANs configured.
+                                             * Delete all VLANs before
+                                             * creating team */
+       BFA_STATUS_IM_PVID_MISMATCH = 116, /*  Mismatching PVIDs configured
+                                           * for adapters */
+       BFA_STATUS_IM_LINK_SPEED_MISMATCH = 117, /*  Mismatching link speeds
+                                                 * configured for adapters */
+       BFA_STATUS_IM_MTU_MISMATCH = 118, /*  Mismatching MTUs configured for
+                                          * adapters */
+       BFA_STATUS_IM_RSS_MISMATCH = 119, /*  Mismatching RSS parameters
+                                          * configured for adapters */
+       BFA_STATUS_IM_HDS_MISMATCH = 120, /*  Mismatching HDS parameters
+                                          * configured for adapters */
+       BFA_STATUS_IM_OFFLOAD_MISMATCH = 121, /*  Mismatching offload
+                                              * parameters configured for
+                                              * adapters */
+       BFA_STATUS_IM_PORT_PARAMS = 122, /*  Error setting port parameters */
+       BFA_STATUS_IM_PORT_NOT_IN_TEAM = 123, /*  Port is not part of team */
+       BFA_STATUS_IM_CANNOT_REM_PRI = 124, /*  Primary adapter cannot be
+                                            * removed. Change primary before
+                                            * removing */
+       BFA_STATUS_IM_MAX_PORTS_REACHED = 125, /*  Exceeding maximum ports
+                                               * per team */
+       BFA_STATUS_IM_LAST_PORT_DELETE = 126, /*  Last port in team being
+                                              * deleted */
+       BFA_STATUS_IM_NO_DRIVER = 127, /*  IM driver is not installed */
+       BFA_STATUS_IM_MAX_VLANS_REACHED = 128, /*  Exceeding maximum VLANs
+                                               * per port */
+       BFA_STATUS_TOMCAT_SPD_NOT_ALLOWED = 129, /* Bios speed config not
+                                                 * allowed for CNA */
+       BFA_STATUS_NO_MINPORT_DRIVER = 130, /*  Miniport driver is not
+                                            * loaded */
+       BFA_STATUS_CARD_TYPE_MISMATCH = 131, /*  Card type mismatch */
+       BFA_STATUS_BAD_ASICBLK = 132, /*  Bad ASIC block */
+       BFA_STATUS_NO_DRIVER = 133, /*  Storage/Ethernet driver not loaded */
+       BFA_STATUS_INVALID_MAC = 134, /*  Invalid mac address */
+       BFA_STATUS_IM_NO_VLAN = 135, /*  No VLANs configured on the adapter */
+       BFA_STATUS_IM_ETH_LB_FAILED = 136, /*  Ethernet loopback test failed */
+       BFA_STATUS_IM_PVID_REMOVE = 137, /*  Cannot remove port vlan (PVID) */
+       BFA_STATUS_IM_PVID_EDIT = 138, /*  Cannot edit port vlan (PVID) */
+       BFA_STATUS_CNA_NO_BOOT = 139, /*  Boot upload not allowed for CNA */
+       BFA_STATUS_IM_PVID_NON_ZERO = 140, /*  Port VLAN ID (PVID) is Set to
+                                           * Non-Zero Value */
+       BFA_STATUS_IM_INETCFG_LOCK_FAILED = 141, /*  Acquiring Network
+                                                 * Subsytem Lock Failed.Please
+                                                 * try after some time */
+       BFA_STATUS_IM_GET_INETCFG_FAILED = 142, /*  Acquiring Network Subsytem
+                                                * handle Failed. Please try
+                                                * after some time */
+       BFA_STATUS_IM_NOT_BOUND = 143, /*  Brocade 10G Ethernet Service is not
+                                       * Enabled on this port */
+       BFA_STATUS_INSUFFICIENT_PERMS = 144, /*  User doesn't have sufficient
+                                             * permissions to execute the BCU
+                                             * application */
+       BFA_STATUS_IM_INV_VLAN_NAME = 145, /*  Invalid/Reserved Vlan name
+                                           * string. The name is not allowed
+                                           * for the normal Vlans */
+       BFA_STATUS_CMD_NOTSUPP_CNA = 146, /*  Command not supported for CNA */
+       BFA_STATUS_IM_PASSTHRU_EDIT = 147, /*  Can not edit passthru vlan id */
+       BFA_STATUS_IM_BIND_FAILED = 148, /*! < IM Driver bind operation
+                                         * failed */
+       BFA_STATUS_IM_UNBIND_FAILED = 149, /* ! < IM Driver unbind operation
+                                           * failed */
+       BFA_STATUS_MAX_VAL              /*  Unknown error code */
+};
+#define bfa_status_t enum bfa_status
+
+enum bfa_eproto_status {
+       BFA_EPROTO_BAD_ACCEPT = 0,
+       BFA_EPROTO_UNKNOWN_RSP = 1
+};
+#define bfa_eproto_status_t enum bfa_eproto_status
+
+#endif /* __BFA_DEFS_STATUS_H__ */
diff --git a/drivers/scsi/bfa/include/defs/bfa_defs_tin.h b/drivers/scsi/bfa/include/defs/bfa_defs_tin.h
new file mode 100644 (file)
index 0000000..e05a2db
--- /dev/null
@@ -0,0 +1,118 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ */
+
+#ifndef __BFA_DEFS_TIN_H__
+#define __BFA_DEFS_TIN_H__
+
+#include <protocol/types.h>
+#include <protocol/fc.h>
+
+/**
+ * FCS tin states
+ */
+enum bfa_tin_state_e {
+       BFA_TIN_SM_OFFLINE = 0,         /*  tin is offline */
+       BFA_TIN_SM_WOS_LOGIN = 1,       /*  Waiting PRLI ACC/RJT from ULP */
+       BFA_TIN_SM_WFW_ONLINE = 2,      /*  Waiting ACK to PRLI ACC from FW */
+       BFA_TIN_SM_ONLINE = 3,          /*  tin login is complete */
+       BFA_TIN_SM_WIO_RELOGIN = 4,     /*  tin relogin is in progress */
+       BFA_TIN_SM_WIO_LOGOUT = 5,      /*  Processing of PRLO req from
+                                        *   Initiator is in progress
+                                        */
+       BFA_TIN_SM_WOS_LOGOUT = 6,      /*  Processing of PRLO req from
+                                        *   Initiator is in progress
+                                        */
+       BFA_TIN_SM_WIO_CLEAN = 7,       /*  Waiting for IO cleanup before tin
+                                        *   is offline. This can be triggered
+                                        *   by RPORT LOGO (rcvd/sent) or by
+                                        *   PRLO (rcvd/sent)
+                                        */
+};
+
+struct bfa_prli_req_s {
+       struct fchs_s fchs;
+       struct fc_prli_s prli_payload;
+};
+
+struct bfa_prlo_req_s {
+       struct fchs_s fchs;
+       struct fc_prlo_s prlo_payload;
+};
+
+void bfa_tin_send_login_rsp(void *bfa_tin, u32 login_rsp,
+                               struct fc_ls_rjt_s rjt_payload);
+void bfa_tin_send_logout_rsp(void *bfa_tin, u32 logout_rsp,
+                               struct fc_ls_rjt_s rjt_payload);
+/**
+ * FCS target port statistics
+ */
+struct bfa_tin_stats_s {
+       u32 onlines;    /*  ITN nexus onlines (PRLI done) */
+       u32 offlines;   /*  ITN Nexus offlines  */
+       u32 prli_req_parse_err; /*  prli req parsing errors */
+       u32 prli_rsp_rjt;       /*  num prli rsp rejects sent */
+       u32 prli_rsp_acc;       /*  num prli rsp accepts sent */
+       u32 cleanup_comps;      /*  ITN cleanup completions */
+};
+
+/**
+ * FCS tin attributes returned in queries
+ */
+struct bfa_tin_attr_s {
+       enum bfa_tin_state_e state;
+       u8      seq_retry;    /*  Sequence retry supported      */
+       u8      rsvd[3];
+};
+
+/**
+ * BFA TIN async event data structure for BFAL
+ */
+enum bfa_tin_aen_event {
+       BFA_TIN_AEN_ONLINE      = 1,    /*  Target online */
+       BFA_TIN_AEN_OFFLINE     = 2,    /*  Target offline */
+       BFA_TIN_AEN_DISCONNECT  = 3,    /*  Target disconnected */
+};
+
+/**
+ * BFA TIN event data structure.
+ */
+struct bfa_tin_aen_data_s {
+       u16 vf_id;      /*  vf_id of the IT nexus */
+       u16 rsvd[3];
+       wwn_t lpwwn;    /*  WWN of logical port */
+       wwn_t rpwwn;    /*  WWN of remote(target) port */
+};
+
+/**
+ * Below APIs are needed from BFA driver
+ * Move these to BFA driver public header file?
+ */
+/*  TIN rcvd new PRLI & gets bfad_tin_t ptr from driver this callback */
+void *bfad_tin_rcvd_login_req(void *bfad_tm_port, void *bfa_tin,
+                               wwn_t rp_wwn, u32 rp_fcid,
+                               struct bfa_prli_req_s prli_req);
+/*  TIN rcvd new PRLO */
+void bfad_tin_rcvd_logout_req(void *bfad_tin, wwn_t rp_wwn, u32 rp_fcid,
+                               struct bfa_prlo_req_s prlo_req);
+/*  TIN is online and ready for IO */
+void bfad_tin_online(void *bfad_tin);
+/*  TIN is offline and BFA driver can shutdown its upper stack */
+void bfad_tin_offline(void *bfad_tin);
+/*  TIN does not need this BFA driver tin tag anymore, so can be freed */
+void bfad_tin_res_free(void *bfad_tin);
+
+#endif /* __BFA_DEFS_TIN_H__ */
diff --git a/drivers/scsi/bfa/include/defs/bfa_defs_tsensor.h b/drivers/scsi/bfa/include/defs/bfa_defs_tsensor.h
new file mode 100644 (file)
index 0000000..31881d2
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ */
+
+#ifndef __BFA_DEFS_TSENSOR_H__
+#define __BFA_DEFS_TSENSOR_H__
+
+#include <bfa_os_inc.h>
+#include <defs/bfa_defs_types.h>
+
+/**
+ * Temperature sensor status values
+ */
+enum bfa_tsensor_status {
+       BFA_TSENSOR_STATUS_UNKNOWN   = 1,   /*  unkown status */
+       BFA_TSENSOR_STATUS_FAULTY    = 2,   /*  sensor is faulty */
+       BFA_TSENSOR_STATUS_BELOW_MIN = 3,   /*  temperature below mininum */
+       BFA_TSENSOR_STATUS_NOMINAL   = 4,   /*  normal temperature */
+       BFA_TSENSOR_STATUS_ABOVE_MAX = 5,   /*  temperature above maximum */
+};
+
+/**
+ * Temperature sensor attribute
+ */
+struct bfa_tsensor_attr_s {
+       enum bfa_tsensor_status status; /*  temperature sensor status */
+       u32             value;  /*  current temperature in celsius */
+};
+
+#endif /* __BFA_DEFS_TSENSOR_H__ */
diff --git a/drivers/scsi/bfa/include/defs/bfa_defs_types.h b/drivers/scsi/bfa/include/defs/bfa_defs_types.h
new file mode 100644 (file)
index 0000000..4348332
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ */
+#ifndef __BFA_DEFS_TYPES_H__
+#define __BFA_DEFS_TYPES_H__
+
+#include <bfa_os_inc.h>
+
+enum bfa_boolean {
+       BFA_FALSE = 0,
+       BFA_TRUE  = 1
+};
+#define bfa_boolean_t enum bfa_boolean
+
+#define BFA_STRING_32  32
+
+#endif /* __BFA_DEFS_TYPES_H__ */
diff --git a/drivers/scsi/bfa/include/defs/bfa_defs_version.h b/drivers/scsi/bfa/include/defs/bfa_defs_version.h
new file mode 100644 (file)
index 0000000..f8902a2
--- /dev/null
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ */
+#ifndef __BFA_DEFS_VERSION_H__
+#define __BFA_DEFS_VERSION_H__
+
+#define BFA_VERSION_LEN                64
+
+#endif
diff --git a/drivers/scsi/bfa/include/defs/bfa_defs_vf.h b/drivers/scsi/bfa/include/defs/bfa_defs_vf.h
new file mode 100644 (file)
index 0000000..3235be5
--- /dev/null
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ */
+
+#ifndef __BFA_DEFS_VF_H__
+#define __BFA_DEFS_VF_H__
+
+#include <bfa_os_inc.h>
+#include <defs/bfa_defs_port.h>
+#include <protocol/types.h>
+
+/**
+ * VF states
+ */
+enum bfa_vf_state {
+       BFA_VF_UNINIT    = 0,   /*  fabric is not yet initialized */
+       BFA_VF_LINK_DOWN = 1,   /*  link is down */
+       BFA_VF_FLOGI     = 2,   /*  flogi is in progress */
+       BFA_VF_AUTH      = 3,   /*  authentication in progress */
+       BFA_VF_NOFABRIC  = 4,   /*  fabric is not present */
+       BFA_VF_ONLINE    = 5,   /*  login to fabric is complete */
+       BFA_VF_EVFP      = 6,   /*  EVFP is in progress */
+       BFA_VF_ISOLATED  = 7,   /*  port isolated due to vf_id mismatch */
+};
+
+/**
+ * VF statistics
+ */
+struct bfa_vf_stats_s {
+       u32        flogi_sent;  /*  Num FLOGIs sent             */
+       u32        flogi_rsp_err;       /*  FLOGI response errors       */
+       u32        flogi_acc_err;       /*  FLOGI accept errors         */
+       u32        flogi_accepts;       /*  FLOGI accepts received      */
+       u32        flogi_rejects;       /*  FLOGI rejects received      */
+       u32        flogi_unknown_rsp; /*  Unknown responses for FLOGI */
+       u32        flogi_alloc_wait; /*  Allocation waits prior to
+                                          * sending FLOGI
+                                          */
+       u32        flogi_rcvd;  /*  FLOGIs received */
+       u32        flogi_rejected;      /*  Incoming FLOGIs rejected */
+       u32        fabric_onlines;      /*  Internal fabric online
+                                        * notification sent to other
+                                        * modules
+                                        */
+       u32        fabric_offlines; /*  Internal fabric offline
+                                         * notification sent to other
+                                         * modules
+                                         */
+       u32        resvd;
+};
+
+/**
+ * VF attributes returned in queries
+ */
+struct bfa_vf_attr_s {
+       enum bfa_vf_state  state;               /*  VF state */
+       u32        rsvd;
+       wwn_t           fabric_name;    /*  fabric name */
+};
+
+#endif /* __BFA_DEFS_VF_H__ */
diff --git a/drivers/scsi/bfa/include/defs/bfa_defs_vport.h b/drivers/scsi/bfa/include/defs/bfa_defs_vport.h
new file mode 100644 (file)
index 0000000..9f021f4
--- /dev/null
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ */
+
+#ifndef __BFA_DEFS_VPORT_H__
+#define __BFA_DEFS_VPORT_H__
+
+#include <bfa_os_inc.h>
+#include <defs/bfa_defs_port.h>
+#include <protocol/types.h>
+
+/**
+ * VPORT states
+ */
+enum bfa_vport_state {
+       BFA_FCS_VPORT_UNINIT            = 0,
+       BFA_FCS_VPORT_CREATED           = 1,
+       BFA_FCS_VPORT_OFFLINE           = 1,
+       BFA_FCS_VPORT_FDISC_SEND        = 2,
+       BFA_FCS_VPORT_FDISC             = 3,
+       BFA_FCS_VPORT_FDISC_RETRY       = 4,
+       BFA_FCS_VPORT_ONLINE            = 5,
+       BFA_FCS_VPORT_DELETING          = 6,
+       BFA_FCS_VPORT_CLEANUP           = 6,
+       BFA_FCS_VPORT_LOGO_SEND         = 7,
+       BFA_FCS_VPORT_LOGO                      = 8,
+       BFA_FCS_VPORT_ERROR                     = 9,
+       BFA_FCS_VPORT_MAX_STATE,
+};
+
+/**
+ * vport statistics
+ */
+struct bfa_vport_stats_s {
+       struct bfa_port_stats_s port_stats;     /*  base class (port) stats */
+       /*
+        * TODO - remove
+        */
+
+       u32        fdisc_sent;  /*  num fdisc sent */
+       u32        fdisc_accepts;       /*  fdisc accepts */
+       u32        fdisc_retries;       /*  fdisc retries */
+       u32        fdisc_timeouts;      /*  fdisc timeouts */
+       u32        fdisc_rsp_err;       /*  fdisc response error */
+       u32        fdisc_acc_bad;       /*  bad fdisc accepts */
+       u32        fdisc_rejects;       /*  fdisc rejects */
+       u32        fdisc_unknown_rsp;
+       /*
+        *!< fdisc rsp unknown error
+        */
+       u32        fdisc_alloc_wait;/*  fdisc req (fcxp)alloc wait */
+
+       u32        logo_alloc_wait;/*  logo req (fcxp) alloc wait */
+       u32        logo_sent;   /*  logo sent */
+       u32        logo_accepts;        /*  logo accepts */
+       u32        logo_rejects;        /*  logo rejects */
+       u32        logo_rsp_err;        /*  logo rsp errors */
+       u32        logo_unknown_rsp;
+                       /*  logo rsp unknown errors */
+
+       u32        fab_no_npiv; /*  fabric does not support npiv */
+
+       u32        fab_offline; /*  offline events from fab SM */
+       u32        fab_online;  /*  online events from fab SM */
+       u32        fab_cleanup; /*  cleanup request from fab SM */
+       u32        rsvd;
+};
+
+/**
+ * BFA vport attribute returned in queries
+ */
+struct bfa_vport_attr_s {
+       struct bfa_port_attr_s   port_attr; /*  base class (port) attributes */
+       enum bfa_vport_state vport_state; /*  vport state */
+       u32          rsvd;
+};
+
+#endif /* __BFA_DEFS_VPORT_H__ */
diff --git a/drivers/scsi/bfa/include/fcb/bfa_fcb.h b/drivers/scsi/bfa/include/fcb/bfa_fcb.h
new file mode 100644 (file)
index 0000000..2963b0b
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) 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.
+ */
+
+/**
+ *  bfa_fcb.h BFA FCS callback interfaces
+ */
+
+#ifndef __BFA_FCB_H__
+#define __BFA_FCB_H__
+
+/**
+ *  fcb Main fcs callbacks
+ */
+
+void bfa_fcb_exit(struct bfad_s *bfad);
+
+
+
+#endif /* __BFA_FCB_H__ */
diff --git a/drivers/scsi/bfa/include/fcb/bfa_fcb_fcpim.h b/drivers/scsi/bfa/include/fcb/bfa_fcb_fcpim.h
new file mode 100644 (file)
index 0000000..a6c70ae
--- /dev/null
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) 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.
+ */
+
+/**
+* : bfad_fcpim.h - BFA FCS initiator mode remote port callbacks
+ */
+
+#ifndef __BFAD_FCB_FCPIM_H__
+#define __BFAD_FCB_FCPIM_H__
+
+struct bfad_itnim_s;
+
+/*
+ * RPIM callbacks
+ */
+
+/**
+ *     Memory allocation for remote port instance. Called before PRLI is
+ *     initiated to the remote target port.
+ *
+ * @param[in] bfad             - driver instance
+ * @param[out] itnim           - FCS remote port (IM) instance
+ * @param[out] itnim_drv       - driver remote port (IM) instance
+ *
+ * @return None
+ */
+void bfa_fcb_itnim_alloc(struct bfad_s *bfad, struct bfa_fcs_itnim_s **itnim,
+                                   struct bfad_itnim_s **itnim_drv);
+
+/**
+ *             Free remote port (IM) instance.
+ *
+ * @param[in] bfad     - driver instance
+ * @param[in] itnim_drv        - driver remote port instance
+ *
+ * @return None
+ */
+void            bfa_fcb_itnim_free(struct bfad_s *bfad,
+                                  struct bfad_itnim_s *itnim_drv);
+
+/**
+ *     Notification of when login with a remote target device is complete.
+ *
+ * @param[in] itnim_drv        - driver remote port instance
+ *
+ * @return None
+ */
+void            bfa_fcb_itnim_online(struct bfad_itnim_s *itnim_drv);
+
+/**
+ *     Notification when login with the remote device is severed.
+ *
+ * @param[in] itnim_drv        - driver remote port instance
+ *
+ * @return None
+ */
+void            bfa_fcb_itnim_offline(struct bfad_itnim_s *itnim_drv);
+
+void            bfa_fcb_itnim_tov_begin(struct bfad_itnim_s *itnim_drv);
+void            bfa_fcb_itnim_tov(struct bfad_itnim_s *itnim_drv);
+
+#endif /* __BFAD_FCB_FCPIM_H__ */
diff --git a/drivers/scsi/bfa/include/fcb/bfa_fcb_port.h b/drivers/scsi/bfa/include/fcb/bfa_fcb_port.h
new file mode 100644 (file)
index 0000000..5fd7f98
--- /dev/null
@@ -0,0 +1,113 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) 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.
+ */
+
+/**
+ *  bfa_fcb_port.h BFA FCS virtual port driver interfaces
+ */
+
+#ifndef __BFA_FCB_PORT_H__
+#define __BFA_FCB_PORT_H__
+
+#include <fcb/bfa_fcb_vport.h>
+/**
+ *  fcs_port_fcb FCS port driver interfaces
+ */
+
+/*
+ * Forward declarations
+ */
+struct bfad_port_s;
+
+/*
+ * Callback functions from BFA FCS to driver
+ */
+
+/**
+ *     Call from FCS to driver module when a port is instantiated. The port
+ *     can be a base port or a virtual port with in the base fabric or
+ *     a virtual fabric.
+ *
+ *  On this callback, driver is supposed to create scsi_host, scsi_tgt or
+ *  network interfaces bases on ports personality/roles.
+ *
+ *      base port of base fabric:      vf_drv == NULL && vp_drv == NULL
+ *      vport of base fabric:          vf_drv == NULL && vp_drv != NULL
+ *      base port of VF:               vf_drv != NULL && vp_drv == NULL
+ *      vport of VF:                   vf_drv != NULL && vp_drv != NULL
+ *
+ * @param[in] bfad   - driver instance
+ * @param[in] port   - FCS port instance
+ * @param[in] roles  - port roles: IM, TM, IP
+ * @param[in] vf_drv - VF driver instance, NULL if base fabric (no VF)
+ * @param[in] vp_drv - vport driver instance, NULL if base port
+ *
+ * @return None
+ */
+struct bfad_port_s *bfa_fcb_port_new(struct bfad_s *bfad,
+                       struct bfa_fcs_port_s *port,
+                       enum bfa_port_role roles, struct bfad_vf_s *vf_drv,
+                       struct bfad_vport_s *vp_drv);
+
+/**
+ *     Call from FCS to driver module when a port is deleted. The port
+ *     can be a base port or a virtual port with in the base fabric or
+ *     a virtual fabric.
+ *
+ * @param[in] bfad   - driver instance
+ * @param[in] roles  - port roles: IM, TM, IP
+ * @param[in] vf_drv - VF driver instance, NULL if base fabric (no VF)
+ * @param[in] vp_drv - vport driver instance, NULL if base port
+ *
+ * @return None
+ */
+void bfa_fcb_port_delete(struct bfad_s *bfad, enum bfa_port_role roles,
+                       struct bfad_vf_s *vf_drv, struct bfad_vport_s *vp_drv);
+
+/**
+ *     Notification when port transitions to ONLINE state.
+ *
+ * Online notification is a logical link up for the local port. This
+ * notification is sent after a successfull FLOGI, or a successful
+ * link initialization in proviate-loop or N2N topologies.
+ *
+ * @param[in] bfad   - driver instance
+ * @param[in] roles  - port roles: IM, TM, IP
+ * @param[in] vf_drv - VF driver instance, NULL if base fabric (no VF)
+ * @param[in] vp_drv - vport driver instance, NULL if base port
+ *
+ * @return None
+ */
+void bfa_fcb_port_online(struct bfad_s *bfad, enum bfa_port_role roles,
+                       struct bfad_vf_s *vf_drv, struct bfad_vport_s *vp_drv);
+
+/**
+ *     Notification when port transitions to OFFLINE state.
+ *
+ * Offline notification is a logical link down for the local port.
+ *
+ * @param[in] bfad   - driver instance
+ * @param[in] roles  - port roles: IM, TM, IP
+ * @param[in] vf_drv - VF driver instance, NULL if base fabric (no VF)
+ * @param[in] vp_drv - vport driver instance, NULL if base port
+ *
+ * @return None
+ */
+void bfa_fcb_port_offline(struct bfad_s *bfad, enum bfa_port_role roles,
+                       struct bfad_vf_s *vf_drv, struct bfad_vport_s *vp_drv);
+
+
+#endif /* __BFA_FCB_PORT_H__ */
diff --git a/drivers/scsi/bfa/include/fcb/bfa_fcb_rport.h b/drivers/scsi/bfa/include/fcb/bfa_fcb_rport.h
new file mode 100644 (file)
index 0000000..e0261bb
--- /dev/null
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) 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.
+ */
+
+/**
+ *  bfa_fcb_rport.h BFA FCS rport driver interfaces
+ */
+
+#ifndef __BFA_FCB_RPORT_H__
+#define __BFA_FCB_RPORT_H__
+
+/**
+ *  fcs_rport_fcb Remote port driver interfaces
+ */
+
+
+struct bfad_rport_s;
+
+/*
+ * Callback functions from BFA FCS to driver
+ */
+
+/**
+ *     Completion callback for bfa_fcs_rport_add().
+ *
+ * @param[in] rport_drv - driver instance of rport
+ *
+ * @return None
+ */
+void bfa_fcb_rport_add(struct bfad_rport_s *rport_drv);
+
+/**
+ *     Completion callback for bfa_fcs_rport_remove().
+ *
+ * @param[in] rport_drv - driver instance of rport
+ *
+ * @return None
+ */
+void bfa_fcb_rport_remove(struct bfad_rport_s *rport_drv);
+
+/**
+ *             Call to allocate a rport instance.
+ *
+ * @param[in] bfad - driver instance
+ * @param[out] rport - BFA FCS instance of rport
+ * @param[out] rport_drv - driver instance of rport
+ *
+ * @retval BFA_STATUS_OK - successfully allocated
+ * @retval BFA_STATUS_ENOMEM - cannot allocate
+ */
+bfa_status_t bfa_fcb_rport_alloc(struct bfad_s *bfad,
+                       struct bfa_fcs_rport_s **rport,
+                       struct bfad_rport_s **rport_drv);
+
+/**
+ *     Call to free rport memory resources.
+ *
+ * @param[in] bfad - driver instance
+ * @param[in] rport_drv - driver instance of rport
+ *
+ * @return None
+ */
+void bfa_fcb_rport_free(struct bfad_s *bfad, struct bfad_rport_s **rport_drv);
+
+
+
+#endif /* __BFA_FCB_RPORT_H__ */
diff --git a/drivers/scsi/bfa/include/fcb/bfa_fcb_vf.h b/drivers/scsi/bfa/include/fcb/bfa_fcb_vf.h
new file mode 100644 (file)
index 0000000..cfd3fac
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) 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.
+ */
+
+/**
+ *  bfa_fcb_vf.h BFA FCS virtual fabric driver interfaces
+ */
+
+#ifndef __BFA_FCB_VF_H__
+#define __BFA_FCB_VF_H__
+
+/**
+ *  fcs_vf_fcb Virtual fabric driver intrefaces
+ */
+
+
+struct bfad_vf_s;
+
+/*
+ * Callback functions from BFA FCS to driver
+ */
+
+/**
+ *     Completion callback for bfa_fcs_vf_stop().
+ *
+ * @param[in] vf_drv - driver instance of vf
+ *
+ * @return None
+ */
+void            bfa_fcb_vf_stop(struct bfad_vf_s *vf_drv);
+
+
+
+#endif /* __BFA_FCB_VF_H__ */
diff --git a/drivers/scsi/bfa/include/fcb/bfa_fcb_vport.h b/drivers/scsi/bfa/include/fcb/bfa_fcb_vport.h
new file mode 100644 (file)
index 0000000..a39f474
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) 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.
+ */
+
+/**
+ *  bfa_fcb_vport.h BFA FCS virtual port driver interfaces
+ */
+
+#ifndef __BFA_FCB_VPORT_H__
+#define __BFA_FCB_VPORT_H__
+
+/**
+ *  fcs_vport_fcb Virtual port driver interfaces
+ */
+
+
+struct bfad_vport_s;
+
+/*
+ * Callback functions from BFA FCS to driver
+ */
+
+/**
+ *     Completion callback for bfa_fcs_vport_delete().
+ *
+ * @param[in] vport_drv - driver instance of vport
+ *
+ * @return None
+ */
+void            bfa_fcb_vport_delete(struct bfad_vport_s *vport_drv);
+
+
+
+#endif /* __BFA_FCB_VPORT_H__ */
diff --git a/drivers/scsi/bfa/include/fcs/bfa_fcs.h b/drivers/scsi/bfa/include/fcs/bfa_fcs.h
new file mode 100644 (file)
index 0000000..627669c
--- /dev/null
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ */
+
+#ifndef __BFA_FCS_H__
+#define __BFA_FCS_H__
+
+#include <cs/bfa_debug.h>
+#include <defs/bfa_defs_status.h>
+#include <defs/bfa_defs_version.h>
+#include <bfa.h>
+#include <fcs/bfa_fcs_fabric.h>
+
+#define BFA_FCS_OS_STR_LEN             64
+
+struct bfa_fcs_stats_s {
+       struct {
+               u32        untagged; /*  untagged receive frames */
+               u32        tagged;      /*  tagged receive frames */
+               u32        vfid_unknown;        /*  VF id is unknown */
+       } uf;
+};
+
+struct bfa_fcs_driver_info_s {
+       u8  version[BFA_VERSION_LEN];           /*  Driver Version */
+       u8  host_machine_name[BFA_FCS_OS_STR_LEN];
+       u8  host_os_name[BFA_FCS_OS_STR_LEN]; /*  OS name and version */
+       u8  host_os_patch[BFA_FCS_OS_STR_LEN];/*  patch or service pack */
+       u8  os_device_name[BFA_FCS_OS_STR_LEN]; /*  Driver Device Name */
+};
+
+struct bfa_fcs_s {
+       struct bfa_s      *bfa; /*  corresponding BFA bfa instance */
+       struct bfad_s         *bfad; /*  corresponding BDA driver instance */
+       struct bfa_log_mod_s  *logm;    /*  driver logging module instance */
+       struct bfa_trc_mod_s  *trcmod;  /*  tracing module */
+       struct bfa_aen_s      *aen;     /*  aen component */
+       bfa_boolean_t   vf_enabled;     /*  VF mode is enabled */
+       bfa_boolean_t min_cfg;          /* min cfg enabled/disabled */
+       u16        port_vfid;   /*  port default VF ID */
+       struct bfa_fcs_driver_info_s driver_info;
+       struct bfa_fcs_fabric_s fabric; /*  base fabric state machine */
+       struct bfa_fcs_stats_s  stats;  /*  FCS statistics */
+       struct bfa_wc_s         wc;     /*  waiting counter */
+};
+
+/*
+ * bfa fcs API functions
+ */
+void bfa_fcs_init(struct bfa_fcs_s *fcs, struct bfa_s *bfa, struct bfad_s *bfad,
+                       bfa_boolean_t min_cfg);
+void bfa_fcs_driver_info_init(struct bfa_fcs_s *fcs,
+                       struct bfa_fcs_driver_info_s *driver_info);
+void bfa_fcs_exit(struct bfa_fcs_s *fcs);
+void bfa_fcs_trc_init(struct bfa_fcs_s *fcs, struct bfa_trc_mod_s *trcmod);
+void bfa_fcs_log_init(struct bfa_fcs_s *fcs, struct bfa_log_mod_s *logmod);
+void bfa_fcs_aen_init(struct bfa_fcs_s *fcs, struct bfa_aen_s *aen);
+void           bfa_fcs_start(struct bfa_fcs_s *fcs);
+
+#endif /* __BFA_FCS_H__ */
diff --git a/drivers/scsi/bfa/include/fcs/bfa_fcs_auth.h b/drivers/scsi/bfa/include/fcs/bfa_fcs_auth.h
new file mode 100644 (file)
index 0000000..28c4c9f
--- /dev/null
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ */
+
+#ifndef __BFA_FCS_AUTH_H__
+#define __BFA_FCS_AUTH_H__
+
+struct bfa_fcs_s;
+
+#include <defs/bfa_defs_status.h>
+#include <defs/bfa_defs_auth.h>
+#include <defs/bfa_defs_vf.h>
+#include <cs/bfa_q.h>
+#include <cs/bfa_sm.h>
+#include <defs/bfa_defs_pport.h>
+#include <fcs/bfa_fcs_lport.h>
+#include <protocol/fc_sp.h>
+
+struct bfa_fcs_fabric_s;
+
+
+
+struct bfa_fcs_auth_s {
+       bfa_sm_t        sm;     /*  state machine */
+       bfa_boolean_t   policy; /*  authentication enabled/disabled */
+       enum bfa_auth_status status;    /*  authentication status */
+       enum auth_rjt_codes  rjt_code;  /*  auth reject status */
+       enum auth_rjt_code_exps  rjt_code_exp;  /*  auth reject reason */
+       enum bfa_auth_algo algo;        /*  Authentication algorithm */
+       struct bfa_auth_stats_s stats;  /*  Statistics */
+       enum auth_dh_gid   group;       /*  DH(diffie-hellman) Group */
+       enum bfa_auth_secretsource source;      /*  Secret source */
+       char            secret[BFA_AUTH_SECRET_STRING_LEN];
+                               /*  secret string */
+       u8         secret_len;
+                               /*  secret string length */
+       u8         nretries;
+                               /*  number of retries */
+       struct bfa_fcs_fabric_s *fabric;/*  pointer to fabric */
+       u8         sentcode;    /*  pointer to response data */
+       u8        *response;    /*  pointer to response data */
+       struct bfa_timer_s delay_timer;         /*  delay timer */
+       struct bfa_fcxp_s *fcxp;                /*  pointer to fcxp */
+       struct bfa_fcxp_wqe_s fcxp_wqe;
+};
+
+/**
+ * bfa fcs authentication public functions
+ */
+bfa_status_t    bfa_fcs_auth_get_attr(struct bfa_fcs_s *port,
+                                     struct bfa_auth_attr_s *attr);
+bfa_status_t    bfa_fcs_auth_set_policy(struct bfa_fcs_s *port,
+                                       bfa_boolean_t policy);
+enum bfa_auth_status bfa_fcs_auth_get_status(struct bfa_fcs_s *port);
+bfa_status_t    bfa_fcs_auth_set_algo(struct bfa_fcs_s *port,
+                                     enum bfa_auth_algo algo);
+bfa_status_t    bfa_fcs_auth_get_stats(struct bfa_fcs_s *port,
+                                      struct bfa_auth_stats_s *stats);
+bfa_status_t    bfa_fcs_auth_set_dh_group(struct bfa_fcs_s *port, int group);
+bfa_status_t    bfa_fcs_auth_set_secretstring(struct bfa_fcs_s *port,
+                                             char *secret);
+bfa_status_t    bfa_fcs_auth_set_secretstring_encrypt(struct bfa_fcs_s *port,
+                                             u32 secret[], u32 len);
+bfa_status_t    bfa_fcs_auth_set_secretsource(struct bfa_fcs_s *port,
+                                             enum bfa_auth_secretsource src);
+bfa_status_t    bfa_fcs_auth_reset_stats(struct bfa_fcs_s *port);
+bfa_status_t    bfa_fcs_auth_reinit(struct bfa_fcs_s *port);
+
+#endif /* __BFA_FCS_AUTH_H__ */
diff --git a/drivers/scsi/bfa/include/fcs/bfa_fcs_fabric.h b/drivers/scsi/bfa/include/fcs/bfa_fcs_fabric.h
new file mode 100644 (file)
index 0000000..4ffd224
--- /dev/null
@@ -0,0 +1,112 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ */
+
+#ifndef __BFA_FCS_FABRIC_H__
+#define __BFA_FCS_FABRIC_H__
+
+struct bfa_fcs_s;
+
+#include <defs/bfa_defs_status.h>
+#include <defs/bfa_defs_vf.h>
+#include <cs/bfa_q.h>
+#include <cs/bfa_sm.h>
+#include <defs/bfa_defs_pport.h>
+#include <fcs/bfa_fcs_lport.h>
+#include <protocol/fc_sp.h>
+#include <fcs/bfa_fcs_auth.h>
+
+/*
+ * forward declaration
+ */
+struct bfad_vf_s;
+
+enum bfa_fcs_fabric_type {
+       BFA_FCS_FABRIC_UNKNOWN = 0,
+       BFA_FCS_FABRIC_SWITCHED = 1,
+       BFA_FCS_FABRIC_PLOOP = 2,
+       BFA_FCS_FABRIC_N2N = 3,
+};
+
+
+struct bfa_fcs_fabric_s {
+       struct list_head   qe;          /*  queue element */
+       bfa_sm_t         sm;            /*  state machine */
+       struct bfa_fcs_s *fcs;          /*  FCS instance */
+       struct bfa_fcs_port_s  bport;   /*  base logical port */
+       enum bfa_fcs_fabric_type fab_type; /*  fabric type */
+       enum bfa_pport_type oper_type;  /*  current link topology */
+       u8         is_vf;               /*  is virtual fabric? */
+       u8         is_npiv;     /*  is NPIV supported ? */
+       u8         is_auth;     /*  is Security/Auth supported ? */
+       u16        bb_credit;   /*  BB credit from fabric */
+       u16        vf_id;               /*  virtual fabric ID */
+       u16        num_vports;  /*  num vports */
+       u16        rsvd;
+       struct list_head         vport_q;       /*  queue of virtual ports */
+       struct list_head         vf_q;  /*  queue of virtual fabrics */
+       struct bfad_vf_s      *vf_drv;  /*  driver vf structure */
+       struct bfa_timer_s link_timer;  /*  Link Failure timer. Vport */
+       wwn_t           fabric_name;    /*  attached fabric name */
+       bfa_boolean_t   auth_reqd;      /*  authentication required     */
+       struct bfa_timer_s delay_timer; /*  delay timer         */
+       union {
+               u16        swp_vfid;/*  switch port VF id               */
+       } event_arg;
+       struct bfa_fcs_auth_s  auth;    /*  authentication config       */
+       struct bfa_wc_s        wc;      /*  wait counter for delete     */
+       struct bfa_vf_stats_s  stats;   /*  fabric/vf stats             */
+       struct bfa_lps_s        *lps;   /*  lport login services        */
+       u8      fabric_ip_addr[BFA_FCS_FABRIC_IPADDR_SZ];  /*  attached
+                                                           * fabric's ip addr
+                                                           */
+};
+
+#define bfa_fcs_fabric_npiv_capable(__f)    (__f)->is_npiv
+#define bfa_fcs_fabric_is_switched(__f)                        \
+       ((__f)->fab_type == BFA_FCS_FABRIC_SWITCHED)
+
+/**
+ *   The design calls for a single implementation of base fabric and vf.
+ */
+#define bfa_fcs_vf_t struct bfa_fcs_fabric_s
+
+struct bfa_vf_event_s {
+       u32        undefined;
+};
+
+/**
+ * bfa fcs vf public functions
+ */
+bfa_status_t bfa_fcs_vf_mode_enable(struct bfa_fcs_s *fcs, u16 vf_id);
+bfa_status_t bfa_fcs_vf_mode_disable(struct bfa_fcs_s *fcs);
+bfa_status_t bfa_fcs_vf_create(bfa_fcs_vf_t *vf, struct bfa_fcs_s *fcs,
+                              u16 vf_id, struct bfa_port_cfg_s *port_cfg,
+                              struct bfad_vf_s *vf_drv);
+bfa_status_t bfa_fcs_vf_delete(bfa_fcs_vf_t *vf);
+void bfa_fcs_vf_start(bfa_fcs_vf_t *vf);
+bfa_status_t bfa_fcs_vf_stop(bfa_fcs_vf_t *vf);
+void bfa_fcs_vf_list(struct bfa_fcs_s *fcs, u16 *vf_ids, int *nvfs);
+void bfa_fcs_vf_list_all(struct bfa_fcs_s *fcs, u16 *vf_ids, int *nvfs);
+void bfa_fcs_vf_get_attr(bfa_fcs_vf_t *vf, struct bfa_vf_attr_s *vf_attr);
+void bfa_fcs_vf_get_stats(bfa_fcs_vf_t *vf,
+                         struct bfa_vf_stats_s *vf_stats);
+void bfa_fcs_vf_clear_stats(bfa_fcs_vf_t *vf);
+void bfa_fcs_vf_get_ports(bfa_fcs_vf_t *vf, wwn_t vpwwn[], int *nports);
+bfa_fcs_vf_t *bfa_fcs_vf_lookup(struct bfa_fcs_s *fcs, u16 vf_id);
+struct bfad_vf_s *bfa_fcs_vf_get_drv_vf(bfa_fcs_vf_t *vf);
+
+#endif /* __BFA_FCS_FABRIC_H__ */
diff --git a/drivers/scsi/bfa/include/fcs/bfa_fcs_fcpim.h b/drivers/scsi/bfa/include/fcs/bfa_fcs_fcpim.h
new file mode 100644 (file)
index 0000000..e719f2c
--- /dev/null
@@ -0,0 +1,131 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) 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.
+ */
+
+/**
+ *  bfa_fcs_fcpim.h BFA FCS FCP Initiator Mode interfaces/defines.
+ */
+
+#ifndef __BFA_FCS_FCPIM_H__
+#define __BFA_FCS_FCPIM_H__
+
+#include <defs/bfa_defs_status.h>
+#include <defs/bfa_defs_itnim.h>
+#include <fcs/bfa_fcs.h>
+#include <fcs/bfa_fcs_rport.h>
+#include <fcs/bfa_fcs_lport.h>
+#include <bfa_fcpim.h>
+
+/*
+ * forward declarations
+ */
+struct bfad_itnim_s;
+
+struct bfa_fcs_itnim_s {
+       bfa_sm_t                sm;             /*  state machine */
+       struct bfa_fcs_rport_s  *rport;         /*  parent remote rport  */
+       struct bfad_itnim_s     *itnim_drv;     /*  driver peer instance */
+       struct bfa_fcs_s        *fcs;           /*  fcs instance         */
+       struct bfa_timer_s      timer;          /*  timer functions      */
+       struct bfa_itnim_s      *bfa_itnim;     /*  BFA itnim struct     */
+       bfa_boolean_t           seq_rec;        /*  seq recovery support */
+       bfa_boolean_t           rec_support;    /*  REC supported        */
+       bfa_boolean_t           conf_comp;      /*  FCP_CONF     support */
+       bfa_boolean_t           task_retry_id;  /*  task retry id supp   */
+       struct bfa_fcxp_wqe_s   fcxp_wqe;       /*  wait qelem for fcxp  */
+       struct bfa_fcxp_s *fcxp;                /*  FCXP in use          */
+       struct bfa_itnim_stats_s        stats;  /*  itn statistics       */
+};
+
+
+static inline struct bfad_port_s *
+bfa_fcs_itnim_get_drvport(struct bfa_fcs_itnim_s *itnim)
+{
+       return itnim->rport->port->bfad_port;
+}
+
+
+static inline struct bfa_fcs_port_s *
+bfa_fcs_itnim_get_port(struct bfa_fcs_itnim_s *itnim)
+{
+       return itnim->rport->port;
+}
+
+
+static inline wwn_t
+bfa_fcs_itnim_get_nwwn(struct bfa_fcs_itnim_s *itnim)
+{
+       return itnim->rport->nwwn;
+}
+
+
+static inline wwn_t
+bfa_fcs_itnim_get_pwwn(struct bfa_fcs_itnim_s *itnim)
+{
+       return itnim->rport->pwwn;
+}
+
+
+static inline u32
+bfa_fcs_itnim_get_fcid(struct bfa_fcs_itnim_s *itnim)
+{
+       return itnim->rport->pid;
+}
+
+
+static inline   u32
+bfa_fcs_itnim_get_maxfrsize(struct bfa_fcs_itnim_s *itnim)
+{
+       return itnim->rport->maxfrsize;
+}
+
+
+static inline   enum fc_cos
+bfa_fcs_itnim_get_cos(struct bfa_fcs_itnim_s *itnim)
+{
+       return itnim->rport->fc_cos;
+}
+
+
+static inline struct bfad_itnim_s *
+bfa_fcs_itnim_get_drvitn(struct bfa_fcs_itnim_s *itnim)
+{
+       return itnim->itnim_drv;
+}
+
+
+static inline struct bfa_itnim_s *
+bfa_fcs_itnim_get_halitn(struct bfa_fcs_itnim_s *itnim)
+{
+       return itnim->bfa_itnim;
+}
+
+/**
+ * bfa fcs FCP Initiator mode API functions
+ */
+void bfa_fcs_itnim_get_attr(struct bfa_fcs_itnim_s *itnim,
+                       struct bfa_itnim_attr_s *attr);
+void bfa_fcs_itnim_get_stats(struct bfa_fcs_itnim_s *itnim,
+                       struct bfa_itnim_stats_s *stats);
+struct bfa_fcs_itnim_s *bfa_fcs_itnim_lookup(struct bfa_fcs_port_s *port,
+                       wwn_t rpwwn);
+bfa_status_t bfa_fcs_itnim_attr_get(struct bfa_fcs_port_s *port, wwn_t rpwwn,
+                       struct bfa_itnim_attr_s *attr);
+bfa_status_t bfa_fcs_itnim_stats_get(struct bfa_fcs_port_s *port, wwn_t rpwwn,
+                       struct bfa_itnim_stats_s *stats);
+bfa_status_t bfa_fcs_itnim_stats_clear(struct bfa_fcs_port_s *port,
+                       wwn_t rpwwn);
+#endif /* __BFA_FCS_FCPIM_H__ */
diff --git a/drivers/scsi/bfa/include/fcs/bfa_fcs_fdmi.h b/drivers/scsi/bfa/include/fcs/bfa_fcs_fdmi.h
new file mode 100644 (file)
index 0000000..4441fff
--- /dev/null
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) 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.
+ */
+
+/**
+ *  bfa_fcs_fdmi.h BFA fcs fdmi module public interface
+ */
+
+#ifndef __BFA_FCS_FDMI_H__
+#define __BFA_FCS_FDMI_H__
+#include <bfa_os_inc.h>
+#include <protocol/fdmi.h>
+
+#define        BFA_FCS_FDMI_SUPORTED_SPEEDS  (FDMI_TRANS_SPEED_1G  | \
+                                       FDMI_TRANS_SPEED_2G | \
+                                       FDMI_TRANS_SPEED_4G | \
+                                       FDMI_TRANS_SPEED_8G)
+
+/*
+* HBA Attribute Block : BFA internal representation. Note : Some variable
+* sizes have been trimmed to suit BFA For Ex : Model will be "Brocade". Based
+ * on this the size has been reduced to 16 bytes from the standard's 64 bytes.
+ */
+struct bfa_fcs_fdmi_hba_attr_s {
+       wwn_t           node_name;
+       u8         manufacturer[64];
+       u8         serial_num[64];
+       u8         model[16];
+       u8         model_desc[256];
+       u8         hw_version[8];
+       u8         driver_version[8];
+       u8         option_rom_ver[BFA_VERSION_LEN];
+       u8         fw_version[8];
+       u8         os_name[256];
+       u32        max_ct_pyld;
+};
+
+/*
+ * Port Attribute Block
+ */
+struct bfa_fcs_fdmi_port_attr_s {
+       u8         supp_fc4_types[32];  /* supported FC4 types */
+       u32        supp_speed;  /* supported speed */
+       u32        curr_speed;  /* current Speed */
+       u32        max_frm_size;        /* max frame size */
+       u8         os_device_name[256]; /* OS device Name */
+       u8         host_name[256];      /* host name */
+};
+
+#endif /* __BFA_FCS_FDMI_H__ */
diff --git a/drivers/scsi/bfa/include/fcs/bfa_fcs_lport.h b/drivers/scsi/bfa/include/fcs/bfa_fcs_lport.h
new file mode 100644 (file)
index 0000000..b85cba8
--- /dev/null
@@ -0,0 +1,226 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) 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.
+ */
+
+/**
+ *  bfa_fcs_port.h BFA fcs port module public interface
+ */
+
+#ifndef __BFA_FCS_PORT_H__
+#define __BFA_FCS_PORT_H__
+
+#include <defs/bfa_defs_status.h>
+#include <defs/bfa_defs_port.h>
+#include <defs/bfa_defs_pport.h>
+#include <defs/bfa_defs_rport.h>
+#include <cs/bfa_q.h>
+#include <bfa_svc.h>
+#include <cs/bfa_wc.h>
+
+struct bfa_fcs_s;
+struct bfa_fcs_fabric_s;
+
+/*
+* @todo : need to move to a global config file.
+ * Maximum Vports supported per physical port or vf.
+ */
+#define BFA_FCS_MAX_VPORTS_SUPP_CB  255
+#define BFA_FCS_MAX_VPORTS_SUPP_CT  191
+
+/*
+* @todo : need to move to a global config file.
+ * Maximum Rports supported per port (physical/logical).
+ */
+#define BFA_FCS_MAX_RPORTS_SUPP  256   /* @todo : tentative value */
+
+
+struct bfa_fcs_port_ns_s {
+       bfa_sm_t        sm;             /*  state machine */
+       struct bfa_timer_s timer;
+       struct bfa_fcs_port_s *port;    /*  parent port */
+       struct bfa_fcxp_s *fcxp;
+       struct bfa_fcxp_wqe_s fcxp_wqe;
+};
+
+
+struct bfa_fcs_port_scn_s {
+       bfa_sm_t        sm;             /*  state machine */
+       struct bfa_timer_s timer;
+       struct bfa_fcs_port_s *port;    /*  parent port */
+       struct bfa_fcxp_s *fcxp;
+       struct bfa_fcxp_wqe_s fcxp_wqe;
+};
+
+
+struct bfa_fcs_port_fdmi_s {
+       bfa_sm_t        sm;             /*  state machine */
+       struct bfa_timer_s timer;
+       struct bfa_fcs_port_ms_s *ms;   /*  parent ms */
+       struct bfa_fcxp_s *fcxp;
+       struct bfa_fcxp_wqe_s fcxp_wqe;
+       u8         retry_cnt;   /*  retry count */
+       u8                 rsvd[3];
+};
+
+
+struct bfa_fcs_port_ms_s {
+       bfa_sm_t        sm;             /*  state machine */
+       struct bfa_timer_s timer;
+       struct bfa_fcs_port_s *port;    /*  parent port */
+       struct bfa_fcxp_s *fcxp;
+       struct bfa_fcxp_wqe_s fcxp_wqe;
+       struct bfa_fcs_port_fdmi_s fdmi;        /*  FDMI component of MS */
+       u8         retry_cnt;   /*  retry count */
+       u8                 rsvd[3];
+};
+
+
+struct bfa_fcs_port_fab_s {
+       struct bfa_fcs_port_ns_s ns;    /*  NS component of port */
+       struct bfa_fcs_port_scn_s scn;  /*  scn component of port */
+       struct bfa_fcs_port_ms_s ms;    /*  MS component of port */
+};
+
+
+
+#define        MAX_ALPA_COUNT          127
+
+struct bfa_fcs_port_loop_s {
+       u8         num_alpa;    /*  Num of ALPA entries in the map */
+       u8         alpa_pos_map[MAX_ALPA_COUNT];        /*  ALPA Positional
+                                                        *Map */
+       struct bfa_fcs_port_s *port;    /*  parent port */
+};
+
+
+
+struct bfa_fcs_port_n2n_s {
+       u32        rsvd;
+       u16        reply_oxid;  /*  ox_id from the req flogi to be
+                                        *used in flogi acc */
+       wwn_t           rem_port_wwn;   /*  Attached port's wwn */
+};
+
+
+union bfa_fcs_port_topo_u {
+       struct bfa_fcs_port_fab_s pfab;
+       struct bfa_fcs_port_loop_s ploop;
+       struct bfa_fcs_port_n2n_s pn2n;
+};
+
+
+struct bfa_fcs_port_s {
+       struct list_head         qe;    /*  used by port/vport */
+       bfa_sm_t               sm;      /*  state machine */
+       struct bfa_fcs_fabric_s *fabric;        /*  parent fabric */
+       struct bfa_port_cfg_s  port_cfg;        /*  port configuration */
+       struct bfa_timer_s link_timer;  /*  timer for link offline */
+       u32        pid : 24;    /*  FC address */
+       u8         lp_tag;              /*  lport tag */
+       u16        num_rports;  /*  Num of r-ports */
+       struct list_head rport_q;       /*  queue of discovered r-ports */
+       struct bfa_fcs_s *fcs;  /*  FCS instance */
+       union bfa_fcs_port_topo_u port_topo;    /*  fabric/loop/n2n details */
+       struct bfad_port_s *bfad_port;  /*  driver peer instance */
+       struct bfa_fcs_vport_s *vport;  /*  NULL for base ports */
+       struct bfa_fcxp_s *fcxp;
+       struct bfa_fcxp_wqe_s fcxp_wqe;
+       struct bfa_port_stats_s stats;
+       struct bfa_wc_s        wc;      /*  waiting counter for events */
+};
+
+#define bfa_fcs_lport_t struct bfa_fcs_port_s
+
+/**
+ * Symbolic Name related defines
+ *  Total bytes 255.
+ *  Physical Port's symbolic name 128 bytes.
+ *  For Vports, Vport's symbolic name is appended to the Physical port's
+ *  Symbolic Name.
+ *
+ *  Physical Port's symbolic name Format : (Total 128 bytes)
+ *  Adapter Model number/name : 12 bytes
+ *  Driver Version     : 10 bytes
+ *  Host Machine Name  : 30 bytes
+ *     Host OS Info       : 48 bytes
+ *     Host OS PATCH Info : 16 bytes
+ *  ( remaining 12 bytes reserved to be used for separator)
+ */
+#define BFA_FCS_PORT_SYMBNAME_SEPARATOR                " | "
+
+#define BFA_FCS_PORT_SYMBNAME_MODEL_SZ                 12
+#define BFA_FCS_PORT_SYMBNAME_VERSION_SZ               10
+#define BFA_FCS_PORT_SYMBNAME_MACHINENAME_SZ   30
+#define BFA_FCS_PORT_SYMBNAME_OSINFO_SZ                        48
+#define BFA_FCS_PORT_SYMBNAME_OSPATCH_SZ               16
+
+/**
+ * Get FC port ID for a logical port.
+ */
+#define bfa_fcs_port_get_fcid(_lport)  ((_lport)->pid)
+#define bfa_fcs_port_get_pwwn(_lport)  ((_lport)->port_cfg.pwwn)
+#define bfa_fcs_port_get_nwwn(_lport)  ((_lport)->port_cfg.nwwn)
+#define bfa_fcs_port_get_psym_name(_lport)     ((_lport)->port_cfg.sym_name)
+#define bfa_fcs_port_is_initiator(_lport)      \
+                       ((_lport)->port_cfg.roles & BFA_PORT_ROLE_FCP_IM)
+#define bfa_fcs_port_is_target(_lport) \
+                       ((_lport)->port_cfg.roles & BFA_PORT_ROLE_FCP_TM)
+#define bfa_fcs_port_get_nrports(_lport)       \
+                       ((_lport) ? (_lport)->num_rports : 0)
+
+static inline struct bfad_port_s *
+bfa_fcs_port_get_drvport(struct bfa_fcs_port_s *port)
+{
+       return port->bfad_port;
+}
+
+
+#define bfa_fcs_port_get_opertype(_lport)      (_lport)->fabric->oper_type
+
+
+#define bfa_fcs_port_get_fabric_name(_lport)   (_lport)->fabric->fabric_name
+
+
+#define bfa_fcs_port_get_fabric_ipaddr(_lport) (_lport)->fabric->fabric_ip_addr
+
+/**
+ * bfa fcs port public functions
+ */
+void bfa_fcs_cfg_base_port(struct bfa_fcs_s *fcs,
+                       struct bfa_port_cfg_s *port_cfg);
+struct bfa_fcs_port_s *bfa_fcs_get_base_port(struct bfa_fcs_s *fcs);
+void bfa_fcs_port_get_rports(struct bfa_fcs_port_s *port,
+                       wwn_t rport_wwns[], int *nrports);
+
+wwn_t bfa_fcs_port_get_rport(struct bfa_fcs_port_s *port, wwn_t wwn,
+                       int index, int nrports, bfa_boolean_t bwwn);
+
+struct bfa_fcs_port_s *bfa_fcs_lookup_port(struct bfa_fcs_s *fcs,
+                       u16 vf_id, wwn_t lpwwn);
+
+void bfa_fcs_port_get_info(struct bfa_fcs_port_s *port,
+                       struct bfa_port_info_s *port_info);
+void bfa_fcs_port_get_attr(struct bfa_fcs_port_s *port,
+                       struct bfa_port_attr_s *port_attr);
+void bfa_fcs_port_get_stats(struct bfa_fcs_port_s *fcs_port,
+                       struct bfa_port_stats_s *port_stats);
+void bfa_fcs_port_clear_stats(struct bfa_fcs_port_s *fcs_port);
+enum bfa_pport_speed bfa_fcs_port_get_rport_max_speed(
+                       struct bfa_fcs_port_s *port);
+void bfa_fcs_port_enable_ipfc_roles(struct bfa_fcs_port_s *fcs_port);
+void bfa_fcs_port_disable_ipfc_roles(struct bfa_fcs_port_s *fcs_port);
+
+#endif /* __BFA_FCS_PORT_H__ */
diff --git a/drivers/scsi/bfa/include/fcs/bfa_fcs_rport.h b/drivers/scsi/bfa/include/fcs/bfa_fcs_rport.h
new file mode 100644 (file)
index 0000000..702b95b
--- /dev/null
@@ -0,0 +1,104 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ */
+
+#ifndef __BFA_FCS_RPORT_H__
+#define __BFA_FCS_RPORT_H__
+
+#include <defs/bfa_defs_status.h>
+#include <cs/bfa_q.h>
+#include <fcs/bfa_fcs.h>
+#include <defs/bfa_defs_rport.h>
+
+#define BFA_FCS_RPORT_DEF_DEL_TIMEOUT  90      /* in secs */
+/*
+ * forward declarations
+ */
+struct bfad_rport_s;
+
+struct bfa_fcs_itnim_s;
+struct bfa_fcs_tin_s;
+struct bfa_fcs_iprp_s;
+
+/* Rport Features (RPF) */
+struct bfa_fcs_rpf_s {
+       bfa_sm_t               sm;      /*  state machine */
+       struct bfa_fcs_rport_s *rport;  /*  parent rport */
+       struct bfa_timer_s      timer;  /*  general purpose timer */
+       struct bfa_fcxp_s       *fcxp;  /*  FCXP needed for discarding */
+       struct bfa_fcxp_wqe_s   fcxp_wqe;       /*  fcxp wait queue element */
+       int                     rpsc_retries;   /*  max RPSC retry attempts */
+       enum bfa_pport_speed    rpsc_speed;     /* Current Speed from RPSC.
+                                                * O if RPSC fails */
+       enum bfa_pport_speed    assigned_speed; /* Speed assigned by the user.
+                                                * will be used if RPSC is not
+                                                * supported by the rport */
+};
+
+struct bfa_fcs_rport_s {
+       struct list_head         qe;    /*  used by port/vport */
+       struct bfa_fcs_port_s *port;    /*  parent FCS port */
+       struct bfa_fcs_s      *fcs;     /*  fcs instance */
+       struct bfad_rport_s   *rp_drv;  /*  driver peer instance */
+       u32        pid; /*  port ID of rport */
+       u16        maxfrsize;   /*  maximum frame size */
+       u16        reply_oxid;  /*  OX_ID of inbound requests */
+       enum fc_cos        fc_cos;      /*  FC classes of service supp */
+       bfa_boolean_t   cisc;   /*  CISC capable device */
+       wwn_t           pwwn;   /*  port wwn of rport */
+       wwn_t           nwwn;   /*  node wwn of rport */
+       struct bfa_rport_symname_s psym_name; /*  port symbolic name  */
+       bfa_sm_t        sm;             /*  state machine */
+       struct bfa_timer_s timer;       /*  general purpose timer */
+       struct bfa_fcs_itnim_s *itnim;  /*  ITN initiator mode role */
+       struct bfa_fcs_tin_s *tin;      /*  ITN initiator mode role */
+       struct bfa_fcs_iprp_s *iprp;    /*  IP/FC role */
+       struct bfa_rport_s *bfa_rport;  /*  BFA Rport */
+       struct bfa_fcxp_s *fcxp;        /*  FCXP needed for discarding */
+       int             plogi_retries;  /*  max plogi retry attempts */
+       int             ns_retries;     /*  max NS query retry attempts */
+       struct bfa_fcxp_wqe_s   fcxp_wqe; /*  fcxp wait queue element */
+       struct bfa_rport_stats_s stats; /*  rport stats */
+       enum bfa_rport_function scsi_function;  /*  Initiator/Target */
+       struct bfa_fcs_rpf_s rpf;       /* Rport features module */
+};
+
+static inline struct bfa_rport_s *
+bfa_fcs_rport_get_halrport(struct bfa_fcs_rport_s *rport)
+{
+       return rport->bfa_rport;
+}
+
+/**
+ * bfa fcs rport API functions
+ */
+bfa_status_t bfa_fcs_rport_add(struct bfa_fcs_port_s *port, wwn_t *pwwn,
+                       struct bfa_fcs_rport_s *rport,
+                       struct bfad_rport_s *rport_drv);
+bfa_status_t bfa_fcs_rport_remove(struct bfa_fcs_rport_s *rport);
+void bfa_fcs_rport_get_attr(struct bfa_fcs_rport_s *rport,
+                       struct bfa_rport_attr_s *attr);
+void bfa_fcs_rport_get_stats(struct bfa_fcs_rport_s *rport,
+                       struct bfa_rport_stats_s *stats);
+void bfa_fcs_rport_clear_stats(struct bfa_fcs_rport_s *rport);
+struct bfa_fcs_rport_s *bfa_fcs_rport_lookup(struct bfa_fcs_port_s *port,
+                       wwn_t rpwwn);
+struct bfa_fcs_rport_s *bfa_fcs_rport_lookup_by_nwwn(
+                       struct bfa_fcs_port_s *port, wwn_t rnwwn);
+void bfa_fcs_rport_set_del_timeout(u8 rport_tmo);
+void bfa_fcs_rport_set_speed(struct bfa_fcs_rport_s *rport,
+                       enum bfa_pport_speed speed);
+#endif /* __BFA_FCS_RPORT_H__ */
diff --git a/drivers/scsi/bfa/include/fcs/bfa_fcs_vport.h b/drivers/scsi/bfa/include/fcs/bfa_fcs_vport.h
new file mode 100644 (file)
index 0000000..cd33f2c
--- /dev/null
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) 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.
+ */
+
+/**
+ *  bfa_fcs_vport.h BFA fcs vport module public interface
+ */
+
+#ifndef __BFA_FCS_VPORT_H__
+#define __BFA_FCS_VPORT_H__
+
+#include <defs/bfa_defs_status.h>
+#include <defs/bfa_defs_port.h>
+#include <defs/bfa_defs_vport.h>
+#include <fcs/bfa_fcs.h>
+#include <fcb/bfa_fcb_vport.h>
+
+struct bfa_fcs_vport_s {
+       struct list_head                qe;             /*  queue elem   */
+       bfa_sm_t                sm;             /*  state machine       */
+       bfa_fcs_lport_t         lport;          /*  logical port        */
+       struct bfa_timer_s      timer;          /*  general purpose timer */
+       struct bfad_vport_s     *vport_drv;     /*  Driver private      */
+       struct bfa_vport_stats_s vport_stats;   /*  vport statistics    */
+       struct bfa_lps_s        *lps;           /*  Lport login service */
+       int                     fdisc_retries;
+};
+
+#define bfa_fcs_vport_get_port(vport) \
+                       ((struct bfa_fcs_port_s  *)(&vport->port))
+
+/**
+ * bfa fcs vport public functions
+ */
+bfa_status_t bfa_fcs_vport_create(struct bfa_fcs_vport_s *vport,
+                       struct bfa_fcs_s *fcs, u16 vf_id,
+                       struct bfa_port_cfg_s *port_cfg,
+                       struct bfad_vport_s *vport_drv);
+bfa_status_t bfa_fcs_vport_delete(struct bfa_fcs_vport_s *vport);
+bfa_status_t bfa_fcs_vport_start(struct bfa_fcs_vport_s *vport);
+bfa_status_t bfa_fcs_vport_stop(struct bfa_fcs_vport_s *vport);
+void bfa_fcs_vport_get_attr(struct bfa_fcs_vport_s *vport,
+                       struct bfa_vport_attr_s *vport_attr);
+void bfa_fcs_vport_get_stats(struct bfa_fcs_vport_s *vport,
+                       struct bfa_vport_stats_s *vport_stats);
+void bfa_fcs_vport_clr_stats(struct bfa_fcs_vport_s *vport);
+struct bfa_fcs_vport_s *bfa_fcs_vport_lookup(struct bfa_fcs_s *fcs,
+                       u16 vf_id, wwn_t vpwwn);
+
+#endif /* __BFA_FCS_VPORT_H__ */
diff --git a/drivers/scsi/bfa/include/log/bfa_log_fcs.h b/drivers/scsi/bfa/include/log/bfa_log_fcs.h
new file mode 100644 (file)
index 0000000..b6f5df8
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) 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.
+ */
+
+/*
+ * messages define for FCS Module
+ */
+#ifndef        __BFA_LOG_FCS_H__
+#define        __BFA_LOG_FCS_H__
+#include  <cs/bfa_log.h>
+#define BFA_LOG_FCS_FABRIC_NOSWITCH    \
+       (((u32) BFA_LOG_FCS_ID << BFA_LOG_MODID_OFFSET) | 1)
+#define BFA_LOG_FCS_FABRIC_ISOLATED    \
+       (((u32) BFA_LOG_FCS_ID << BFA_LOG_MODID_OFFSET) | 2)
+#endif
diff --git a/drivers/scsi/bfa/include/log/bfa_log_hal.h b/drivers/scsi/bfa/include/log/bfa_log_hal.h
new file mode 100644 (file)
index 0000000..0412aea
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) 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.
+ */
+
+/* messages define for HAL Module */
+#ifndef        __BFA_LOG_HAL_H__
+#define        __BFA_LOG_HAL_H__
+#include  <cs/bfa_log.h>
+#define BFA_LOG_HAL_ASSERT \
+       (((u32) BFA_LOG_HAL_ID << BFA_LOG_MODID_OFFSET) | 1)
+#define BFA_LOG_HAL_HEARTBEAT_FAILURE \
+       (((u32) BFA_LOG_HAL_ID << BFA_LOG_MODID_OFFSET) | 2)
+#define BFA_LOG_HAL_FCPIM_PARM_INVALID \
+       (((u32) BFA_LOG_HAL_ID << BFA_LOG_MODID_OFFSET) | 3)
+#define BFA_LOG_HAL_SM_ASSERT \
+       (((u32) BFA_LOG_HAL_ID << BFA_LOG_MODID_OFFSET) | 4)
+#endif
diff --git a/drivers/scsi/bfa/include/log/bfa_log_linux.h b/drivers/scsi/bfa/include/log/bfa_log_linux.h
new file mode 100644 (file)
index 0000000..317c054
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) 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.
+ */
+
+/* messages define for LINUX Module */
+#ifndef        __BFA_LOG_LINUX_H__
+#define        __BFA_LOG_LINUX_H__
+#include  <cs/bfa_log.h>
+#define BFA_LOG_LINUX_DEVICE_CLAIMED \
+               (((u32) BFA_LOG_LINUX_ID << BFA_LOG_MODID_OFFSET) | 1)
+#define BFA_LOG_LINUX_HASH_INIT_FAILED \
+               (((u32) BFA_LOG_LINUX_ID << BFA_LOG_MODID_OFFSET) | 2)
+#define BFA_LOG_LINUX_SYSFS_FAILED \
+               (((u32) BFA_LOG_LINUX_ID << BFA_LOG_MODID_OFFSET) | 3)
+#define BFA_LOG_LINUX_MEM_ALLOC_FAILED \
+               (((u32) BFA_LOG_LINUX_ID << BFA_LOG_MODID_OFFSET) | 4)
+#define BFA_LOG_LINUX_DRIVER_REGISTRATION_FAILED \
+               (((u32) BFA_LOG_LINUX_ID << BFA_LOG_MODID_OFFSET) | 5)
+#define BFA_LOG_LINUX_ITNIM_FREE \
+               (((u32) BFA_LOG_LINUX_ID << BFA_LOG_MODID_OFFSET) | 6)
+#define BFA_LOG_LINUX_ITNIM_ONLINE \
+               (((u32) BFA_LOG_LINUX_ID << BFA_LOG_MODID_OFFSET) | 7)
+#define BFA_LOG_LINUX_ITNIM_OFFLINE \
+               (((u32) BFA_LOG_LINUX_ID << BFA_LOG_MODID_OFFSET) | 8)
+#define BFA_LOG_LINUX_SCSI_HOST_FREE \
+               (((u32) BFA_LOG_LINUX_ID << BFA_LOG_MODID_OFFSET) | 9)
+#define BFA_LOG_LINUX_SCSI_ABORT \
+               (((u32) BFA_LOG_LINUX_ID << BFA_LOG_MODID_OFFSET) | 10)
+#define BFA_LOG_LINUX_SCSI_ABORT_COMP \
+               (((u32) BFA_LOG_LINUX_ID << BFA_LOG_MODID_OFFSET) | 11)
+#endif
diff --git a/drivers/scsi/bfa/include/log/bfa_log_wdrv.h b/drivers/scsi/bfa/include/log/bfa_log_wdrv.h
new file mode 100644 (file)
index 0000000..809a95f
--- /dev/null
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) 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.
+ */
+
+/*
+ * messages define for WDRV Module
+ */
+#ifndef        __BFA_LOG_WDRV_H__
+#define        __BFA_LOG_WDRV_H__
+#include  <cs/bfa_log.h>
+#define BFA_LOG_WDRV_IOC_INIT_ERROR    \
+       (((u32) BFA_LOG_WDRV_ID << BFA_LOG_MODID_OFFSET) | 1)
+#define BFA_LOG_WDRV_IOC_INTERNAL_ERROR \
+       (((u32) BFA_LOG_WDRV_ID << BFA_LOG_MODID_OFFSET) | 2)
+#define BFA_LOG_WDRV_IOC_START_ERROR   \
+       (((u32) BFA_LOG_WDRV_ID << BFA_LOG_MODID_OFFSET) | 3)
+#define BFA_LOG_WDRV_IOC_STOP_ERROR    \
+       (((u32) BFA_LOG_WDRV_ID << BFA_LOG_MODID_OFFSET) | 4)
+#define BFA_LOG_WDRV_INSUFFICIENT_RESOURCES \
+       (((u32) BFA_LOG_WDRV_ID << BFA_LOG_MODID_OFFSET) | 5)
+#define BFA_LOG_WDRV_BASE_ADDRESS_MAP_ERROR \
+       (((u32) BFA_LOG_WDRV_ID << BFA_LOG_MODID_OFFSET) | 6)
+#endif
diff --git a/drivers/scsi/bfa/include/protocol/ct.h b/drivers/scsi/bfa/include/protocol/ct.h
new file mode 100644 (file)
index 0000000..c59d663
--- /dev/null
@@ -0,0 +1,492 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ */
+
+#ifndef __CT_H__
+#define __CT_H__
+
+#include <protocol/types.h>
+
+#pragma pack(1)
+
+struct ct_hdr_s{
+       u32     rev_id:8;       /* Revision of the CT */
+       u32     in_id:24;       /* Initiator Id */
+       u32     gs_type:8;      /* Generic service Type */
+       u32     gs_sub_type:8;  /* Generic service sub type */
+       u32     options:8;      /* options */
+       u32     rsvrd:8;        /* reserved */
+       u32     cmd_rsp_code:16;/* ct command/response code */
+       u32     max_res_size:16;/* maximum/residual size */
+       u32     frag_id:8;      /* fragment ID */
+       u32     reason_code:8;  /* reason code */
+       u32     exp_code:8;     /* explanation code */
+       u32     vendor_unq:8;   /* vendor unique */
+};
+
+/*
+ * defines for the Revision
+ */
+enum {
+       CT_GS3_REVISION = 0x01,
+};
+
+/*
+ * defines for gs_type
+ */
+enum {
+       CT_GSTYPE_KEYSERVICE    = 0xF7,
+       CT_GSTYPE_ALIASSERVICE  = 0xF8,
+       CT_GSTYPE_MGMTSERVICE   = 0xFA,
+       CT_GSTYPE_TIMESERVICE   = 0xFB,
+       CT_GSTYPE_DIRSERVICE    = 0xFC,
+};
+
+/*
+ * defines for gs_sub_type for gs type directory service
+ */
+enum {
+       CT_GSSUBTYPE_NAMESERVER = 0x02,
+};
+
+/*
+ * defines for gs_sub_type for gs type management service
+ */
+enum {
+       CT_GSSUBTYPE_CFGSERVER  = 0x01,
+       CT_GSSUBTYPE_UNZONED_NS = 0x02,
+       CT_GSSUBTYPE_ZONESERVER = 0x03,
+       CT_GSSUBTYPE_LOCKSERVER = 0x04,
+       CT_GSSUBTYPE_HBA_MGMTSERVER = 0x10,     /* for FDMI */
+};
+
+/*
+ * defines for CT response code field
+ */
+enum {
+       CT_RSP_REJECT = 0x8001,
+       CT_RSP_ACCEPT = 0x8002,
+};
+
+/*
+ * defintions for CT reason code
+ */
+enum {
+       CT_RSN_INV_CMD          = 0x01,
+       CT_RSN_INV_VER          = 0x02,
+       CT_RSN_LOGIC_ERR        = 0x03,
+       CT_RSN_INV_SIZE         = 0x04,
+       CT_RSN_LOGICAL_BUSY     = 0x05,
+       CT_RSN_PROTO_ERR        = 0x07,
+       CT_RSN_UNABLE_TO_PERF   = 0x09,
+       CT_RSN_NOT_SUPP                 = 0x0B,
+       CT_RSN_SERVER_NOT_AVBL  = 0x0D,
+       CT_RSN_SESSION_COULD_NOT_BE_ESTBD = 0x0E,
+       CT_RSN_VENDOR_SPECIFIC  = 0xFF,
+
+};
+
+/*
+ * definitions for explanations code for Name server
+ */
+enum {
+       CT_NS_EXP_NOADDITIONAL  = 0x00,
+       CT_NS_EXP_ID_NOT_REG    = 0x01,
+       CT_NS_EXP_PN_NOT_REG    = 0x02,
+       CT_NS_EXP_NN_NOT_REG    = 0x03,
+       CT_NS_EXP_CS_NOT_REG    = 0x04,
+       CT_NS_EXP_IPN_NOT_REG   = 0x05,
+       CT_NS_EXP_IPA_NOT_REG   = 0x06,
+       CT_NS_EXP_FT_NOT_REG    = 0x07,
+       CT_NS_EXP_SPN_NOT_REG   = 0x08,
+       CT_NS_EXP_SNN_NOT_REG   = 0x09,
+       CT_NS_EXP_PT_NOT_REG    = 0x0A,
+       CT_NS_EXP_IPP_NOT_REG   = 0x0B,
+       CT_NS_EXP_FPN_NOT_REG   = 0x0C,
+       CT_NS_EXP_HA_NOT_REG    = 0x0D,
+       CT_NS_EXP_FD_NOT_REG    = 0x0E,
+       CT_NS_EXP_FF_NOT_REG    = 0x0F,
+       CT_NS_EXP_ACCESSDENIED  = 0x10,
+       CT_NS_EXP_UNACCEPTABLE_ID = 0x11,
+       CT_NS_EXP_DATABASEEMPTY                 = 0x12,
+       CT_NS_EXP_NOT_REG_IN_SCOPE              = 0x13,
+       CT_NS_EXP_DOM_ID_NOT_PRESENT    = 0x14,
+       CT_NS_EXP_PORT_NUM_NOT_PRESENT  = 0x15,
+       CT_NS_EXP_NO_DEVICE_ATTACHED    = 0x16
+};
+
+/*
+ * defintions for the explanation code for all servers
+ */
+enum {
+       CT_EXP_AUTH_EXCEPTION                   = 0xF1,
+       CT_EXP_DB_FULL                                  = 0xF2,
+       CT_EXP_DB_EMPTY                                 = 0xF3,
+       CT_EXP_PROCESSING_REQ                   = 0xF4,
+       CT_EXP_UNABLE_TO_VERIFY_CONN    = 0xF5,
+       CT_EXP_DEVICES_NOT_IN_CMN_ZONE  = 0xF6
+};
+
+/*
+ * Command codes for Name server
+ */
+enum {
+       GS_GID_PN       = 0x0121,       /* Get Id on port name */
+       GS_GPN_ID       = 0x0112,       /* Get port name on ID */
+       GS_GNN_ID       = 0x0113,       /* Get node name on ID */
+       GS_GID_FT       = 0x0171,       /* Get Id on FC4 type */
+       GS_GSPN_ID      = 0x0118,       /* Get symbolic PN on ID */
+       GS_RFT_ID       = 0x0217,       /* Register fc4type on ID */
+       GS_RSPN_ID      = 0x0218,       /* Register symbolic PN on ID */
+       GS_RPN_ID       = 0x0212,       /* Register port name */
+       GS_RNN_ID       = 0x0213,       /* Register node name */
+       GS_RCS_ID       = 0x0214,       /* Register class of service */
+       GS_RPT_ID       = 0x021A,       /* Register port type */
+       GS_GA_NXT       = 0x0100,       /* Get all next */
+       GS_RFF_ID       = 0x021F,       /* Register FC4 Feature         */
+};
+
+struct fcgs_id_req_s{
+       u32     rsvd:8;
+       u32     dap:24; /* port identifier */
+};
+#define fcgs_gpnid_req_t struct fcgs_id_req_s
+#define fcgs_gnnid_req_t struct fcgs_id_req_s
+#define fcgs_gspnid_req_t struct fcgs_id_req_s
+
+struct fcgs_gidpn_req_s{
+       wwn_t   port_name;      /* port wwn */
+};
+
+struct fcgs_gidpn_resp_s{
+       u32     rsvd:8;
+       u32     dap:24; /* port identifier */
+};
+
+/**
+ * RFT_ID
+ */
+struct fcgs_rftid_req_s {
+       u32     rsvd:8;
+       u32     dap:24;         /* port identifier */
+       u32     fc4_type[8];    /* fc4 types */
+};
+
+/**
+ * RFF_ID : Register FC4 features.
+ */
+
+#define FC_GS_FCP_FC4_FEATURE_INITIATOR  0x02
+#define FC_GS_FCP_FC4_FEATURE_TARGET    0x01
+
+struct fcgs_rffid_req_s{
+    u32    rsvd          :8;
+    u32    dap           :24;          /* port identifier      */
+    u32    rsvd1         :16;
+    u32    fc4ftr_bits   :8;           /* fc4 feature bits     */
+    u32    fc4_type      :8;           /* corresponding FC4 Type */
+};
+
+/**
+ * GID_FT Request
+ */
+struct fcgs_gidft_req_s{
+       u8      reserved;
+       u8      domain_id;      /* domain, 0 - all fabric */
+       u8      area_id;        /* area, 0 - whole domain */
+       u8      fc4_type;       /* FC_TYPE_FCP for SCSI devices */
+};                             /* GID_FT Request */
+
+/**
+ * GID_FT Response
+ */
+struct fcgs_gidft_resp_s {
+       u8              last:1; /* last port identifier flag */
+       u8              reserved:7;
+       u32     pid:24; /* port identifier */
+};                             /* GID_FT Response */
+
+/**
+ * RSPN_ID
+ */
+struct fcgs_rspnid_req_s{
+       u32     rsvd:8;
+       u32     dap:24;         /* port identifier */
+       u8              spn_len;        /* symbolic port name length */
+       u8              spn[256];       /* symbolic port name */
+};
+
+/**
+ * RPN_ID
+ */
+struct fcgs_rpnid_req_s{
+       u32     rsvd:8;
+       u32     port_id:24;
+       wwn_t           port_name;
+};
+
+/**
+ * RNN_ID
+ */
+struct fcgs_rnnid_req_s{
+       u32     rsvd:8;
+       u32     port_id:24;
+       wwn_t           node_name;
+};
+
+/**
+ * RCS_ID
+ */
+struct fcgs_rcsid_req_s{
+       u32     rsvd:8;
+       u32     port_id:24;
+       u32     cos;
+};
+
+/**
+ * RPT_ID
+ */
+struct fcgs_rptid_req_s{
+       u32     rsvd:8;
+       u32     port_id:24;
+       u32     port_type:8;
+       u32     rsvd1:24;
+};
+
+/**
+ * GA_NXT Request
+ */
+struct fcgs_ganxt_req_s{
+       u32     rsvd:8;
+       u32     port_id:24;
+};
+
+/**
+ * GA_NXT Response
+ */
+struct fcgs_ganxt_rsp_s{
+       u32     port_type:8;    /* Port Type */
+       u32     port_id:24;     /* Port Identifier */
+       wwn_t           port_name;      /* Port Name */
+       u8              spn_len;        /* Length of Symbolic Port Name */
+       char            spn[255];       /* Symbolic Port Name */
+       wwn_t           node_name;      /* Node Name */
+       u8              snn_len;        /* Length of Symbolic Node Name */
+       char            snn[255];       /* Symbolic Node Name */
+       u8              ipa[8];         /* Initial Process Associator */
+       u8              ip[16];         /* IP Address */
+       u32     cos;            /* Class of Service */
+       u32     fc4types[8];    /* FC-4 TYPEs */
+       wwn_t           fabric_port_name;
+                                       /* Fabric Port Name */
+       u32     rsvd:8;         /* Reserved */
+       u32     hard_addr:24;   /* Hard Address */
+};
+
+/*
+ * Fabric Config Server
+ */
+
+/*
+ * Command codes for Fabric Configuration Server
+ */
+enum {
+       GS_FC_GFN_CMD   = 0x0114,       /* GS FC Get Fabric Name  */
+       GS_FC_GMAL_CMD  = 0x0116,       /* GS FC GMAL  */
+       GS_FC_TRACE_CMD = 0x0400,       /* GS FC Trace Route */
+       GS_FC_PING_CMD  = 0x0401,       /* GS FC Ping */
+};
+
+/*
+ * Source or Destination Port Tags.
+ */
+enum {
+       GS_FTRACE_TAG_NPORT_ID          = 1,
+       GS_FTRACE_TAG_NPORT_NAME        = 2,
+};
+
+/*
+* Port Value : Could be a Port id or wwn
+ */
+union fcgs_port_val_u{
+       u32     nport_id;
+       wwn_t           nport_wwn;
+};
+
+#define GS_FTRACE_MAX_HOP_COUNT        20
+#define GS_FTRACE_REVISION     1
+
+/*
+ * Ftrace Related Structures.
+ */
+
+/*
+ * STR (Switch Trace) Reject Reason Codes. From FC-SW.
+ */
+enum {
+       GS_FTRACE_STR_CMD_COMPLETED_SUCC        = 0,
+       GS_FTRACE_STR_CMD_NOT_SUPP_IN_NEXT_SWITCH,
+       GS_FTRACE_STR_NO_RESP_FROM_NEXT_SWITCH,
+       GS_FTRACE_STR_MAX_HOP_CNT_REACHED,
+       GS_FTRACE_STR_SRC_PORT_NOT_FOUND,
+       GS_FTRACE_STR_DST_PORT_NOT_FOUND,
+       GS_FTRACE_STR_DEVICES_NOT_IN_COMMON_ZONE,
+       GS_FTRACE_STR_NO_ROUTE_BW_PORTS,
+       GS_FTRACE_STR_NO_ADDL_EXPLN,
+       GS_FTRACE_STR_FABRIC_BUSY,
+       GS_FTRACE_STR_FABRIC_BUILD_IN_PROGRESS,
+       GS_FTRACE_STR_VENDOR_SPECIFIC_ERR_START = 0xf0,
+       GS_FTRACE_STR_VENDOR_SPECIFIC_ERR_END = 0xff,
+};
+
+/*
+ * Ftrace Request
+ */
+struct fcgs_ftrace_req_s{
+       u32     revision;
+       u16     src_port_tag;   /* Source Port tag */
+       u16     src_port_len;   /* Source Port len */
+       union fcgs_port_val_u src_port_val;     /* Source Port value */
+       u16     dst_port_tag;   /* Destination Port tag */
+       u16     dst_port_len;   /* Destination Port len */
+       union fcgs_port_val_u dst_port_val;     /* Destination Port value */
+       u32     token;
+       u8              vendor_id[8];   /* T10 Vendor Identifier */
+       u8              vendor_info[8]; /* Vendor specific Info */
+       u32     max_hop_cnt;    /* Max Hop Count */
+};
+
+/*
+ * Path info structure
+ */
+struct fcgs_ftrace_path_info_s{
+       wwn_t           switch_name;            /* Switch WWN */
+       u32     domain_id;
+       wwn_t           ingress_port_name;      /* Ingress ports wwn */
+       u32     ingress_phys_port_num;  /* Ingress ports physical port
+                                                * number
+                                                */
+       wwn_t           egress_port_name;       /* Ingress ports wwn */
+       u32     egress_phys_port_num;   /* Ingress ports physical port
+                                                * number
+                                                */
+};
+
+/*
+ * Ftrace Acc Response
+ */
+struct fcgs_ftrace_resp_s{
+       u32     revision;
+       u32     token;
+       u8              vendor_id[8];           /* T10 Vendor Identifier */
+       u8              vendor_info[8];         /* Vendor specific Info */
+       u32     str_rej_reason_code;    /* STR Reject Reason Code */
+       u32     num_path_info_entries;  /* No. of path info entries */
+       /*
+        * path info entry/entries.
+        */
+       struct fcgs_ftrace_path_info_s path_info[1];
+
+};
+
+/*
+* Fabric Config Server : FCPing
+ */
+
+/*
+ * FC Ping Request
+ */
+struct fcgs_fcping_req_s{
+       u32     revision;
+       u16     port_tag;
+       u16     port_len;       /* Port len */
+       union fcgs_port_val_u port_val; /* Port value */
+       u32     token;
+};
+
+/*
+ * FC Ping Response
+ */
+struct fcgs_fcping_resp_s{
+       u32     token;
+};
+
+/*
+ * Command codes for zone server query.
+ */
+enum {
+       ZS_GZME = 0x0124,       /* Get zone member extended */
+};
+
+/*
+ * ZS GZME request
+ */
+#define ZS_GZME_ZNAMELEN       32
+struct zs_gzme_req_s{
+       u8      znamelen;
+       u8      rsvd[3];
+       u8      zname[ZS_GZME_ZNAMELEN];
+};
+
+enum zs_mbr_type{
+       ZS_MBR_TYPE_PWWN        = 1,
+       ZS_MBR_TYPE_DOMPORT     = 2,
+       ZS_MBR_TYPE_PORTID      = 3,
+       ZS_MBR_TYPE_NWWN        = 4,
+};
+
+struct zs_mbr_wwn_s{
+       u8      mbr_type;
+       u8      rsvd[3];
+       wwn_t   wwn;
+};
+
+struct zs_query_resp_s{
+       u32     nmbrs;  /*  number of zone members */
+       struct zs_mbr_wwn_s     mbr[1];
+};
+
+/*
+ * GMAL Command ( Get ( interconnect Element) Management Address List)
+ * To retrieve the IP Address of a Switch.
+ */
+
+#define CT_GMAL_RESP_PREFIX_TELNET      "telnet://"
+#define CT_GMAL_RESP_PREFIX_HTTP        "http://"
+
+/*  GMAL/GFN request */
+struct fcgs_req_s {
+       wwn_t    wwn;   /* PWWN/NWWN */
+};
+
+#define fcgs_gmal_req_t struct fcgs_req_s
+#define fcgs_gfn_req_t struct fcgs_req_s
+
+/* Accept Response to GMAL */
+struct fcgs_gmal_resp_s {
+       u32             ms_len;   /* Num of entries */
+       u8      ms_ma[256];
+};
+
+struct fc_gmal_entry_s {
+       u8  len;
+       u8  prefix[7]; /* like "http://" */
+       u8  ip_addr[248];
+};
+
+#pragma pack()
+
+#endif
diff --git a/drivers/scsi/bfa/include/protocol/fc.h b/drivers/scsi/bfa/include/protocol/fc.h
new file mode 100644 (file)
index 0000000..3e39ba5
--- /dev/null
@@ -0,0 +1,1105 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ */
+
+#ifndef __FC_H__
+#define __FC_H__
+
+#include <protocol/types.h>
+
+#pragma pack(1)
+
+/*
+ * Fibre Channel Header Structure (FCHS) definition
+ */
+struct fchs_s {
+#ifdef __BIGENDIAN
+       u32        routing:4;   /* routing bits */
+       u32        cat_info:4;  /* category info */
+#else
+       u32        cat_info:4;  /* category info */
+       u32        routing:4;   /* routing bits */
+#endif
+       u32        d_id:24;     /* destination identifier */
+
+       u32        cs_ctl:8;    /* class specific control */
+       u32        s_id:24;     /* source identifier */
+
+       u32        type:8;              /* data structure type */
+       u32        f_ctl:24;    /* initial frame control */
+
+       u8         seq_id;              /* sequence identifier */
+       u8         df_ctl;              /* data field control */
+       u16        seq_cnt;     /* sequence count */
+
+       u16        ox_id;               /* originator exchange ID */
+       u16        rx_id;               /* responder exchange ID */
+
+       u32        ro;          /* relative offset */
+};
+/*
+ * Fibre Channel BB_E Header Structure
+ */
+struct fcbbehs_s {
+       u16     ver_rsvd;
+       u32     rsvd[2];
+       u32     rsvd__sof;
+};
+
+#define FC_SEQ_ID_MAX          256
+
+/*
+ * routing bit definitions
+ */
+enum {
+       FC_RTG_FC4_DEV_DATA     = 0x0,  /* FC-4 Device Data */
+       FC_RTG_EXT_LINK         = 0x2,  /* Extended Link Data */
+       FC_RTG_FC4_LINK_DATA    = 0x3,  /* FC-4 Link Data */
+       FC_RTG_VIDEO_DATA       = 0x4,  /* Video Data */
+       FC_RTG_EXT_HDR          = 0x5,  /* VFT, IFR or Encapsuled */
+       FC_RTG_BASIC_LINK       = 0x8,  /* Basic Link data */
+       FC_RTG_LINK_CTRL        = 0xC,  /* Link Control */
+};
+
+/*
+ * information category for extended link data and FC-4 Link Data
+ */
+enum {
+       FC_CAT_LD_REQUEST       = 0x2,  /* Request */
+       FC_CAT_LD_REPLY         = 0x3,  /* Reply */
+       FC_CAT_LD_DIAG          = 0xF,  /* for DIAG use only */
+};
+
+/*
+ * information category for extended headers (VFT, IFR or encapsulation)
+ */
+enum {
+       FC_CAT_VFT_HDR = 0x0,   /* Virtual fabric tagging header */
+       FC_CAT_IFR_HDR = 0x1,   /* Inter-Fabric routing header */
+       FC_CAT_ENC_HDR = 0x2,   /* Encapsulation header */
+};
+
+/*
+ * information category for FC-4 device data
+ */
+enum {
+       FC_CAT_UNCATEG_INFO     = 0x0,  /* Uncategorized information */
+       FC_CAT_SOLICIT_DATA     = 0x1,  /* Solicited Data */
+       FC_CAT_UNSOLICIT_CTRL   = 0x2,  /* Unsolicited Control */
+       FC_CAT_SOLICIT_CTRL     = 0x3,  /* Solicited Control */
+       FC_CAT_UNSOLICIT_DATA   = 0x4,  /* Unsolicited Data */
+       FC_CAT_DATA_DESC        = 0x5,  /* Data Descriptor */
+       FC_CAT_UNSOLICIT_CMD    = 0x6,  /* Unsolicited Command */
+       FC_CAT_CMD_STATUS       = 0x7,  /* Command Status */
+};
+
+/*
+ * information category for Link Control
+ */
+enum {
+       FC_CAT_ACK_1            = 0x00,
+       FC_CAT_ACK_0_N          = 0x01,
+       FC_CAT_P_RJT            = 0x02,
+       FC_CAT_F_RJT            = 0x03,
+       FC_CAT_P_BSY            = 0x04,
+       FC_CAT_F_BSY_DATA       = 0x05,
+       FC_CAT_F_BSY_LINK_CTL   = 0x06,
+       FC_CAT_F_LCR            = 0x07,
+       FC_CAT_NTY              = 0x08,
+       FC_CAT_END              = 0x09,
+};
+
+/*
+ * Type Field Definitions. FC-PH Section 18.5 pg. 165
+ */
+enum {
+       FC_TYPE_BLS             = 0x0,  /* Basic Link Service */
+       FC_TYPE_ELS             = 0x1,  /* Extended Link Service */
+       FC_TYPE_IP              = 0x5,  /* IP */
+       FC_TYPE_FCP             = 0x8,  /* SCSI-FCP */
+       FC_TYPE_GPP             = 0x9,  /* SCSI_GPP */
+       FC_TYPE_SERVICES        = 0x20, /* Fibre Channel Services */
+       FC_TYPE_FC_FSS          = 0x22, /* Fabric Switch Services */
+       FC_TYPE_FC_AL           = 0x23, /* FC-AL */
+       FC_TYPE_FC_SNMP         = 0x24, /* FC-SNMP */
+       FC_TYPE_MAX             = 256,  /* 256 FC-4 types */
+};
+
+struct fc_fc4types_s{
+       u8         bits[FC_TYPE_MAX / 8];
+};
+
+/*
+ * Frame Control Definitions. FC-PH Table-45. pg. 168
+ */
+enum {
+       FCTL_EC_ORIG = 0x000000,        /* exchange originator */
+       FCTL_EC_RESP = 0x800000,        /* exchange responder */
+       FCTL_SEQ_INI = 0x000000,        /* sequence initiator */
+       FCTL_SEQ_REC = 0x400000,        /* sequence recipient */
+       FCTL_FS_EXCH = 0x200000,        /* first sequence of xchg */
+       FCTL_LS_EXCH = 0x100000,        /* last sequence of xchg */
+       FCTL_END_SEQ = 0x080000,        /* last frame of sequence */
+       FCTL_SI_XFER = 0x010000,        /* seq initiative transfer */
+       FCTL_RO_PRESENT = 0x000008,     /* relative offset present */
+       FCTL_FILLBYTE_MASK = 0x000003   /* , fill byte mask */
+};
+
+/*
+ * Fabric Well Known Addresses
+ */
+enum {
+       FC_MIN_WELL_KNOWN_ADDR          = 0xFFFFF0,
+       FC_DOMAIN_CONTROLLER_MASK       = 0xFFFC00,
+       FC_ALIAS_SERVER                 = 0xFFFFF8,
+       FC_MGMT_SERVER                  = 0xFFFFFA,
+       FC_TIME_SERVER                  = 0xFFFFFB,
+       FC_NAME_SERVER                  = 0xFFFFFC,
+       FC_FABRIC_CONTROLLER            = 0xFFFFFD,
+       FC_FABRIC_PORT                  = 0xFFFFFE,
+       FC_BROADCAST_SERVER             = 0xFFFFFF
+};
+
+/*
+ * domain/area/port defines
+ */
+#define FC_DOMAIN_MASK  0xFF0000
+#define FC_DOMAIN_SHIFT 16
+#define FC_AREA_MASK    0x00FF00
+#define FC_AREA_SHIFT   8
+#define FC_PORT_MASK    0x0000FF
+#define FC_PORT_SHIFT   0
+
+#define FC_GET_DOMAIN(p)       (((p) & FC_DOMAIN_MASK) >> FC_DOMAIN_SHIFT)
+#define FC_GET_AREA(p)         (((p) & FC_AREA_MASK) >> FC_AREA_SHIFT)
+#define FC_GET_PORT(p)         (((p) & FC_PORT_MASK) >> FC_PORT_SHIFT)
+
+#define FC_DOMAIN_CTRLR(p)     (FC_DOMAIN_CONTROLLER_MASK | (FC_GET_DOMAIN(p)))
+
+enum {
+       FC_RXID_ANY = 0xFFFFU,
+};
+
+/*
+ * generic ELS command
+ */
+struct fc_els_cmd_s{
+       u32        els_code:8;  /* ELS Command Code */
+       u32        reserved:24;
+};
+
+/*
+ * ELS Command Codes. FC-PH Table-75. pg. 223
+ */
+enum {
+       FC_ELS_LS_RJT = 0x1,    /* Link Service Reject. */
+       FC_ELS_ACC = 0x02,      /* Accept */
+       FC_ELS_PLOGI = 0x03,    /* N_Port Login. */
+       FC_ELS_FLOGI = 0x04,    /* F_Port Login. */
+       FC_ELS_LOGO = 0x05,     /* Logout. */
+       FC_ELS_ABTX = 0x06,     /* Abort Exchange */
+       FC_ELS_RES = 0x08,      /* Read Exchange status */
+       FC_ELS_RSS = 0x09,      /* Read sequence status block */
+       FC_ELS_RSI = 0x0A,      /* Request Sequence Initiative */
+       FC_ELS_ESTC = 0x0C,     /* Estimate Credit. */
+       FC_ELS_RTV = 0x0E,      /* Read Timeout Value. */
+       FC_ELS_RLS = 0x0F,      /* Read Link Status. */
+       FC_ELS_ECHO = 0x10,     /* Echo */
+       FC_ELS_TEST = 0x11,     /* Test */
+       FC_ELS_RRQ = 0x12,      /* Reinstate Recovery Qualifier. */
+       FC_ELS_REC = 0x13,      /* Add this for TAPE support in FCR */
+       FC_ELS_PRLI = 0x20,     /* Process Login */
+       FC_ELS_PRLO = 0x21,     /* Process Logout. */
+       FC_ELS_SCN = 0x22,      /* State Change Notification. */
+       FC_ELS_TPRLO = 0x24,    /* Third Party Process Logout. */
+       FC_ELS_PDISC = 0x50,    /* Discover N_Port Parameters. */
+       FC_ELS_FDISC = 0x51,    /* Discover F_Port Parameters. */
+       FC_ELS_ADISC = 0x52,    /* Discover Address. */
+       FC_ELS_FAN = 0x60,      /* Fabric Address Notification */
+       FC_ELS_RSCN = 0x61,     /* Reg State Change Notification */
+       FC_ELS_SCR = 0x62,      /* State Change Registration. */
+       FC_ELS_RTIN = 0x77,     /* Mangement server request */
+       FC_ELS_RNID = 0x78,     /* Mangement server request */
+       FC_ELS_RLIR = 0x79,     /* Registered Link Incident Record */
+
+       FC_ELS_RPSC = 0x7D,     /* Report Port Speed Capabilities */
+       FC_ELS_QSA = 0x7E,      /* Query Security Attributes. Ref FC-SP */
+       FC_ELS_E2E_LBEACON = 0x81,
+                               /* End-to-End Link Beacon */
+       FC_ELS_AUTH = 0x90,     /* Authentication. Ref FC-SP */
+       FC_ELS_RFCN = 0x97,     /* Request Fabric Change Notification. Ref
+                                *FC-SP */
+
+};
+
+/*
+ *  Version numbers for FC-PH standards,
+ *  used in login to indicate what port
+ *  supports. See FC-PH-X table 158.
+ */
+enum {
+       FC_PH_VER_4_3 = 0x09,
+       FC_PH_VER_PH_3 = 0x20,
+};
+
+/*
+ * PDU size defines
+ */
+enum {
+       FC_MIN_PDUSZ = 512,
+       FC_MAX_PDUSZ = 2112,
+};
+
+/*
+ * N_Port PLOGI Common Service Parameters.
+ * FC-PH-x. Figure-76. pg. 308.
+ */
+struct fc_plogi_csp_s{
+       u8         verhi;       /* FC-PH high version */
+       u8         verlo;       /* FC-PH low version */
+       u16        bbcred;      /* BB_Credit */
+
+#ifdef __BIGENDIAN
+       u8         ciro:1,              /* continuously increasing RO */
+                       rro:1,          /* random relative offset */
+                       npiv_supp:1,    /* NPIV supported */
+                       port_type:1,    /* N_Port/F_port */
+                       altbbcred:1,    /* alternate BB_Credit */
+                       resolution:1,   /* ms/ns ED_TOV resolution */
+                       vvl_info:1,     /* VVL Info included */
+                       reserved1:1;
+
+       u8         hg_supp:1,
+                       query_dbc:1,
+                       security:1,
+                       sync_cap:1,
+                       r_t_tov:1,
+                       dh_dup_supp:1,
+                       cisc:1,         /* continuously increasing seq count */
+                       payload:1;
+#else
+       u8         reserved2:2,
+                       resolution:1,   /* ms/ns ED_TOV resolution */
+                       altbbcred:1,    /* alternate BB_Credit */
+                       port_type:1,    /* N_Port/F_port */
+                       npiv_supp:1,    /* NPIV supported */
+                       rro:1,          /* random relative offset */
+                       ciro:1;         /* continuously increasing RO */
+
+       u8         payload:1,
+                       cisc:1,         /* continuously increasing seq count */
+                       dh_dup_supp:1,
+                       r_t_tov:1,
+                       sync_cap:1,
+                       security:1,
+                       query_dbc:1,
+                       hg_supp:1;
+#endif
+
+       u16        rxsz;                /* recieve data_field size */
+
+       u16        conseq;
+       u16        ro_bitmap;
+
+       u32        e_d_tov;
+};
+
+/*
+ * N_Port PLOGI Class Specific Parameters.
+ * FC-PH-x. Figure 78. pg. 318.
+ */
+struct fc_plogi_clp_s{
+#ifdef __BIGENDIAN
+       u32        class_valid:1;
+       u32        intermix:1;  /* class intermix supported if set =1.
+                                        * valid only for class1. Reserved for
+                                        * class2 & class3
+                                        */
+       u32        reserved1:2;
+       u32        sequential:1;
+       u32        reserved2:3;
+#else
+       u32        reserved2:3;
+       u32        sequential:1;
+       u32        reserved1:2;
+       u32        intermix:1;  /* class intermix supported if set =1.
+                                        * valid only for class1. Reserved for
+                                        * class2 & class3
+                                        */
+       u32        class_valid:1;
+#endif
+
+       u32        reserved3:24;
+
+       u32        reserved4:16;
+       u32        rxsz:16;     /* Receive data_field size */
+
+       u32        reserved5:8;
+       u32        conseq:8;
+       u32        e2e_credit:16;       /* end to end credit */
+
+       u32        reserved7:8;
+       u32        ospx:8;
+       u32        reserved8:16;
+};
+
+#define FLOGI_VVL_BRCD    0x42524344 /* ASCII value for each character in
+                                     * string "BRCD" */
+
+/*
+ * PLOGI els command and reply payload
+ */
+struct fc_logi_s{
+       struct fc_els_cmd_s els_cmd;    /* ELS command code */
+       struct fc_plogi_csp_s  csp;             /* common service params */
+       wwn_t           port_name;
+       wwn_t           node_name;
+       struct fc_plogi_clp_s  class1;          /* class 1 service parameters */
+       struct fc_plogi_clp_s  class2;          /* class 2 service parameters */
+       struct fc_plogi_clp_s  class3;          /* class 3 service parameters */
+       struct fc_plogi_clp_s  class4;          /* class 4 service parameters */
+       u8         vvl[16];     /* vendor version level */
+};
+
+/*
+ * LOGO els command payload
+ */
+struct fc_logo_s{
+       struct fc_els_cmd_s    els_cmd; /* ELS command code */
+       u32        res1:8;
+       u32        nport_id:24; /* N_Port identifier of source */
+       wwn_t           orig_port_name; /* Port name of the LOGO originator */
+};
+
+/*
+ * ADISC els command payload
+ */
+struct fc_adisc_s {
+       struct fc_els_cmd_s    els_cmd; /* ELS command code */
+       u32        res1:8;
+       u32        orig_HA:24;  /* originator hard address */
+       wwn_t           orig_port_name; /* originator port name */
+       wwn_t           orig_node_name; /* originator node name */
+       u32        res2:8;
+       u32        nport_id:24; /* originator NPortID */
+};
+
+/*
+ * Exchange status block
+ */
+struct fc_exch_status_blk_s{
+       u32        oxid:16;
+       u32        rxid:16;
+       u32        res1:8;
+       u32        orig_np:24;  /* originator NPortID */
+       u32        res2:8;
+       u32        resp_np:24;  /* responder NPortID */
+       u32        es_bits;
+       u32        res3;
+       /*
+        * un modified section of the fields
+        */
+};
+
+/*
+ * RES els command payload
+ */
+struct fc_res_s {
+       struct fc_els_cmd_s    els_cmd; /* ELS command code */
+       u32        res1:8;
+       u32        nport_id:24; /* N_Port identifier of source */
+       u32        oxid:16;
+       u32        rxid:16;
+       u8         assoc_hdr[32];
+};
+
+/*
+ * RES els accept payload
+ */
+struct fc_res_acc_s{
+       struct fc_els_cmd_s els_cmd;    /* ELS command code */
+       struct fc_exch_status_blk_s fc_exch_blk; /* Exchange status block */
+};
+
+/*
+ * REC els command payload
+ */
+struct fc_rec_s {
+       struct fc_els_cmd_s    els_cmd; /* ELS command code */
+       u32        res1:8;
+       u32        nport_id:24; /* N_Port identifier of source */
+       u32        oxid:16;
+       u32        rxid:16;
+};
+
+#define FC_REC_ESB_OWN_RSP     0x80000000      /* responder owns */
+#define FC_REC_ESB_SI          0x40000000      /* SI is owned  */
+#define FC_REC_ESB_COMP                0x20000000      /* exchange is complete */
+#define FC_REC_ESB_ENDCOND_ABN 0x10000000      /* abnormal ending      */
+#define FC_REC_ESB_RQACT       0x04000000      /* recovery qual active */
+#define FC_REC_ESB_ERRP_MSK    0x03000000
+#define FC_REC_ESB_OXID_INV    0x00800000      /* invalid OXID         */
+#define FC_REC_ESB_RXID_INV    0x00400000      /* invalid RXID         */
+#define FC_REC_ESB_PRIO_INUSE  0x00200000
+
+/*
+ * REC els accept payload
+ */
+struct fc_rec_acc_s {
+       struct fc_els_cmd_s    els_cmd; /* ELS command code */
+       u32        oxid:16;
+       u32        rxid:16;
+       u32        res1:8;
+       u32        orig_id:24;  /* N_Port id of exchange originator */
+       u32        res2:8;
+       u32        resp_id:24;  /* N_Port id of exchange responder */
+       u32        count;               /* data transfer count */
+       u32        e_stat;              /* exchange status */
+};
+
+/*
+ * RSI els payload
+ */
+struct fc_rsi_s {
+       struct fc_els_cmd_s    els_cmd;
+       u32        res1:8;
+       u32        orig_sid:24;
+       u32        oxid:16;
+       u32        rxid:16;
+};
+
+/*
+ * structure for PRLI paramater pages, both request & response
+ * see FC-PH-X table 113 & 115 for explanation also FCP table 8
+ */
+struct fc_prli_params_s{
+       u32        reserved: 16;
+#ifdef __BIGENDIAN
+       u32        reserved1: 5;
+       u32        rec_support : 1;
+       u32        task_retry_id : 1;
+       u32        retry : 1;
+
+       u32        confirm : 1;
+       u32        doverlay:1;
+       u32        initiator:1;
+       u32        target:1;
+       u32        cdmix:1;
+       u32        drmix:1;
+       u32        rxrdisab:1;
+       u32        wxrdisab:1;
+#else
+       u32        retry : 1;
+       u32        task_retry_id : 1;
+       u32        rec_support : 1;
+       u32        reserved1: 5;
+
+       u32        wxrdisab:1;
+       u32        rxrdisab:1;
+       u32        drmix:1;
+       u32        cdmix:1;
+       u32        target:1;
+       u32        initiator:1;
+       u32        doverlay:1;
+       u32        confirm : 1;
+#endif
+};
+
+/*
+ * valid values for rspcode in PRLI ACC payload
+ */
+enum {
+       FC_PRLI_ACC_XQTD = 0x1,         /* request executed */
+       FC_PRLI_ACC_PREDEF_IMG = 0x5,   /* predefined image - no prli needed */
+};
+
+struct fc_prli_params_page_s{
+       u32        type:8;
+       u32        codext:8;
+#ifdef __BIGENDIAN
+       u32        origprocasv:1;
+       u32        rsppav:1;
+       u32        imagepair:1;
+       u32        reserved1:1;
+       u32        rspcode:4;
+#else
+       u32        rspcode:4;
+       u32        reserved1:1;
+       u32        imagepair:1;
+       u32        rsppav:1;
+       u32        origprocasv:1;
+#endif
+       u32        reserved2:8;
+
+       u32        origprocas;
+       u32        rspprocas;
+       struct fc_prli_params_s  servparams;
+};
+
+/*
+ * PRLI request and accept payload, FC-PH-X tables 112 & 114
+ */
+struct fc_prli_s{
+       u32        command:8;
+       u32        pglen:8;
+       u32        pagebytes:16;
+       struct fc_prli_params_page_s parampage;
+};
+
+/*
+ * PRLO logout params page
+ */
+struct fc_prlo_params_page_s{
+       u32        type:8;
+       u32        type_ext:8;
+#ifdef __BIGENDIAN
+       u32        opa_valid:1; /* originator process associator
+                                        * valid
+                                        */
+       u32        rpa_valid:1; /* responder process associator valid */
+       u32        res1:14;
+#else
+       u32        res1:14;
+       u32        rpa_valid:1; /* responder process associator valid */
+       u32        opa_valid:1; /* originator process associator
+                                        * valid
+                                        */
+#endif
+       u32        orig_process_assc;
+       u32        resp_process_assc;
+
+       u32        res2;
+};
+
+/*
+ * PRLO els command payload
+ */
+struct fc_prlo_s{
+       u32             command:8;
+       u32             page_len:8;
+       u32             payload_len:16;
+       struct fc_prlo_params_page_s    prlo_params[1];
+};
+
+/*
+ * PRLO Logout response parameter page
+ */
+struct fc_prlo_acc_params_page_s{
+       u32        type:8;
+       u32        type_ext:8;
+
+#ifdef __BIGENDIAN
+       u32        opa_valid:1; /* originator process associator
+                                        * valid
+                                        */
+       u32        rpa_valid:1; /* responder process associator valid */
+       u32        res1:14;
+#else
+       u32        res1:14;
+       u32        rpa_valid:1; /* responder process associator valid */
+       u32        opa_valid:1; /* originator process associator
+                                        * valid
+                                        */
+#endif
+       u32        orig_process_assc;
+       u32        resp_process_assc;
+
+       u32        fc4type_csp;
+};
+
+/*
+ * PRLO els command ACC payload
+ */
+struct fc_prlo_acc_s{
+       u32        command:8;
+       u32        page_len:8;
+       u32        payload_len:16;
+       struct fc_prlo_acc_params_page_s prlo_acc_params[1];
+};
+
+/*
+ * SCR els command payload
+ */
+enum {
+       FC_SCR_REG_FUNC_FABRIC_DETECTED = 0x01,
+       FC_SCR_REG_FUNC_N_PORT_DETECTED = 0x02,
+       FC_SCR_REG_FUNC_FULL = 0x03,
+       FC_SCR_REG_FUNC_CLEAR_REG = 0xFF,
+};
+
+/* SCR VU registrations */
+enum {
+       FC_VU_SCR_REG_FUNC_FABRIC_NAME_CHANGE = 0x01
+};
+
+struct fc_scr_s{
+       u32 command:8;
+       u32 res:24;
+       u32 vu_reg_func:8; /* Vendor Unique Registrations */
+       u32 res1:16;
+       u32 reg_func:8;
+};
+
+/*
+ * Information category for Basic link data
+ */
+enum {
+       FC_CAT_NOP      = 0x0,
+       FC_CAT_ABTS     = 0x1,
+       FC_CAT_RMC      = 0x2,
+       FC_CAT_BA_ACC   = 0x4,
+       FC_CAT_BA_RJT   = 0x5,
+       FC_CAT_PRMT     = 0x6,
+};
+
+/*
+ * LS_RJT els reply payload
+ */
+struct fc_ls_rjt_s {
+       struct fc_els_cmd_s    els_cmd;         /* ELS command code */
+       u32        res1:8;
+       u32        reason_code:8;               /* Reason code for reject */
+       u32        reason_code_expl:8;  /* Reason code explanation */
+       u32        vendor_unique:8;     /* Vendor specific */
+};
+
+/*
+ * LS_RJT reason codes
+ */
+enum {
+       FC_LS_RJT_RSN_INV_CMD_CODE      = 0x01,
+       FC_LS_RJT_RSN_LOGICAL_ERROR     = 0x03,
+       FC_LS_RJT_RSN_LOGICAL_BUSY      = 0x05,
+       FC_LS_RJT_RSN_PROTOCOL_ERROR    = 0x07,
+       FC_LS_RJT_RSN_UNABLE_TO_PERF_CMD = 0x09,
+       FC_LS_RJT_RSN_CMD_NOT_SUPP      = 0x0B,
+};
+
+/*
+ * LS_RJT reason code explanation
+ */
+enum {
+       FC_LS_RJT_EXP_NO_ADDL_INFO              = 0x00,
+       FC_LS_RJT_EXP_SPARMS_ERR_OPTIONS        = 0x01,
+       FC_LS_RJT_EXP_SPARMS_ERR_INI_CTL        = 0x03,
+       FC_LS_RJT_EXP_SPARMS_ERR_REC_CTL        = 0x05,
+       FC_LS_RJT_EXP_SPARMS_ERR_RXSZ           = 0x07,
+       FC_LS_RJT_EXP_SPARMS_ERR_CONSEQ         = 0x09,
+       FC_LS_RJT_EXP_SPARMS_ERR_CREDIT         = 0x0B,
+       FC_LS_RJT_EXP_INV_PORT_NAME             = 0x0D,
+       FC_LS_RJT_EXP_INV_NODE_FABRIC_NAME      = 0x0E,
+       FC_LS_RJT_EXP_INV_CSP                   = 0x0F,
+       FC_LS_RJT_EXP_INV_ASSOC_HDR             = 0x11,
+       FC_LS_RJT_EXP_ASSOC_HDR_REQD            = 0x13,
+       FC_LS_RJT_EXP_INV_ORIG_S_ID             = 0x15,
+       FC_LS_RJT_EXP_INV_OXID_RXID_COMB        = 0x17,
+       FC_LS_RJT_EXP_CMD_ALREADY_IN_PROG       = 0x19,
+       FC_LS_RJT_EXP_LOGIN_REQUIRED            = 0x1E,
+       FC_LS_RJT_EXP_INVALID_NPORT_ID          = 0x1F,
+       FC_LS_RJT_EXP_INSUFF_RES                = 0x29,
+       FC_LS_RJT_EXP_CMD_NOT_SUPP              = 0x2C,
+       FC_LS_RJT_EXP_INV_PAYLOAD_LEN           = 0x2D,
+};
+
+/*
+ * RRQ els command payload
+ */
+struct fc_rrq_s{
+       struct fc_els_cmd_s    els_cmd; /* ELS command code */
+       u32        res1:8;
+       u32        s_id:24;     /* exchange originator S_ID */
+
+       u32        ox_id:16;    /* originator exchange ID */
+       u32        rx_id:16;    /* responder exchange ID */
+
+       u32        res2[8];     /* optional association header */
+};
+
+/*
+ * ABTS BA_ACC reply payload
+ */
+struct fc_ba_acc_s{
+       u32        seq_id_valid:8;      /* set to 0x00 for Abort Exchange */
+       u32        seq_id:8;    /* invalid for Abort Exchange */
+       u32        res2:16;
+       u32        ox_id:16;    /* OX_ID from ABTS frame */
+       u32        rx_id:16;    /* RX_ID from ABTS frame */
+       u32        low_seq_cnt:16;      /* set to 0x0000 for Abort Exchange */
+       u32        high_seq_cnt:16;/* set to 0xFFFF for Abort Exchange */
+};
+
+/*
+ * ABTS BA_RJT reject payload
+ */
+struct fc_ba_rjt_s{
+       u32        res1:8;              /* Reserved */
+       u32        reason_code:8;       /* reason code for reject */
+       u32        reason_expl:8;       /* reason code explanation */
+       u32        vendor_unique:8;/* vendor unique reason code,set to 0 */
+};
+
+/*
+ * TPRLO logout parameter page
+ */
+struct fc_tprlo_params_page_s{
+       u32        type:8;
+       u32        type_ext:8;
+
+#ifdef __BIGENDIAN
+       u32        opa_valid:1;
+       u32        rpa_valid:1;
+       u32        tpo_nport_valid:1;
+       u32        global_process_logout:1;
+       u32        res1:12;
+#else
+       u32        res1:12;
+       u32        global_process_logout:1;
+       u32        tpo_nport_valid:1;
+       u32        rpa_valid:1;
+       u32        opa_valid:1;
+#endif
+
+       u32        orig_process_assc;
+       u32        resp_process_assc;
+
+       u32        res2:8;
+       u32        tpo_nport_id;
+};
+
+/*
+ * TPRLO ELS command payload
+ */
+struct fc_tprlo_s{
+       u32        command:8;
+       u32        page_len:8;
+       u32        payload_len:16;
+
+       struct fc_tprlo_params_page_s tprlo_params[1];
+};
+
+enum fc_tprlo_type{
+       FC_GLOBAL_LOGO = 1,
+       FC_TPR_LOGO
+};
+
+/*
+ * TPRLO els command ACC payload
+ */
+struct fc_tprlo_acc_s{
+       u32     command:8;
+       u32     page_len:8;
+       u32     payload_len:16;
+       struct fc_prlo_acc_params_page_s tprlo_acc_params[1];
+};
+
+/*
+ * RSCN els command req payload
+ */
+#define FC_RSCN_PGLEN  0x4
+
+enum fc_rscn_format{
+       FC_RSCN_FORMAT_PORTID   = 0x0,
+       FC_RSCN_FORMAT_AREA     = 0x1,
+       FC_RSCN_FORMAT_DOMAIN   = 0x2,
+       FC_RSCN_FORMAT_FABRIC   = 0x3,
+};
+
+struct fc_rscn_event_s{
+       u32        format:2;
+       u32        qualifier:4;
+       u32        resvd:2;
+       u32        portid:24;
+};
+
+struct fc_rscn_pl_s{
+       u8         command;
+       u8         pagelen;
+       u16        payldlen;
+       struct fc_rscn_event_s event[1];
+};
+
+/*
+ * ECHO els command req payload
+ */
+struct fc_echo_s {
+       struct fc_els_cmd_s    els_cmd;
+};
+
+/*
+ * RNID els command
+ */
+
+#define RNID_NODEID_DATA_FORMAT_COMMON                  0x00
+#define RNID_NODEID_DATA_FORMAT_FCP3                    0x08
+#define RNID_NODEID_DATA_FORMAT_DISCOVERY              0xDF
+
+#define RNID_ASSOCIATED_TYPE_UNKNOWN                    0x00000001
+#define RNID_ASSOCIATED_TYPE_OTHER                      0x00000002
+#define RNID_ASSOCIATED_TYPE_HUB                        0x00000003
+#define RNID_ASSOCIATED_TYPE_SWITCH                     0x00000004
+#define RNID_ASSOCIATED_TYPE_GATEWAY                    0x00000005
+#define RNID_ASSOCIATED_TYPE_STORAGE_DEVICE             0x00000009
+#define RNID_ASSOCIATED_TYPE_HOST                       0x0000000A
+#define RNID_ASSOCIATED_TYPE_STORAGE_SUBSYSTEM          0x0000000B
+#define RNID_ASSOCIATED_TYPE_STORAGE_ACCESS_DEVICE      0x0000000E
+#define RNID_ASSOCIATED_TYPE_NAS_SERVER                 0x00000011
+#define RNID_ASSOCIATED_TYPE_BRIDGE                     0x00000002
+#define RNID_ASSOCIATED_TYPE_VIRTUALIZATION_DEVICE      0x00000003
+#define RNID_ASSOCIATED_TYPE_MULTI_FUNCTION_DEVICE      0x000000FF
+
+/*
+ * RNID els command payload
+ */
+struct fc_rnid_cmd_s{
+       struct fc_els_cmd_s    els_cmd;
+       u32        node_id_data_format:8;
+       u32        reserved:24;
+};
+
+/*
+ * RNID els response payload
+ */
+
+struct fc_rnid_common_id_data_s{
+       wwn_t           port_name;
+       wwn_t           node_name;
+};
+
+struct fc_rnid_general_topology_data_s{
+       u32        vendor_unique[4];
+       u32        asso_type;
+       u32        phy_port_num;
+       u32        num_attached_nodes;
+       u32        node_mgmt:8;
+       u32        ip_version:8;
+       u32        udp_tcp_port_num:16;
+       u32        ip_address[4];
+       u32        reserved:16;
+       u32        vendor_specific:16;
+};
+
+struct fc_rnid_acc_s{
+       struct fc_els_cmd_s    els_cmd;
+       u32        node_id_data_format:8;
+       u32        common_id_data_length:8;
+       u32        reserved:8;
+       u32        specific_id_data_length:8;
+       struct fc_rnid_common_id_data_s common_id_data;
+       struct fc_rnid_general_topology_data_s gen_topology_data;
+};
+
+#define RNID_ASSOCIATED_TYPE_UNKNOWN                    0x00000001
+#define RNID_ASSOCIATED_TYPE_OTHER                      0x00000002
+#define RNID_ASSOCIATED_TYPE_HUB                        0x00000003
+#define RNID_ASSOCIATED_TYPE_SWITCH                     0x00000004
+#define RNID_ASSOCIATED_TYPE_GATEWAY                    0x00000005
+#define RNID_ASSOCIATED_TYPE_STORAGE_DEVICE             0x00000009
+#define RNID_ASSOCIATED_TYPE_HOST                       0x0000000A
+#define RNID_ASSOCIATED_TYPE_STORAGE_SUBSYSTEM          0x0000000B
+#define RNID_ASSOCIATED_TYPE_STORAGE_ACCESS_DEVICE      0x0000000E
+#define RNID_ASSOCIATED_TYPE_NAS_SERVER                 0x00000011
+#define RNID_ASSOCIATED_TYPE_BRIDGE                     0x00000002
+#define RNID_ASSOCIATED_TYPE_VIRTUALIZATION_DEVICE      0x00000003
+#define RNID_ASSOCIATED_TYPE_MULTI_FUNCTION_DEVICE      0x000000FF
+
+enum fc_rpsc_speed_cap{
+       RPSC_SPEED_CAP_1G = 0x8000,
+       RPSC_SPEED_CAP_2G = 0x4000,
+       RPSC_SPEED_CAP_4G = 0x2000,
+       RPSC_SPEED_CAP_10G = 0x1000,
+       RPSC_SPEED_CAP_8G = 0x0800,
+       RPSC_SPEED_CAP_16G = 0x0400,
+
+       RPSC_SPEED_CAP_UNKNOWN = 0x0001,
+};
+
+enum fc_rpsc_op_speed_s{
+       RPSC_OP_SPEED_1G = 0x8000,
+       RPSC_OP_SPEED_2G = 0x4000,
+       RPSC_OP_SPEED_4G = 0x2000,
+       RPSC_OP_SPEED_10G = 0x1000,
+       RPSC_OP_SPEED_8G = 0x0800,
+       RPSC_OP_SPEED_16G = 0x0400,
+
+       RPSC_OP_SPEED_NOT_EST = 0x0001, /*! speed not established */
+};
+
+struct fc_rpsc_speed_info_s{
+       u16        port_speed_cap;      /*! see fc_rpsc_speed_cap_t */
+       u16        port_op_speed;       /*! see fc_rpsc_op_speed_t */
+};
+
+enum link_e2e_beacon_subcmd{
+       LINK_E2E_BEACON_ON = 1,
+       LINK_E2E_BEACON_OFF = 2
+};
+
+enum beacon_type{
+       BEACON_TYPE_NORMAL      = 1,    /*! Normal Beaconing. Green */
+       BEACON_TYPE_WARN        = 2,    /*! Warning Beaconing. Yellow/Amber */
+       BEACON_TYPE_CRITICAL    = 3     /*! Critical Beaconing. Red */
+};
+
+struct link_e2e_beacon_param_s {
+       u8         beacon_type; /* Beacon Type. See beacon_type_t */
+       u8         beacon_frequency;
+                                       /* Beacon frequency. Number of blinks
+                                        * per 10 seconds
+                                        */
+       u16        beacon_duration;/* Beacon duration (in Seconds). The
+                                        * command operation should be
+                                        * terminated at the end of this
+                                        * timeout value.
+                                        *
+                                        * Ignored if diag_sub_cmd is
+                                        * LINK_E2E_BEACON_OFF.
+                                        *
+                                        * If 0, beaconing will continue till a
+                                        * BEACON OFF request is received
+                                        */
+};
+
+/*
+ * Link E2E beacon request/good response format. For LS_RJTs use fc_ls_rjt_t
+ */
+struct link_e2e_beacon_req_s{
+       u32        ls_code;     /*! FC_ELS_E2E_LBEACON in requests *
+                                        *or FC_ELS_ACC in good replies */
+       u32        ls_sub_cmd;  /*! See link_e2e_beacon_subcmd_t */
+       struct link_e2e_beacon_param_s beacon_parm;
+};
+
+/**
+ * If RPSC request is sent to the Domain Controller, the request is for
+ * all the ports within that domain (TODO - I don't think FOS implements
+ * this...).
+ */
+struct fc_rpsc_cmd_s{
+       struct fc_els_cmd_s    els_cmd;
+};
+
+/*
+ * RPSC Acc
+ */
+struct fc_rpsc_acc_s{
+       u32        command:8;
+       u32        rsvd:8;
+       u32        num_entries:16;
+
+       struct fc_rpsc_speed_info_s speed_info[1];
+};
+
+/**
+ * If RPSC2 request is sent to the Domain Controller,
+ */
+#define FC_BRCD_TOKEN    0x42524344
+
+struct fc_rpsc2_cmd_s{
+       struct fc_els_cmd_s    els_cmd;
+       u32             token;
+       u16             resvd;
+       u16             num_pids;       /* Number of pids in the request */
+       struct  {
+               u32     rsvd1:8;
+               u32     pid:24; /* port identifier */
+       } pid_list[1];
+};
+
+enum fc_rpsc2_port_type{
+       RPSC2_PORT_TYPE_UNKNOWN = 0,
+       RPSC2_PORT_TYPE_NPORT   = 1,
+       RPSC2_PORT_TYPE_NLPORT  = 2,
+       RPSC2_PORT_TYPE_NPIV_PORT  = 0x5f,
+       RPSC2_PORT_TYPE_NPORT_TRUNK  = 0x6f,
+};
+
+/*
+ * RPSC2 portInfo entry structure
+ */
+struct fc_rpsc2_port_info_s{
+    u32    pid;        /* PID */
+    u16    resvd1;
+    u16    index;      /* port number / index */
+    u8     resvd2;
+    u8         type;        /* port type N/NL/... */
+    u16    speed;      /* port Operating Speed */
+};
+
+/*
+ * RPSC2 Accept payload
+ */
+struct fc_rpsc2_acc_s{
+       u8        els_cmd;
+       u8        resvd;
+       u16       num_pids;  /* Number of pids in the request */
+       struct fc_rpsc2_port_info_s  port_info[1];    /* port information */
+};
+
+/**
+ * bit fields so that multiple classes can be specified
+ */
+enum fc_cos{
+       FC_CLASS_2      = 0x04,
+       FC_CLASS_3      = 0x08,
+       FC_CLASS_2_3    = 0x0C,
+};
+
+/*
+ * symbolic name
+ */
+struct fc_symname_s{
+       u8         symname[FC_SYMNAME_MAX];
+};
+
+struct fc_alpabm_s{
+       u8         alpa_bm[FC_ALPA_MAX / 8];
+};
+
+/*
+ * protocol default timeout values
+ */
+#define FC_ED_TOV              2
+#define FC_REC_TOV             (FC_ED_TOV + 1)
+#define FC_RA_TOV              10
+#define FC_ELS_TOV             (2 * FC_RA_TOV)
+
+/*
+ * virtual fabric related defines
+ */
+#define FC_VF_ID_NULL    0     /*  must not be used as VF_ID */
+#define FC_VF_ID_MIN     1
+#define FC_VF_ID_MAX     0xEFF
+#define FC_VF_ID_CTL     0xFEF /*  control VF_ID */
+
+/**
+ * Virtual Fabric Tagging header format
+ * @caution This is defined only in BIG ENDIAN format.
+ */
+struct fc_vft_s{
+       u32        r_ctl:8;
+       u32        ver:2;
+       u32        type:4;
+       u32        res_a:2;
+       u32        priority:3;
+       u32        vf_id:12;
+       u32        res_b:1;
+       u32        hopct:8;
+       u32        res_c:24;
+};
+
+#pragma pack()
+
+#endif
diff --git a/drivers/scsi/bfa/include/protocol/fc_sp.h b/drivers/scsi/bfa/include/protocol/fc_sp.h
new file mode 100644 (file)
index 0000000..55bb0b3
--- /dev/null
@@ -0,0 +1,224 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ */
+
+#ifndef __FC_SP_H__
+#define __FC_SP_H__
+
+#include <protocol/types.h>
+
+#pragma pack(1)
+
+enum auth_els_flags{
+       FC_AUTH_ELS_MORE_FRAGS_FLAG     = 0x80, /*! bit-7. More Fragments
+                                                * Follow
+                                                */
+       FC_AUTH_ELS_CONCAT_FLAG         = 0x40, /*! bit-6. Concatenation Flag */
+       FC_AUTH_ELS_SEQ_NUM_FLAG        = 0x01  /*! bit-0. Sequence Number */
+};
+
+enum auth_msg_codes{
+       FC_AUTH_MC_AUTH_RJT             = 0x0A, /*! Auth Reject */
+       FC_AUTH_MC_AUTH_NEG             = 0x0B, /*! Auth Negotiate */
+       FC_AUTH_MC_AUTH_DONE            = 0x0C, /*! Auth Done */
+
+       FC_AUTH_MC_DHCHAP_CHAL          = 0x10, /*! DHCHAP Challenge */
+       FC_AUTH_MC_DHCHAP_REPLY         = 0x11, /*! DHCHAP Reply */
+       FC_AUTH_MC_DHCHAP_SUCC          = 0x12, /*! DHCHAP Success */
+
+       FC_AUTH_MC_FCAP_REQ             = 0x13, /*! FCAP Request */
+       FC_AUTH_MC_FCAP_ACK             = 0x14, /*! FCAP Acknowledge */
+       FC_AUTH_MC_FCAP_CONF            = 0x15, /*! FCAP Confirm */
+
+       FC_AUTH_MC_FCPAP_INIT           = 0x16, /*! FCPAP Init */
+       FC_AUTH_MC_FCPAP_ACC            = 0x17, /*! FCPAP Accept */
+       FC_AUTH_MC_FCPAP_COMP           = 0x18, /*! FCPAP Complete */
+
+       FC_AUTH_MC_IKE_SA_INIT          = 0x22, /*! IKE SA INIT */
+       FC_AUTH_MC_IKE_SA_AUTH          = 0x23, /*! IKE SA Auth */
+       FC_AUTH_MC_IKE_CREATE_CHILD_SA  = 0x24, /*! IKE Create Child SA */
+       FC_AUTH_MC_IKE_INFO             = 0x25, /*! IKE informational */
+};
+
+enum auth_proto_version{
+       FC_AUTH_PROTO_VER_1     = 1,    /*! Protocol Version 1 */
+};
+
+enum {
+       FC_AUTH_ELS_COMMAND_CODE = 0x90,/*! Authentication ELS Command code  */
+       FC_AUTH_PROTO_PARAM_LEN_SZ = 4, /*! Size of Proto Parameter Len Field */
+       FC_AUTH_PROTO_PARAM_VAL_SZ = 4, /*! Size of Proto Parameter Val Field */
+       FC_MAX_AUTH_SECRET_LEN     = 256,
+                                       /*! Maximum secret string length */
+       FC_AUTH_NUM_USABLE_PROTO_LEN_SZ = 4,
+                                       /*! Size of usable protocols field */
+       FC_AUTH_RESP_VALUE_LEN_SZ       = 4,
+                                       /*! Size of response value length */
+       FC_MAX_CHAP_KEY_LEN     = 256,  /*! Maximum md5 digest length */
+       FC_MAX_AUTH_RETRIES     = 3,    /*! Maximum number of retries */
+       FC_MD5_DIGEST_LEN       = 16,   /*! MD5 digest length */
+       FC_SHA1_DIGEST_LEN      = 20,   /*! SHA1 digest length */
+       FC_MAX_DHG_SUPPORTED    = 1,    /*! Maximum DH Groups supported */
+       FC_MAX_ALG_SUPPORTED    = 1,    /*! Maximum algorithms supported */
+       FC_MAX_PROTO_SUPPORTED  = 1,    /*! Maximum protocols supported */
+       FC_START_TXN_ID         = 2,    /*! Starting transaction ID */
+};
+
+enum auth_proto_id{
+       FC_AUTH_PROTO_DHCHAP            = 0x00000001,
+       FC_AUTH_PROTO_FCAP              = 0x00000002,
+       FC_AUTH_PROTO_FCPAP             = 0x00000003,
+       FC_AUTH_PROTO_IKEv2             = 0x00000004,
+       FC_AUTH_PROTO_IKEv2_AUTH        = 0x00000005,
+};
+
+struct auth_name_s{
+       u16     name_tag;       /*! Name Tag = 1 for Authentication */
+       u16     name_len;       /*! Name Length = 8 for Authentication
+                                        */
+       wwn_t           name;           /*! Name. TODO - is this PWWN */
+};
+
+
+enum auth_hash_func{
+       FC_AUTH_HASH_FUNC_MD5           = 0x00000005,
+       FC_AUTH_HASH_FUNC_SHA_1         = 0x00000006,
+};
+
+enum auth_dh_gid{
+       FC_AUTH_DH_GID_0_DHG_NULL       = 0x00000000,
+       FC_AUTH_DH_GID_1_DHG_1024       = 0x00000001,
+       FC_AUTH_DH_GID_2_DHG_1280       = 0x00000002,
+       FC_AUTH_DH_GID_3_DHG_1536       = 0x00000003,
+       FC_AUTH_DH_GID_4_DHG_2048       = 0x00000004,
+       FC_AUTH_DH_GID_6_DHG_3072       = 0x00000006,
+       FC_AUTH_DH_GID_7_DHG_4096       = 0x00000007,
+       FC_AUTH_DH_GID_8_DHG_6144       = 0x00000008,
+       FC_AUTH_DH_GID_9_DHG_8192       = 0x00000009,
+};
+
+struct auth_els_msg_s {
+       u8              auth_els_code;  /*  Authentication ELS Code (0x90) */
+       u8      auth_els_flag;  /*  Authentication ELS Flags */
+       u8      auth_msg_code;  /*  Authentication Message Code */
+       u8      proto_version;  /*  Protocol Version */
+       u32     msg_len;        /*  Message Length */
+       u32     trans_id;       /*  Transaction Identifier (T_ID) */
+
+       /* Msg payload follows... */
+};
+
+
+enum auth_neg_param_tags {
+       FC_AUTH_NEG_DHCHAP_HASHLIST     = 0x0001,
+       FC_AUTH_NEG_DHCHAP_DHG_ID_LIST  = 0x0002,
+};
+
+
+struct dhchap_param_format_s {
+       u16     tag;            /*! Parameter Tag. See
+                                        * auth_neg_param_tags_t
+                                        */
+       u16     word_cnt;
+
+       /* followed by variable length parameter value... */
+};
+
+struct auth_proto_params_s {
+       u32     proto_param_len;
+       u32     proto_id;
+
+       /*
+        * Followed by variable length Protocol specific parameters. DH-CHAP
+        * uses dhchap_param_format_t
+        */
+};
+
+struct auth_neg_msg_s {
+       struct auth_name_s      auth_ini_name;
+       u32             usable_auth_protos;
+       struct auth_proto_params_s proto_params[1]; /*! (1..usable_auth_proto)
+                                                    * protocol params
+                                                    */
+};
+
+struct auth_dh_val_s {
+       u32 dh_val_len;
+       u32 dh_val[1];
+};
+
+struct auth_dhchap_chal_msg_s {
+       struct auth_els_msg_s   hdr;
+       struct auth_name_s auth_responder_name; /* TODO VRK - is auth_name_t
+                                                * type OK?
+                                                */
+       u32     hash_id;
+       u32     dh_grp_id;
+       u32     chal_val_len;
+       char            chal_val[1];
+
+       /* ...followed by variable Challenge length/value and DH length/value */
+};
+
+
+enum auth_rjt_codes {
+       FC_AUTH_RJT_CODE_AUTH_FAILURE   = 0x01,
+       FC_AUTH_RJT_CODE_LOGICAL_ERR    = 0x02,
+};
+
+enum auth_rjt_code_exps {
+       FC_AUTH_CEXP_AUTH_MECH_NOT_USABLE       = 0x01,
+       FC_AUTH_CEXP_DH_GROUP_NOT_USABLE        = 0x02,
+       FC_AUTH_CEXP_HASH_FUNC_NOT_USABLE       = 0x03,
+       FC_AUTH_CEXP_AUTH_XACT_STARTED          = 0x04,
+       FC_AUTH_CEXP_AUTH_FAILED                = 0x05,
+       FC_AUTH_CEXP_INCORRECT_PLD              = 0x06,
+       FC_AUTH_CEXP_INCORRECT_PROTO_MSG        = 0x07,
+       FC_AUTH_CEXP_RESTART_AUTH_PROTO         = 0x08,
+       FC_AUTH_CEXP_AUTH_CONCAT_NOT_SUPP       = 0x09,
+       FC_AUTH_CEXP_PROTO_VER_NOT_SUPP         = 0x0A,
+};
+
+enum auth_status {
+       FC_AUTH_STATE_INPROGRESS = 0,   /*! authentication in progress  */
+       FC_AUTH_STATE_FAILED    = 1,    /*! authentication failed */
+       FC_AUTH_STATE_SUCCESS   = 2     /*! authentication successful   */
+};
+
+struct auth_rjt_msg_s {
+       struct auth_els_msg_s   hdr;
+       u8              reason_code;
+       u8              reason_code_exp;
+       u8              rsvd[2];
+};
+
+
+struct auth_dhchap_neg_msg_s {
+       struct auth_els_msg_s hdr;
+       struct auth_neg_msg_s nego;
+};
+
+struct auth_dhchap_reply_msg_s {
+       struct auth_els_msg_s   hdr;
+
+       /*
+        * followed by response value length & Value + DH Value Length & Value
+        */
+};
+
+#pragma pack()
+
+#endif /* __FC_SP_H__ */
diff --git a/drivers/scsi/bfa/include/protocol/fcp.h b/drivers/scsi/bfa/include/protocol/fcp.h
new file mode 100644 (file)
index 0000000..9ade68a
--- /dev/null
@@ -0,0 +1,186 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ */
+
+#ifndef __FCPPROTO_H__
+#define __FCPPROTO_H__
+
+#include <protocol/scsi.h>
+
+#pragma pack(1)
+
+enum {
+       FCP_RJT         = 0x01000000,   /* SRR reject */
+       FCP_SRR_ACCEPT  = 0x02000000,   /* SRR accept */
+       FCP_SRR         = 0x14000000,   /* Sequence Retransmission Request */
+};
+
+/*
+ * SRR FC-4 LS payload
+ */
+struct fc_srr_s{
+       u32     ls_cmd;
+       u32        ox_id:16;    /* ox-id */
+       u32        rx_id:16;    /* rx-id */
+       u32        ro;          /* relative offset */
+       u32        r_ctl:8;             /* R_CTL for I.U. */
+       u32        res:24;
+};
+
+
+/*
+ * FCP_CMND definitions
+ */
+#define FCP_CMND_CDB_LEN    16
+#define FCP_CMND_LUN_LEN    8
+
+struct fcp_cmnd_s{
+       lun_t           lun;            /* 64-bit LU number */
+       u8         crn;         /* command reference number */
+#ifdef __BIGENDIAN
+       u8         resvd:1,
+                       priority:4,     /* FCP-3: SAM-3 priority */
+                       taskattr:3;     /* scsi task attribute */
+#else
+       u8         taskattr:3,  /* scsi task attribute */
+                       priority:4,     /* FCP-3: SAM-3 priority */
+                       resvd:1;
+#endif
+       u8         tm_flags;    /* task management flags */
+#ifdef __BIGENDIAN
+       u8         addl_cdb_len:6,      /* additional CDB length words */
+                       iodir:2;        /* read/write FCP_DATA IUs */
+#else
+       u8         iodir:2,     /* read/write FCP_DATA IUs */
+                       addl_cdb_len:6; /* additional CDB length */
+#endif
+       struct scsi_cdb_s      cdb;
+
+       /*
+        * !!! additional cdb bytes follows here!!!
+        */
+       u32        fcp_dl;      /* bytes to be transferred */
+};
+
+#define fcp_cmnd_cdb_len(_cmnd) ((_cmnd)->addl_cdb_len * 4 + FCP_CMND_CDB_LEN)
+#define fcp_cmnd_fcpdl(_cmnd)  ((&(_cmnd)->fcp_dl)[(_cmnd)->addl_cdb_len])
+
+/*
+ * fcp_cmnd_t.iodir field values
+ */
+enum fcp_iodir{
+       FCP_IODIR_NONE  = 0,
+       FCP_IODIR_WRITE = 1,
+       FCP_IODIR_READ  = 2,
+       FCP_IODIR_RW    = 3,
+};
+
+/*
+ * Task attribute field
+ */
+enum {
+       FCP_TASK_ATTR_SIMPLE    = 0,
+       FCP_TASK_ATTR_HOQ       = 1,
+       FCP_TASK_ATTR_ORDERED   = 2,
+       FCP_TASK_ATTR_ACA       = 4,
+       FCP_TASK_ATTR_UNTAGGED  = 5,    /* obsolete in FCP-3 */
+};
+
+/*
+ * Task management flags field - only one bit shall be set
+ */
+#ifndef BIT
+#define BIT(_x)        (1 << (_x))
+#endif
+enum fcp_tm_cmnd{
+       FCP_TM_ABORT_TASK_SET   = BIT(1),
+       FCP_TM_CLEAR_TASK_SET   = BIT(2),
+       FCP_TM_LUN_RESET        = BIT(4),
+       FCP_TM_TARGET_RESET     = BIT(5),       /* obsolete in FCP-3 */
+       FCP_TM_CLEAR_ACA        = BIT(6),
+};
+
+/*
+ * FCP_XFER_RDY IU defines
+ */
+struct fcp_xfer_rdy_s{
+       u32        data_ro;
+       u32        burst_len;
+       u32        reserved;
+};
+
+/*
+ * FCP_RSP residue flags
+ */
+enum fcp_residue{
+       FCP_NO_RESIDUE = 0,     /* no residue */
+       FCP_RESID_OVER = 1,     /* more data left that was not sent */
+       FCP_RESID_UNDER = 2,    /* less data than requested */
+};
+
+enum {
+       FCP_RSPINFO_GOOD = 0,
+       FCP_RSPINFO_DATALEN_MISMATCH = 1,
+       FCP_RSPINFO_CMND_INVALID = 2,
+       FCP_RSPINFO_ROLEN_MISMATCH = 3,
+       FCP_RSPINFO_TM_NOT_SUPP = 4,
+       FCP_RSPINFO_TM_FAILED = 5,
+};
+
+struct fcp_rspinfo_s{
+       u32        res0:24;
+       u32        rsp_code:8;  /* response code (as above) */
+       u32        res1;
+};
+
+struct fcp_resp_s{
+       u32        reserved[2]; /* 2 words reserved */
+       u16        reserved2;
+#ifdef __BIGENDIAN
+       u8         reserved3:3;
+       u8         fcp_conf_req:1;      /* FCP_CONF is requested */
+       u8         resid_flags:2;       /* underflow/overflow */
+       u8         sns_len_valid:1;/* sense len is valid */
+       u8         rsp_len_valid:1;/* response len is valid */
+#else
+       u8         rsp_len_valid:1;/* response len is valid */
+       u8         sns_len_valid:1;/* sense len is valid */
+       u8         resid_flags:2;       /* underflow/overflow */
+       u8         fcp_conf_req:1;      /* FCP_CONF is requested */
+       u8         reserved3:3;
+#endif
+       u8         scsi_status; /* one byte SCSI status */
+       u32        residue;     /* residual data bytes */
+       u32        sns_len;     /* length od sense info */
+       u32        rsp_len;     /* length of response info */
+};
+
+#define fcp_snslen(__fcprsp)   ((__fcprsp)->sns_len_valid ?            \
+                                       (__fcprsp)->sns_len : 0)
+#define fcp_rsplen(__fcprsp)   ((__fcprsp)->rsp_len_valid ?            \
+                                       (__fcprsp)->rsp_len : 0)
+#define fcp_rspinfo(__fcprsp)  ((struct fcp_rspinfo_s *)((__fcprsp) + 1))
+#define fcp_snsinfo(__fcprsp)  (((u8 *)fcp_rspinfo(__fcprsp)) +        \
+                                               fcp_rsplen(__fcprsp))
+
+struct fcp_cmnd_fr_s{
+       struct fchs_s          fchs;
+       struct fcp_cmnd_s      fcp;
+};
+
+#pragma pack()
+
+#endif
diff --git a/drivers/scsi/bfa/include/protocol/fdmi.h b/drivers/scsi/bfa/include/protocol/fdmi.h
new file mode 100644 (file)
index 0000000..6c05c26
--- /dev/null
@@ -0,0 +1,163 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ */
+
+#ifndef __FDMI_H__
+#define __FDMI_H__
+
+#include <protocol/types.h>
+#include <protocol/fc.h>
+#include <protocol/ct.h>
+
+#pragma pack(1)
+
+/*
+ * FDMI Command Codes
+ */
+#define        FDMI_GRHL               0x0100
+#define        FDMI_GHAT               0x0101
+#define        FDMI_GRPL               0x0102
+#define        FDMI_GPAT               0x0110
+#define        FDMI_RHBA               0x0200
+#define        FDMI_RHAT               0x0201
+#define        FDMI_RPRT               0x0210
+#define        FDMI_RPA                0x0211
+#define        FDMI_DHBA               0x0300
+#define        FDMI_DPRT               0x0310
+
+/*
+ * FDMI reason codes
+ */
+#define        FDMI_NO_ADDITIONAL_EXP          0x00
+#define        FDMI_HBA_ALREADY_REG            0x10
+#define        FDMI_HBA_ATTRIB_NOT_REG         0x11
+#define        FDMI_HBA_ATTRIB_MULTIPLE        0x12
+#define        FDMI_HBA_ATTRIB_LENGTH_INVALID  0x13
+#define        FDMI_HBA_ATTRIB_NOT_PRESENT     0x14
+#define        FDMI_PORT_ORIG_NOT_IN_LIST      0x15
+#define        FDMI_PORT_HBA_NOT_IN_LIST       0x16
+#define        FDMI_PORT_ATTRIB_NOT_REG        0x20
+#define        FDMI_PORT_NOT_REG               0x21
+#define        FDMI_PORT_ATTRIB_MULTIPLE       0x22
+#define        FDMI_PORT_ATTRIB_LENGTH_INVALID 0x23
+#define        FDMI_PORT_ALREADY_REGISTEREED   0x24
+
+/*
+ * FDMI Transmission Speed Mask values
+ */
+#define        FDMI_TRANS_SPEED_1G             0x00000001
+#define        FDMI_TRANS_SPEED_2G             0x00000002
+#define        FDMI_TRANS_SPEED_10G            0x00000004
+#define        FDMI_TRANS_SPEED_4G             0x00000008
+#define        FDMI_TRANS_SPEED_8G             0x00000010
+#define        FDMI_TRANS_SPEED_16G            0x00000020
+#define        FDMI_TRANS_SPEED_UNKNOWN        0x00008000
+
+/*
+ * FDMI HBA attribute types
+ */
+enum fdmi_hba_attribute_type {
+       FDMI_HBA_ATTRIB_NODENAME = 1,   /* 0x0001 */
+       FDMI_HBA_ATTRIB_MANUFACTURER,   /* 0x0002 */
+       FDMI_HBA_ATTRIB_SERIALNUM,      /* 0x0003 */
+       FDMI_HBA_ATTRIB_MODEL,          /* 0x0004 */
+       FDMI_HBA_ATTRIB_MODEL_DESC,     /* 0x0005 */
+       FDMI_HBA_ATTRIB_HW_VERSION,     /* 0x0006 */
+       FDMI_HBA_ATTRIB_DRIVER_VERSION, /* 0x0007 */
+       FDMI_HBA_ATTRIB_ROM_VERSION,    /* 0x0008 */
+       FDMI_HBA_ATTRIB_FW_VERSION,     /* 0x0009 */
+       FDMI_HBA_ATTRIB_OS_NAME,        /* 0x000A */
+       FDMI_HBA_ATTRIB_MAX_CT,         /* 0x000B */
+
+       FDMI_HBA_ATTRIB_MAX_TYPE
+};
+
+/*
+ * FDMI Port attribute types
+ */
+enum fdmi_port_attribute_type {
+       FDMI_PORT_ATTRIB_FC4_TYPES = 1, /* 0x0001 */
+       FDMI_PORT_ATTRIB_SUPP_SPEED,    /* 0x0002 */
+       FDMI_PORT_ATTRIB_PORT_SPEED,    /* 0x0003 */
+       FDMI_PORT_ATTRIB_FRAME_SIZE,    /* 0x0004 */
+       FDMI_PORT_ATTRIB_DEV_NAME,      /* 0x0005 */
+       FDMI_PORT_ATTRIB_HOST_NAME,     /* 0x0006 */
+
+       FDMI_PORT_ATTR_MAX_TYPE
+};
+
+/*
+ * FDMI attribute
+ */
+struct fdmi_attr_s {
+       u16        type;
+       u16        len;
+       u8         value[1];
+};
+
+/*
+ * HBA Attribute Block
+ */
+struct fdmi_hba_attr_s {
+       u32        attr_count;  /* # of attributes */
+       struct fdmi_attr_s     hba_attr;        /* n attributes */
+};
+
+/*
+ * Registered Port List
+ */
+struct fdmi_port_list_s {
+       u32        num_ports;   /* number Of Port Entries */
+       wwn_t           port_entry;     /* one or more */
+};
+
+/*
+ * Port Attribute Block
+ */
+struct fdmi_port_attr_s {
+       u32        attr_count;  /* # of attributes */
+       struct fdmi_attr_s     port_attr;       /* n attributes */
+};
+
+/*
+ * FDMI Register HBA Attributes
+ */
+struct fdmi_rhba_s {
+       wwn_t           hba_id;         /* HBA Identifier */
+       struct fdmi_port_list_s port_list;      /* Registered Port List */
+       struct fdmi_hba_attr_s hba_attr_blk;    /* HBA attribute block */
+};
+
+/*
+ * FDMI Register Port
+ */
+struct fdmi_rprt_s {
+       wwn_t           hba_id;         /* HBA Identifier */
+       wwn_t           port_name;      /* Port wwn */
+       struct fdmi_port_attr_s port_attr_blk;  /* Port Attr Block */
+};
+
+/*
+ * FDMI Register Port Attributes
+ */
+struct fdmi_rpa_s {
+       wwn_t           port_name;      /* port wwn */
+       struct fdmi_port_attr_s port_attr_blk;  /* Port Attr Block */
+};
+
+#pragma pack()
+
+#endif
diff --git a/drivers/scsi/bfa/include/protocol/pcifw.h b/drivers/scsi/bfa/include/protocol/pcifw.h
new file mode 100644 (file)
index 0000000..6830dc3
--- /dev/null
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) 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.
+ */
+
+/**
+ *  pcifw.h PCI FW related headers
+ */
+
+#ifndef __PCIFW_H__
+#define __PCIFW_H__
+
+#pragma pack(1)
+
+struct pnp_hdr_s{
+  u32  signature;      /* "$PnP" */
+  u8   rev;            /* Struct revision */
+  u8   len;            /* Header structure len in multiples
+                                * of 16 bytes */
+  u16  off;            /* Offset to next header 00 if none */
+  u8   rsvd;           /* Reserved byte */
+  u8   cksum;          /* 8-bit checksum for this header */
+  u32  pnp_dev_id;     /* PnP Device Id */
+  u16  mfstr;          /* Pointer to manufacturer string */
+  u16  prstr;          /* Pointer to product string */
+  u8   devtype[3];     /* Device Type Code */
+  u8   devind;         /* Device Indicator */
+  u16  bcventr;        /* Bootstrap entry vector */
+  u16  rsvd2;          /* Reserved */
+  u16  sriv;           /* Static resource information vector */
+};
+
+struct pci_3_0_ds_s{
+ u32   sig;            /* Signature "PCIR" */
+ u16   vendid;         /* Vendor ID */
+ u16   devid;          /* Device ID */
+ u16   devlistoff;     /* Device List Offset */
+ u16   len;            /* PCI Data Structure Length */
+ u8    rev;            /* PCI Data Structure Revision */
+ u8    clcode[3];      /* Class Code */
+ u16   imglen;         /* Code image length in multiples of
+                                * 512 bytes */
+ u16   coderev;        /* Revision level of code/data */
+ u8    codetype;       /* Code type 0x00 - BIOS */
+ u8    indr;           /* Last image indicator */
+ u16   mrtimglen;      /* Max Run Time Image Length */
+ u16   cuoff;          /* Config Utility Code Header Offset */
+ u16   dmtfclp;        /* DMTF CLP entry point offset */
+};
+
+struct pci_optrom_hdr_s{
+ u16   sig;            /* Signature 0x55AA */
+ u8    len;            /* Option ROM length in units of 512 bytes */
+ u8    inivec[3];      /* Initialization vector */
+ u8    rsvd[16];       /* Reserved field */
+ u16   verptr;         /* Pointer to version string - private */
+ u16   pcids;          /* Pointer to PCI data structure */
+ u16   pnphdr;         /* Pointer to PnP expansion header */
+};
+
+#pragma pack()
+
+#endif
diff --git a/drivers/scsi/bfa/include/protocol/scsi.h b/drivers/scsi/bfa/include/protocol/scsi.h
new file mode 100644 (file)
index 0000000..b220e6b
--- /dev/null
@@ -0,0 +1,1648 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ */
+
+#ifndef __SCSI_H__
+#define __SCSI_H__
+
+#include <protocol/types.h>
+
+#pragma pack(1)
+
+/*
+ * generic SCSI cdb definition
+ */
+#define SCSI_MAX_CDBLEN     16
+struct scsi_cdb_s{
+       u8         scsi_cdb[SCSI_MAX_CDBLEN];
+};
+
+/*
+ * scsi lun serial number definition
+ */
+#define SCSI_LUN_SN_LEN     32
+struct scsi_lun_sn_s{
+       u8         lun_sn[SCSI_LUN_SN_LEN];
+};
+
+/*
+ * SCSI Direct Access Commands
+ */
+enum {
+       SCSI_OP_TEST_UNIT_READY         = 0x00,
+       SCSI_OP_REQUEST_SENSE           = 0x03,
+       SCSI_OP_FORMAT_UNIT             = 0x04,
+       SCSI_OP_READ6                   = 0x08,
+       SCSI_OP_WRITE6                  = 0x0A,
+       SCSI_OP_WRITE_FILEMARKS         = 0x10,
+       SCSI_OP_INQUIRY                 = 0x12,
+       SCSI_OP_MODE_SELECT6            = 0x15,
+       SCSI_OP_RESERVE6                = 0x16,
+       SCSI_OP_RELEASE6                = 0x17,
+       SCSI_OP_MODE_SENSE6             = 0x1A,
+       SCSI_OP_START_STOP_UNIT         = 0x1B,
+       SCSI_OP_SEND_DIAGNOSTIC         = 0x1D,
+       SCSI_OP_READ_CAPACITY           = 0x25,
+       SCSI_OP_READ10                  = 0x28,
+       SCSI_OP_WRITE10                 = 0x2A,
+       SCSI_OP_VERIFY10                = 0x2F,
+       SCSI_OP_READ_DEFECT_DATA        = 0x37,
+       SCSI_OP_LOG_SELECT              = 0x4C,
+       SCSI_OP_LOG_SENSE               = 0x4D,
+       SCSI_OP_MODE_SELECT10           = 0x55,
+       SCSI_OP_RESERVE10               = 0x56,
+       SCSI_OP_RELEASE10               = 0x57,
+       SCSI_OP_MODE_SENSE10            = 0x5A,
+       SCSI_OP_PER_RESERVE_IN          = 0x5E,
+       SCSI_OP_PER_RESERVE_OUR         = 0x5E,
+       SCSI_OP_READ16                  = 0x88,
+       SCSI_OP_WRITE16                 = 0x8A,
+       SCSI_OP_VERIFY16                = 0x8F,
+       SCSI_OP_READ_CAPACITY16         = 0x9E,
+       SCSI_OP_REPORT_LUNS             = 0xA0,
+       SCSI_OP_READ12                  = 0xA8,
+       SCSI_OP_WRITE12                 = 0xAA,
+       SCSI_OP_UNDEF                   = 0xFF,
+};
+
+/*
+ * SCSI START_STOP_UNIT command
+ */
+struct scsi_start_stop_unit_s{
+       u8         opcode;
+#ifdef __BIGENDIAN
+       u8         lun:3;
+       u8         reserved1:4;
+       u8         immed:1;
+#else
+       u8         immed:1;
+       u8         reserved1:4;
+       u8         lun:3;
+#endif
+       u8         reserved2;
+       u8         reserved3;
+#ifdef __BIGENDIAN
+       u8         power_conditions:4;
+       u8         reserved4:2;
+       u8         loEj:1;
+       u8         start:1;
+#else
+       u8         start:1;
+       u8         loEj:1;
+       u8         reserved4:2;
+       u8         power_conditions:4;
+#endif
+       u8         control;
+};
+
+/*
+ * SCSI SEND_DIAGNOSTIC command
+ */
+struct scsi_send_diagnostic_s{
+       u8         opcode;
+#ifdef __BIGENDIAN
+       u8         self_test_code:3;
+       u8         pf:1;
+       u8         reserved1:1;
+       u8         self_test:1;
+       u8         dev_offl:1;
+       u8         unit_offl:1;
+#else
+       u8         unit_offl:1;
+       u8         dev_offl:1;
+       u8         self_test:1;
+       u8         reserved1:1;
+       u8         pf:1;
+       u8         self_test_code:3;
+#endif
+       u8         reserved2;
+
+       u8         param_list_length[2];        /* MSB first */
+       u8         control;
+
+};
+
+/*
+ * SCSI READ10/WRITE10 commands
+ */
+struct scsi_rw10_s{
+       u8         opcode;
+#ifdef __BIGENDIAN
+       u8         lun:3;
+       u8         dpo:1;       /* Disable Page Out */
+       u8         fua:1;       /* Force Unit Access */
+       u8         reserved1:2;
+       u8         rel_adr:1;   /* relative address */
+#else
+       u8         rel_adr:1;
+       u8         reserved1:2;
+       u8         fua:1;
+       u8         dpo:1;
+       u8         lun:3;
+#endif
+       u8         lba0;        /* logical block address - MSB */
+       u8         lba1;
+       u8         lba2;
+       u8         lba3;        /* LSB */
+       u8         reserved3;
+       u8         xfer_length0;        /* transfer length in blocks - MSB */
+       u8         xfer_length1;        /* LSB */
+       u8         control;
+};
+
+#define SCSI_CDB10_GET_LBA(cdb)                     \
+    (((cdb)->lba0 << 24) | ((cdb)->lba1 << 16) |    \
+     ((cdb)->lba2 << 8) | (cdb)->lba3)
+
+#define SCSI_CDB10_SET_LBA(cdb, lba) {      \
+    (cdb)->lba0 = lba >> 24;            \
+    (cdb)->lba1 = (lba >> 16) & 0xFF;   \
+    (cdb)->lba2 = (lba >> 8) & 0xFF;    \
+    (cdb)->lba3 = lba & 0xFF;           \
+}
+
+#define SCSI_CDB10_GET_TL(cdb)  \
+    ((cdb)->xfer_length0 << 8 | (cdb)->xfer_length1)
+#define SCSI_CDB10_SET_TL(cdb, tl) {      \
+    (cdb)->xfer_length0 = tl >> 8;       \
+    (cdb)->xfer_length1 = tl & 0xFF;     \
+}
+
+/*
+ * SCSI READ6/WRITE6 commands
+ */
+struct scsi_rw6_s{
+       u8         opcode;
+#ifdef __BIGENDIAN
+       u8         lun:3;
+       u8         lba0:5;              /* MSb */
+#else
+       u8         lba0:5;              /* MSb */
+       u8         lun:3;
+#endif
+       u8         lba1;
+       u8         lba2;                /* LSB */
+       u8         xfer_length;
+       u8         control;
+};
+
+#define SCSI_TAPE_CDB6_GET_TL(cdb)              \
+    (((cdb)->tl0 << 16) | ((cdb)->tl1 << 8) | (cdb)->tl2)
+
+#define SCSI_TAPE_CDB6_SET_TL(cdb, tl) {      \
+    (cdb)->tl0 = tl >> 16;            \
+    (cdb)->tl1 = (tl >> 8) & 0xFF;    \
+    (cdb)->tl2 = tl & 0xFF;           \
+}
+
+/*
+ * SCSI sequential (TAPE) wrtie command
+ */
+struct scsi_tape_wr_s{
+       u8         opcode;
+#ifdef __BIGENDIAN
+       u8         rsvd:7;
+       u8         fixed:1;     /* MSb */
+#else
+       u8         fixed:1;     /* MSb */
+       u8         rsvd:7;
+#endif
+       u8         tl0;         /* Msb */
+       u8         tl1;
+       u8         tl2;         /* Lsb */
+
+       u8         control;
+};
+
+#define SCSI_CDB6_GET_LBA(cdb)              \
+    (((cdb)->lba0 << 16) | ((cdb)->lba1 << 8) | (cdb)->lba2)
+
+#define SCSI_CDB6_SET_LBA(cdb, lba) {      \
+    (cdb)->lba0 = lba >> 16;            \
+    (cdb)->lba1 = (lba >> 8) & 0xFF;    \
+    (cdb)->lba2 = lba & 0xFF;           \
+}
+
+#define SCSI_CDB6_GET_TL(cdb) ((cdb)->xfer_length)
+#define SCSI_CDB6_SET_TL(cdb, tl) {      \
+    (cdb)->xfer_length = tl;         \
+}
+
+/*
+ * SCSI sense data format
+ */
+struct scsi_sense_s{
+#ifdef __BIGENDIAN
+       u8         valid:1;
+       u8         rsp_code:7;
+#else
+       u8         rsp_code:7;
+       u8         valid:1;
+#endif
+       u8         seg_num;
+#ifdef __BIGENDIAN
+       u8         file_mark:1;
+       u8         eom:1;               /* end of media */
+       u8         ili:1;               /* incorrect length indicator */
+       u8         reserved:1;
+       u8         sense_key:4;
+#else
+       u8         sense_key:4;
+       u8         reserved:1;
+       u8         ili:1;               /* incorrect length indicator */
+       u8         eom:1;               /* end of media */
+       u8         file_mark:1;
+#endif
+       u8         information[4];      /* device-type or command specific info
+                                        */
+       u8         add_sense_length;
+                                       /* additional sense length */
+       u8         command_info[4];/* command specific information
+                                                */
+       u8         asc;         /* additional sense code */
+       u8         ascq;                /* additional sense code qualifier */
+       u8         fru_code;    /* field replaceable unit code */
+#ifdef __BIGENDIAN
+       u8         sksv:1;              /* sense key specific valid */
+       u8         c_d:1;               /* command/data bit */
+       u8         res1:2;
+       u8         bpv:1;               /* bit pointer valid */
+       u8         bpointer:3;  /* bit pointer */
+#else
+       u8         bpointer:3;  /* bit pointer */
+       u8         bpv:1;               /* bit pointer valid */
+       u8         res1:2;
+       u8         c_d:1;               /* command/data bit */
+       u8         sksv:1;              /* sense key specific valid */
+#endif
+       u8         fpointer[2]; /* field pointer */
+};
+
+#define SCSI_SENSE_CUR_ERR          0x70
+#define SCSI_SENSE_DEF_ERR          0x71
+
+/*
+ * SCSI sense key values
+ */
+#define SCSI_SK_NO_SENSE        0x0
+#define SCSI_SK_REC_ERR         0x1    /* recovered error */
+#define SCSI_SK_NOT_READY       0x2
+#define SCSI_SK_MED_ERR         0x3    /* medium error */
+#define SCSI_SK_HW_ERR          0x4    /* hardware error */
+#define SCSI_SK_ILLEGAL_REQ     0x5
+#define SCSI_SK_UNIT_ATT        0x6    /* unit attention */
+#define SCSI_SK_DATA_PROTECT    0x7
+#define SCSI_SK_BLANK_CHECK     0x8
+#define SCSI_SK_VENDOR_SPEC     0x9
+#define SCSI_SK_COPY_ABORTED    0xA
+#define SCSI_SK_ABORTED_CMND    0xB
+#define SCSI_SK_VOL_OVERFLOW    0xD
+#define SCSI_SK_MISCOMPARE      0xE
+
+/*
+ * SCSI additional sense codes
+ */
+#define SCSI_ASC_NO_ADD_SENSE           0x00
+#define SCSI_ASC_LUN_NOT_READY          0x04
+#define SCSI_ASC_LUN_COMMUNICATION      0x08
+#define SCSI_ASC_WRITE_ERROR            0x0C
+#define SCSI_ASC_INVALID_CMND_CODE      0x20
+#define SCSI_ASC_BAD_LBA                0x21
+#define SCSI_ASC_INVALID_FIELD_IN_CDB   0x24
+#define SCSI_ASC_LUN_NOT_SUPPORTED      0x25
+#define SCSI_ASC_LUN_WRITE_PROTECT      0x27
+#define SCSI_ASC_POWERON_BDR            0x29   /* power on reset, bus reset,
+                                                * bus device reset
+                                                */
+#define SCSI_ASC_PARAMS_CHANGED         0x2A
+#define SCSI_ASC_CMND_CLEARED_BY_A_I    0x2F
+#define SCSI_ASC_SAVING_PARAM_NOTSUPP   0x39
+#define SCSI_ASC_TOCC                   0x3F   /* target operating condtions
+                                                * changed
+                                                */
+#define SCSI_ASC_PARITY_ERROR           0x47
+#define SCSI_ASC_CMND_PHASE_ERROR       0x4A
+#define SCSI_ASC_DATA_PHASE_ERROR       0x4B
+#define SCSI_ASC_VENDOR_SPEC            0x7F
+
+/*
+ * SCSI additional sense code qualifiers
+ */
+#define SCSI_ASCQ_CAUSE_NOT_REPORT      0x00
+#define SCSI_ASCQ_BECOMING_READY        0x01
+#define SCSI_ASCQ_INIT_CMD_REQ          0x02
+#define SCSI_ASCQ_FORMAT_IN_PROGRESS    0x04
+#define SCSI_ASCQ_OPERATION_IN_PROGRESS 0x07
+#define SCSI_ASCQ_SELF_TEST_IN_PROGRESS 0x09
+#define SCSI_ASCQ_WR_UNEXP_UNSOL_DATA   0x0C
+#define SCSI_ASCQ_WR_NOTENG_UNSOL_DATA  0x0D
+
+#define SCSI_ASCQ_LBA_OUT_OF_RANGE      0x00
+#define SCSI_ASCQ_INVALID_ELEMENT_ADDR  0x01
+
+#define SCSI_ASCQ_LUN_WRITE_PROTECTED       0x00
+#define SCSI_ASCQ_LUN_HW_WRITE_PROTECTED    0x01
+#define SCSI_ASCQ_LUN_SW_WRITE_PROTECTED    0x02
+
+#define SCSI_ASCQ_POR   0x01   /* power on reset */
+#define SCSI_ASCQ_SBR   0x02   /* scsi bus reset */
+#define SCSI_ASCQ_BDR   0x03   /* bus device reset */
+#define SCSI_ASCQ_DIR   0x04   /* device internal reset */
+
+#define SCSI_ASCQ_MODE_PARAMS_CHANGED       0x01
+#define SCSI_ASCQ_LOG_PARAMS_CHANGED        0x02
+#define SCSI_ASCQ_RESERVATIONS_PREEMPTED    0x03
+#define SCSI_ASCQ_RESERVATIONS_RELEASED     0x04
+#define SCSI_ASCQ_REGISTRATIONS_PREEMPTED   0x05
+
+#define SCSI_ASCQ_MICROCODE_CHANGED 0x01
+#define SCSI_ASCQ_CHANGED_OPER_COND 0x02
+#define SCSI_ASCQ_INQ_CHANGED       0x03       /* inquiry data changed */
+#define SCSI_ASCQ_DI_CHANGED        0x05       /* device id changed */
+#define SCSI_ASCQ_RL_DATA_CHANGED   0x0E       /* report luns data changed */
+
+#define SCSI_ASCQ_DP_CRC_ERR            0x01   /* data phase crc error */
+#define SCSI_ASCQ_DP_SCSI_PARITY_ERR    0x02   /* data phase scsi parity error
+                                                */
+#define SCSI_ASCQ_IU_CRC_ERR            0x03   /* information unit crc error */
+#define SCSI_ASCQ_PROTO_SERV_CRC_ERR    0x05
+
+#define SCSI_ASCQ_LUN_TIME_OUT          0x01
+
+/* ------------------------------------------------------------
+ * SCSI INQUIRY
+ * ------------------------------------------------------------*/
+
+struct scsi_inquiry_s{
+       u8         opcode;
+#ifdef __BIGENDIAN
+       u8         lun:3;
+       u8         reserved1:3;
+       u8         cmd_dt:1;
+       u8         evpd:1;
+#else
+       u8         evpd:1;
+       u8         cmd_dt:1;
+       u8         reserved1:3;
+       u8         lun:3;
+#endif
+       u8         page_code;
+       u8         reserved2;
+       u8         alloc_length;
+       u8         control;
+};
+
+struct scsi_inquiry_vendor_s{
+       u8         vendor_id[8];
+};
+
+struct scsi_inquiry_prodid_s{
+       u8         product_id[16];
+};
+
+struct scsi_inquiry_prodrev_s{
+       u8         product_rev[4];
+};
+
+struct scsi_inquiry_data_s{
+#ifdef __BIGENDIAN
+       u8         peripheral_qual:3;   /* peripheral qualifier */
+       u8         device_type:5;               /* peripheral device type */
+
+       u8         rmb:1;                       /* removable medium bit */
+       u8         device_type_mod:7;   /* device type modifier */
+
+       u8         version;
+
+       u8         aenc:1;              /* async event notification capability
+                                        */
+       u8         trm_iop:1;   /* terminate I/O process */
+       u8         norm_aca:1;  /* normal ACA supported */
+       u8         hi_support:1;        /* SCSI-3: supports REPORT LUNS */
+       u8         rsp_data_format:4;
+
+       u8         additional_len;
+       u8         sccs:1;
+       u8         reserved1:7;
+
+       u8         reserved2:1;
+       u8         enc_serv:1;  /* enclosure service component */
+       u8         reserved3:1;
+       u8         multi_port:1;        /* multi-port device */
+       u8         m_chngr:1;   /* device in medium transport element */
+       u8         ack_req_q:1; /* SIP specific bit */
+       u8         addr32:1;    /* SIP specific bit */
+       u8         addr16:1;    /* SIP specific bit */
+
+       u8         rel_adr:1;   /* relative address */
+       u8         w_bus32:1;
+       u8         w_bus16:1;
+       u8         synchronous:1;
+       u8         linked_commands:1;
+       u8         trans_dis:1;
+       u8         cmd_queue:1; /* command queueing supported */
+       u8         soft_reset:1;        /* soft reset alternative (VS) */
+#else
+       u8         device_type:5;       /* peripheral device type */
+       u8         peripheral_qual:3;
+                                       /* peripheral qualifier */
+
+       u8         device_type_mod:7;
+                                       /* device type modifier */
+       u8         rmb:1;               /* removable medium bit */
+
+       u8         version;
+
+       u8         rsp_data_format:4;
+       u8         hi_support:1;        /* SCSI-3: supports REPORT LUNS */
+       u8         norm_aca:1;  /* normal ACA supported */
+       u8         terminate_iop:1;/* terminate I/O process */
+       u8         aenc:1;              /* async event notification capability
+                                        */
+
+       u8         additional_len;
+       u8         reserved1:7;
+       u8         sccs:1;
+
+       u8         addr16:1;    /* SIP specific bit */
+       u8         addr32:1;    /* SIP specific bit */
+       u8         ack_req_q:1; /* SIP specific bit */
+       u8         m_chngr:1;   /* device in medium transport element */
+       u8         multi_port:1;        /* multi-port device */
+       u8         reserved3:1; /* TBD - Vendor Specific */
+       u8         enc_serv:1;  /* enclosure service component */
+       u8         reserved2:1;
+
+       u8         soft_seset:1;        /* soft reset alternative (VS) */
+       u8         cmd_queue:1; /* command queueing supported */
+       u8         trans_dis:1;
+       u8         linked_commands:1;
+       u8         synchronous:1;
+       u8         w_bus16:1;
+       u8         w_bus32:1;
+       u8         rel_adr:1;   /* relative address */
+#endif
+       struct scsi_inquiry_vendor_s vendor_id;
+       struct scsi_inquiry_prodid_s product_id;
+       struct scsi_inquiry_prodrev_s product_rev;
+       u8         vendor_specific[20];
+       u8         reserved4[40];
+};
+
+/*
+ * inquiry.peripheral_qual field values
+ */
+#define SCSI_DEVQUAL_DEFAULT        0
+#define SCSI_DEVQUAL_NOT_CONNECTED  1
+#define SCSI_DEVQUAL_NOT_SUPPORTED  3
+
+/*
+ * inquiry.device_type field values
+ */
+#define SCSI_DEVICE_DIRECT_ACCESS       0x00
+#define SCSI_DEVICE_SEQ_ACCESS          0x01
+#define SCSI_DEVICE_ARRAY_CONTROLLER    0x0C
+#define SCSI_DEVICE_UNKNOWN             0x1F
+
+/*
+ * inquiry.version
+ */
+#define SCSI_VERSION_ANSI_X3131     2  /* ANSI X3.131 SCSI-2 */
+#define SCSI_VERSION_SPC            3  /* SPC (SCSI-3), ANSI X3.301:1997 */
+#define SCSI_VERSION_SPC_2          4  /* SPC-2 */
+
+/*
+ * response data format
+ */
+#define SCSI_RSP_DATA_FORMAT        2  /* SCSI-2 & SPC */
+
+/*
+ * SCSI inquiry page codes
+ */
+#define SCSI_INQ_PAGE_VPD_PAGES     0x00       /* supported vpd pages */
+#define SCSI_INQ_PAGE_USN_PAGE      0x80       /* unit serial number page */
+#define SCSI_INQ_PAGE_DEV_IDENT     0x83       /* device indentification page
+                                                */
+#define SCSI_INQ_PAGES_MAX          3
+
+/*
+ * supported vital product data pages
+ */
+struct scsi_inq_page_vpd_pages_s{
+#ifdef __BIGENDIAN
+       u8         peripheral_qual:3;
+       u8         device_type:5;
+#else
+       u8         device_type:5;
+       u8         peripheral_qual:3;
+#endif
+       u8         page_code;
+       u8         reserved;
+       u8         page_length;
+       u8         pages[SCSI_INQ_PAGES_MAX];
+};
+
+/*
+ * Unit serial number page
+ */
+#define SCSI_INQ_USN_LEN 32
+
+struct scsi_inq_usn_s{
+       char            usn[SCSI_INQ_USN_LEN];
+};
+
+struct scsi_inq_page_usn_s{
+#ifdef __BIGENDIAN
+       u8         peripheral_qual:3;
+       u8         device_type:5;
+#else
+       u8         device_type:5;
+       u8         peripheral_qual:3;
+#endif
+       u8         page_code;
+       u8         reserved1;
+       u8         page_length;
+       struct scsi_inq_usn_s  usn;
+};
+
+enum {
+       SCSI_INQ_DIP_CODE_BINARY = 1,   /* identifier has binary value */
+       SCSI_INQ_DIP_CODE_ASCII = 2,    /* identifier has ascii value */
+};
+
+enum {
+       SCSI_INQ_DIP_ASSOC_LUN = 0,     /* id is associated with device */
+       SCSI_INQ_DIP_ASSOC_PORT = 1,    /* id is associated with port that
+                                        * received the request
+                                        */
+};
+
+enum {
+       SCSI_INQ_ID_TYPE_VENDOR = 1,
+       SCSI_INQ_ID_TYPE_IEEE = 2,
+       SCSI_INQ_ID_TYPE_FC_FS = 3,
+       SCSI_INQ_ID_TYPE_OTHER = 4,
+};
+
+struct scsi_inq_dip_desc_s{
+#ifdef __BIGENDIAN
+       u8         res0:4;
+       u8         code_set:4;
+       u8         res1:2;
+       u8         association:2;
+       u8         id_type:4;
+#else
+       u8         code_set:4;
+       u8         res0:4;
+       u8         id_type:4;
+       u8         association:2;
+       u8         res1:2;
+#endif
+       u8         res2;
+       u8         id_len;
+       struct scsi_lun_sn_s   id;
+};
+
+/*
+ * Device indentification page
+ */
+struct scsi_inq_page_dev_ident_s{
+#ifdef __BIGENDIAN
+       u8         peripheral_qual:3;
+       u8         device_type:5;
+#else
+       u8         device_type:5;
+       u8         peripheral_qual:3;
+#endif
+       u8         page_code;
+       u8         reserved1;
+       u8         page_length;
+       struct scsi_inq_dip_desc_s desc;
+};
+
+/* ------------------------------------------------------------
+ * READ CAPACITY
+ * ------------------------------------------------------------
+ */
+
+struct scsi_read_capacity_s{
+       u8         opcode;
+#ifdef __BIGENDIAN
+       u8         lun:3;
+       u8         reserved1:4;
+       u8         rel_adr:1;
+#else
+       u8         rel_adr:1;
+       u8         reserved1:4;
+       u8         lun:3;
+#endif
+       u8         lba0;        /* MSB */
+       u8         lba1;
+       u8         lba2;
+       u8         lba3;        /* LSB */
+       u8         reserved2;
+       u8         reserved3;
+#ifdef __BIGENDIAN
+       u8         reserved4:7;
+       u8         pmi:1;       /* partial medium indicator */
+#else
+       u8         pmi:1;       /* partial medium indicator */
+       u8         reserved4:7;
+#endif
+       u8         control;
+};
+
+struct scsi_read_capacity_data_s{
+       u32        max_lba;     /* maximum LBA available */
+       u32        block_length;        /* in bytes */
+};
+
+struct scsi_read_capacity16_data_s{
+       u64        lba; /* maximum LBA available */
+       u32        block_length;        /* in bytes */
+#ifdef __BIGENDIAN
+       u8         reserved1:4,
+                       p_type:3,
+                       prot_en:1;
+       u8              reserved2:4,
+                       lb_pbe:4;       /* logical blocks per physical block
+                                        * exponent */
+       u16     reserved3:2,
+                       lba_align:14;   /* lowest aligned logical block
+                                        * address */
+#else
+       u16     lba_align:14,   /* lowest aligned logical block
+                                        * address */
+                       reserved3:2;
+       u8              lb_pbe:4,       /* logical blocks per physical block
+                                        * exponent */
+                       reserved2:4;
+       u8              prot_en:1,
+                       p_type:3,
+                       reserved1:4;
+#endif
+       u64     reserved4;
+       u64     reserved5;
+};
+
+/* ------------------------------------------------------------
+ * REPORT LUNS command
+ * ------------------------------------------------------------
+ */
+
+struct scsi_report_luns_s{
+       u8         opcode;              /* A0h - REPORT LUNS opCode */
+       u8         reserved1[5];
+       u8         alloc_length[4];/* allocation length MSB first */
+       u8         reserved2;
+       u8         control;
+};
+
+#define SCSI_REPORT_LUN_ALLOC_LENGTH(rl)                               \
+    ((rl->alloc_length[0] << 24) | (rl->alloc_length[1] << 16) |       \
+     (rl->alloc_length[2] << 8) | (rl->alloc_length[3]))
+
+#define SCSI_REPORT_LUNS_SET_ALLOCLEN(rl, alloc_len) {      \
+    (rl)->alloc_length[0] = (alloc_len) >> 24;                         \
+    (rl)->alloc_length[1] = ((alloc_len) >> 16) & 0xFF;                \
+    (rl)->alloc_length[2] = ((alloc_len) >> 8) & 0xFF;                 \
+    (rl)->alloc_length[3] = (alloc_len) & 0xFF;                        \
+}
+
+struct scsi_report_luns_data_s{
+       u32        lun_list_length;     /* length of LUN list length */
+       u32        reserved;
+       lun_t           lun[1];                 /* first LUN in lun list */
+};
+
+/* -------------------------------------------------------------
+ * SCSI mode  parameters
+ * -----------------------------------------------------------
+ */
+enum {
+       SCSI_DA_MEDIUM_DEF = 0, /* direct access default medium type */
+       SCSI_DA_MEDIUM_SS = 1,  /* direct access single sided */
+       SCSI_DA_MEDIUM_DS = 2,  /* direct access double sided */
+};
+
+/*
+ * SCSI Mode Select(6) cdb
+ */
+struct scsi_mode_select6_s{
+       u8         opcode;
+#ifdef __BIGENDIAN
+       u8         reserved1:3;
+       u8         pf:1;                /* page format */
+       u8         reserved2:3;
+       u8         sp:1;                /* save pages if set to 1 */
+#else
+       u8         sp:1;        /* save pages if set to 1 */
+       u8         reserved2:3;
+       u8         pf:1;        /* page format */
+       u8         reserved1:3;
+#endif
+       u8         reserved3[2];
+       u8         alloc_len;
+       u8         control;
+};
+
+/*
+ * SCSI Mode Select(10) cdb
+ */
+struct scsi_mode_select10_s{
+       u8         opcode;
+#ifdef __BIGENDIAN
+       u8         reserved1:3;
+       u8         pf:1;        /* page format */
+       u8         reserved2:3;
+       u8         sp:1;        /* save pages if set to 1 */
+#else
+       u8         sp:1;        /* save pages if set to 1 */
+       u8         reserved2:3;
+       u8         pf:1;        /* page format */
+       u8         reserved1:3;
+#endif
+       u8         reserved3[5];
+       u8         alloc_len_msb;
+       u8         alloc_len_lsb;
+       u8         control;
+};
+
+/*
+ * SCSI Mode Sense(6) cdb
+ */
+struct scsi_mode_sense6_s{
+       u8         opcode;
+#ifdef __BIGENDIAN
+       u8         reserved1:4;
+       u8         dbd:1;       /* disable block discriptors if set to 1 */
+       u8         reserved2:3;
+
+       u8         pc:2;        /* page control */
+       u8         page_code:6;
+#else
+       u8         reserved2:3;
+       u8         dbd:1;       /* disable block descriptors if set to 1 */
+       u8         reserved1:4;
+
+       u8         page_code:6;
+       u8         pc:2;        /* page control */
+#endif
+       u8         reserved3;
+       u8         alloc_len;
+       u8         control;
+};
+
+/*
+ * SCSI Mode Sense(10) cdb
+ */
+struct scsi_mode_sense10_s{
+       u8         opcode;
+#ifdef __BIGENDIAN
+       u8         reserved1:3;
+       u8         LLBAA:1;     /* long LBA accepted if set to 1 */
+       u8         dbd:1;               /* disable block descriptors if set
+                                        * to 1
+                                        */
+       u8         reserved2:3;
+
+       u8         pc:2;                /* page control */
+       u8         page_code:6;
+#else
+       u8         reserved2:3;
+       u8         dbd:1;               /* disable block descriptors if set to
+                                        * 1
+                                        */
+       u8         LLBAA:1;     /* long LBA accepted if set to 1 */
+       u8         reserved1:3;
+
+       u8         page_code:6;
+       u8         pc:2;                /* page control */
+#endif
+       u8         reserved3[4];
+       u8         alloc_len_msb;
+       u8         alloc_len_lsb;
+       u8         control;
+};
+
+#define SCSI_CDB10_GET_AL(cdb)                                         \
+    ((cdb)->alloc_len_msb << 8 | (cdb)->alloc_len_lsb)
+
+#define SCSI_CDB10_SET_AL(cdb, al) {      \
+    (cdb)->alloc_len_msb = al >> 8;                                    \
+    (cdb)->alloc_len_lsb = al & 0xFF;                                  \
+}
+
+#define SCSI_CDB6_GET_AL(cdb) ((cdb)->alloc_len)
+
+#define SCSI_CDB6_SET_AL(cdb, al) {      \
+    (cdb)->alloc_len = al;                                             \
+}
+
+/*
+ * page control field values
+ */
+#define SCSI_PC_CURRENT_VALUES       0x0
+#define SCSI_PC_CHANGEABLE_VALUES    0x1
+#define SCSI_PC_DEFAULT_VALUES       0x2
+#define SCSI_PC_SAVED_VALUES         0x3
+
+/*
+ * SCSI mode page codes
+ */
+#define SCSI_MP_VENDOR_SPEC     0x00
+#define SCSI_MP_DISC_RECN       0x02   /* disconnect-reconnect page */
+#define SCSI_MP_FORMAT_DEVICE   0x03
+#define SCSI_MP_RDG             0x04   /* rigid disk geometry page */
+#define SCSI_MP_FDP             0x05   /* flexible disk page */
+#define SCSI_MP_CACHING         0x08   /* caching page */
+#define SCSI_MP_CONTROL         0x0A   /* control mode page */
+#define SCSI_MP_MED_TYPES_SUP   0x0B   /* medium types supported page */
+#define SCSI_MP_INFO_EXCP_CNTL  0x1C   /* informational exception control */
+#define SCSI_MP_ALL             0x3F   /* return all pages - mode sense only */
+
+/*
+ * mode parameter header
+ */
+struct scsi_mode_param_header6_s{
+       u8         mode_datalen;
+       u8         medium_type;
+
+       /*
+        * device specific parameters expanded for direct access devices
+        */
+#ifdef __BIGENDIAN
+       u32        wp:1;                /* write protected */
+       u32        reserved1:2;
+       u32        dpofua:1;    /* disable page out + force unit access
+                                        */
+       u32        reserved2:4;
+#else
+       u32        reserved2:4;
+       u32        dpofua:1;    /* disable page out + force unit access
+                                        */
+       u32        reserved1:2;
+       u32        wp:1;                /* write protected */
+#endif
+
+       u8         block_desclen;
+};
+
+struct scsi_mode_param_header10_s{
+       u32        mode_datalen:16;
+       u32        medium_type:8;
+
+       /*
+        * device specific parameters expanded for direct access devices
+        */
+#ifdef __BIGENDIAN
+       u32        wp:1;                /* write protected */
+       u32        reserved1:2;
+       u32        dpofua:1;    /* disable page out + force unit access
+                                        */
+       u32        reserved2:4;
+#else
+       u32        reserved2:4;
+       u32        dpofua:1;    /* disable page out + force unit access
+                                        */
+       u32        reserved1:2;
+       u32        wp:1;                /* write protected */
+#endif
+
+#ifdef __BIGENDIAN
+       u32        reserved3:7;
+       u32        longlba:1;
+#else
+       u32        longlba:1;
+       u32        reserved3:7;
+#endif
+       u32        reserved4:8;
+       u32        block_desclen:16;
+};
+
+/*
+ * mode parameter block descriptor
+ */
+struct scsi_mode_param_desc_s{
+       u32        nblks;
+       u32        density_code:8;
+       u32        block_length:24;
+};
+
+/*
+ * Disconnect-reconnect mode page format
+ */
+struct scsi_mp_disc_recn_s{
+#ifdef __BIGENDIAN
+       u8         ps:1;
+       u8         reserved1:1;
+       u8         page_code:6;
+#else
+       u8         page_code:6;
+       u8         reserved1:1;
+       u8         ps:1;
+#endif
+       u8         page_len;
+       u8         buf_full_ratio;
+       u8         buf_empty_ratio;
+
+       u8         bil_msb;     /* bus inactivity limit -MSB */
+       u8         bil_lsb;     /* bus inactivity limit -LSB */
+
+       u8         dtl_msb;     /* disconnect time limit - MSB */
+       u8         dtl_lsb;     /* disconnect time limit - LSB */
+
+       u8         ctl_msb;     /* connect time limit - MSB */
+       u8         ctl_lsb;     /* connect time limit - LSB */
+
+       u8         max_burst_len_msb;
+       u8         max_burst_len_lsb;
+#ifdef __BIGENDIAN
+       u8         emdp:1;      /* enable modify data pointers */
+       u8         fa:3;        /* fair arbitration */
+       u8         dimm:1;      /* disconnect immediate */
+       u8         dtdc:3;      /* data transfer disconnect control */
+#else
+       u8         dtdc:3;      /* data transfer disconnect control */
+       u8         dimm:1;      /* disconnect immediate */
+       u8         fa:3;        /* fair arbitration */
+       u8         emdp:1;      /* enable modify data pointers */
+#endif
+
+       u8         reserved3;
+
+       u8         first_burst_len_msb;
+       u8         first_burst_len_lsb;
+};
+
+/*
+ * SCSI format device mode page
+ */
+struct scsi_mp_format_device_s{
+#ifdef __BIGENDIAN
+       u32        ps:1;
+       u32        reserved1:1;
+       u32        page_code:6;
+#else
+       u32        page_code:6;
+       u32        reserved1:1;
+       u32        ps:1;
+#endif
+       u32        page_len:8;
+       u32        tracks_per_zone:16;
+
+       u32        a_sec_per_zone:16;
+       u32        a_tracks_per_zone:16;
+
+       u32        a_tracks_per_lun:16; /* alternate tracks/lun-MSB */
+       u32        sec_per_track:16;    /* sectors/track-MSB */
+
+       u32        bytes_per_sector:16;
+       u32        interleave:16;
+
+       u32        tsf:16;                      /* track skew factor-MSB */
+       u32        csf:16;                      /* cylinder skew factor-MSB */
+
+#ifdef __BIGENDIAN
+       u32        ssec:1;      /* soft sector formatting */
+       u32        hsec:1;      /* hard sector formatting */
+       u32        rmb:1;       /* removable media */
+       u32        surf:1;      /* surface */
+       u32        reserved2:4;
+#else
+       u32        reserved2:4;
+       u32        surf:1;      /* surface */
+       u32        rmb:1;       /* removable media */
+       u32        hsec:1;      /* hard sector formatting */
+       u32        ssec:1;      /* soft sector formatting */
+#endif
+       u32        reserved3:24;
+};
+
+/*
+ * SCSI rigid disk device geometry page
+ */
+struct scsi_mp_rigid_device_geometry_s{
+#ifdef __BIGENDIAN
+       u32        ps:1;
+       u32        reserved1:1;
+       u32        page_code:6;
+#else
+       u32        page_code:6;
+       u32        reserved1:1;
+       u32        ps:1;
+#endif
+       u32        page_len:8;
+       u32        num_cylinders0:8;
+       u32        num_cylinders1:8;
+
+       u32        num_cylinders2:8;
+       u32        num_heads:8;
+       u32        scwp0:8;
+       u32        scwp1:8;
+
+       u32        scwp2:8;
+       u32        scrwc0:8;
+       u32        scrwc1:8;
+       u32        scrwc2:8;
+
+       u32        dsr:16;
+       u32        lscyl0:8;
+       u32        lscyl1:8;
+
+       u32        lscyl2:8;
+#ifdef __BIGENDIAN
+       u32        reserved2:6;
+       u32        rpl:2;       /* rotational position locking */
+#else
+       u32        rpl:2;       /* rotational position locking */
+       u32        reserved2:6;
+#endif
+       u32        rot_off:8;
+       u32        reserved3:8;
+
+       u32        med_rot_rate:16;
+       u32        reserved4:16;
+};
+
+/*
+ * SCSI caching mode page
+ */
+struct scsi_mp_caching_s{
+#ifdef __BIGENDIAN
+       u8         ps:1;
+       u8         res1:1;
+       u8         page_code:6;
+#else
+       u8         page_code:6;
+       u8         res1:1;
+       u8         ps:1;
+#endif
+       u8         page_len;
+#ifdef __BIGENDIAN
+       u8         ic:1;        /* initiator control */
+       u8         abpf:1;      /* abort pre-fetch */
+       u8         cap:1;       /* caching analysis permitted */
+       u8         disc:1;      /* discontinuity */
+       u8         size:1;      /* size enable */
+       u8         wce:1;       /* write cache enable */
+       u8         mf:1;        /* multiplication factor */
+       u8         rcd:1;       /* read cache disable */
+
+       u8         drrp:4;      /* demand read retention priority */
+       u8         wrp:4;       /* write retention priority */
+#else
+       u8         rcd:1;       /* read cache disable */
+       u8         mf:1;        /* multiplication factor */
+       u8         wce:1;       /* write cache enable */
+       u8         size:1;      /* size enable */
+       u8         disc:1;      /* discontinuity */
+       u8         cap:1;       /* caching analysis permitted */
+       u8         abpf:1;      /* abort pre-fetch */
+       u8         ic:1;        /* initiator control */
+
+       u8         wrp:4;       /* write retention priority */
+       u8         drrp:4;      /* demand read retention priority */
+#endif
+       u8         dptl[2];/* disable pre-fetch transfer length */
+       u8         min_prefetch[2];
+       u8         max_prefetch[2];
+       u8         max_prefetch_limit[2];
+#ifdef __BIGENDIAN
+       u8         fsw:1;       /* force sequential write */
+       u8         lbcss:1;/* logical block cache segment size */
+       u8         dra:1;       /* disable read ahead */
+       u8         vs:2;        /* vendor specific */
+       u8         res2:3;
+#else
+       u8         res2:3;
+       u8         vs:2;        /* vendor specific */
+       u8         dra:1;       /* disable read ahead */
+       u8         lbcss:1;/* logical block cache segment size */
+       u8         fsw:1;       /* force sequential write */
+#endif
+       u8         num_cache_segs;
+
+       u8         cache_seg_size[2];
+       u8         res3;
+       u8         non_cache_seg_size[3];
+};
+
+/*
+ * SCSI control mode page
+ */
+struct scsi_mp_control_page_s{
+#ifdef __BIGENDIAN
+u8         ps:1;
+u8         reserved1:1;
+u8         page_code:6;
+#else
+u8         page_code:6;
+u8         reserved1:1;
+u8         ps:1;
+#endif
+       u8         page_len;
+#ifdef __BIGENDIAN
+       u8         tst:3;               /* task set type */
+       u8         reserved3:3;
+       u8         gltsd:1;     /* global logging target save disable */
+       u8         rlec:1;              /* report log exception condition */
+
+       u8         qalgo_mod:4; /* queue alogorithm modifier */
+       u8         reserved4:1;
+       u8         qerr:2;              /* queue error management */
+       u8         dque:1;              /* disable queuing */
+
+       u8         reserved5:1;
+       u8         rac:1;               /* report a check */
+       u8         reserved6:2;
+       u8         swp:1;               /* software write protect */
+       u8         raerp:1;     /* ready AER permission */
+       u8         uaaerp:1;    /* unit attenstion AER permission */
+       u8         eaerp:1;     /* error AER permission */
+
+       u8         reserved7:5;
+       u8         autoload_mod:3;
+#else
+       u8         rlec:1;              /* report log exception condition */
+       u8         gltsd:1;     /* global logging target save disable */
+       u8         reserved3:3;
+       u8         tst:3;               /* task set type */
+
+       u8         dque:1;              /* disable queuing */
+       u8         qerr:2;              /* queue error management */
+       u8         reserved4:1;
+       u8         qalgo_mod:4; /* queue alogorithm modifier */
+
+       u8         eaerp:1;     /* error AER permission */
+       u8         uaaerp:1;    /* unit attenstion AER permission */
+       u8         raerp:1;     /* ready AER permission */
+       u8         swp:1;               /* software write protect */
+       u8         reserved6:2;
+       u8         rac:1;               /* report a check */
+       u8         reserved5:1;
+
+       u8         autoload_mod:3;
+       u8         reserved7:5;
+#endif
+       u8         rahp_msb;    /* ready AER holdoff period - MSB */
+       u8         rahp_lsb;    /* ready AER holdoff period - LSB */
+
+       u8         busy_timeout_period_msb;
+       u8         busy_timeout_period_lsb;
+
+       u8         ext_selftest_compl_time_msb;
+       u8         ext_selftest_compl_time_lsb;
+};
+
+/*
+ * SCSI medium types supported mode page
+ */
+struct scsi_mp_medium_types_sup_s{
+#ifdef __BIGENDIAN
+       u8         ps:1;
+       u8         reserved1:1;
+       u8         page_code:6;
+#else
+       u8         page_code:6;
+       u8         reserved1:1;
+       u8         ps:1;
+#endif
+       u8         page_len;
+
+       u8         reserved3[2];
+       u8         med_type1_sup;       /* medium type one supported */
+       u8         med_type2_sup;       /* medium type two supported */
+       u8         med_type3_sup;       /* medium type three supported */
+       u8         med_type4_sup;       /* medium type four supported */
+};
+
+/*
+ * SCSI informational exception control mode page
+ */
+struct scsi_mp_info_excpt_cntl_s{
+#ifdef __BIGENDIAN
+       u8         ps:1;
+       u8         reserved1:1;
+       u8         page_code:6;
+#else
+       u8         page_code:6;
+       u8         reserved1:1;
+       u8         ps:1;
+#endif
+       u8         page_len;
+#ifdef __BIGENDIAN
+       u8         perf:1;              /* performance */
+       u8         reserved3:1;
+       u8         ebf:1;               /* enable background fucntion */
+       u8         ewasc:1;     /* enable warning */
+       u8         dexcpt:1;    /* disable exception control */
+       u8         test:1;              /* enable test device failure
+                                        * notification
+                                        */
+       u8         reserved4:1;
+       u8         log_error:1;
+
+       u8         reserved5:4;
+       u8         mrie:4;              /* method of reporting info
+                                        * exceptions
+                                        */
+#else
+       u8         log_error:1;
+       u8         reserved4:1;
+       u8         test:1;              /* enable test device failure
+                                        * notification
+                                        */
+       u8         dexcpt:1;    /* disable exception control */
+       u8         ewasc:1;     /* enable warning */
+       u8         ebf:1;               /* enable background fucntion */
+       u8         reserved3:1;
+       u8         perf:1;              /* performance */
+
+       u8         mrie:4;              /* method of reporting info
+                                        * exceptions
+                                        */
+       u8         reserved5:4;
+#endif
+       u8         interval_timer_msb;
+       u8         interval_timer_lsb;
+
+       u8         report_count_msb;
+       u8         report_count_lsb;
+};
+
+/*
+ * Methods of reporting informational exceptions
+ */
+#define SCSI_MP_IEC_NO_REPORT       0x0        /* no reporting of exceptions */
+#define SCSI_MP_IEC_AER             0x1        /* async event reporting */
+#define SCSI_MP_IEC_UNIT_ATTN       0x2        /* generate unit attenstion */
+#define SCSI_MO_IEC_COND_REC_ERR    0x3        /* conditionally generate recovered
+                                        * error
+                                        */
+#define SCSI_MP_IEC_UNCOND_REC_ERR  0x4        /* unconditionally generate recovered
+                                        * error
+                                        */
+#define SCSI_MP_IEC_NO_SENSE        0x5        /* generate no sense */
+#define SCSI_MP_IEC_ON_REQUEST      0x6        /* only report exceptions on request */
+
+/*
+ * SCSI flexible disk page
+ */
+struct scsi_mp_flexible_disk_s{
+#ifdef __BIGENDIAN
+       u8         ps:1;
+       u8         reserved1:1;
+       u8         page_code:6;
+#else
+       u8         page_code:6;
+       u8         reserved1:1;
+       u8         ps:1;
+#endif
+       u8         page_len;
+
+       u8         transfer_rate_msb;
+       u8         transfer_rate_lsb;
+
+       u8         num_heads;
+       u8         num_sectors;
+
+       u8         bytes_per_sector_msb;
+       u8         bytes_per_sector_lsb;
+
+       u8         num_cylinders_msb;
+       u8         num_cylinders_lsb;
+
+       u8         sc_wpc_msb;  /* starting cylinder-write
+                                        * precompensation msb
+                                        */
+       u8         sc_wpc_lsb;  /* starting cylinder-write
+                                        * precompensation lsb
+                                        */
+       u8         sc_rwc_msb;  /* starting cylinder-reduced write
+                                        * current msb
+                                        */
+       u8         sc_rwc_lsb;  /* starting cylinder-reduced write
+                                        * current lsb
+                                        */
+
+       u8         dev_step_rate_msb;
+       u8         dev_step_rate_lsb;
+
+       u8         dev_step_pulse_width;
+
+       u8         head_sd_msb; /* head settle delay msb */
+       u8         head_sd_lsb; /* head settle delay lsb */
+
+       u8         motor_on_delay;
+       u8         motor_off_delay;
+#ifdef __BIGENDIAN
+       u8         trdy:1;              /* true ready bit */
+       u8         ssn:1;               /* start sector number bit */
+       u8         mo:1;                /* motor on bit */
+       u8         reserved3:5;
+
+       u8         reserved4:4;
+       u8         spc:4;               /* step pulse per cylinder */
+#else
+       u8         reserved3:5;
+       u8         mo:1;                /* motor on bit */
+       u8         ssn:1;               /* start sector number bit */
+       u8         trdy:1;              /* true ready bit */
+
+       u8         spc:4;               /* step pulse per cylinder */
+       u8         reserved4:4;
+#endif
+       u8         write_comp;
+       u8         head_load_delay;
+       u8         head_unload_delay;
+#ifdef __BIGENDIAN
+       u8         pin34:4;     /* pin34 usage */
+       u8         pin2:4;              /* pin2 usage */
+
+       u8         pin4:4;              /* pin4 usage */
+       u8         pin1:4;              /* pin1 usage */
+#else
+       u8         pin2:4;              /* pin2 usage */
+       u8         pin34:4;     /* pin34 usage */
+
+       u8         pin1:4;              /* pin1 usage */
+       u8         pin4:4;              /* pin4 usage */
+#endif
+       u8         med_rot_rate_msb;
+       u8         med_rot_rate_lsb;
+
+       u8         reserved5[2];
+};
+
+struct scsi_mode_page_format_data6_s{
+       struct scsi_mode_param_header6_s mph;   /* mode page header */
+       struct scsi_mode_param_desc_s desc;     /* block descriptor */
+       struct scsi_mp_format_device_s format;  /* format device data */
+};
+
+struct scsi_mode_page_format_data10_s{
+       struct scsi_mode_param_header10_s mph;  /* mode page header */
+       struct scsi_mode_param_desc_s desc;     /* block descriptor */
+       struct scsi_mp_format_device_s format;  /* format device data */
+};
+
+struct scsi_mode_page_rdg_data6_s{
+       struct scsi_mode_param_header6_s mph;   /* mode page header */
+       struct scsi_mode_param_desc_s desc;     /* block descriptor */
+       struct scsi_mp_rigid_device_geometry_s rdg;
+                                       /* rigid geometry data */
+};
+
+struct scsi_mode_page_rdg_data10_s{
+       struct scsi_mode_param_header10_s mph;  /* mode page header */
+       struct scsi_mode_param_desc_s desc;     /* block descriptor */
+       struct scsi_mp_rigid_device_geometry_s rdg;
+                                       /* rigid geometry data */
+};
+
+struct scsi_mode_page_cache6_s{
+       struct scsi_mode_param_header6_s mph;   /* mode page header */
+       struct scsi_mode_param_desc_s desc;     /* block descriptor */
+       struct scsi_mp_caching_s cache; /* cache page data */
+};
+
+struct scsi_mode_page_cache10_s{
+       struct scsi_mode_param_header10_s mph;  /* mode page header */
+       struct scsi_mode_param_desc_s desc;     /* block descriptor */
+       struct scsi_mp_caching_s cache; /* cache page data */
+};
+
+/* --------------------------------------------------------------
+ * Format Unit command
+ * ------------------------------------------------------------
+ */
+
+/*
+ * Format Unit CDB
+ */
+struct scsi_format_unit_s{
+       u8         opcode;
+#ifdef __BIGENDIAN
+       u8         res1:3;
+       u8         fmtdata:1;   /* if set, data out phase has format
+                                        * data
+                                        */
+       u8         cmplst:1;    /* if set, defect list is complete */
+       u8         def_list:3;  /* format of defect descriptor is
+                                        * fmtdata =1
+                                        */
+#else
+       u8         def_list:3;  /* format of defect descriptor is
+                                        * fmtdata = 1
+                                        */
+       u8         cmplst:1;    /* if set, defect list is complete */
+       u8         fmtdata:1;   /* if set, data out phase has format
+                                        * data
+                                        */
+       u8         res1:3;
+#endif
+       u8         interleave_msb;
+       u8         interleave_lsb;
+       u8         vendor_spec;
+       u8         control;
+};
+
+/*
+ * h
+ */
+struct scsi_reserve6_s{
+       u8         opcode;
+#ifdef __BIGENDIAN
+       u8         reserved:3;
+       u8         obsolete:4;
+       u8         extent:1;
+#else
+       u8         extent:1;
+       u8         obsolete:4;
+       u8         reserved:3;
+#endif
+       u8         reservation_id;
+       u16        param_list_len;
+       u8         control;
+};
+
+/*
+ * h
+ */
+struct scsi_release6_s{
+       u8         opcode;
+#ifdef __BIGENDIAN
+       u8         reserved1:3;
+       u8         obsolete:4;
+       u8         extent:1;
+#else
+       u8         extent:1;
+       u8         obsolete:4;
+       u8         reserved1:3;
+#endif
+       u8         reservation_id;
+       u16        reserved2;
+       u8         control;
+};
+
+/*
+ * h
+ */
+struct scsi_reserve10_s{
+       u8         opcode;
+#ifdef __BIGENDIAN
+       u8         reserved1:3;
+       u8         third_party:1;
+       u8         reserved2:2;
+       u8         long_id:1;
+       u8         extent:1;
+#else
+       u8         extent:1;
+       u8         long_id:1;
+       u8         reserved2:2;
+       u8         third_party:1;
+       u8         reserved1:3;
+#endif
+       u8         reservation_id;
+       u8         third_pty_dev_id;
+       u8         reserved3;
+       u8         reserved4;
+       u8         reserved5;
+       u16        param_list_len;
+       u8         control;
+};
+
+struct scsi_release10_s{
+       u8         opcode;
+#ifdef __BIGENDIAN
+       u8         reserved1:3;
+       u8         third_party:1;
+       u8         reserved2:2;
+       u8         long_id:1;
+       u8         extent:1;
+#else
+       u8         extent:1;
+       u8         long_id:1;
+       u8         reserved2:2;
+       u8         third_party:1;
+       u8         reserved1:3;
+#endif
+       u8         reservation_id;
+       u8         third_pty_dev_id;
+       u8         reserved3;
+       u8         reserved4;
+       u8         reserved5;
+       u16        param_list_len;
+       u8         control;
+};
+
+struct scsi_verify10_s{
+       u8         opcode;
+#ifdef __BIGENDIAN
+       u8         lun:3;
+       u8         dpo:1;
+       u8         reserved:2;
+       u8         bytchk:1;
+       u8         reladdr:1;
+#else
+       u8         reladdr:1;
+       u8         bytchk:1;
+       u8         reserved:2;
+       u8         dpo:1;
+       u8         lun:3;
+#endif
+       u8         lba0;
+       u8         lba1;
+       u8         lba2;
+       u8         lba3;
+       u8         reserved1;
+       u8         verification_len0;
+       u8         verification_len1;
+       u8         control_byte;
+};
+
+struct scsi_request_sense_s{
+       u8         opcode;
+#ifdef __BIGENDIAN
+       u8         lun:3;
+       u8         reserved:5;
+#else
+       u8         reserved:5;
+       u8         lun:3;
+#endif
+       u8         reserved0;
+       u8         reserved1;
+       u8         alloc_len;
+       u8         control_byte;
+};
+
+/* ------------------------------------------------------------
+ * SCSI status byte values
+ * ------------------------------------------------------------
+ */
+#define SCSI_STATUS_GOOD                   0x00
+#define SCSI_STATUS_CHECK_CONDITION        0x02
+#define SCSI_STATUS_CONDITION_MET          0x04
+#define SCSI_STATUS_BUSY                   0x08
+#define SCSI_STATUS_INTERMEDIATE           0x10
+#define SCSI_STATUS_ICM                    0x14        /* intermediate condition met */
+#define SCSI_STATUS_RESERVATION_CONFLICT   0x18
+#define SCSI_STATUS_COMMAND_TERMINATED     0x22
+#define SCSI_STATUS_QUEUE_FULL             0x28
+#define SCSI_STATUS_ACA_ACTIVE             0x30
+
+#define SCSI_MAX_ALLOC_LEN             0xFF    /* maximum allocarion length
+                                                * in CDBs
+                                                */
+
+#define SCSI_OP_WRITE_VERIFY10      0x2E
+#define SCSI_OP_WRITE_VERIFY12      0xAE
+#define SCSI_OP_UNDEF               0xFF
+
+/*
+ * SCSI WRITE-VERIFY(10) command
+ */
+struct scsi_write_verify10_s{
+       u8         opcode;
+#ifdef __BIGENDIAN
+       u8         reserved1:3;
+       u8         dpo:1;               /* Disable Page Out */
+       u8         reserved2:1;
+       u8         ebp:1;               /* erse by-pass */
+       u8         bytchk:1;    /* byte check */
+       u8         rel_adr:1;   /* relative address */
+#else
+       u8         rel_adr:1;   /* relative address */
+       u8         bytchk:1;    /* byte check */
+       u8         ebp:1;               /* erse by-pass */
+       u8         reserved2:1;
+       u8         dpo:1;               /* Disable Page Out */
+       u8         reserved1:3;
+#endif
+       u8         lba0;                /* logical block address - MSB */
+       u8         lba1;
+       u8         lba2;
+       u8         lba3;                /* LSB */
+       u8         reserved3;
+       u8         xfer_length0;        /* transfer length in blocks - MSB */
+       u8         xfer_length1;        /* LSB */
+       u8         control;
+};
+
+#pragma pack()
+
+#endif /* __SCSI_H__ */
diff --git a/drivers/scsi/bfa/include/protocol/types.h b/drivers/scsi/bfa/include/protocol/types.h
new file mode 100644 (file)
index 0000000..2875a6c
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) 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.
+ */
+
+/**
+ *  types.h Protocol defined base types
+ */
+
+#ifndef __TYPES_H__
+#define __TYPES_H__
+
+#include <bfa_os_inc.h>
+
+#define wwn_t u64
+#define lun_t u64
+
+#define WWN_NULL       (0)
+#define FC_SYMNAME_MAX 256     /*  max name server symbolic name size */
+#define FC_ALPA_MAX    128
+
+#pragma pack(1)
+
+#define MAC_ADDRLEN    (6)
+struct mac_s { u8 mac[MAC_ADDRLEN]; };
+#define mac_t struct mac_s
+
+#pragma pack()
+
+#endif
diff --git a/drivers/scsi/bfa/loop.c b/drivers/scsi/bfa/loop.c
new file mode 100644 (file)
index 0000000..a418ded
--- /dev/null
@@ -0,0 +1,422 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) 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.
+ */
+
+/**
+ *  port_loop.c vport private loop implementation.
+ */
+#include <bfa.h>
+#include <bfa_svc.h>
+#include "fcs_lport.h"
+#include "fcs_rport.h"
+#include "fcs_trcmod.h"
+#include "lport_priv.h"
+
+BFA_TRC_FILE(FCS, LOOP);
+
+/**
+ *   ALPA to LIXA bitmap mapping
+ *
+ *   ALPA 0x00 (Word 0, Bit 30) is invalid for N_Ports. Also Word 0 Bit 31
+ * is for L_bit (login required) and is filled as ALPA 0x00 here.
+ */
+static const u8   port_loop_alpa_map[] = {
+       0xEF, 0xE8, 0xE4, 0xE2, 0xE1, 0xE0, 0xDC, 0xDA, /* Word 3 Bits 0..7 */
+       0xD9, 0xD6, 0xD5, 0xD4, 0xD3, 0xD2, 0xD1, 0xCE, /* Word 3 Bits 8..15 */
+       0xCD, 0xCC, 0xCB, 0xCA, 0xC9, 0xC7, 0xC6, 0xC5, /* Word 3 Bits 16..23 */
+       0xC3, 0xBC, 0xBA, 0xB9, 0xB6, 0xB5, 0xB4, 0xB3, /* Word 3 Bits 24..31 */
+
+       0xB2, 0xB1, 0xAE, 0xAD, 0xAC, 0xAB, 0xAA, 0xA9, /* Word 2 Bits 0..7 */
+       0xA7, 0xA6, 0xA5, 0xA3, 0x9F, 0x9E, 0x9D, 0x9B, /* Word 2 Bits 8..15 */
+       0x98, 0x97, 0x90, 0x8F, 0x88, 0x84, 0x82, 0x81, /* Word 2 Bits 16..23 */
+       0x80, 0x7C, 0x7A, 0x79, 0x76, 0x75, 0x74, 0x73, /* Word 2 Bits 24..31 */
+
+       0x72, 0x71, 0x6E, 0x6D, 0x6C, 0x6B, 0x6A, 0x69, /* Word 1 Bits 0..7 */
+       0x67, 0x66, 0x65, 0x63, 0x5C, 0x5A, 0x59, 0x56, /* Word 1 Bits 8..15 */
+       0x55, 0x54, 0x53, 0x52, 0x51, 0x4E, 0x4D, 0x4C, /* Word 1 Bits 16..23 */
+       0x4B, 0x4A, 0x49, 0x47, 0x46, 0x45, 0x43, 0x3C, /* Word 1 Bits 24..31 */
+
+       0x3A, 0x39, 0x36, 0x35, 0x34, 0x33, 0x32, 0x31, /* Word 0 Bits 0..7 */
+       0x2E, 0x2D, 0x2C, 0x2B, 0x2A, 0x29, 0x27, 0x26, /* Word 0 Bits 8..15 */
+       0x25, 0x23, 0x1F, 0x1E, 0x1D, 0x1B, 0x18, 0x17, /* Word 0 Bits 16..23 */
+       0x10, 0x0F, 0x08, 0x04, 0x02, 0x01, 0x00, 0x00, /* Word 0 Bits 24..31 */
+};
+
+/*
+ * Local Functions
+ */
+bfa_status_t    bfa_fcs_port_loop_send_plogi(struct bfa_fcs_port_s *port,
+                                            u8 alpa);
+
+void            bfa_fcs_port_loop_plogi_response(void *fcsarg,
+                                                struct bfa_fcxp_s *fcxp,
+                                                void *cbarg,
+                                                bfa_status_t req_status,
+                                                u32 rsp_len,
+                                                u32 resid_len,
+                                                struct fchs_s *rsp_fchs);
+
+bfa_status_t    bfa_fcs_port_loop_send_adisc(struct bfa_fcs_port_s *port,
+                                            u8 alpa);
+
+void            bfa_fcs_port_loop_adisc_response(void *fcsarg,
+                                                struct bfa_fcxp_s *fcxp,
+                                                void *cbarg,
+                                                bfa_status_t req_status,
+                                                u32 rsp_len,
+                                                u32 resid_len,
+                                                struct fchs_s *rsp_fchs);
+
+bfa_status_t    bfa_fcs_port_loop_send_plogi_acc(struct bfa_fcs_port_s *port,
+                                                u8 alpa);
+
+void            bfa_fcs_port_loop_plogi_acc_response(void *fcsarg,
+                                                    struct bfa_fcxp_s *fcxp,
+                                                    void *cbarg,
+                                                    bfa_status_t req_status,
+                                                    u32 rsp_len,
+                                                    u32 resid_len,
+                                                    struct fchs_s *rsp_fchs);
+
+bfa_status_t    bfa_fcs_port_loop_send_adisc_acc(struct bfa_fcs_port_s *port,
+                                                u8 alpa);
+
+void            bfa_fcs_port_loop_adisc_acc_response(void *fcsarg,
+                                                    struct bfa_fcxp_s *fcxp,
+                                                    void *cbarg,
+                                                    bfa_status_t req_status,
+                                                    u32 rsp_len,
+                                                    u32 resid_len,
+                                                    struct fchs_s *rsp_fchs);
+/**
+ *   Called by port to initializar in provate LOOP topology.
+ */
+void
+bfa_fcs_port_loop_init(struct bfa_fcs_port_s *port)
+{
+}
+
+/**
+ *   Called by port to notify transition to online state.
+ */
+void
+bfa_fcs_port_loop_online(struct bfa_fcs_port_s *port)
+{
+
+       u8         num_alpa = port->port_topo.ploop.num_alpa;
+       u8        *alpa_pos_map = port->port_topo.ploop.alpa_pos_map;
+       struct bfa_fcs_rport_s *r_port;
+       int             ii = 0;
+
+       /*
+        * If the port role is Initiator Mode, create Rports.
+        */
+       if (port->port_cfg.roles == BFA_PORT_ROLE_FCP_IM) {
+               /*
+                * Check if the ALPA positional bitmap is available.
+                * if not, we send PLOGI to all possible ALPAs.
+                */
+               if (num_alpa > 0) {
+                       for (ii = 0; ii < num_alpa; ii++) {
+                               /*
+                                * ignore ALPA of bfa port
+                                */
+                               if (alpa_pos_map[ii] != port->pid) {
+                                       r_port = bfa_fcs_rport_create(port,
+                                               alpa_pos_map[ii]);
+                               }
+                       }
+               } else {
+                       for (ii = 0; ii < MAX_ALPA_COUNT; ii++) {
+                               /*
+                                * ignore ALPA of bfa port
+                                */
+                               if ((port_loop_alpa_map[ii] > 0)
+                                   && (port_loop_alpa_map[ii] != port->pid))
+                                       bfa_fcs_port_loop_send_plogi(port,
+                                               port_loop_alpa_map[ii]);
+                               /**TBD */
+                       }
+               }
+       } else {
+               /*
+                * TBD Target Mode ??
+                */
+       }
+
+}
+
+/**
+ *   Called by port to notify transition to offline state.
+ */
+void
+bfa_fcs_port_loop_offline(struct bfa_fcs_port_s *port)
+{
+
+}
+
+/**
+ *   Called by port to notify a LIP on the loop.
+ */
+void
+bfa_fcs_port_loop_lip(struct bfa_fcs_port_s *port)
+{
+}
+
+/**
+ * Local Functions.
+ */
+bfa_status_t
+bfa_fcs_port_loop_send_plogi(struct bfa_fcs_port_s *port, u8 alpa)
+{
+       struct fchs_s          fchs;
+       struct bfa_fcxp_s *fcxp = NULL;
+       int             len;
+
+       bfa_trc(port->fcs, alpa);
+
+       fcxp = bfa_fcxp_alloc(NULL, port->fcs->bfa, 0, 0, NULL, NULL, NULL,
+                                 NULL);
+       bfa_assert(fcxp);
+
+       len = fc_plogi_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), alpa,
+                            bfa_fcs_port_get_fcid(port), 0,
+                            port->port_cfg.pwwn, port->port_cfg.nwwn,
+                                bfa_pport_get_maxfrsize(port->fcs->bfa));
+
+       bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
+                         FC_CLASS_3, len, &fchs,
+                         bfa_fcs_port_loop_plogi_response, (void *)port,
+                         FC_MAX_PDUSZ, FC_RA_TOV);
+
+       return BFA_STATUS_OK;
+}
+
+/**
+ *   Called by fcxp to notify the Plogi response
+ */
+void
+bfa_fcs_port_loop_plogi_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
+                                void *cbarg, bfa_status_t req_status,
+                                u32 rsp_len, u32 resid_len,
+                                struct fchs_s *rsp_fchs)
+{
+       struct bfa_fcs_port_s *port = (struct bfa_fcs_port_s *) cbarg;
+       struct fc_logi_s     *plogi_resp;
+       struct fc_els_cmd_s   *els_cmd;
+
+       bfa_trc(port->fcs, req_status);
+
+       /*
+        * Sanity Checks
+        */
+       if (req_status != BFA_STATUS_OK) {
+               bfa_trc(port->fcs, req_status);
+               /*
+                * @todo
+                * This could mean that the device with this APLA does not
+                * exist on the loop.
+                */
+
+               return;
+       }
+
+       els_cmd = (struct fc_els_cmd_s *) BFA_FCXP_RSP_PLD(fcxp);
+       plogi_resp = (struct fc_logi_s *) els_cmd;
+
+       if (els_cmd->els_code == FC_ELS_ACC) {
+               bfa_fcs_rport_start(port, rsp_fchs, plogi_resp);
+       } else {
+               bfa_trc(port->fcs, plogi_resp->els_cmd.els_code);
+               bfa_assert(0);
+       }
+}
+
+bfa_status_t
+bfa_fcs_port_loop_send_plogi_acc(struct bfa_fcs_port_s *port, u8 alpa)
+{
+       struct fchs_s          fchs;
+       struct bfa_fcxp_s *fcxp;
+       int             len;
+
+       bfa_trc(port->fcs, alpa);
+
+       fcxp = bfa_fcxp_alloc(NULL, port->fcs->bfa, 0, 0, NULL, NULL, NULL,
+                                 NULL);
+       bfa_assert(fcxp);
+
+       len = fc_plogi_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), alpa,
+                                bfa_fcs_port_get_fcid(port), 0,
+                                port->port_cfg.pwwn, port->port_cfg.nwwn,
+                                bfa_pport_get_maxfrsize(port->fcs->bfa));
+
+       bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
+                                FC_CLASS_3, len, &fchs,
+                                bfa_fcs_port_loop_plogi_acc_response,
+                                (void *)port, FC_MAX_PDUSZ, 0); /* No response
+                                                                 * expected
+                                                                 */
+
+       return BFA_STATUS_OK;
+}
+
+/*
+ *  Plogi Acc Response
+ * We donot do any processing here.
+ */
+void
+bfa_fcs_port_loop_plogi_acc_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
+                                    void *cbarg, bfa_status_t req_status,
+                                    u32 rsp_len, u32 resid_len,
+                                    struct fchs_s *rsp_fchs)
+{
+
+       struct bfa_fcs_port_s *port = (struct bfa_fcs_port_s *) cbarg;
+
+       bfa_trc(port->fcs, port->pid);
+
+       /*
+        * Sanity Checks
+        */
+       if (req_status != BFA_STATUS_OK) {
+               bfa_trc(port->fcs, req_status);
+               return;
+       }
+}
+
+bfa_status_t
+bfa_fcs_port_loop_send_adisc(struct bfa_fcs_port_s *port, u8 alpa)
+{
+       struct fchs_s          fchs;
+       struct bfa_fcxp_s *fcxp;
+       int             len;
+
+       bfa_trc(port->fcs, alpa);
+
+       fcxp = bfa_fcxp_alloc(NULL, port->fcs->bfa, 0, 0, NULL, NULL, NULL,
+                                 NULL);
+       bfa_assert(fcxp);
+
+       len = fc_adisc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), alpa,
+                            bfa_fcs_port_get_fcid(port), 0,
+                            port->port_cfg.pwwn, port->port_cfg.nwwn);
+
+       bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
+                         FC_CLASS_3, len, &fchs,
+                         bfa_fcs_port_loop_adisc_response, (void *)port,
+                         FC_MAX_PDUSZ, FC_RA_TOV);
+
+       return BFA_STATUS_OK;
+}
+
+/**
+ *   Called by fcxp to notify the ADISC response
+ */
+void
+bfa_fcs_port_loop_adisc_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
+                                void *cbarg, bfa_status_t req_status,
+                                u32 rsp_len, u32 resid_len,
+                                struct fchs_s *rsp_fchs)
+{
+       struct bfa_fcs_port_s *port = (struct bfa_fcs_port_s *) cbarg;
+       struct bfa_fcs_rport_s *rport;
+       struct fc_adisc_s     *adisc_resp;
+       struct fc_els_cmd_s   *els_cmd;
+       u32        pid = rsp_fchs->s_id;
+
+       bfa_trc(port->fcs, req_status);
+
+       /*
+        * Sanity Checks
+        */
+       if (req_status != BFA_STATUS_OK) {
+               /*
+                * TBD : we may need to retry certain requests
+                */
+               bfa_fcxp_free(fcxp);
+               return;
+       }
+
+       els_cmd = (struct fc_els_cmd_s *) BFA_FCXP_RSP_PLD(fcxp);
+       adisc_resp = (struct fc_adisc_s *) els_cmd;
+
+       if (els_cmd->els_code == FC_ELS_ACC) {
+       } else {
+               bfa_trc(port->fcs, adisc_resp->els_cmd.els_code);
+
+               /*
+                * TBD: we may need to check for reject codes and retry
+                */
+               rport = bfa_fcs_port_get_rport_by_pid(port, pid);
+               if (rport) {
+                       list_del(&rport->qe);
+                       bfa_fcs_rport_delete(rport);
+               }
+
+       }
+       return;
+}
+
+bfa_status_t
+bfa_fcs_port_loop_send_adisc_acc(struct bfa_fcs_port_s *port, u8 alpa)
+{
+       struct fchs_s          fchs;
+       struct bfa_fcxp_s *fcxp;
+       int             len;
+
+       bfa_trc(port->fcs, alpa);
+
+       fcxp = bfa_fcxp_alloc(NULL, port->fcs->bfa, 0, 0, NULL, NULL, NULL,
+                                 NULL);
+       bfa_assert(fcxp);
+
+       len = fc_adisc_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), alpa,
+                                bfa_fcs_port_get_fcid(port), 0,
+                                port->port_cfg.pwwn, port->port_cfg.nwwn);
+
+       bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
+                               FC_CLASS_3, len, &fchs,
+                               bfa_fcs_port_loop_adisc_acc_response,
+                               (void *)port, FC_MAX_PDUSZ, 0); /* no reponse
+                                                                * expected
+                                                                */
+
+       return BFA_STATUS_OK;
+}
+
+/*
+ *  Adisc Acc Response
+ * We donot do any processing here.
+ */
+void
+bfa_fcs_port_loop_adisc_acc_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
+                                    void *cbarg, bfa_status_t req_status,
+                                    u32 rsp_len, u32 resid_len,
+                                    struct fchs_s *rsp_fchs)
+{
+
+       struct bfa_fcs_port_s *port = (struct bfa_fcs_port_s *) cbarg;
+
+       bfa_trc(port->fcs, port->pid);
+
+       /*
+        * Sanity Checks
+        */
+       if (req_status != BFA_STATUS_OK) {
+               bfa_trc(port->fcs, req_status);
+               return;
+       }
+}
diff --git a/drivers/scsi/bfa/lport_api.c b/drivers/scsi/bfa/lport_api.c
new file mode 100644 (file)
index 0000000..8f51a83
--- /dev/null
@@ -0,0 +1,291 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) 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.
+ */
+
+/**
+ *  port_api.c BFA FCS port
+ */
+
+#include <fcs/bfa_fcs.h>
+#include <fcs/bfa_fcs_lport.h>
+#include <fcs/bfa_fcs_rport.h>
+#include "fcs_rport.h"
+#include "fcs_fabric.h"
+#include "fcs_trcmod.h"
+#include "fcs_vport.h"
+
+BFA_TRC_FILE(FCS, PORT_API);
+
+
+
+/**
+ *  fcs_port_api BFA FCS port API
+ */
+
+void
+bfa_fcs_cfg_base_port(struct bfa_fcs_s *fcs, struct bfa_port_cfg_s *port_cfg)
+{
+}
+
+struct bfa_fcs_port_s *
+bfa_fcs_get_base_port(struct bfa_fcs_s *fcs)
+{
+       return (&fcs->fabric.bport);
+}
+
+wwn_t
+bfa_fcs_port_get_rport(struct bfa_fcs_port_s *port, wwn_t wwn, int index,
+                      int nrports, bfa_boolean_t bwwn)
+{
+       struct list_head *qh, *qe;
+       struct bfa_fcs_rport_s *rport = NULL;
+       int             i;
+       struct bfa_fcs_s *fcs;
+
+       if (port == NULL || nrports == 0)
+               return (wwn_t) 0;
+
+       fcs = port->fcs;
+       bfa_trc(fcs, (u32) nrports);
+
+       i = 0;
+       qh = &port->rport_q;
+       qe = bfa_q_first(qh);
+
+       while ((qe != qh) && (i < nrports)) {
+               rport = (struct bfa_fcs_rport_s *)qe;
+               if (bfa_os_ntoh3b(rport->pid) > 0xFFF000) {
+                       qe = bfa_q_next(qe);
+                       bfa_trc(fcs, (u32) rport->pwwn);
+                       bfa_trc(fcs, rport->pid);
+                       bfa_trc(fcs, i);
+                       continue;
+               }
+
+               if (bwwn) {
+                       if (!memcmp(&wwn, &rport->pwwn, 8))
+                               break;
+               } else {
+                       if (i == index)
+                               break;
+               }
+
+               i++;
+               qe = bfa_q_next(qe);
+       }
+
+       bfa_trc(fcs, i);
+       if (rport) {
+               return rport->pwwn;
+       } else {
+               return (wwn_t) 0;
+       }
+}
+
+void
+bfa_fcs_port_get_rports(struct bfa_fcs_port_s *port, wwn_t rport_wwns[],
+                       int *nrports)
+{
+       struct list_head *qh, *qe;
+       struct bfa_fcs_rport_s *rport = NULL;
+       int             i;
+       struct bfa_fcs_s *fcs;
+
+       if (port == NULL || rport_wwns == NULL || *nrports == 0)
+               return;
+
+       fcs = port->fcs;
+       bfa_trc(fcs, (u32) *nrports);
+
+       i = 0;
+       qh = &port->rport_q;
+       qe = bfa_q_first(qh);
+
+       while ((qe != qh) && (i < *nrports)) {
+               rport = (struct bfa_fcs_rport_s *)qe;
+               if (bfa_os_ntoh3b(rport->pid) > 0xFFF000) {
+                       qe = bfa_q_next(qe);
+                       bfa_trc(fcs, (u32) rport->pwwn);
+                       bfa_trc(fcs, rport->pid);
+                       bfa_trc(fcs, i);
+                       continue;
+               }
+
+               rport_wwns[i] = rport->pwwn;
+
+               i++;
+               qe = bfa_q_next(qe);
+       }
+
+       bfa_trc(fcs, i);
+       *nrports = i;
+       return;
+}
+
+/*
+ * Iterate's through all the rport's in the given port to
+ * determine the maximum operating speed.
+ */
+enum bfa_pport_speed
+bfa_fcs_port_get_rport_max_speed(struct bfa_fcs_port_s *port)
+{
+       struct list_head *qh, *qe;
+       struct bfa_fcs_rport_s *rport = NULL;
+       struct bfa_fcs_s *fcs;
+       enum bfa_pport_speed max_speed = 0;
+       struct bfa_pport_attr_s pport_attr;
+       enum bfa_pport_speed pport_speed;
+
+       if (port == NULL)
+               return 0;
+
+       fcs = port->fcs;
+
+       /*
+        * Get Physical port's current speed
+        */
+       bfa_pport_get_attr(port->fcs->bfa, &pport_attr);
+       pport_speed = pport_attr.speed;
+       bfa_trc(fcs, pport_speed);
+
+       qh = &port->rport_q;
+       qe = bfa_q_first(qh);
+
+       while (qe != qh) {
+               rport = (struct bfa_fcs_rport_s *)qe;
+               if ((bfa_os_ntoh3b(rport->pid) > 0xFFF000)
+                   || (bfa_fcs_rport_get_state(rport) == BFA_RPORT_OFFLINE)) {
+                       qe = bfa_q_next(qe);
+                       continue;
+               }
+
+               if ((rport->rpf.rpsc_speed == BFA_PPORT_SPEED_8GBPS)
+                   || (rport->rpf.rpsc_speed > pport_speed)) {
+                       max_speed = rport->rpf.rpsc_speed;
+                       break;
+               } else if (rport->rpf.rpsc_speed > max_speed) {
+                       max_speed = rport->rpf.rpsc_speed;
+               }
+
+               qe = bfa_q_next(qe);
+       }
+
+       bfa_trc(fcs, max_speed);
+       return max_speed;
+}
+
+struct bfa_fcs_port_s *
+bfa_fcs_lookup_port(struct bfa_fcs_s *fcs, u16 vf_id, wwn_t lpwwn)
+{
+       struct bfa_fcs_vport_s *vport;
+       bfa_fcs_vf_t   *vf;
+
+       bfa_assert(fcs != NULL);
+
+       vf = bfa_fcs_vf_lookup(fcs, vf_id);
+       if (vf == NULL) {
+               bfa_trc(fcs, vf_id);
+               return (NULL);
+       }
+
+       if (!lpwwn || (vf->bport.port_cfg.pwwn == lpwwn))
+               return (&vf->bport);
+
+       vport = bfa_fcs_fabric_vport_lookup(vf, lpwwn);
+       if (vport)
+               return (&vport->lport);
+
+       return (NULL);
+}
+
+/*
+ *  API corresponding to VmWare's NPIV_VPORT_GETINFO.
+ */
+void
+bfa_fcs_port_get_info(struct bfa_fcs_port_s *port,
+                     struct bfa_port_info_s *port_info)
+{
+
+       bfa_trc(port->fcs, port->fabric->fabric_name);
+
+       if (port->vport == NULL) {
+               /*
+                * This is a Physical port
+                */
+               port_info->port_type = BFA_PORT_TYPE_PHYSICAL;
+
+               /*
+                * @todo : need to fix the state & reason
+                */
+               port_info->port_state = 0;
+               port_info->offline_reason = 0;
+
+               port_info->port_wwn = bfa_fcs_port_get_pwwn(port);
+               port_info->node_wwn = bfa_fcs_port_get_nwwn(port);
+
+               port_info->max_vports_supp = bfa_fcs_vport_get_max(port->fcs);
+               port_info->num_vports_inuse =
+                       bfa_fcs_fabric_vport_count(port->fabric);
+               port_info->max_rports_supp = BFA_FCS_MAX_RPORTS_SUPP;
+               port_info->num_rports_inuse = port->num_rports;
+       } else {
+               /*
+                * This is a virtual port
+                */
+               port_info->port_type = BFA_PORT_TYPE_VIRTUAL;
+
+               /*
+                * @todo : need to fix the state & reason
+                */
+               port_info->port_state = 0;
+               port_info->offline_reason = 0;
+
+               port_info->port_wwn = bfa_fcs_port_get_pwwn(port);
+               port_info->node_wwn = bfa_fcs_port_get_nwwn(port);
+       }
+}
+
+void
+bfa_fcs_port_get_stats(struct bfa_fcs_port_s *fcs_port,
+                      struct bfa_port_stats_s *port_stats)
+{
+       bfa_os_memcpy(port_stats, &fcs_port->stats,
+                     sizeof(struct bfa_port_stats_s));
+       return;
+}
+
+void
+bfa_fcs_port_clear_stats(struct bfa_fcs_port_s *fcs_port)
+{
+       bfa_os_memset(&fcs_port->stats, 0, sizeof(struct bfa_port_stats_s));
+       return;
+}
+
+void
+bfa_fcs_port_enable_ipfc_roles(struct bfa_fcs_port_s *fcs_port)
+{
+       fcs_port->port_cfg.roles |= BFA_PORT_ROLE_FCP_IPFC;
+       return;
+}
+
+void
+bfa_fcs_port_disable_ipfc_roles(struct bfa_fcs_port_s *fcs_port)
+{
+       fcs_port->port_cfg.roles &= ~BFA_PORT_ROLE_FCP_IPFC;
+       return;
+}
+
+
diff --git a/drivers/scsi/bfa/lport_priv.h b/drivers/scsi/bfa/lport_priv.h
new file mode 100644 (file)
index 0000000..dbae370
--- /dev/null
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ */
+
+#ifndef __VP_PRIV_H__
+#define __VP_PRIV_H__
+
+#include <fcs/bfa_fcs_lport.h>
+#include <fcs/bfa_fcs_vport.h>
+
+/*
+ * Functions exported by vps
+ */
+void            bfa_fcs_vport_init(struct bfa_fcs_vport_s *vport);
+
+/*
+ * Functions exported by vps
+ */
+void            bfa_fcs_vps_online(struct bfa_fcs_port_s *port);
+void            bfa_fcs_vps_offline(struct bfa_fcs_port_s *port);
+void            bfa_fcs_vps_lip(struct bfa_fcs_port_s *port);
+
+/*
+ * Functions exported by port_fab
+ */
+void            bfa_fcs_port_fab_init(struct bfa_fcs_port_s *vport);
+void            bfa_fcs_port_fab_online(struct bfa_fcs_port_s *vport);
+void            bfa_fcs_port_fab_offline(struct bfa_fcs_port_s *vport);
+void            bfa_fcs_port_fab_rx_frame(struct bfa_fcs_port_s *port,
+                                         u8 *rx_frame, u32 len);
+
+/*
+ * Functions exported by VP-NS.
+ */
+void            bfa_fcs_port_ns_init(struct bfa_fcs_port_s *vport);
+void            bfa_fcs_port_ns_offline(struct bfa_fcs_port_s *vport);
+void            bfa_fcs_port_ns_online(struct bfa_fcs_port_s *vport);
+void            bfa_fcs_port_ns_query(struct bfa_fcs_port_s *port);
+
+/*
+ * Functions exported by VP-SCN
+ */
+void            bfa_fcs_port_scn_init(struct bfa_fcs_port_s *vport);
+void            bfa_fcs_port_scn_offline(struct bfa_fcs_port_s *vport);
+void            bfa_fcs_port_scn_online(struct bfa_fcs_port_s *vport);
+void            bfa_fcs_port_scn_process_rscn(struct bfa_fcs_port_s *port,
+                                             struct fchs_s *rx_frame, u32 len);
+
+/*
+ * Functions exported by VP-N2N
+ */
+
+void            bfa_fcs_port_n2n_init(struct bfa_fcs_port_s *port);
+void            bfa_fcs_port_n2n_online(struct bfa_fcs_port_s *port);
+void            bfa_fcs_port_n2n_offline(struct bfa_fcs_port_s *port);
+void            bfa_fcs_port_n2n_rx_frame(struct bfa_fcs_port_s *port,
+                                         u8 *rx_frame, u32 len);
+
+/*
+ * Functions exported by VP-LOOP
+ */
+void            bfa_fcs_port_loop_init(struct bfa_fcs_port_s *port);
+void            bfa_fcs_port_loop_online(struct bfa_fcs_port_s *port);
+void            bfa_fcs_port_loop_offline(struct bfa_fcs_port_s *port);
+void            bfa_fcs_port_loop_lip(struct bfa_fcs_port_s *port);
+void            bfa_fcs_port_loop_rx_frame(struct bfa_fcs_port_s *port,
+                                          u8 *rx_frame, u32 len);
+
+#endif /* __VP_PRIV_H__ */
diff --git a/drivers/scsi/bfa/ms.c b/drivers/scsi/bfa/ms.c
new file mode 100644 (file)
index 0000000..c96b3ca
--- /dev/null
@@ -0,0 +1,759 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ */
+
+
+#include <bfa.h>
+#include <bfa_svc.h>
+#include "fcs_lport.h"
+#include "fcs_rport.h"
+#include "fcs_trcmod.h"
+#include "fcs_fcxp.h"
+#include "lport_priv.h"
+
+BFA_TRC_FILE(FCS, MS);
+
+#define BFA_FCS_MS_CMD_MAX_RETRIES  2
+/*
+ * forward declarations
+ */
+static void     bfa_fcs_port_ms_send_plogi(void *ms_cbarg,
+                                          struct bfa_fcxp_s *fcxp_alloced);
+static void     bfa_fcs_port_ms_timeout(void *arg);
+static void     bfa_fcs_port_ms_plogi_response(void *fcsarg,
+                                              struct bfa_fcxp_s *fcxp,
+                                              void *cbarg,
+                                              bfa_status_t req_status,
+                                              u32 rsp_len,
+                                              u32 resid_len,
+                                              struct fchs_s *rsp_fchs);
+
+static void     bfa_fcs_port_ms_send_gmal(void *ms_cbarg,
+                                         struct bfa_fcxp_s *fcxp_alloced);
+static void     bfa_fcs_port_ms_gmal_response(void *fcsarg,
+                                             struct bfa_fcxp_s *fcxp,
+                                             void *cbarg,
+                                             bfa_status_t req_status,
+                                             u32 rsp_len,
+                                             u32 resid_len,
+                                             struct fchs_s *rsp_fchs);
+static void     bfa_fcs_port_ms_send_gfn(void *ms_cbarg,
+                                        struct bfa_fcxp_s *fcxp_alloced);
+static void     bfa_fcs_port_ms_gfn_response(void *fcsarg,
+                                            struct bfa_fcxp_s *fcxp,
+                                            void *cbarg,
+                                            bfa_status_t req_status,
+                                            u32 rsp_len,
+                                            u32 resid_len,
+                                            struct fchs_s *rsp_fchs);
+/**
+ *  fcs_ms_sm FCS MS state machine
+ */
+
+/**
+ *  MS State Machine events
+ */
+enum port_ms_event {
+       MSSM_EVENT_PORT_ONLINE = 1,
+       MSSM_EVENT_PORT_OFFLINE = 2,
+       MSSM_EVENT_RSP_OK = 3,
+       MSSM_EVENT_RSP_ERROR = 4,
+       MSSM_EVENT_TIMEOUT = 5,
+       MSSM_EVENT_FCXP_SENT = 6,
+       MSSM_EVENT_PORT_FABRIC_RSCN = 7
+};
+
+static void     bfa_fcs_port_ms_sm_offline(struct bfa_fcs_port_ms_s *ms,
+                                          enum port_ms_event event);
+static void     bfa_fcs_port_ms_sm_plogi_sending(struct bfa_fcs_port_ms_s *ms,
+                                                enum port_ms_event event);
+static void     bfa_fcs_port_ms_sm_plogi(struct bfa_fcs_port_ms_s *ms,
+                                        enum port_ms_event event);
+static void     bfa_fcs_port_ms_sm_plogi_retry(struct bfa_fcs_port_ms_s *ms,
+                                              enum port_ms_event event);
+static void     bfa_fcs_port_ms_sm_gmal_sending(struct bfa_fcs_port_ms_s *ms,
+                                               enum port_ms_event event);
+static void     bfa_fcs_port_ms_sm_gmal(struct bfa_fcs_port_ms_s *ms,
+                                       enum port_ms_event event);
+static void     bfa_fcs_port_ms_sm_gmal_retry(struct bfa_fcs_port_ms_s *ms,
+                                             enum port_ms_event event);
+static void     bfa_fcs_port_ms_sm_gfn_sending(struct bfa_fcs_port_ms_s *ms,
+                                              enum port_ms_event event);
+static void     bfa_fcs_port_ms_sm_gfn(struct bfa_fcs_port_ms_s *ms,
+                                      enum port_ms_event event);
+static void     bfa_fcs_port_ms_sm_gfn_retry(struct bfa_fcs_port_ms_s *ms,
+                                            enum port_ms_event event);
+static void     bfa_fcs_port_ms_sm_online(struct bfa_fcs_port_ms_s *ms,
+                                         enum port_ms_event event);
+/**
+ *             Start in offline state - awaiting NS to send start.
+ */
+static void
+bfa_fcs_port_ms_sm_offline(struct bfa_fcs_port_ms_s *ms,
+                          enum port_ms_event event)
+{
+       bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
+       bfa_trc(ms->port->fcs, event);
+
+       switch (event) {
+       case MSSM_EVENT_PORT_ONLINE:
+               bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_plogi_sending);
+               bfa_fcs_port_ms_send_plogi(ms, NULL);
+               break;
+
+       case MSSM_EVENT_PORT_OFFLINE:
+               break;
+
+       default:
+               bfa_assert(0);
+       }
+}
+
+static void
+bfa_fcs_port_ms_sm_plogi_sending(struct bfa_fcs_port_ms_s *ms,
+                                enum port_ms_event event)
+{
+       bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
+       bfa_trc(ms->port->fcs, event);
+
+       switch (event) {
+       case MSSM_EVENT_FCXP_SENT:
+               bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_plogi);
+               break;
+
+       case MSSM_EVENT_PORT_OFFLINE:
+               bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_offline);
+               bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(ms->port),
+                                      &ms->fcxp_wqe);
+               break;
+
+       default:
+               bfa_assert(0);
+       }
+}
+
+static void
+bfa_fcs_port_ms_sm_plogi(struct bfa_fcs_port_ms_s *ms, enum port_ms_event event)
+{
+       bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
+       bfa_trc(ms->port->fcs, event);
+
+       switch (event) {
+       case MSSM_EVENT_RSP_ERROR:
+               /*
+                * Start timer for a delayed retry
+                */
+               bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_plogi_retry);
+               bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(ms->port), &ms->timer,
+                               bfa_fcs_port_ms_timeout, ms,
+                               BFA_FCS_RETRY_TIMEOUT);
+               break;
+
+       case MSSM_EVENT_RSP_OK:
+               /*
+                * since plogi is done, now invoke MS related sub-modules
+                */
+               bfa_fcs_port_fdmi_online(ms);
+
+               /**
+                * if this is a Vport, go to online state.
+                */
+               if (ms->port->vport) {
+                       bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_online);
+                       break;
+               }
+
+               /*
+                * For a base port we need to get the
+                * switch's IP address.
+                */
+               bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_gmal_sending);
+               bfa_fcs_port_ms_send_gmal(ms, NULL);
+               break;
+
+       case MSSM_EVENT_PORT_OFFLINE:
+               bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_offline);
+               bfa_fcxp_discard(ms->fcxp);
+               break;
+
+       default:
+               bfa_assert(0);
+       }
+}
+
+static void
+bfa_fcs_port_ms_sm_plogi_retry(struct bfa_fcs_port_ms_s *ms,
+                              enum port_ms_event event)
+{
+       bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
+       bfa_trc(ms->port->fcs, event);
+
+       switch (event) {
+       case MSSM_EVENT_TIMEOUT:
+               /*
+                * Retry Timer Expired. Re-send
+                */
+               bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_plogi_sending);
+               bfa_fcs_port_ms_send_plogi(ms, NULL);
+               break;
+
+       case MSSM_EVENT_PORT_OFFLINE:
+               bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_offline);
+               bfa_timer_stop(&ms->timer);
+               break;
+
+       default:
+               bfa_assert(0);
+       }
+}
+
+static void
+bfa_fcs_port_ms_sm_online(struct bfa_fcs_port_ms_s *ms,
+                         enum port_ms_event event)
+{
+       bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
+       bfa_trc(ms->port->fcs, event);
+
+       switch (event) {
+       case MSSM_EVENT_PORT_OFFLINE:
+               bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_offline);
+               /*
+                * now invoke MS related sub-modules
+                */
+               bfa_fcs_port_fdmi_offline(ms);
+               break;
+
+       case MSSM_EVENT_PORT_FABRIC_RSCN:
+               bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_gfn_sending);
+               ms->retry_cnt = 0;
+               bfa_fcs_port_ms_send_gfn(ms, NULL);
+               break;
+
+       default:
+               bfa_assert(0);
+       }
+}
+
+static void
+bfa_fcs_port_ms_sm_gmal_sending(struct bfa_fcs_port_ms_s *ms,
+                               enum port_ms_event event)
+{
+       bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
+       bfa_trc(ms->port->fcs, event);
+
+       switch (event) {
+       case MSSM_EVENT_FCXP_SENT:
+               bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_gmal);
+               break;
+
+       case MSSM_EVENT_PORT_OFFLINE:
+               bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_offline);
+               bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(ms->port),
+                                      &ms->fcxp_wqe);
+               break;
+
+       default:
+               bfa_assert(0);
+       }
+}
+
+static void
+bfa_fcs_port_ms_sm_gmal(struct bfa_fcs_port_ms_s *ms, enum port_ms_event event)
+{
+       bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
+       bfa_trc(ms->port->fcs, event);
+
+       switch (event) {
+       case MSSM_EVENT_RSP_ERROR:
+               /*
+                * Start timer for a delayed retry
+                */
+               if (ms->retry_cnt++ < BFA_FCS_MS_CMD_MAX_RETRIES) {
+                       bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_gmal_retry);
+                       bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(ms->port),
+                                       &ms->timer, bfa_fcs_port_ms_timeout, ms,
+                                       BFA_FCS_RETRY_TIMEOUT);
+               } else {
+                       bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_gfn_sending);
+                       bfa_fcs_port_ms_send_gfn(ms, NULL);
+                       ms->retry_cnt = 0;
+               }
+               break;
+
+       case MSSM_EVENT_RSP_OK:
+               bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_gfn_sending);
+               bfa_fcs_port_ms_send_gfn(ms, NULL);
+               break;
+
+       case MSSM_EVENT_PORT_OFFLINE:
+               bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_offline);
+               bfa_fcxp_discard(ms->fcxp);
+               break;
+
+       default:
+               bfa_assert(0);
+       }
+}
+
+static void
+bfa_fcs_port_ms_sm_gmal_retry(struct bfa_fcs_port_ms_s *ms,
+                             enum port_ms_event event)
+{
+       bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
+       bfa_trc(ms->port->fcs, event);
+
+       switch (event) {
+       case MSSM_EVENT_TIMEOUT:
+               /*
+                * Retry Timer Expired. Re-send
+                */
+               bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_gmal_sending);
+               bfa_fcs_port_ms_send_gmal(ms, NULL);
+               break;
+
+       case MSSM_EVENT_PORT_OFFLINE:
+               bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_offline);
+               bfa_timer_stop(&ms->timer);
+               break;
+
+       default:
+               bfa_assert(0);
+       }
+}
+
+/**
+ *  ms_pvt MS local functions
+ */
+
+static void
+bfa_fcs_port_ms_send_gmal(void *ms_cbarg, struct bfa_fcxp_s *fcxp_alloced)
+{
+       struct bfa_fcs_port_ms_s *ms = ms_cbarg;
+       struct bfa_fcs_port_s *port = ms->port;
+       struct fchs_s          fchs;
+       int             len;
+       struct bfa_fcxp_s *fcxp;
+
+       bfa_trc(port->fcs, port->pid);
+
+       fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
+       if (!fcxp) {
+               bfa_fcxp_alloc_wait(port->fcs->bfa, &ms->fcxp_wqe,
+                                   bfa_fcs_port_ms_send_gmal, ms);
+               return;
+       }
+       ms->fcxp = fcxp;
+
+       len = fc_gmal_req_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
+                               bfa_fcs_port_get_fcid(port),
+                               bfa_lps_get_peer_nwwn(port->fabric->lps));
+
+       bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
+                     FC_CLASS_3, len, &fchs, bfa_fcs_port_ms_gmal_response,
+                     (void *)ms, FC_MAX_PDUSZ, FC_RA_TOV);
+
+       bfa_sm_send_event(ms, MSSM_EVENT_FCXP_SENT);
+}
+
+static void
+bfa_fcs_port_ms_gmal_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
+                             void *cbarg, bfa_status_t req_status,
+                             u32 rsp_len, u32 resid_len,
+                             struct fchs_s *rsp_fchs)
+{
+       struct bfa_fcs_port_ms_s *ms = (struct bfa_fcs_port_ms_s *)cbarg;
+       struct bfa_fcs_port_s *port = ms->port;
+       struct ct_hdr_s       *cthdr = NULL;
+       struct fcgs_gmal_resp_s *gmal_resp;
+       struct fc_gmal_entry_s *gmal_entry;
+       u32        num_entries;
+       u8        *rsp_str;
+
+       bfa_trc(port->fcs, req_status);
+       bfa_trc(port->fcs, port->port_cfg.pwwn);
+
+       /*
+        * Sanity Checks
+        */
+       if (req_status != BFA_STATUS_OK) {
+               bfa_trc(port->fcs, req_status);
+               bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR);
+               return;
+       }
+
+       cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp);
+       cthdr->cmd_rsp_code = bfa_os_ntohs(cthdr->cmd_rsp_code);
+
+       if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) {
+               gmal_resp = (struct fcgs_gmal_resp_s *)(cthdr + 1);
+               num_entries = bfa_os_ntohl(gmal_resp->ms_len);
+               if (num_entries == 0) {
+                       bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR);
+                       return;
+               }
+               /*
+                * The response could contain multiple Entries.
+                * Entries for SNMP interface, etc.
+                * We look for the entry with a telnet prefix.
+                * First "http://" entry refers to IP addr
+                */
+
+               gmal_entry = (struct fc_gmal_entry_s *)gmal_resp->ms_ma;
+               while (num_entries > 0) {
+                       if (strncmp
+                           (gmal_entry->prefix, CT_GMAL_RESP_PREFIX_HTTP,
+                            sizeof(gmal_entry->prefix)) == 0) {
+
+                               /*
+                                * if the IP address is terminating with a '/',
+                                * remove it. *Byte 0 consists of the length
+                                * of the string.
+                                */
+                               rsp_str = &(gmal_entry->prefix[0]);
+                               if (rsp_str[gmal_entry->len - 1] == '/')
+                                       rsp_str[gmal_entry->len - 1] = 0;
+                               /*
+                                * copy IP Address to fabric
+                                */
+                               strncpy(bfa_fcs_port_get_fabric_ipaddr(port),
+                                       gmal_entry->ip_addr,
+                                       BFA_FCS_FABRIC_IPADDR_SZ);
+                               break;
+                       } else {
+                               --num_entries;
+                               ++gmal_entry;
+                       }
+               }
+
+               bfa_sm_send_event(ms, MSSM_EVENT_RSP_OK);
+               return;
+       }
+
+       bfa_trc(port->fcs, cthdr->reason_code);
+       bfa_trc(port->fcs, cthdr->exp_code);
+       bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR);
+}
+
+static void
+bfa_fcs_port_ms_sm_gfn_sending(struct bfa_fcs_port_ms_s *ms,
+                              enum port_ms_event event)
+{
+       bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
+       bfa_trc(ms->port->fcs, event);
+
+       switch (event) {
+       case MSSM_EVENT_FCXP_SENT:
+               bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_gfn);
+               break;
+
+       case MSSM_EVENT_PORT_OFFLINE:
+               bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_offline);
+               bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(ms->port),
+                                      &ms->fcxp_wqe);
+               break;
+
+       default:
+               bfa_assert(0);
+       }
+}
+
+static void
+bfa_fcs_port_ms_sm_gfn(struct bfa_fcs_port_ms_s *ms, enum port_ms_event event)
+{
+       bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
+       bfa_trc(ms->port->fcs, event);
+
+       switch (event) {
+       case MSSM_EVENT_RSP_ERROR:
+               /*
+                * Start timer for a delayed retry
+                */
+               if (ms->retry_cnt++ < BFA_FCS_MS_CMD_MAX_RETRIES) {
+                       bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_gfn_retry);
+                       bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(ms->port),
+                                       &ms->timer, bfa_fcs_port_ms_timeout, ms,
+                                       BFA_FCS_RETRY_TIMEOUT);
+               } else {
+                       bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_online);
+                       ms->retry_cnt = 0;
+               }
+               break;
+
+       case MSSM_EVENT_RSP_OK:
+               bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_online);
+               break;
+
+       case MSSM_EVENT_PORT_OFFLINE:
+               bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_offline);
+               bfa_fcxp_discard(ms->fcxp);
+               break;
+
+       default:
+               bfa_assert(0);
+       }
+}
+
+static void
+bfa_fcs_port_ms_sm_gfn_retry(struct bfa_fcs_port_ms_s *ms,
+                            enum port_ms_event event)
+{
+       bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
+       bfa_trc(ms->port->fcs, event);
+
+       switch (event) {
+       case MSSM_EVENT_TIMEOUT:
+               /*
+                * Retry Timer Expired. Re-send
+                */
+               bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_gfn_sending);
+               bfa_fcs_port_ms_send_gfn(ms, NULL);
+               break;
+
+       case MSSM_EVENT_PORT_OFFLINE:
+               bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_offline);
+               bfa_timer_stop(&ms->timer);
+               break;
+
+       default:
+               bfa_assert(0);
+       }
+}
+
+/**
+ *  ms_pvt MS local functions
+ */
+
+static void
+bfa_fcs_port_ms_send_gfn(void *ms_cbarg, struct bfa_fcxp_s *fcxp_alloced)
+{
+       struct bfa_fcs_port_ms_s *ms = ms_cbarg;
+       struct bfa_fcs_port_s *port = ms->port;
+       struct fchs_s          fchs;
+       int             len;
+       struct bfa_fcxp_s *fcxp;
+
+       bfa_trc(port->fcs, port->pid);
+
+       fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
+       if (!fcxp) {
+               bfa_fcxp_alloc_wait(port->fcs->bfa, &ms->fcxp_wqe,
+                                   bfa_fcs_port_ms_send_gfn, ms);
+               return;
+       }
+       ms->fcxp = fcxp;
+
+       len = fc_gfn_req_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
+                              bfa_fcs_port_get_fcid(port),
+                              bfa_lps_get_peer_nwwn(port->fabric->lps));
+
+       bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
+                     FC_CLASS_3, len, &fchs, bfa_fcs_port_ms_gfn_response,
+                     (void *)ms, FC_MAX_PDUSZ, FC_RA_TOV);
+
+       bfa_sm_send_event(ms, MSSM_EVENT_FCXP_SENT);
+}
+
+static void
+bfa_fcs_port_ms_gfn_response(void *fcsarg, struct bfa_fcxp_s *fcxp, void *cbarg,
+                            bfa_status_t req_status, u32 rsp_len,
+                              u32 resid_len, struct fchs_s *rsp_fchs)
+{
+       struct bfa_fcs_port_ms_s *ms = (struct bfa_fcs_port_ms_s *)cbarg;
+       struct bfa_fcs_port_s *port = ms->port;
+       struct ct_hdr_s       *cthdr = NULL;
+       wwn_t          *gfn_resp;
+
+       bfa_trc(port->fcs, req_status);
+       bfa_trc(port->fcs, port->port_cfg.pwwn);
+
+       /*
+        * Sanity Checks
+        */
+       if (req_status != BFA_STATUS_OK) {
+               bfa_trc(port->fcs, req_status);
+               bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR);
+               return;
+       }
+
+       cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp);
+       cthdr->cmd_rsp_code = bfa_os_ntohs(cthdr->cmd_rsp_code);
+
+       if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) {
+               gfn_resp = (wwn_t *) (cthdr + 1);
+               /*
+                * check if it has actually changed
+                */
+               if ((memcmp
+                    ((void *)&bfa_fcs_port_get_fabric_name(port), gfn_resp,
+                     sizeof(wwn_t)) != 0))
+                       bfa_fcs_fabric_set_fabric_name(port->fabric, *gfn_resp);
+               bfa_sm_send_event(ms, MSSM_EVENT_RSP_OK);
+               return;
+       }
+
+       bfa_trc(port->fcs, cthdr->reason_code);
+       bfa_trc(port->fcs, cthdr->exp_code);
+       bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR);
+}
+
+/**
+ *  ms_pvt MS local functions
+ */
+
+static void
+bfa_fcs_port_ms_send_plogi(void *ms_cbarg, struct bfa_fcxp_s *fcxp_alloced)
+{
+       struct bfa_fcs_port_ms_s *ms = ms_cbarg;
+       struct bfa_fcs_port_s *port = ms->port;
+       struct fchs_s          fchs;
+       int             len;
+       struct bfa_fcxp_s *fcxp;
+
+       bfa_trc(port->fcs, port->pid);
+
+       fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
+       if (!fcxp) {
+               port->stats.ms_plogi_alloc_wait++;
+               bfa_fcxp_alloc_wait(port->fcs->bfa, &ms->fcxp_wqe,
+                                   bfa_fcs_port_ms_send_plogi, ms);
+               return;
+       }
+       ms->fcxp = fcxp;
+
+       len = fc_plogi_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
+                            bfa_os_hton3b(FC_MGMT_SERVER),
+                            bfa_fcs_port_get_fcid(port), 0,
+                            port->port_cfg.pwwn, port->port_cfg.nwwn,
+                            bfa_pport_get_maxfrsize(port->fcs->bfa));
+
+       bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
+                     FC_CLASS_3, len, &fchs, bfa_fcs_port_ms_plogi_response,
+                     (void *)ms, FC_MAX_PDUSZ, FC_RA_TOV);
+
+       port->stats.ms_plogi_sent++;
+       bfa_sm_send_event(ms, MSSM_EVENT_FCXP_SENT);
+}
+
+static void
+bfa_fcs_port_ms_plogi_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
+                              void *cbarg, bfa_status_t req_status,
+                              u32 rsp_len, u32 resid_len,
+                              struct fchs_s *rsp_fchs)
+{
+       struct bfa_fcs_port_ms_s *ms = (struct bfa_fcs_port_ms_s *)cbarg;
+
+       struct bfa_fcs_port_s *port = ms->port;
+       struct fc_els_cmd_s   *els_cmd;
+       struct fc_ls_rjt_s    *ls_rjt;
+
+       bfa_trc(port->fcs, req_status);
+       bfa_trc(port->fcs, port->port_cfg.pwwn);
+
+       /*
+        * Sanity Checks
+        */
+       if (req_status != BFA_STATUS_OK) {
+               port->stats.ms_plogi_rsp_err++;
+               bfa_trc(port->fcs, req_status);
+               bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR);
+               return;
+       }
+
+       els_cmd = (struct fc_els_cmd_s *) BFA_FCXP_RSP_PLD(fcxp);
+
+       switch (els_cmd->els_code) {
+
+       case FC_ELS_ACC:
+               if (rsp_len < sizeof(struct fc_logi_s)) {
+                       bfa_trc(port->fcs, rsp_len);
+                       port->stats.ms_plogi_acc_err++;
+                       bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR);
+                       break;
+               }
+               port->stats.ms_plogi_accepts++;
+               bfa_sm_send_event(ms, MSSM_EVENT_RSP_OK);
+               break;
+
+       case FC_ELS_LS_RJT:
+               ls_rjt = (struct fc_ls_rjt_s *) BFA_FCXP_RSP_PLD(fcxp);
+
+               bfa_trc(port->fcs, ls_rjt->reason_code);
+               bfa_trc(port->fcs, ls_rjt->reason_code_expl);
+
+               port->stats.ms_rejects++;
+               bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR);
+               break;
+
+       default:
+               port->stats.ms_plogi_unknown_rsp++;
+               bfa_trc(port->fcs, els_cmd->els_code);
+               bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR);
+       }
+}
+
+static void
+bfa_fcs_port_ms_timeout(void *arg)
+{
+       struct bfa_fcs_port_ms_s *ms = (struct bfa_fcs_port_ms_s *)arg;
+
+       ms->port->stats.ms_timeouts++;
+       bfa_sm_send_event(ms, MSSM_EVENT_TIMEOUT);
+}
+
+
+void
+bfa_fcs_port_ms_init(struct bfa_fcs_port_s *port)
+{
+       struct bfa_fcs_port_ms_s *ms = BFA_FCS_GET_MS_FROM_PORT(port);
+
+       ms->port = port;
+       bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_offline);
+
+       /*
+        * Invoke init routines of sub modules.
+        */
+       bfa_fcs_port_fdmi_init(ms);
+}
+
+void
+bfa_fcs_port_ms_offline(struct bfa_fcs_port_s *port)
+{
+       struct bfa_fcs_port_ms_s *ms = BFA_FCS_GET_MS_FROM_PORT(port);
+
+       ms->port = port;
+       bfa_sm_send_event(ms, MSSM_EVENT_PORT_OFFLINE);
+}
+
+void
+bfa_fcs_port_ms_online(struct bfa_fcs_port_s *port)
+{
+       struct bfa_fcs_port_ms_s *ms = BFA_FCS_GET_MS_FROM_PORT(port);
+
+       ms->port = port;
+       bfa_sm_send_event(ms, MSSM_EVENT_PORT_ONLINE);
+}
+
+void
+bfa_fcs_port_ms_fabric_rscn(struct bfa_fcs_port_s *port)
+{
+       struct bfa_fcs_port_ms_s *ms = BFA_FCS_GET_MS_FROM_PORT(port);
+
+       /*
+        * @todo.  Handle this only when in Online state
+        */
+       if (bfa_sm_cmp_state(ms, bfa_fcs_port_ms_sm_online))
+               bfa_sm_send_event(ms, MSSM_EVENT_PORT_FABRIC_RSCN);
+}
diff --git a/drivers/scsi/bfa/n2n.c b/drivers/scsi/bfa/n2n.c
new file mode 100644 (file)
index 0000000..7354568
--- /dev/null
@@ -0,0 +1,105 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) 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.
+ */
+
+/**
+ *  n2n.c n2n implementation.
+ */
+#include <bfa.h>
+#include <bfa_svc.h>
+#include "fcs_lport.h"
+#include "fcs_rport.h"
+#include "fcs_trcmod.h"
+#include "lport_priv.h"
+
+BFA_TRC_FILE(FCS, N2N);
+
+/**
+ *   Called by fcs/port to initialize N2N topology.
+ */
+void
+bfa_fcs_port_n2n_init(struct bfa_fcs_port_s *port)
+{
+}
+
+/**
+ *   Called by fcs/port to notify transition to online state.
+ */
+void
+bfa_fcs_port_n2n_online(struct bfa_fcs_port_s *port)
+{
+       struct bfa_fcs_port_n2n_s *n2n_port = &port->port_topo.pn2n;
+       struct bfa_port_cfg_s *pcfg = &port->port_cfg;
+       struct bfa_fcs_rport_s *rport;
+
+       bfa_trc(port->fcs, pcfg->pwwn);
+
+       /*
+        * If our PWWN is > than that of the r-port, we have to initiate PLOGI
+        * and assign an Address. if not, we need to wait for its PLOGI.
+        *
+        * If our PWWN is < than that of the remote port, it will send a PLOGI
+        * with the PIDs assigned. The rport state machine take care of this
+        * incoming PLOGI.
+        */
+       if (memcmp
+           ((void *)&pcfg->pwwn, (void *)&n2n_port->rem_port_wwn,
+            sizeof(wwn_t)) > 0) {
+               port->pid = N2N_LOCAL_PID;
+               /**
+                * First, check if we know the device by pwwn.
+                */
+               rport = bfa_fcs_port_get_rport_by_pwwn(port,
+                                                      n2n_port->rem_port_wwn);
+               if (rport) {
+                       bfa_trc(port->fcs, rport->pid);
+                       bfa_trc(port->fcs, rport->pwwn);
+                       rport->pid = N2N_REMOTE_PID;
+                       bfa_fcs_rport_online(rport);
+                       return;
+               }
+
+               /*
+                * In n2n there can be only one rport. Delete the old one whose
+                * pid should be zero, because it is offline.
+                */
+               if (port->num_rports > 0) {
+                       rport = bfa_fcs_port_get_rport_by_pid(port, 0);
+                       bfa_assert(rport != NULL);
+                       if (rport) {
+                               bfa_trc(port->fcs, rport->pwwn);
+                               bfa_fcs_rport_delete(rport);
+                       }
+               }
+               bfa_fcs_rport_create(port, N2N_REMOTE_PID);
+       }
+}
+
+/**
+ *   Called by fcs/port to notify transition to offline state.
+ */
+void
+bfa_fcs_port_n2n_offline(struct bfa_fcs_port_s *port)
+{
+       struct bfa_fcs_port_n2n_s *n2n_port = &port->port_topo.pn2n;
+
+       bfa_trc(port->fcs, port->pid);
+       port->pid = 0;
+       n2n_port->rem_port_wwn = 0;
+       n2n_port->reply_oxid = 0;
+}
+
+
diff --git a/drivers/scsi/bfa/ns.c b/drivers/scsi/bfa/ns.c
new file mode 100644 (file)
index 0000000..59fea99
--- /dev/null
@@ -0,0 +1,1243 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) 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.
+ */
+
+/**
+ * @page ns_sm_info VPORT NS State Machine
+ *
+ * @section ns_sm_interactions VPORT NS State Machine Interactions
+ *
+ * @section ns_sm VPORT NS State Machine
+ *     img ns_sm.jpg
+ */
+#include <bfa.h>
+#include <bfa_svc.h>
+#include <bfa_iocfc.h>
+#include "fcs_lport.h"
+#include "fcs_rport.h"
+#include "fcs_trcmod.h"
+#include "fcs_fcxp.h"
+#include "fcs.h"
+#include "lport_priv.h"
+
+BFA_TRC_FILE(FCS, NS);
+
+/*
+ * forward declarations
+ */
+static void     bfa_fcs_port_ns_send_plogi(void *ns_cbarg,
+                                          struct bfa_fcxp_s *fcxp_alloced);
+static void     bfa_fcs_port_ns_send_rspn_id(void *ns_cbarg,
+                                            struct bfa_fcxp_s *fcxp_alloced);
+static void     bfa_fcs_port_ns_send_rft_id(void *ns_cbarg,
+                                           struct bfa_fcxp_s *fcxp_alloced);
+static void     bfa_fcs_port_ns_send_rff_id(void *ns_cbarg,
+                                           struct bfa_fcxp_s *fcxp_alloced);
+static void     bfa_fcs_port_ns_send_gid_ft(void *ns_cbarg,
+                                           struct bfa_fcxp_s *fcxp_alloced);
+static void     bfa_fcs_port_ns_timeout(void *arg);
+static void     bfa_fcs_port_ns_plogi_response(void *fcsarg,
+                                              struct bfa_fcxp_s *fcxp,
+                                              void *cbarg,
+                                              bfa_status_t req_status,
+                                              u32 rsp_len,
+                                              u32 resid_len,
+                                              struct fchs_s *rsp_fchs);
+static void     bfa_fcs_port_ns_rspn_id_response(void *fcsarg,
+                                                struct bfa_fcxp_s *fcxp,
+                                                void *cbarg,
+                                                bfa_status_t req_status,
+                                                u32 rsp_len,
+                                                u32 resid_len,
+                                                struct fchs_s *rsp_fchs);
+static void     bfa_fcs_port_ns_rft_id_response(void *fcsarg,
+                                               struct bfa_fcxp_s *fcxp,
+                                               void *cbarg,
+                                               bfa_status_t req_status,
+                                               u32 rsp_len,
+                                               u32 resid_len,
+                                               struct fchs_s *rsp_fchs);
+static void     bfa_fcs_port_ns_rff_id_response(void *fcsarg,
+                                               struct bfa_fcxp_s *fcxp,
+                                               void *cbarg,
+                                               bfa_status_t req_status,
+                                               u32 rsp_len,
+                                               u32 resid_len,
+                                               struct fchs_s *rsp_fchs);
+static void     bfa_fcs_port_ns_gid_ft_response(void *fcsarg,
+                                               struct bfa_fcxp_s *fcxp,
+                                               void *cbarg,
+                                               bfa_status_t req_status,
+                                               u32 rsp_len,
+                                               u32 resid_len,
+                                               struct fchs_s *rsp_fchs);
+static void     bfa_fcs_port_ns_process_gidft_pids(struct bfa_fcs_port_s *port,
+                                                  u32 *pid_buf,
+                                                  u32 n_pids);
+
+static void     bfa_fcs_port_ns_boot_target_disc(struct bfa_fcs_port_s *port);
+/**
+ *  fcs_ns_sm FCS nameserver interface state machine
+ */
+
+/**
+ * VPort NS State Machine events
+ */
+enum vport_ns_event {
+       NSSM_EVENT_PORT_ONLINE = 1,
+       NSSM_EVENT_PORT_OFFLINE = 2,
+       NSSM_EVENT_PLOGI_SENT = 3,
+       NSSM_EVENT_RSP_OK = 4,
+       NSSM_EVENT_RSP_ERROR = 5,
+       NSSM_EVENT_TIMEOUT = 6,
+       NSSM_EVENT_NS_QUERY = 7,
+       NSSM_EVENT_RSPNID_SENT = 8,
+       NSSM_EVENT_RFTID_SENT = 9,
+       NSSM_EVENT_RFFID_SENT = 10,
+       NSSM_EVENT_GIDFT_SENT = 11,
+};
+
+static void     bfa_fcs_port_ns_sm_offline(struct bfa_fcs_port_ns_s *ns,
+                                          enum vport_ns_event event);
+static void     bfa_fcs_port_ns_sm_plogi_sending(struct bfa_fcs_port_ns_s *ns,
+                                                enum vport_ns_event event);
+static void     bfa_fcs_port_ns_sm_plogi(struct bfa_fcs_port_ns_s *ns,
+                                        enum vport_ns_event event);
+static void     bfa_fcs_port_ns_sm_plogi_retry(struct bfa_fcs_port_ns_s *ns,
+                                              enum vport_ns_event event);
+static void     bfa_fcs_port_ns_sm_sending_rspn_id(struct bfa_fcs_port_ns_s *ns,
+                                                  enum vport_ns_event event);
+static void     bfa_fcs_port_ns_sm_rspn_id(struct bfa_fcs_port_ns_s *ns,
+                                          enum vport_ns_event event);
+static void     bfa_fcs_port_ns_sm_rspn_id_retry(struct bfa_fcs_port_ns_s *ns,
+                                                enum vport_ns_event event);
+static void     bfa_fcs_port_ns_sm_sending_rft_id(struct bfa_fcs_port_ns_s *ns,
+                                                 enum vport_ns_event event);
+static void     bfa_fcs_port_ns_sm_rft_id_retry(struct bfa_fcs_port_ns_s *ns,
+                                               enum vport_ns_event event);
+static void     bfa_fcs_port_ns_sm_rft_id(struct bfa_fcs_port_ns_s *ns,
+                                         enum vport_ns_event event);
+static void     bfa_fcs_port_ns_sm_sending_rff_id(struct bfa_fcs_port_ns_s *ns,
+                                                 enum vport_ns_event event);
+static void     bfa_fcs_port_ns_sm_rff_id_retry(struct bfa_fcs_port_ns_s *ns,
+                                               enum vport_ns_event event);
+static void     bfa_fcs_port_ns_sm_rff_id(struct bfa_fcs_port_ns_s *ns,
+                                         enum vport_ns_event event);
+static void     bfa_fcs_port_ns_sm_sending_gid_ft(struct bfa_fcs_port_ns_s *ns,
+                                                 enum vport_ns_event event);
+static void     bfa_fcs_port_ns_sm_gid_ft(struct bfa_fcs_port_ns_s *ns,
+                                         enum vport_ns_event event);
+static void     bfa_fcs_port_ns_sm_gid_ft_retry(struct bfa_fcs_port_ns_s *ns,
+                                               enum vport_ns_event event);
+static void     bfa_fcs_port_ns_sm_online(struct bfa_fcs_port_ns_s *ns,
+                                         enum vport_ns_event event);
+/**
+ *             Start in offline state - awaiting linkup
+ */
+static void
+bfa_fcs_port_ns_sm_offline(struct bfa_fcs_port_ns_s *ns,
+                          enum vport_ns_event event)
+{
+       bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
+       bfa_trc(ns->port->fcs, event);
+
+       switch (event) {
+       case NSSM_EVENT_PORT_ONLINE:
+               bfa_sm_set_state(ns, bfa_fcs_port_ns_sm_plogi_sending);
+               bfa_fcs_port_ns_send_plogi(ns, NULL);
+               break;
+
+       case NSSM_EVENT_PORT_OFFLINE:
+               break;
+
+       default:
+               bfa_assert(0);
+       }
+}
+
+static void
+bfa_fcs_port_ns_sm_plogi_sending(struct bfa_fcs_port_ns_s *ns,
+                                enum vport_ns_event event)
+{
+       bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
+       bfa_trc(ns->port->fcs, event);
+
+       switch (event) {
+       case NSSM_EVENT_PLOGI_SENT:
+               bfa_sm_set_state(ns, bfa_fcs_port_ns_sm_plogi);
+               break;
+
+       case NSSM_EVENT_PORT_OFFLINE:
+               bfa_sm_set_state(ns, bfa_fcs_port_ns_sm_offline);
+               bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(ns->port),
+                                      &ns->fcxp_wqe);
+               break;
+
+       default:
+               bfa_assert(0);
+       }
+}
+
+static void
+bfa_fcs_port_ns_sm_plogi(struct bfa_fcs_port_ns_s *ns,
+                        enum vport_ns_event event)
+{
+       bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
+       bfa_trc(ns->port->fcs, event);
+
+       switch (event) {
+       case NSSM_EVENT_RSP_ERROR:
+               /*
+                * Start timer for a delayed retry
+                */
+               bfa_sm_set_state(ns, bfa_fcs_port_ns_sm_plogi_retry);
+               ns->port->stats.ns_retries++;
+               bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(ns->port), &ns->timer,
+                               bfa_fcs_port_ns_timeout, ns,
+                               BFA_FCS_RETRY_TIMEOUT);
+               break;
+
+       case NSSM_EVENT_RSP_OK:
+               bfa_sm_set_state(ns, bfa_fcs_port_ns_sm_sending_rspn_id);
+               bfa_fcs_port_ns_send_rspn_id(ns, NULL);
+               break;
+
+       case NSSM_EVENT_PORT_OFFLINE:
+               bfa_sm_set_state(ns, bfa_fcs_port_ns_sm_offline);
+               bfa_fcxp_discard(ns->fcxp);
+               break;
+
+       default:
+               bfa_assert(0);
+       }
+}
+
+static void
+bfa_fcs_port_ns_sm_plogi_retry(struct bfa_fcs_port_ns_s *ns,
+                              enum vport_ns_event event)
+{
+       bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
+       bfa_trc(ns->port->fcs, event);
+
+       switch (event) {
+       case NSSM_EVENT_TIMEOUT:
+               /*
+                * Retry Timer Expired. Re-send
+                */
+               bfa_sm_set_state(ns, bfa_fcs_port_ns_sm_plogi_sending);
+               bfa_fcs_port_ns_send_plogi(ns, NULL);
+               break;
+
+       case NSSM_EVENT_PORT_OFFLINE:
+               bfa_sm_set_state(ns, bfa_fcs_port_ns_sm_offline);
+               bfa_timer_stop(&ns->timer);
+               break;
+
+       default:
+               bfa_assert(0);
+       }
+}
+
+static void
+bfa_fcs_port_ns_sm_sending_rspn_id(struct bfa_fcs_port_ns_s *ns,
+                                  enum vport_ns_event event)
+{
+       bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
+       bfa_trc(ns->port->fcs, event);
+
+       switch (event) {
+       case NSSM_EVENT_RSPNID_SENT:
+               bfa_sm_set_state(ns, bfa_fcs_port_ns_sm_rspn_id);
+               break;
+
+       case NSSM_EVENT_PORT_OFFLINE:
+               bfa_sm_set_state(ns, bfa_fcs_port_ns_sm_offline);
+               bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(ns->port),
+                                      &ns->fcxp_wqe);
+               break;
+
+       default:
+               bfa_assert(0);
+       }
+}
+
+static void
+bfa_fcs_port_ns_sm_rspn_id(struct bfa_fcs_port_ns_s *ns,
+                          enum vport_ns_event event)
+{
+       bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
+       bfa_trc(ns->port->fcs, event);
+
+       switch (event) {
+       case NSSM_EVENT_RSP_ERROR:
+               /*
+                * Start timer for a delayed retry
+                */
+               bfa_sm_set_state(ns, bfa_fcs_port_ns_sm_rspn_id_retry);
+               ns->port->stats.ns_retries++;
+               bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(ns->port), &ns->timer,
+                               bfa_fcs_port_ns_timeout, ns,
+                               BFA_FCS_RETRY_TIMEOUT);
+               break;
+
+       case NSSM_EVENT_RSP_OK:
+               bfa_sm_set_state(ns, bfa_fcs_port_ns_sm_sending_rft_id);
+               bfa_fcs_port_ns_send_rft_id(ns, NULL);
+               break;
+
+       case NSSM_EVENT_PORT_OFFLINE:
+               bfa_fcxp_discard(ns->fcxp);
+               bfa_sm_set_state(ns, bfa_fcs_port_ns_sm_offline);
+               break;
+
+       default:
+               bfa_assert(0);
+       }
+}
+
+static void
+bfa_fcs_port_ns_sm_rspn_id_retry(struct bfa_fcs_port_ns_s *ns,
+                                enum vport_ns_event event)
+{
+       bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
+       bfa_trc(ns->port->fcs, event);
+
+       switch (event) {
+       case NSSM_EVENT_TIMEOUT:
+               /*
+                * Retry Timer Expired. Re-send
+                */
+               bfa_sm_set_state(ns, bfa_fcs_port_ns_sm_sending_rspn_id);
+               bfa_fcs_port_ns_send_rspn_id(ns, NULL);
+               break;
+
+       case NSSM_EVENT_PORT_OFFLINE:
+               bfa_sm_set_state(ns, bfa_fcs_port_ns_sm_offline);
+               bfa_timer_stop(&ns->timer);
+               break;
+
+       default:
+               bfa_assert(0);
+       }
+}
+
+static void
+bfa_fcs_port_ns_sm_sending_rft_id(struct bfa_fcs_port_ns_s *ns,
+                                 enum vport_ns_event event)
+{
+       bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
+       bfa_trc(ns->port->fcs, event);
+
+       switch (event) {
+       case NSSM_EVENT_RFTID_SENT:
+               bfa_sm_set_state(ns, bfa_fcs_port_ns_sm_rft_id);
+               break;
+
+       case NSSM_EVENT_PORT_OFFLINE:
+               bfa_sm_set_state(ns, bfa_fcs_port_ns_sm_offline);
+               bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(ns->port),
+                                      &ns->fcxp_wqe);
+               break;
+
+       default:
+               bfa_assert(0);
+       }
+}
+
+static void
+bfa_fcs_port_ns_sm_rft_id(struct bfa_fcs_port_ns_s *ns,
+                         enum vport_ns_event event)
+{
+       bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
+       bfa_trc(ns->port->fcs, event);
+
+       switch (event) {
+       case NSSM_EVENT_RSP_OK:
+               /*
+                * Now move to register FC4 Features
+                */
+               bfa_sm_set_state(ns, bfa_fcs_port_ns_sm_sending_rff_id);
+               bfa_fcs_port_ns_send_rff_id(ns, NULL);
+               break;
+
+       case NSSM_EVENT_RSP_ERROR:
+               /*
+                * Start timer for a delayed retry
+                */
+               bfa_sm_set_state(ns, bfa_fcs_port_ns_sm_rft_id_retry);
+               ns->port->stats.ns_retries++;
+               bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(ns->port), &ns->timer,
+                               bfa_fcs_port_ns_timeout, ns,
+                               BFA_FCS_RETRY_TIMEOUT);
+               break;
+
+       case NSSM_EVENT_PORT_OFFLINE:
+               bfa_sm_set_state(ns, bfa_fcs_port_ns_sm_offline);
+               bfa_fcxp_discard(ns->fcxp);
+               break;
+
+       default:
+               bfa_assert(0);
+       }
+}
+
+static void
+bfa_fcs_port_ns_sm_rft_id_retry(struct bfa_fcs_port_ns_s *ns,
+                               enum vport_ns_event event)
+{
+       bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
+       bfa_trc(ns->port->fcs, event);
+
+       switch (event) {
+       case NSSM_EVENT_TIMEOUT:
+               bfa_sm_set_state(ns, bfa_fcs_port_ns_sm_sending_rft_id);
+               bfa_fcs_port_ns_send_rft_id(ns, NULL);
+               break;
+
+       case NSSM_EVENT_PORT_OFFLINE:
+               bfa_sm_set_state(ns, bfa_fcs_port_ns_sm_offline);
+               bfa_timer_stop(&ns->timer);
+               break;
+
+       default:
+               bfa_assert(0);
+       }
+}
+
+static void
+bfa_fcs_port_ns_sm_sending_rff_id(struct bfa_fcs_port_ns_s *ns,
+                                 enum vport_ns_event event)
+{
+       bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
+       bfa_trc(ns->port->fcs, event);
+
+       switch (event) {
+       case NSSM_EVENT_RFFID_SENT:
+               bfa_sm_set_state(ns, bfa_fcs_port_ns_sm_rff_id);
+               break;
+
+       case NSSM_EVENT_PORT_OFFLINE:
+               bfa_sm_set_state(ns, bfa_fcs_port_ns_sm_offline);
+               bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(ns->port),
+                                      &ns->fcxp_wqe);
+               break;
+
+       default:
+               bfa_assert(0);
+       }
+}
+
+static void
+bfa_fcs_port_ns_sm_rff_id(struct bfa_fcs_port_ns_s *ns,
+                         enum vport_ns_event event)
+{
+       bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
+       bfa_trc(ns->port->fcs, event);
+
+       switch (event) {
+       case NSSM_EVENT_RSP_OK:
+
+               /*
+                * If min cfg mode is enabled, we donot initiate rport
+                * discovery with the fabric. Instead, we will retrieve the
+                * boot targets from HAL/FW.
+                */
+               if (__fcs_min_cfg(ns->port->fcs)) {
+                       bfa_fcs_port_ns_boot_target_disc(ns->port);
+                       bfa_sm_set_state(ns, bfa_fcs_port_ns_sm_online);
+                       return;
+               }
+
+               /*
+                * If the port role is Initiator Mode issue NS query.
+                * If it is Target Mode, skip this and go to online.
+                */
+               if (BFA_FCS_VPORT_IS_INITIATOR_MODE(ns->port)) {
+                       bfa_sm_set_state(ns, bfa_fcs_port_ns_sm_sending_gid_ft);
+                       bfa_fcs_port_ns_send_gid_ft(ns, NULL);
+               } else if (BFA_FCS_VPORT_IS_TARGET_MODE(ns->port)) {
+                       bfa_sm_set_state(ns, bfa_fcs_port_ns_sm_online);
+               }
+               /*
+                * kick off mgmt srvr state machine
+                */
+               bfa_fcs_port_ms_online(ns->port);
+               break;
+
+       case NSSM_EVENT_RSP_ERROR:
+               /*
+                * Start timer for a delayed retry
+                */
+               bfa_sm_set_state(ns, bfa_fcs_port_ns_sm_rff_id_retry);
+               ns->port->stats.ns_retries++;
+               bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(ns->port), &ns->timer,
+                               bfa_fcs_port_ns_timeout, ns,
+                               BFA_FCS_RETRY_TIMEOUT);
+               break;
+
+       case NSSM_EVENT_PORT_OFFLINE:
+               bfa_sm_set_state(ns, bfa_fcs_port_ns_sm_offline);
+               bfa_fcxp_discard(ns->fcxp);
+               break;
+
+       default:
+               bfa_assert(0);
+       }
+}
+
+static void
+bfa_fcs_port_ns_sm_rff_id_retry(struct bfa_fcs_port_ns_s *ns,
+                               enum vport_ns_event event)
+{
+       bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
+       bfa_trc(ns->port->fcs, event);
+
+       switch (event) {
+       case NSSM_EVENT_TIMEOUT:
+               bfa_sm_set_state(ns, bfa_fcs_port_ns_sm_sending_rff_id);
+               bfa_fcs_port_ns_send_rff_id(ns, NULL);
+               break;
+
+       case NSSM_EVENT_PORT_OFFLINE:
+               bfa_sm_set_state(ns, bfa_fcs_port_ns_sm_offline);
+               bfa_timer_stop(&ns->timer);
+               break;
+
+       default:
+               bfa_assert(0);
+       }
+}
+static void
+bfa_fcs_port_ns_sm_sending_gid_ft(struct bfa_fcs_port_ns_s *ns,
+                                 enum vport_ns_event event)
+{
+       bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
+       bfa_trc(ns->port->fcs, event);
+
+       switch (event) {
+       case NSSM_EVENT_GIDFT_SENT:
+               bfa_sm_set_state(ns, bfa_fcs_port_ns_sm_gid_ft);
+               break;
+
+       case NSSM_EVENT_PORT_OFFLINE:
+               bfa_sm_set_state(ns, bfa_fcs_port_ns_sm_offline);
+               bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(ns->port),
+                                      &ns->fcxp_wqe);
+               break;
+
+       default:
+               bfa_assert(0);
+       }
+}
+
+static void
+bfa_fcs_port_ns_sm_gid_ft(struct bfa_fcs_port_ns_s *ns,
+                         enum vport_ns_event event)
+{
+       bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
+       bfa_trc(ns->port->fcs, event);
+
+       switch (event) {
+       case NSSM_EVENT_RSP_OK:
+               bfa_sm_set_state(ns, bfa_fcs_port_ns_sm_online);
+               break;
+
+       case NSSM_EVENT_RSP_ERROR:
+               /*
+                * TBD: for certain reject codes, we don't need to retry
+                */
+               /*
+                * Start timer for a delayed retry
+                */
+               bfa_sm_set_state(ns, bfa_fcs_port_ns_sm_gid_ft_retry);
+               ns->port->stats.ns_retries++;
+               bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(ns->port), &ns->timer,
+                               bfa_fcs_port_ns_timeout, ns,
+                               BFA_FCS_RETRY_TIMEOUT);
+               break;
+
+       case NSSM_EVENT_PORT_OFFLINE:
+               bfa_sm_set_state(ns, bfa_fcs_port_ns_sm_offline);
+               bfa_fcxp_discard(ns->fcxp);
+               break;
+
+       default:
+               bfa_assert(0);
+       }
+}
+
+static void
+bfa_fcs_port_ns_sm_gid_ft_retry(struct bfa_fcs_port_ns_s *ns,
+                               enum vport_ns_event event)
+{
+       bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
+       bfa_trc(ns->port->fcs, event);
+
+       switch (event) {
+       case NSSM_EVENT_TIMEOUT:
+               bfa_sm_set_state(ns, bfa_fcs_port_ns_sm_sending_gid_ft);
+               bfa_fcs_port_ns_send_gid_ft(ns, NULL);
+               break;
+
+       case NSSM_EVENT_PORT_OFFLINE:
+               bfa_sm_set_state(ns, bfa_fcs_port_ns_sm_offline);
+               bfa_timer_stop(&ns->timer);
+               break;
+
+       default:
+               bfa_assert(0);
+       }
+}
+
+static void
+bfa_fcs_port_ns_sm_online(struct bfa_fcs_port_ns_s *ns,
+                         enum vport_ns_event event)
+{
+       bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
+       bfa_trc(ns->port->fcs, event);
+
+       switch (event) {
+       case NSSM_EVENT_PORT_OFFLINE:
+               bfa_sm_set_state(ns, bfa_fcs_port_ns_sm_offline);
+               break;
+
+       case NSSM_EVENT_NS_QUERY:
+               /*
+                * If the port role is Initiator Mode issue NS query.
+                * If it is Target Mode, skip this and go to online.
+                */
+               if (BFA_FCS_VPORT_IS_INITIATOR_MODE(ns->port)) {
+                       bfa_sm_set_state(ns, bfa_fcs_port_ns_sm_sending_gid_ft);
+                       bfa_fcs_port_ns_send_gid_ft(ns, NULL);
+               };
+               break;
+
+       default:
+               bfa_assert(0);
+       }
+}
+
+
+
+/**
+ *  ns_pvt Nameserver local functions
+ */
+
+static void
+bfa_fcs_port_ns_send_plogi(void *ns_cbarg, struct bfa_fcxp_s *fcxp_alloced)
+{
+       struct bfa_fcs_port_ns_s *ns = ns_cbarg;
+       struct bfa_fcs_port_s *port = ns->port;
+       struct fchs_s          fchs;
+       int             len;
+       struct bfa_fcxp_s *fcxp;
+
+       bfa_trc(port->fcs, port->pid);
+
+       fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
+       if (!fcxp) {
+               port->stats.ns_plogi_alloc_wait++;
+               bfa_fcxp_alloc_wait(port->fcs->bfa, &ns->fcxp_wqe,
+                                   bfa_fcs_port_ns_send_plogi, ns);
+               return;
+       }
+       ns->fcxp = fcxp;
+
+       len = fc_plogi_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
+                            bfa_os_hton3b(FC_NAME_SERVER),
+                            bfa_fcs_port_get_fcid(port), 0,
+                            port->port_cfg.pwwn, port->port_cfg.nwwn,
+                            bfa_pport_get_maxfrsize(port->fcs->bfa));
+
+       bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
+                     FC_CLASS_3, len, &fchs, bfa_fcs_port_ns_plogi_response,
+                     (void *)ns, FC_MAX_PDUSZ, FC_RA_TOV);
+       port->stats.ns_plogi_sent++;
+
+       bfa_sm_send_event(ns, NSSM_EVENT_PLOGI_SENT);
+}
+
+static void
+bfa_fcs_port_ns_plogi_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
+                              void *cbarg, bfa_status_t req_status,
+                              u32 rsp_len, u32 resid_len,
+                              struct fchs_s *rsp_fchs)
+{
+       struct bfa_fcs_port_ns_s *ns = (struct bfa_fcs_port_ns_s *)cbarg;
+       struct bfa_fcs_port_s *port = ns->port;
+       /* struct fc_logi_s *plogi_resp; */
+       struct fc_els_cmd_s   *els_cmd;
+       struct fc_ls_rjt_s    *ls_rjt;
+
+       bfa_trc(port->fcs, req_status);
+       bfa_trc(port->fcs, port->port_cfg.pwwn);
+
+       /*
+        * Sanity Checks
+        */
+       if (req_status != BFA_STATUS_OK) {
+               bfa_trc(port->fcs, req_status);
+               port->stats.ns_plogi_rsp_err++;
+               bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
+               return;
+       }
+
+       els_cmd = (struct fc_els_cmd_s *) BFA_FCXP_RSP_PLD(fcxp);
+
+       switch (els_cmd->els_code) {
+
+       case FC_ELS_ACC:
+               if (rsp_len < sizeof(struct fc_logi_s)) {
+                       bfa_trc(port->fcs, rsp_len);
+                       port->stats.ns_plogi_acc_err++;
+                       bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
+                       break;
+               }
+               port->stats.ns_plogi_accepts++;
+               bfa_sm_send_event(ns, NSSM_EVENT_RSP_OK);
+               break;
+
+       case FC_ELS_LS_RJT:
+               ls_rjt = (struct fc_ls_rjt_s *) BFA_FCXP_RSP_PLD(fcxp);
+
+               bfa_trc(port->fcs, ls_rjt->reason_code);
+               bfa_trc(port->fcs, ls_rjt->reason_code_expl);
+
+               port->stats.ns_rejects++;
+
+               bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
+               break;
+
+       default:
+               port->stats.ns_plogi_unknown_rsp++;
+               bfa_trc(port->fcs, els_cmd->els_code);
+               bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
+       }
+}
+
+/**
+ * Register the symbolic port name.
+ */
+static void
+bfa_fcs_port_ns_send_rspn_id(void *ns_cbarg, struct bfa_fcxp_s *fcxp_alloced)
+{
+       struct bfa_fcs_port_ns_s *ns = ns_cbarg;
+       struct bfa_fcs_port_s *port = ns->port;
+       struct fchs_s          fchs;
+       int             len;
+       struct bfa_fcxp_s *fcxp;
+       u8         symbl[256];
+       u8        *psymbl = &symbl[0];
+
+       bfa_os_memset(symbl, 0, sizeof(symbl));
+
+       bfa_trc(port->fcs, port->port_cfg.pwwn);
+
+       fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
+       if (!fcxp) {
+               port->stats.ns_rspnid_alloc_wait++;
+               bfa_fcxp_alloc_wait(port->fcs->bfa, &ns->fcxp_wqe,
+                                   bfa_fcs_port_ns_send_rspn_id, ns);
+               return;
+       }
+       ns->fcxp = fcxp;
+
+       /*
+        * for V-Port, form a Port Symbolic Name
+        */
+       if (port->vport) {
+               /**For Vports,
+                *  we append the vport's port symbolic name to that of the base port.
+                */
+
+               strncpy((char *)psymbl,
+                       (char *)
+                       &(bfa_fcs_port_get_psym_name
+                         (bfa_fcs_get_base_port(port->fcs))),
+                       strlen((char *)
+                              &bfa_fcs_port_get_psym_name(bfa_fcs_get_base_port
+                                                          (port->fcs))));
+
+               /*
+                * Ensure we have a null terminating string.
+                */
+               ((char *)
+                psymbl)[strlen((char *)
+                               &bfa_fcs_port_get_psym_name
+                               (bfa_fcs_get_base_port(port->fcs)))] = 0;
+
+               strncat((char *)psymbl,
+                       (char *)&(bfa_fcs_port_get_psym_name(port)),
+                       strlen((char *)&bfa_fcs_port_get_psym_name(port)));
+       } else {
+               psymbl = (u8 *) &(bfa_fcs_port_get_psym_name(port));
+       }
+
+       len = fc_rspnid_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
+                             bfa_fcs_port_get_fcid(port), 0, psymbl);
+
+       bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
+                     FC_CLASS_3, len, &fchs, bfa_fcs_port_ns_rspn_id_response,
+                     (void *)ns, FC_MAX_PDUSZ, FC_RA_TOV);
+
+       port->stats.ns_rspnid_sent++;
+
+       bfa_sm_send_event(ns, NSSM_EVENT_RSPNID_SENT);
+}
+
+static void
+bfa_fcs_port_ns_rspn_id_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
+                                void *cbarg, bfa_status_t req_status,
+                                u32 rsp_len, u32 resid_len,
+                                struct fchs_s *rsp_fchs)
+{
+       struct bfa_fcs_port_ns_s *ns = (struct bfa_fcs_port_ns_s *)cbarg;
+       struct bfa_fcs_port_s *port = ns->port;
+       struct ct_hdr_s       *cthdr = NULL;
+
+       bfa_trc(port->fcs, port->port_cfg.pwwn);
+
+       /*
+        * Sanity Checks
+        */
+       if (req_status != BFA_STATUS_OK) {
+               bfa_trc(port->fcs, req_status);
+               port->stats.ns_rspnid_rsp_err++;
+               bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
+               return;
+       }
+
+       cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp);
+       cthdr->cmd_rsp_code = bfa_os_ntohs(cthdr->cmd_rsp_code);
+
+       if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) {
+               port->stats.ns_rspnid_accepts++;
+               bfa_sm_send_event(ns, NSSM_EVENT_RSP_OK);
+               return;
+       }
+
+       port->stats.ns_rspnid_rejects++;
+       bfa_trc(port->fcs, cthdr->reason_code);
+       bfa_trc(port->fcs, cthdr->exp_code);
+       bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
+}
+
+/**
+ * Register FC4-Types
+ * TBD, Need to retrieve this from the OS driver, in case IPFC is enabled ?
+ */
+static void
+bfa_fcs_port_ns_send_rft_id(void *ns_cbarg, struct bfa_fcxp_s *fcxp_alloced)
+{
+       struct bfa_fcs_port_ns_s *ns = ns_cbarg;
+       struct bfa_fcs_port_s *port = ns->port;
+       struct fchs_s          fchs;
+       int             len;
+       struct bfa_fcxp_s *fcxp;
+
+       bfa_trc(port->fcs, port->port_cfg.pwwn);
+
+       fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
+       if (!fcxp) {
+               port->stats.ns_rftid_alloc_wait++;
+               bfa_fcxp_alloc_wait(port->fcs->bfa, &ns->fcxp_wqe,
+                                   bfa_fcs_port_ns_send_rft_id, ns);
+               return;
+       }
+       ns->fcxp = fcxp;
+
+       len = fc_rftid_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
+                            bfa_fcs_port_get_fcid(port), 0,
+                            port->port_cfg.roles);
+
+       bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
+                     FC_CLASS_3, len, &fchs, bfa_fcs_port_ns_rft_id_response,
+                     (void *)ns, FC_MAX_PDUSZ, FC_RA_TOV);
+
+       port->stats.ns_rftid_sent++;
+       bfa_sm_send_event(ns, NSSM_EVENT_RFTID_SENT);
+}
+
+static void
+bfa_fcs_port_ns_rft_id_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
+                               void *cbarg, bfa_status_t req_status,
+                               u32 rsp_len, u32 resid_len,
+                               struct fchs_s *rsp_fchs)
+{
+       struct bfa_fcs_port_ns_s *ns = (struct bfa_fcs_port_ns_s *)cbarg;
+       struct bfa_fcs_port_s *port = ns->port;
+       struct ct_hdr_s       *cthdr = NULL;
+
+       bfa_trc(port->fcs, port->port_cfg.pwwn);
+
+       /*
+        * Sanity Checks
+        */
+       if (req_status != BFA_STATUS_OK) {
+               bfa_trc(port->fcs, req_status);
+               port->stats.ns_rftid_rsp_err++;
+               bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
+               return;
+       }
+
+       cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp);
+       cthdr->cmd_rsp_code = bfa_os_ntohs(cthdr->cmd_rsp_code);
+
+       if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) {
+               port->stats.ns_rftid_accepts++;
+               bfa_sm_send_event(ns, NSSM_EVENT_RSP_OK);
+               return;
+       }
+
+       port->stats.ns_rftid_rejects++;
+       bfa_trc(port->fcs, cthdr->reason_code);
+       bfa_trc(port->fcs, cthdr->exp_code);
+       bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
+}
+
+/**
+* Register FC4-Features : Should be done after RFT_ID
+ */
+static void
+bfa_fcs_port_ns_send_rff_id(void *ns_cbarg, struct bfa_fcxp_s *fcxp_alloced)
+{
+       struct bfa_fcs_port_ns_s *ns = ns_cbarg;
+       struct bfa_fcs_port_s *port = ns->port;
+       struct fchs_s          fchs;
+       int             len;
+       struct bfa_fcxp_s *fcxp;
+       u8         fc4_ftrs = 0;
+
+       bfa_trc(port->fcs, port->port_cfg.pwwn);
+
+       fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
+       if (!fcxp) {
+               port->stats.ns_rffid_alloc_wait++;
+               bfa_fcxp_alloc_wait(port->fcs->bfa, &ns->fcxp_wqe,
+                                   bfa_fcs_port_ns_send_rff_id, ns);
+               return;
+       }
+       ns->fcxp = fcxp;
+
+       if (BFA_FCS_VPORT_IS_INITIATOR_MODE(ns->port)) {
+               fc4_ftrs = FC_GS_FCP_FC4_FEATURE_INITIATOR;
+       } else if (BFA_FCS_VPORT_IS_TARGET_MODE(ns->port)) {
+               fc4_ftrs = FC_GS_FCP_FC4_FEATURE_TARGET;
+       }
+
+       len = fc_rffid_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
+                            bfa_fcs_port_get_fcid(port), 0, FC_TYPE_FCP,
+                            fc4_ftrs);
+
+       bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
+                     FC_CLASS_3, len, &fchs, bfa_fcs_port_ns_rff_id_response,
+                     (void *)ns, FC_MAX_PDUSZ, FC_RA_TOV);
+
+       port->stats.ns_rffid_sent++;
+       bfa_sm_send_event(ns, NSSM_EVENT_RFFID_SENT);
+}
+
+static void
+bfa_fcs_port_ns_rff_id_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
+                               void *cbarg, bfa_status_t req_status,
+                               u32 rsp_len, u32 resid_len,
+                               struct fchs_s *rsp_fchs)
+{
+       struct bfa_fcs_port_ns_s *ns = (struct bfa_fcs_port_ns_s *)cbarg;
+       struct bfa_fcs_port_s *port = ns->port;
+       struct ct_hdr_s       *cthdr = NULL;
+
+       bfa_trc(port->fcs, port->port_cfg.pwwn);
+
+       /*
+        * Sanity Checks
+        */
+       if (req_status != BFA_STATUS_OK) {
+               bfa_trc(port->fcs, req_status);
+               port->stats.ns_rffid_rsp_err++;
+               bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
+               return;
+       }
+
+       cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp);
+       cthdr->cmd_rsp_code = bfa_os_ntohs(cthdr->cmd_rsp_code);
+
+       if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) {
+               port->stats.ns_rffid_accepts++;
+               bfa_sm_send_event(ns, NSSM_EVENT_RSP_OK);
+               return;
+       }
+
+       port->stats.ns_rffid_rejects++;
+       bfa_trc(port->fcs, cthdr->reason_code);
+       bfa_trc(port->fcs, cthdr->exp_code);
+
+       if (cthdr->reason_code == CT_RSN_NOT_SUPP) {
+               /*
+                * if this command is not supported, we don't retry
+                */
+               bfa_sm_send_event(ns, NSSM_EVENT_RSP_OK);
+       } else {
+               bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
+       }
+}
+
+/**
+ * Query Fabric for FC4-Types Devices.
+ *
+*  TBD : Need to use a local (FCS private) response buffer, since the response
+ * can be larger than 2K.
+ */
+static void
+bfa_fcs_port_ns_send_gid_ft(void *ns_cbarg, struct bfa_fcxp_s *fcxp_alloced)
+{
+       struct bfa_fcs_port_ns_s *ns = ns_cbarg;
+       struct bfa_fcs_port_s *port = ns->port;
+       struct fchs_s          fchs;
+       int             len;
+       struct bfa_fcxp_s *fcxp;
+
+       bfa_trc(port->fcs, port->pid);
+
+       fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
+       if (!fcxp) {
+               port->stats.ns_gidft_alloc_wait++;
+               bfa_fcxp_alloc_wait(port->fcs->bfa, &ns->fcxp_wqe,
+                                   bfa_fcs_port_ns_send_gid_ft, ns);
+               return;
+       }
+       ns->fcxp = fcxp;
+
+       /*
+        * This query is only initiated for FCP initiator mode.
+        */
+       len = fc_gid_ft_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), ns->port->pid,
+                             FC_TYPE_FCP);
+
+       bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
+                     FC_CLASS_3, len, &fchs, bfa_fcs_port_ns_gid_ft_response,
+                     (void *)ns, bfa_fcxp_get_maxrsp(port->fcs->bfa),
+                     FC_RA_TOV);
+
+       port->stats.ns_gidft_sent++;
+
+       bfa_sm_send_event(ns, NSSM_EVENT_GIDFT_SENT);
+}
+
+static void
+bfa_fcs_port_ns_gid_ft_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
+                               void *cbarg, bfa_status_t req_status,
+                               u32 rsp_len, u32 resid_len,
+                               struct fchs_s *rsp_fchs)
+{
+       struct bfa_fcs_port_ns_s *ns = (struct bfa_fcs_port_ns_s *)cbarg;
+       struct bfa_fcs_port_s *port = ns->port;
+       struct ct_hdr_s       *cthdr = NULL;
+       u32        n_pids;
+
+       bfa_trc(port->fcs, port->port_cfg.pwwn);
+
+       /*
+        * Sanity Checks
+        */
+       if (req_status != BFA_STATUS_OK) {
+               bfa_trc(port->fcs, req_status);
+               port->stats.ns_gidft_rsp_err++;
+               bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
+               return;
+       }
+
+       if (resid_len != 0) {
+               /*
+                * TBD : we will need to allocate a larger buffer & retry the
+                * command
+                */
+               bfa_trc(port->fcs, rsp_len);
+               bfa_trc(port->fcs, resid_len);
+               return;
+       }
+
+       cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp);
+       cthdr->cmd_rsp_code = bfa_os_ntohs(cthdr->cmd_rsp_code);
+
+       switch (cthdr->cmd_rsp_code) {
+
+       case CT_RSP_ACCEPT:
+
+               port->stats.ns_gidft_accepts++;
+               n_pids = (fc_get_ctresp_pyld_len(rsp_len) / sizeof(u32));
+               bfa_trc(port->fcs, n_pids);
+               bfa_fcs_port_ns_process_gidft_pids(port,
+                                                  (u32 *) (cthdr + 1),
+                                                  n_pids);
+               bfa_sm_send_event(ns, NSSM_EVENT_RSP_OK);
+               break;
+
+       case CT_RSP_REJECT:
+
+               /*
+                * Check the reason code  & explanation.
+                * There may not have been any FC4 devices in the fabric
+                */
+               port->stats.ns_gidft_rejects++;
+               bfa_trc(port->fcs, cthdr->reason_code);
+               bfa_trc(port->fcs, cthdr->exp_code);
+
+               if ((cthdr->reason_code == CT_RSN_UNABLE_TO_PERF)
+                   && (cthdr->exp_code == CT_NS_EXP_FT_NOT_REG)) {
+
+                       bfa_sm_send_event(ns, NSSM_EVENT_RSP_OK);
+               } else {
+                       /*
+                        * for all other errors, retry
+                        */
+                       bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
+               }
+               break;
+
+       default:
+               port->stats.ns_gidft_unknown_rsp++;
+               bfa_trc(port->fcs, cthdr->cmd_rsp_code);
+               bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
+       }
+}
+
+/**
+ *     This routine will be called by bfa_timer on timer timeouts.
+ *
+ *     param[in]       port    - pointer to bfa_fcs_port_t.
+ *
+ *     return
+ *             void
+ *
+*      Special Considerations:
+ *
+ *     note
+ */
+static void
+bfa_fcs_port_ns_timeout(void *arg)
+{
+       struct bfa_fcs_port_ns_s *ns = (struct bfa_fcs_port_ns_s *)arg;
+
+       ns->port->stats.ns_timeouts++;
+       bfa_sm_send_event(ns, NSSM_EVENT_TIMEOUT);
+}
+
+/*
+ * Process the PID list in GID_FT response
+ */
+static void
+bfa_fcs_port_ns_process_gidft_pids(struct bfa_fcs_port_s *port,
+                                  u32 *pid_buf, u32 n_pids)
+{
+       struct fcgs_gidft_resp_s *gidft_entry;
+       struct bfa_fcs_rport_s *rport;
+       u32        ii;
+
+       for (ii = 0; ii < n_pids; ii++) {
+               gidft_entry = (struct fcgs_gidft_resp_s *) &pid_buf[ii];
+
+               if (gidft_entry->pid == port->pid)
+                       continue;
+
+               /*
+                * Check if this rport already exists
+                */
+               rport = bfa_fcs_port_get_rport_by_pid(port, gidft_entry->pid);
+               if (rport == NULL) {
+                       /*
+                        * this is a new device. create rport
+                        */
+                       rport = bfa_fcs_rport_create(port, gidft_entry->pid);
+               } else {
+                       /*
+                        * this rport already exists
+                        */
+                       bfa_fcs_rport_scn(rport);
+               }
+
+               bfa_trc(port->fcs, gidft_entry->pid);
+
+               /*
+                * if the last entry bit is set, bail out.
+                */
+               if (gidft_entry->last)
+                       return;
+       }
+}
+
+/**
+ *  fcs_ns_public FCS nameserver public interfaces
+ */
+
+/*
+ * Functions called by port/fab.
+ * These will send relevant Events to the ns state machine.
+ */
+void
+bfa_fcs_port_ns_init(struct bfa_fcs_port_s *port)
+{
+       struct bfa_fcs_port_ns_s *ns = BFA_FCS_GET_NS_FROM_PORT(port);
+
+       ns->port = port;
+       bfa_sm_set_state(ns, bfa_fcs_port_ns_sm_offline);
+}
+
+void
+bfa_fcs_port_ns_offline(struct bfa_fcs_port_s *port)
+{
+       struct bfa_fcs_port_ns_s *ns = BFA_FCS_GET_NS_FROM_PORT(port);
+
+       ns->port = port;
+       bfa_sm_send_event(ns, NSSM_EVENT_PORT_OFFLINE);
+}
+
+void
+bfa_fcs_port_ns_online(struct bfa_fcs_port_s *port)
+{
+       struct bfa_fcs_port_ns_s *ns = BFA_FCS_GET_NS_FROM_PORT(port);
+
+       ns->port = port;
+       bfa_sm_send_event(ns, NSSM_EVENT_PORT_ONLINE);
+}
+
+void
+bfa_fcs_port_ns_query(struct bfa_fcs_port_s *port)
+{
+       struct bfa_fcs_port_ns_s *ns = BFA_FCS_GET_NS_FROM_PORT(port);
+
+       bfa_trc(port->fcs, port->pid);
+       bfa_sm_send_event(ns, NSSM_EVENT_NS_QUERY);
+}
+
+static void
+bfa_fcs_port_ns_boot_target_disc(struct bfa_fcs_port_s *port)
+{
+
+       struct bfa_fcs_rport_s *rport;
+       u8         nwwns;
+       wwn_t          *wwns;
+       int             ii;
+
+       bfa_iocfc_get_bootwwns(port->fcs->bfa, &nwwns, &wwns);
+
+       for (ii = 0; ii < nwwns; ++ii) {
+               rport = bfa_fcs_rport_create_by_wwn(port, wwns[ii]);
+               bfa_assert(rport);
+       }
+}
+
+
diff --git a/drivers/scsi/bfa/plog.c b/drivers/scsi/bfa/plog.c
new file mode 100644 (file)
index 0000000..86af818
--- /dev/null
@@ -0,0 +1,184 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ */
+
+#include <bfa_os_inc.h>
+#include <cs/bfa_plog.h>
+#include <cs/bfa_debug.h>
+
+static int
+plkd_validate_logrec(struct bfa_plog_rec_s *pl_rec)
+{
+       if ((pl_rec->log_type != BFA_PL_LOG_TYPE_INT)
+           && (pl_rec->log_type != BFA_PL_LOG_TYPE_STRING))
+               return 1;
+
+       if ((pl_rec->log_type != BFA_PL_LOG_TYPE_INT)
+           && (pl_rec->log_num_ints > BFA_PL_INT_LOG_SZ))
+               return 1;
+
+       return 0;
+}
+
+static void
+bfa_plog_add(struct bfa_plog_s *plog, struct bfa_plog_rec_s *pl_rec)
+{
+       u16        tail;
+       struct bfa_plog_rec_s *pl_recp;
+
+       if (plog->plog_enabled == 0)
+               return;
+
+       if (plkd_validate_logrec(pl_rec)) {
+               bfa_assert(0);
+               return;
+       }
+
+       tail = plog->tail;
+
+       pl_recp = &(plog->plog_recs[tail]);
+
+       bfa_os_memcpy(pl_recp, pl_rec, sizeof(struct bfa_plog_rec_s));
+
+       pl_recp->tv = BFA_TRC_TS(plog);
+       BFA_PL_LOG_REC_INCR(plog->tail);
+
+       if (plog->head == plog->tail)
+               BFA_PL_LOG_REC_INCR(plog->head);
+}
+
+void
+bfa_plog_init(struct bfa_plog_s *plog)
+{
+       bfa_os_memset((char *)plog, 0, sizeof(struct bfa_plog_s));
+
+       bfa_os_memcpy(plog->plog_sig, BFA_PL_SIG_STR, BFA_PL_SIG_LEN);
+       plog->head = plog->tail = 0;
+       plog->plog_enabled = 1;
+}
+
+void
+bfa_plog_str(struct bfa_plog_s *plog, enum bfa_plog_mid mid,
+               enum bfa_plog_eid event,
+               u16 misc, char *log_str)
+{
+       struct bfa_plog_rec_s  lp;
+
+       if (plog->plog_enabled) {
+               bfa_os_memset(&lp, 0, sizeof(struct bfa_plog_rec_s));
+               lp.mid = mid;
+               lp.eid = event;
+               lp.log_type = BFA_PL_LOG_TYPE_STRING;
+               lp.misc = misc;
+               strncpy(lp.log_entry.string_log, log_str,
+                       BFA_PL_STRING_LOG_SZ - 1);
+               lp.log_entry.string_log[BFA_PL_STRING_LOG_SZ - 1] = '\0';
+               bfa_plog_add(plog, &lp);
+       }
+}
+
+void
+bfa_plog_intarr(struct bfa_plog_s *plog, enum bfa_plog_mid mid,
+               enum bfa_plog_eid event,
+               u16 misc, u32 *intarr, u32 num_ints)
+{
+       struct bfa_plog_rec_s  lp;
+       u32        i;
+
+       if (num_ints > BFA_PL_INT_LOG_SZ)
+               num_ints = BFA_PL_INT_LOG_SZ;
+
+       if (plog->plog_enabled) {
+               bfa_os_memset(&lp, 0, sizeof(struct bfa_plog_rec_s));
+               lp.mid = mid;
+               lp.eid = event;
+               lp.log_type = BFA_PL_LOG_TYPE_INT;
+               lp.misc = misc;
+
+               for (i = 0; i < num_ints; i++)
+                       bfa_os_assign(lp.log_entry.int_log[i],
+                                       intarr[i]);
+
+               lp.log_num_ints = (u8) num_ints;
+
+               bfa_plog_add(plog, &lp);
+       }
+}
+
+void
+bfa_plog_fchdr(struct bfa_plog_s *plog, enum bfa_plog_mid mid,
+                       enum bfa_plog_eid event,
+                       u16 misc, struct fchs_s *fchdr)
+{
+       struct bfa_plog_rec_s  lp;
+       u32       *tmp_int = (u32 *) fchdr;
+       u32        ints[BFA_PL_INT_LOG_SZ];
+
+       if (plog->plog_enabled) {
+               bfa_os_memset(&lp, 0, sizeof(struct bfa_plog_rec_s));
+
+               ints[0] = tmp_int[0];
+               ints[1] = tmp_int[1];
+               ints[2] = tmp_int[4];
+
+               bfa_plog_intarr(plog, mid, event, misc, ints, 3);
+       }
+}
+
+void
+bfa_plog_fchdr_and_pl(struct bfa_plog_s *plog, enum bfa_plog_mid mid,
+                     enum bfa_plog_eid event, u16 misc, struct fchs_s *fchdr,
+                     u32 pld_w0)
+{
+       struct bfa_plog_rec_s  lp;
+       u32       *tmp_int = (u32 *) fchdr;
+       u32        ints[BFA_PL_INT_LOG_SZ];
+
+       if (plog->plog_enabled) {
+               bfa_os_memset(&lp, 0, sizeof(struct bfa_plog_rec_s));
+
+               ints[0] = tmp_int[0];
+               ints[1] = tmp_int[1];
+               ints[2] = tmp_int[4];
+               ints[3] = pld_w0;
+
+               bfa_plog_intarr(plog, mid, event, misc, ints, 4);
+       }
+}
+
+void
+bfa_plog_clear(struct bfa_plog_s *plog)
+{
+       plog->head = plog->tail = 0;
+}
+
+void
+bfa_plog_enable(struct bfa_plog_s *plog)
+{
+       plog->plog_enabled = 1;
+}
+
+void
+bfa_plog_disable(struct bfa_plog_s *plog)
+{
+       plog->plog_enabled = 0;
+}
+
+bfa_boolean_t
+bfa_plog_get_setting(struct bfa_plog_s *plog)
+{
+       return((bfa_boolean_t)plog->plog_enabled);
+}
diff --git a/drivers/scsi/bfa/rport.c b/drivers/scsi/bfa/rport.c
new file mode 100644 (file)
index 0000000..9cf58bb
--- /dev/null
@@ -0,0 +1,2618 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) 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.
+ */
+
+/**
+ *  rport.c Remote port implementation.
+ */
+
+#include <bfa.h>
+#include <bfa_svc.h>
+#include "fcbuild.h"
+#include "fcs_vport.h"
+#include "fcs_lport.h"
+#include "fcs_rport.h"
+#include "fcs_fcpim.h"
+#include "fcs_fcptm.h"
+#include "fcs_trcmod.h"
+#include "fcs_fcxp.h"
+#include "fcs.h"
+#include <fcb/bfa_fcb_rport.h>
+#include <aen/bfa_aen_rport.h>
+
+BFA_TRC_FILE(FCS, RPORT);
+
+#define BFA_FCS_RPORT_MAX_RETRIES              (5)
+
+/* In millisecs */
+static u32 bfa_fcs_rport_del_timeout =
+                       BFA_FCS_RPORT_DEF_DEL_TIMEOUT * 1000;
+
+/*
+ * forward declarations
+ */
+static struct bfa_fcs_rport_s *bfa_fcs_rport_alloc(struct bfa_fcs_port_s *port,
+                                                  wwn_t pwwn, u32 rpid);
+static void     bfa_fcs_rport_free(struct bfa_fcs_rport_s *rport);
+static void     bfa_fcs_rport_hal_online(struct bfa_fcs_rport_s *rport);
+static void     bfa_fcs_rport_online_action(struct bfa_fcs_rport_s *rport);
+static void     bfa_fcs_rport_offline_action(struct bfa_fcs_rport_s *rport);
+static void     bfa_fcs_rport_update(struct bfa_fcs_rport_s *rport,
+                                    struct fc_logi_s *plogi);
+static void     bfa_fcs_rport_fc4_pause(struct bfa_fcs_rport_s *rport);
+static void     bfa_fcs_rport_fc4_resume(struct bfa_fcs_rport_s *rport);
+static void     bfa_fcs_rport_timeout(void *arg);
+static void     bfa_fcs_rport_send_plogi(void *rport_cbarg,
+                                        struct bfa_fcxp_s *fcxp_alloced);
+static void     bfa_fcs_rport_send_plogiacc(void *rport_cbarg,
+                                           struct bfa_fcxp_s *fcxp_alloced);
+static void     bfa_fcs_rport_plogi_response(void *fcsarg,
+                                            struct bfa_fcxp_s *fcxp,
+                                            void *cbarg,
+                                            bfa_status_t req_status,
+                                            u32 rsp_len,
+                                            u32 resid_len,
+                                            struct fchs_s *rsp_fchs);
+static void     bfa_fcs_rport_send_adisc(void *rport_cbarg,
+                                        struct bfa_fcxp_s *fcxp_alloced);
+static void     bfa_fcs_rport_adisc_response(void *fcsarg,
+                                            struct bfa_fcxp_s *fcxp,
+                                            void *cbarg,
+                                            bfa_status_t req_status,
+                                            u32 rsp_len,
+                                            u32 resid_len,
+                                            struct fchs_s *rsp_fchs);
+static void     bfa_fcs_rport_send_gidpn(void *rport_cbarg,
+                                        struct bfa_fcxp_s *fcxp_alloced);
+static void     bfa_fcs_rport_gidpn_response(void *fcsarg,
+                                            struct bfa_fcxp_s *fcxp,
+                                            void *cbarg,
+                                            bfa_status_t req_status,
+                                            u32 rsp_len,
+                                            u32 resid_len,
+                                            struct fchs_s *rsp_fchs);
+static void     bfa_fcs_rport_send_logo(void *rport_cbarg,
+                                       struct bfa_fcxp_s *fcxp_alloced);
+static void     bfa_fcs_rport_send_logo_acc(void *rport_cbarg);
+static void     bfa_fcs_rport_process_prli(struct bfa_fcs_rport_s *rport,
+                       struct fchs_s *rx_fchs, u16 len);
+static void     bfa_fcs_rport_send_ls_rjt(struct bfa_fcs_rport_s *rport,
+                       struct fchs_s *rx_fchs, u8 reason_code,
+                       u8 reason_code_expl);
+static void     bfa_fcs_rport_process_adisc(struct bfa_fcs_rport_s *rport,
+                       struct fchs_s *rx_fchs, u16 len);
+/**
+ *  fcs_rport_sm FCS rport state machine events
+ */
+
+enum rport_event {
+       RPSM_EVENT_PLOGI_SEND = 1,      /*  new rport; start with PLOGI */
+       RPSM_EVENT_PLOGI_RCVD = 2,      /*  Inbound PLOGI from remote port */
+       RPSM_EVENT_PLOGI_COMP = 3,      /*  PLOGI completed to rport */
+       RPSM_EVENT_LOGO_RCVD = 4,       /*  LOGO from remote device */
+       RPSM_EVENT_LOGO_IMP = 5,        /*  implicit logo for SLER */
+       RPSM_EVENT_FCXP_SENT = 6,       /*  Frame from has been sent */
+       RPSM_EVENT_DELETE = 7,  /*  RPORT delete request */
+       RPSM_EVENT_SCN = 8,     /*  state change notification */
+       RPSM_EVENT_ACCEPTED = 9,/*  Good response from remote device */
+       RPSM_EVENT_FAILED = 10, /*  Request to rport failed.  */
+       RPSM_EVENT_TIMEOUT = 11,        /*  Rport SM timeout event */
+       RPSM_EVENT_HCB_ONLINE = 12,     /*  BFA rport online callback */
+       RPSM_EVENT_HCB_OFFLINE = 13,    /*  BFA rport offline callback */
+       RPSM_EVENT_FC4_OFFLINE = 14,    /*  FC-4 offline complete */
+       RPSM_EVENT_ADDRESS_CHANGE = 15, /*  Rport's PID has changed */
+       RPSM_EVENT_ADDRESS_DISC = 16    /*  Need to Discover rport's PID */
+};
+
+static void     bfa_fcs_rport_sm_uninit(struct bfa_fcs_rport_s *rport,
+                                       enum rport_event event);
+static void     bfa_fcs_rport_sm_plogi_sending(struct bfa_fcs_rport_s *rport,
+                                              enum rport_event event);
+static void     bfa_fcs_rport_sm_plogiacc_sending(struct bfa_fcs_rport_s *rport,
+                                                 enum rport_event event);
+static void     bfa_fcs_rport_sm_plogi_retry(struct bfa_fcs_rport_s *rport,
+                                            enum rport_event event);
+static void     bfa_fcs_rport_sm_plogi(struct bfa_fcs_rport_s *rport,
+                                      enum rport_event event);
+static void     bfa_fcs_rport_sm_hal_online(struct bfa_fcs_rport_s *rport,
+                                           enum rport_event event);
+static void     bfa_fcs_rport_sm_online(struct bfa_fcs_rport_s *rport,
+                                       enum rport_event event);
+static void     bfa_fcs_rport_sm_nsquery_sending(struct bfa_fcs_rport_s *rport,
+                                                enum rport_event event);
+static void     bfa_fcs_rport_sm_nsquery(struct bfa_fcs_rport_s *rport,
+                                        enum rport_event event);
+static void     bfa_fcs_rport_sm_adisc_sending(struct bfa_fcs_rport_s *rport,
+                                              enum rport_event event);
+static void     bfa_fcs_rport_sm_adisc(struct bfa_fcs_rport_s *rport,
+                                      enum rport_event event);
+static void     bfa_fcs_rport_sm_fc4_logorcv(struct bfa_fcs_rport_s *rport,
+                                            enum rport_event event);
+static void     bfa_fcs_rport_sm_fc4_logosend(struct bfa_fcs_rport_s *rport,
+                                             enum rport_event event);
+static void     bfa_fcs_rport_sm_fc4_offline(struct bfa_fcs_rport_s *rport,
+                                            enum rport_event event);
+static void     bfa_fcs_rport_sm_hcb_offline(struct bfa_fcs_rport_s *rport,
+                                            enum rport_event event);
+static void     bfa_fcs_rport_sm_hcb_logorcv(struct bfa_fcs_rport_s *rport,
+                                            enum rport_event event);
+static void     bfa_fcs_rport_sm_hcb_logosend(struct bfa_fcs_rport_s *rport,
+                                             enum rport_event event);
+static void     bfa_fcs_rport_sm_logo_sending(struct bfa_fcs_rport_s *rport,
+                                             enum rport_event event);
+static void     bfa_fcs_rport_sm_offline(struct bfa_fcs_rport_s *rport,
+                                        enum rport_event event);
+static void     bfa_fcs_rport_sm_nsdisc_sending(struct bfa_fcs_rport_s *rport,
+                                               enum rport_event event);
+static void     bfa_fcs_rport_sm_nsdisc_retry(struct bfa_fcs_rport_s *rport,
+                                             enum rport_event event);
+static void     bfa_fcs_rport_sm_nsdisc_sent(struct bfa_fcs_rport_s *rport,
+                                            enum rport_event event);
+static void     bfa_fcs_rport_sm_nsdisc_sent(struct bfa_fcs_rport_s *rport,
+                                            enum rport_event event);
+
+static struct bfa_sm_table_s rport_sm_table[] = {
+       {BFA_SM(bfa_fcs_rport_sm_uninit), BFA_RPORT_UNINIT},
+       {BFA_SM(bfa_fcs_rport_sm_plogi_sending), BFA_RPORT_PLOGI},
+       {BFA_SM(bfa_fcs_rport_sm_plogiacc_sending), BFA_RPORT_ONLINE},
+       {BFA_SM(bfa_fcs_rport_sm_plogi_retry), BFA_RPORT_PLOGI_RETRY},
+       {BFA_SM(bfa_fcs_rport_sm_plogi), BFA_RPORT_PLOGI},
+       {BFA_SM(bfa_fcs_rport_sm_hal_online), BFA_RPORT_ONLINE},
+       {BFA_SM(bfa_fcs_rport_sm_online), BFA_RPORT_ONLINE},
+       {BFA_SM(bfa_fcs_rport_sm_nsquery_sending), BFA_RPORT_NSQUERY},
+       {BFA_SM(bfa_fcs_rport_sm_nsquery), BFA_RPORT_NSQUERY},
+       {BFA_SM(bfa_fcs_rport_sm_adisc_sending), BFA_RPORT_ADISC},
+       {BFA_SM(bfa_fcs_rport_sm_adisc), BFA_RPORT_ADISC},
+       {BFA_SM(bfa_fcs_rport_sm_fc4_logorcv), BFA_RPORT_LOGORCV},
+       {BFA_SM(bfa_fcs_rport_sm_fc4_logosend), BFA_RPORT_LOGO},
+       {BFA_SM(bfa_fcs_rport_sm_fc4_offline), BFA_RPORT_OFFLINE},
+       {BFA_SM(bfa_fcs_rport_sm_hcb_offline), BFA_RPORT_OFFLINE},
+       {BFA_SM(bfa_fcs_rport_sm_hcb_logorcv), BFA_RPORT_LOGORCV},
+       {BFA_SM(bfa_fcs_rport_sm_hcb_logosend), BFA_RPORT_LOGO},
+       {BFA_SM(bfa_fcs_rport_sm_logo_sending), BFA_RPORT_LOGO},
+       {BFA_SM(bfa_fcs_rport_sm_offline), BFA_RPORT_OFFLINE},
+       {BFA_SM(bfa_fcs_rport_sm_nsdisc_sending), BFA_RPORT_NSDISC},
+       {BFA_SM(bfa_fcs_rport_sm_nsdisc_retry), BFA_RPORT_NSDISC},
+       {BFA_SM(bfa_fcs_rport_sm_nsdisc_sent), BFA_RPORT_NSDISC},
+};
+
+/**
+ *             Beginning state.
+ */
+static void
+bfa_fcs_rport_sm_uninit(struct bfa_fcs_rport_s *rport, enum rport_event event)
+{
+       bfa_trc(rport->fcs, rport->pwwn);
+       bfa_trc(rport->fcs, rport->pid);
+       bfa_trc(rport->fcs, event);
+
+       switch (event) {
+       case RPSM_EVENT_PLOGI_SEND:
+               bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogi_sending);
+               rport->plogi_retries = 0;
+               bfa_fcs_rport_send_plogi(rport, NULL);
+               break;
+
+       case RPSM_EVENT_PLOGI_RCVD:
+               bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogiacc_sending);
+               bfa_fcs_rport_send_plogiacc(rport, NULL);
+               break;
+
+       case RPSM_EVENT_PLOGI_COMP:
+               bfa_sm_set_state(rport, bfa_fcs_rport_sm_hal_online);
+               bfa_fcs_rport_hal_online(rport);
+               break;
+
+       case RPSM_EVENT_ADDRESS_CHANGE:
+       case RPSM_EVENT_ADDRESS_DISC:
+               bfa_sm_set_state(rport, bfa_fcs_rport_sm_nsdisc_sending);
+               rport->ns_retries = 0;
+               bfa_fcs_rport_send_gidpn(rport, NULL);
+               break;
+
+       default:
+               bfa_assert(0);
+       }
+}
+
+/**
+ *             PLOGI is being sent.
+ */
+static void
+bfa_fcs_rport_sm_plogi_sending(struct bfa_fcs_rport_s *rport,
+                              enum rport_event event)
+{
+       bfa_trc(rport->fcs, rport->pwwn);
+       bfa_trc(rport->fcs, rport->pid);
+       bfa_trc(rport->fcs, event);
+
+       switch (event) {
+       case RPSM_EVENT_FCXP_SENT:
+               bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogi);
+               break;
+
+       case RPSM_EVENT_DELETE:
+               bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit);
+               bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
+               bfa_fcs_rport_free(rport);
+               break;
+
+       case RPSM_EVENT_PLOGI_RCVD:
+               bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogiacc_sending);
+               bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
+               bfa_fcs_rport_send_plogiacc(rport, NULL);
+               break;
+
+       case RPSM_EVENT_ADDRESS_CHANGE:
+               bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
+               bfa_sm_set_state(rport, bfa_fcs_rport_sm_nsdisc_sending);
+               rport->ns_retries = 0;
+               bfa_fcs_rport_send_gidpn(rport, NULL);
+               break;
+
+       case RPSM_EVENT_LOGO_IMP:
+               rport->pid = 0;
+               bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);
+               bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
+               bfa_timer_start(rport->fcs->bfa, &rport->timer,
+                               bfa_fcs_rport_timeout, rport,
+                               bfa_fcs_rport_del_timeout);
+               break;
+
+       case RPSM_EVENT_SCN:
+               break;
+
+       default:
+               bfa_assert(0);
+       }
+}
+
+/**
+ *             PLOGI is being sent.
+ */
+static void
+bfa_fcs_rport_sm_plogiacc_sending(struct bfa_fcs_rport_s *rport,
+                                 enum rport_event event)
+{
+       bfa_trc(rport->fcs, rport->pwwn);
+       bfa_trc(rport->fcs, rport->pid);
+       bfa_trc(rport->fcs, event);
+
+       switch (event) {
+       case RPSM_EVENT_FCXP_SENT:
+               bfa_sm_set_state(rport, bfa_fcs_rport_sm_hal_online);
+               bfa_fcs_rport_hal_online(rport);
+               break;
+
+       case RPSM_EVENT_DELETE:
+               bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit);
+               bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
+               bfa_fcs_rport_free(rport);
+               break;
+
+       case RPSM_EVENT_SCN:
+               /**
+                * Ignore, SCN is possibly online notification.
+                */
+               break;
+
+       case RPSM_EVENT_ADDRESS_CHANGE:
+               bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
+               bfa_sm_set_state(rport, bfa_fcs_rport_sm_nsdisc_sending);
+               rport->ns_retries = 0;
+               bfa_fcs_rport_send_gidpn(rport, NULL);
+               break;
+
+       case RPSM_EVENT_LOGO_IMP:
+               rport->pid = 0;
+               bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);
+               bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
+               bfa_timer_start(rport->fcs->bfa, &rport->timer,
+                               bfa_fcs_rport_timeout, rport,
+                               bfa_fcs_rport_del_timeout);
+               break;
+
+       case RPSM_EVENT_HCB_OFFLINE:
+               /**
+                * Ignore BFA callback, on a PLOGI receive we call bfa offline.
+                */
+               break;
+
+       default:
+               bfa_assert(0);
+       }
+}
+
+/**
+ *             PLOGI is sent.
+ */
+static void
+bfa_fcs_rport_sm_plogi_retry(struct bfa_fcs_rport_s *rport,
+                       enum rport_event event)
+{
+       bfa_trc(rport->fcs, rport->pwwn);
+       bfa_trc(rport->fcs, rport->pid);
+       bfa_trc(rport->fcs, event);
+
+       switch (event) {
+       case RPSM_EVENT_SCN:
+               bfa_timer_stop(&rport->timer);
+               /*
+                * !! fall through !!
+                */
+
+       case RPSM_EVENT_TIMEOUT:
+               rport->plogi_retries++;
+               if (rport->plogi_retries < BFA_FCS_RPORT_MAX_RETRIES) {
+                       bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogi_sending);
+                       bfa_fcs_rport_send_plogi(rport, NULL);
+               } else {
+                       rport->pid = 0;
+                       bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);
+                       bfa_timer_start(rport->fcs->bfa, &rport->timer,
+                                       bfa_fcs_rport_timeout, rport,
+                                       bfa_fcs_rport_del_timeout);
+               }
+               break;
+
+       case RPSM_EVENT_DELETE:
+               bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit);
+               bfa_timer_stop(&rport->timer);
+               bfa_fcs_rport_free(rport);
+               break;
+
+       case RPSM_EVENT_LOGO_RCVD:
+               break;
+
+       case RPSM_EVENT_PLOGI_RCVD:
+               bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogiacc_sending);
+               bfa_timer_stop(&rport->timer);
+               bfa_fcs_rport_send_plogiacc(rport, NULL);
+               break;
+
+       case RPSM_EVENT_ADDRESS_CHANGE:
+               bfa_timer_stop(&rport->timer);
+               bfa_sm_set_state(rport, bfa_fcs_rport_sm_nsdisc_sending);
+               rport->ns_retries = 0;
+               bfa_fcs_rport_send_gidpn(rport, NULL);
+               break;
+
+       case RPSM_EVENT_LOGO_IMP:
+               rport->pid = 0;
+               bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);
+               bfa_timer_stop(&rport->timer);
+               bfa_timer_start(rport->fcs->bfa, &rport->timer,
+                               bfa_fcs_rport_timeout, rport,
+                               bfa_fcs_rport_del_timeout);
+               break;
+
+       case RPSM_EVENT_PLOGI_COMP:
+               bfa_sm_set_state(rport, bfa_fcs_rport_sm_hal_online);
+               bfa_timer_stop(&rport->timer);
+               bfa_fcs_rport_hal_online(rport);
+               break;
+
+       default:
+               bfa_assert(0);
+       }
+}
+
+/**
+ *             PLOGI is sent.
+ */
+static void
+bfa_fcs_rport_sm_plogi(struct bfa_fcs_rport_s *rport, enum rport_event event)
+{
+       bfa_trc(rport->fcs, rport->pwwn);
+       bfa_trc(rport->fcs, rport->pid);
+       bfa_trc(rport->fcs, event);
+
+       switch (event) {
+       case RPSM_EVENT_ACCEPTED:
+               bfa_sm_set_state(rport, bfa_fcs_rport_sm_hal_online);
+               rport->plogi_retries = 0;
+               bfa_fcs_rport_hal_online(rport);
+               break;
+
+       case RPSM_EVENT_LOGO_RCVD:
+               bfa_fcs_rport_send_logo_acc(rport);
+               bfa_fcxp_discard(rport->fcxp);
+               /*
+                * !! fall through !!
+                */
+       case RPSM_EVENT_FAILED:
+               bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogi_retry);
+               bfa_timer_start(rport->fcs->bfa, &rport->timer,
+                               bfa_fcs_rport_timeout, rport,
+                               BFA_FCS_RETRY_TIMEOUT);
+               break;
+
+       case RPSM_EVENT_LOGO_IMP:
+               rport->pid = 0;
+               bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);
+               bfa_fcxp_discard(rport->fcxp);
+               bfa_timer_start(rport->fcs->bfa, &rport->timer,
+                               bfa_fcs_rport_timeout, rport,
+                               bfa_fcs_rport_del_timeout);
+               break;
+
+       case RPSM_EVENT_ADDRESS_CHANGE:
+               bfa_fcxp_discard(rport->fcxp);
+               bfa_sm_set_state(rport, bfa_fcs_rport_sm_nsdisc_sending);
+               rport->ns_retries = 0;
+               bfa_fcs_rport_send_gidpn(rport, NULL);
+               break;
+
+       case RPSM_EVENT_PLOGI_RCVD:
+               bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogiacc_sending);
+               bfa_fcxp_discard(rport->fcxp);
+               bfa_fcs_rport_send_plogiacc(rport, NULL);
+               break;
+
+       case RPSM_EVENT_SCN:
+               /**
+                * Ignore SCN - wait for PLOGI response.
+                */
+               break;
+
+       case RPSM_EVENT_DELETE:
+               bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit);
+               bfa_fcxp_discard(rport->fcxp);
+               bfa_fcs_rport_free(rport);
+               break;
+
+       case RPSM_EVENT_PLOGI_COMP:
+               bfa_sm_set_state(rport, bfa_fcs_rport_sm_hal_online);
+               bfa_fcxp_discard(rport->fcxp);
+               bfa_fcs_rport_hal_online(rport);
+               break;
+
+       default:
+               bfa_assert(0);
+       }
+}
+
+/**
+ *             PLOGI is complete. Awaiting BFA rport online callback. FC-4s
+ *             are offline.
+ */
+static void
+bfa_fcs_rport_sm_hal_online(struct bfa_fcs_rport_s *rport,
+                       enum rport_event event)
+{
+       bfa_trc(rport->fcs, rport->pwwn);
+       bfa_trc(rport->fcs, rport->pid);
+       bfa_trc(rport->fcs, event);
+
+       switch (event) {
+       case RPSM_EVENT_HCB_ONLINE:
+               bfa_sm_set_state(rport, bfa_fcs_rport_sm_online);
+               bfa_fcs_rport_online_action(rport);
+               break;
+
+       case RPSM_EVENT_LOGO_RCVD:
+               bfa_sm_set_state(rport, bfa_fcs_rport_sm_hcb_logorcv);
+               bfa_rport_offline(rport->bfa_rport);
+               break;
+
+       case RPSM_EVENT_LOGO_IMP:
+       case RPSM_EVENT_ADDRESS_CHANGE:
+               bfa_sm_set_state(rport, bfa_fcs_rport_sm_hcb_offline);
+               bfa_rport_offline(rport->bfa_rport);
+               break;
+
+       case RPSM_EVENT_PLOGI_RCVD:
+               bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogiacc_sending);
+               bfa_rport_offline(rport->bfa_rport);
+               bfa_fcs_rport_send_plogiacc(rport, NULL);
+               break;
+
+       case RPSM_EVENT_DELETE:
+               bfa_sm_set_state(rport, bfa_fcs_rport_sm_hcb_logosend);
+               bfa_rport_offline(rport->bfa_rport);
+               break;
+
+       case RPSM_EVENT_SCN:
+               /**
+                * @todo
+                * Ignore SCN - PLOGI just completed, FC-4 login should detect
+                * device failures.
+                */
+               break;
+
+       default:
+               bfa_assert(0);
+       }
+}
+
+/**
+ *             Rport is ONLINE. FC-4s active.
+ */
+static void
+bfa_fcs_rport_sm_online(struct bfa_fcs_rport_s *rport, enum rport_event event)
+{
+       bfa_trc(rport->fcs, rport->pwwn);
+       bfa_trc(rport->fcs, rport->pid);
+       bfa_trc(rport->fcs, event);
+
+       switch (event) {
+       case RPSM_EVENT_SCN:
+               /**
+                * Pause FC-4 activity till rport is authenticated.
+                * In switched fabrics, check presence of device in nameserver
+                * first.
+                */
+               bfa_fcs_rport_fc4_pause(rport);
+
+               if (bfa_fcs_fabric_is_switched(rport->port->fabric)) {
+                       bfa_sm_set_state(rport,
+                                        bfa_fcs_rport_sm_nsquery_sending);
+                       rport->ns_retries = 0;
+                       bfa_fcs_rport_send_gidpn(rport, NULL);
+               } else {
+                       bfa_sm_set_state(rport, bfa_fcs_rport_sm_adisc_sending);
+                       bfa_fcs_rport_send_adisc(rport, NULL);
+               }
+               break;
+
+       case RPSM_EVENT_PLOGI_RCVD:
+       case RPSM_EVENT_LOGO_IMP:
+       case RPSM_EVENT_ADDRESS_CHANGE:
+               bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_offline);
+               bfa_fcs_rport_offline_action(rport);
+               break;
+
+       case RPSM_EVENT_DELETE:
+               bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logosend);
+               bfa_fcs_rport_offline_action(rport);
+               break;
+
+       case RPSM_EVENT_LOGO_RCVD:
+               bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logorcv);
+               bfa_fcs_rport_offline_action(rport);
+               break;
+
+       case RPSM_EVENT_PLOGI_COMP:
+               break;
+
+       default:
+               bfa_assert(0);
+       }
+}
+
+/**
+ *             An SCN event is received in ONLINE state. NS query is being sent
+ *             prior to ADISC authentication with rport. FC-4s are paused.
+ */
+static void
+bfa_fcs_rport_sm_nsquery_sending(struct bfa_fcs_rport_s *rport,
+                                enum rport_event event)
+{
+       bfa_trc(rport->fcs, rport->pwwn);
+       bfa_trc(rport->fcs, rport->pid);
+       bfa_trc(rport->fcs, event);
+
+       switch (event) {
+       case RPSM_EVENT_FCXP_SENT:
+               bfa_sm_set_state(rport, bfa_fcs_rport_sm_nsquery);
+               break;
+
+       case RPSM_EVENT_DELETE:
+               bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logosend);
+               bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
+               bfa_fcs_rport_offline_action(rport);
+               break;
+
+       case RPSM_EVENT_SCN:
+               /**
+                * ignore SCN, wait for response to query itself
+                */
+               break;
+
+       case RPSM_EVENT_LOGO_RCVD:
+               bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logorcv);
+               bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
+               bfa_fcs_rport_offline_action(rport);
+               break;
+
+       case RPSM_EVENT_LOGO_IMP:
+               rport->pid = 0;
+               bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);
+               bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
+               bfa_timer_start(rport->fcs->bfa, &rport->timer,
+                               bfa_fcs_rport_timeout, rport,
+                               bfa_fcs_rport_del_timeout);
+               break;
+
+       case RPSM_EVENT_PLOGI_RCVD:
+       case RPSM_EVENT_ADDRESS_CHANGE:
+       case RPSM_EVENT_PLOGI_COMP:
+               bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_offline);
+               bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
+               bfa_fcs_rport_offline_action(rport);
+               break;
+
+       default:
+               bfa_assert(0);
+       }
+}
+
+/**
+ *     An SCN event is received in ONLINE state. NS query is sent to rport.
+ *     FC-4s are paused.
+ */
+static void
+bfa_fcs_rport_sm_nsquery(struct bfa_fcs_rport_s *rport, enum rport_event event)
+{
+       bfa_trc(rport->fcs, rport->pwwn);
+       bfa_trc(rport->fcs, rport->pid);
+       bfa_trc(rport->fcs, event);
+
+       switch (event) {
+       case RPSM_EVENT_ACCEPTED:
+               bfa_sm_set_state(rport, bfa_fcs_rport_sm_adisc_sending);
+               bfa_fcs_rport_send_adisc(rport, NULL);
+               break;
+
+       case RPSM_EVENT_FAILED:
+               rport->ns_retries++;
+               if (rport->ns_retries < BFA_FCS_RPORT_MAX_RETRIES) {
+                       bfa_sm_set_state(rport,
+                                        bfa_fcs_rport_sm_nsquery_sending);
+                       bfa_fcs_rport_send_gidpn(rport, NULL);
+               } else {
+                       bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_offline);
+                       bfa_fcs_rport_offline_action(rport);
+               }
+               break;
+
+       case RPSM_EVENT_DELETE:
+               bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logosend);
+               bfa_fcxp_discard(rport->fcxp);
+               bfa_fcs_rport_offline_action(rport);
+               break;
+
+       case RPSM_EVENT_SCN:
+               break;
+
+       case RPSM_EVENT_LOGO_RCVD:
+               bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logorcv);
+               bfa_fcxp_discard(rport->fcxp);
+               bfa_fcs_rport_offline_action(rport);
+               break;
+
+       case RPSM_EVENT_PLOGI_COMP:
+       case RPSM_EVENT_ADDRESS_CHANGE:
+       case RPSM_EVENT_PLOGI_RCVD:
+       case RPSM_EVENT_LOGO_IMP:
+               bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_offline);
+               bfa_fcxp_discard(rport->fcxp);
+               bfa_fcs_rport_offline_action(rport);
+               break;
+
+       default:
+               bfa_assert(0);
+       }
+}
+
+/**
+ *     An SCN event is received in ONLINE state. ADISC is being sent for
+ *     authenticating with rport. FC-4s are paused.
+ */
+static void
+bfa_fcs_rport_sm_adisc_sending(struct bfa_fcs_rport_s *rport,
+                              enum rport_event event)
+{
+       bfa_trc(rport->fcs, rport->pwwn);
+       bfa_trc(rport->fcs, rport->pid);
+       bfa_trc(rport->fcs, event);
+
+       switch (event) {
+       case RPSM_EVENT_FCXP_SENT:
+               bfa_sm_set_state(rport, bfa_fcs_rport_sm_adisc);
+               break;
+
+       case RPSM_EVENT_DELETE:
+               bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logosend);
+               bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
+               bfa_fcs_rport_offline_action(rport);
+               break;
+
+       case RPSM_EVENT_LOGO_IMP:
+       case RPSM_EVENT_ADDRESS_CHANGE:
+               bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_offline);
+               bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
+               bfa_fcs_rport_offline_action(rport);
+               break;
+
+       case RPSM_EVENT_LOGO_RCVD:
+               bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logorcv);
+               bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
+               bfa_fcs_rport_offline_action(rport);
+               break;
+
+       case RPSM_EVENT_SCN:
+               break;
+
+       case RPSM_EVENT_PLOGI_RCVD:
+               bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_offline);
+               bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
+               bfa_fcs_rport_offline_action(rport);
+               break;
+
+       default:
+               bfa_assert(0);
+       }
+}
+
+/**
+ *             An SCN event is received in ONLINE state. ADISC is to rport.
+ *             FC-4s are paused.
+ */
+static void
+bfa_fcs_rport_sm_adisc(struct bfa_fcs_rport_s *rport, enum rport_event event)
+{
+       bfa_trc(rport->fcs, rport->pwwn);
+       bfa_trc(rport->fcs, rport->pid);
+       bfa_trc(rport->fcs, event);
+
+       switch (event) {
+       case RPSM_EVENT_ACCEPTED:
+               bfa_sm_set_state(rport, bfa_fcs_rport_sm_online);
+               bfa_fcs_rport_fc4_resume(rport);
+               break;
+
+       case RPSM_EVENT_PLOGI_RCVD:
+               /**
+                * Too complex to cleanup FC-4 & rport and then acc to PLOGI.
+                * At least go offline when a PLOGI is received.
+                */
+               bfa_fcxp_discard(rport->fcxp);
+               /*
+                * !!! fall through !!!
+                */
+
+       case RPSM_EVENT_FAILED:
+       case RPSM_EVENT_ADDRESS_CHANGE:
+               bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_offline);
+               bfa_fcs_rport_offline_action(rport);
+               break;
+
+       case RPSM_EVENT_DELETE:
+               bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logosend);
+               bfa_fcxp_discard(rport->fcxp);
+               bfa_fcs_rport_offline_action(rport);
+               break;
+
+       case RPSM_EVENT_SCN:
+               /**
+                * already processing RSCN
+                */
+               break;
+
+       case RPSM_EVENT_LOGO_IMP:
+               bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_offline);
+               bfa_fcxp_discard(rport->fcxp);
+               bfa_fcs_rport_offline_action(rport);
+               break;
+
+       case RPSM_EVENT_LOGO_RCVD:
+               bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logorcv);
+               bfa_fcxp_discard(rport->fcxp);
+               bfa_fcs_rport_offline_action(rport);
+               break;
+
+       default:
+               bfa_assert(0);
+       }
+}
+
+/**
+ *             Rport has sent LOGO. Awaiting FC-4 offline completion callback.
+ */
+static void
+bfa_fcs_rport_sm_fc4_logorcv(struct bfa_fcs_rport_s *rport,
+                       enum rport_event event)
+{
+       bfa_trc(rport->fcs, rport->pwwn);
+       bfa_trc(rport->fcs, rport->pid);
+       bfa_trc(rport->fcs, event);
+
+       switch (event) {
+       case RPSM_EVENT_FC4_OFFLINE:
+               bfa_sm_set_state(rport, bfa_fcs_rport_sm_hcb_logorcv);
+               bfa_rport_offline(rport->bfa_rport);
+               break;
+
+       case RPSM_EVENT_DELETE:
+               bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logosend);
+               break;
+
+       case RPSM_EVENT_LOGO_RCVD:
+       case RPSM_EVENT_ADDRESS_CHANGE:
+               break;
+
+       default:
+               bfa_assert(0);
+       }
+}
+
+/**
+ *             LOGO needs to be sent to rport. Awaiting FC-4 offline completion
+ *             callback.
+ */
+static void
+bfa_fcs_rport_sm_fc4_logosend(struct bfa_fcs_rport_s *rport,
+                             enum rport_event event)
+{
+       bfa_trc(rport->fcs, rport->pwwn);
+       bfa_trc(rport->fcs, rport->pid);
+       bfa_trc(rport->fcs, event);
+
+       switch (event) {
+       case RPSM_EVENT_FC4_OFFLINE:
+               bfa_sm_set_state(rport, bfa_fcs_rport_sm_hcb_logosend);
+               bfa_rport_offline(rport->bfa_rport);
+               break;
+
+       default:
+               bfa_assert(0);
+       }
+}
+
+/**
+ *     Rport is going offline. Awaiting FC-4 offline completion callback.
+ */
+static void
+bfa_fcs_rport_sm_fc4_offline(struct bfa_fcs_rport_s *rport,
+                       enum rport_event event)
+{
+       bfa_trc(rport->fcs, rport->pwwn);
+       bfa_trc(rport->fcs, rport->pid);
+       bfa_trc(rport->fcs, event);
+
+       switch (event) {
+       case RPSM_EVENT_FC4_OFFLINE:
+               bfa_sm_set_state(rport, bfa_fcs_rport_sm_hcb_offline);
+               bfa_rport_offline(rport->bfa_rport);
+               break;
+
+       case RPSM_EVENT_SCN:
+       case RPSM_EVENT_LOGO_IMP:
+       case RPSM_EVENT_LOGO_RCVD:
+       case RPSM_EVENT_ADDRESS_CHANGE:
+               /**
+                * rport is already going offline.
+                * SCN - ignore and wait till transitioning to offline state
+                */
+               break;
+
+       case RPSM_EVENT_DELETE:
+               bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logosend);
+               break;
+
+       default:
+               bfa_assert(0);
+       }
+}
+
+/**
+ *             Rport is offline. FC-4s are offline. Awaiting BFA rport offline
+ *             callback.
+ */
+static void
+bfa_fcs_rport_sm_hcb_offline(struct bfa_fcs_rport_s *rport,
+                       enum rport_event event)
+{
+       bfa_trc(rport->fcs, rport->pwwn);
+       bfa_trc(rport->fcs, rport->pid);
+       bfa_trc(rport->fcs, event);
+
+       switch (event) {
+       case RPSM_EVENT_HCB_OFFLINE:
+       case RPSM_EVENT_ADDRESS_CHANGE:
+               if (bfa_fcs_port_is_online(rport->port)) {
+                       bfa_sm_set_state(rport,
+                                        bfa_fcs_rport_sm_nsdisc_sending);
+                       rport->ns_retries = 0;
+                       bfa_fcs_rport_send_gidpn(rport, NULL);
+               } else {
+                       rport->pid = 0;
+                       bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);
+                       bfa_timer_start(rport->fcs->bfa, &rport->timer,
+                                       bfa_fcs_rport_timeout, rport,
+                                       bfa_fcs_rport_del_timeout);
+               }
+               break;
+
+       case RPSM_EVENT_DELETE:
+               bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit);
+               bfa_fcs_rport_free(rport);
+               break;
+
+       case RPSM_EVENT_SCN:
+       case RPSM_EVENT_LOGO_RCVD:
+               /**
+                * Ignore, already offline.
+                */
+               break;
+
+       default:
+               bfa_assert(0);
+       }
+}
+
+/**
+ *             Rport is offline. FC-4s are offline. Awaiting BFA rport offline
+ *             callback to send LOGO accept.
+ */
+static void
+bfa_fcs_rport_sm_hcb_logorcv(struct bfa_fcs_rport_s *rport,
+                       enum rport_event event)
+{
+       bfa_trc(rport->fcs, rport->pwwn);
+       bfa_trc(rport->fcs, rport->pid);
+       bfa_trc(rport->fcs, event);
+
+       switch (event) {
+       case RPSM_EVENT_HCB_OFFLINE:
+       case RPSM_EVENT_ADDRESS_CHANGE:
+               if (rport->pid)
+                       bfa_fcs_rport_send_logo_acc(rport);
+               /*
+                * If the lport is online and if the rport is not a well known
+                * address port, we try to re-discover the r-port.
+                */
+               if (bfa_fcs_port_is_online(rport->port)
+                   && (!BFA_FCS_PID_IS_WKA(rport->pid))) {
+                       bfa_sm_set_state(rport,
+                                        bfa_fcs_rport_sm_nsdisc_sending);
+                       rport->ns_retries = 0;
+                       bfa_fcs_rport_send_gidpn(rport, NULL);
+               } else {
+                       /*
+                        * if it is not a well known address, reset the pid to
+                        *
+                        */
+                       if (!BFA_FCS_PID_IS_WKA(rport->pid))
+                               rport->pid = 0;
+                       bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);
+                       bfa_timer_start(rport->fcs->bfa, &rport->timer,
+                                       bfa_fcs_rport_timeout, rport,
+                                       bfa_fcs_rport_del_timeout);
+               }
+               break;
+
+       case RPSM_EVENT_DELETE:
+               bfa_sm_set_state(rport, bfa_fcs_rport_sm_hcb_logosend);
+               break;
+
+       case RPSM_EVENT_LOGO_IMP:
+               bfa_sm_set_state(rport, bfa_fcs_rport_sm_hcb_offline);
+               break;
+
+       case RPSM_EVENT_LOGO_RCVD:
+               /**
+                * Ignore - already processing a LOGO.
+                */
+               break;
+
+       default:
+               bfa_assert(0);
+       }
+}
+
+/**
+ * Rport is being deleted. FC-4s are offline. Awaiting BFA rport offline
+ * callback to send LOGO.
+ */
+static void
+bfa_fcs_rport_sm_hcb_logosend(struct bfa_fcs_rport_s *rport,
+                             enum rport_event event)
+{
+       bfa_trc(rport->fcs, rport->pwwn);
+       bfa_trc(rport->fcs, rport->pid);
+       bfa_trc(rport->fcs, event);
+
+       switch (event) {
+       case RPSM_EVENT_HCB_OFFLINE:
+               bfa_sm_set_state(rport, bfa_fcs_rport_sm_logo_sending);
+               bfa_fcs_rport_send_logo(rport, NULL);
+               break;
+
+       case RPSM_EVENT_LOGO_RCVD:
+       case RPSM_EVENT_ADDRESS_CHANGE:
+               break;
+
+       default:
+               bfa_assert(0);
+       }
+}
+
+/**
+ *             Rport is being deleted. FC-4s are offline. LOGO is being sent.
+ */
+static void
+bfa_fcs_rport_sm_logo_sending(struct bfa_fcs_rport_s *rport,
+                             enum rport_event event)
+{
+       bfa_trc(rport->fcs, rport->pwwn);
+       bfa_trc(rport->fcs, rport->pid);
+       bfa_trc(rport->fcs, event);
+
+       switch (event) {
+       case RPSM_EVENT_FCXP_SENT:
+               /*
+                * Once LOGO is sent, we donot wait for the response
+                */
+               bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit);
+               bfa_fcs_rport_free(rport);
+               break;
+
+       case RPSM_EVENT_SCN:
+       case RPSM_EVENT_ADDRESS_CHANGE:
+               break;
+
+       case RPSM_EVENT_LOGO_RCVD:
+               bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit);
+               bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
+               bfa_fcs_rport_free(rport);
+               break;
+
+       default:
+               bfa_assert(0);
+       }
+}
+
+/**
+ *             Rport is offline. FC-4s are offline. BFA rport is offline.
+ *             Timer active to delete stale rport.
+ */
+static void
+bfa_fcs_rport_sm_offline(struct bfa_fcs_rport_s *rport, enum rport_event event)
+{
+       bfa_trc(rport->fcs, rport->pwwn);
+       bfa_trc(rport->fcs, rport->pid);
+       bfa_trc(rport->fcs, event);
+
+       switch (event) {
+       case RPSM_EVENT_TIMEOUT:
+               bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit);
+               bfa_fcs_rport_free(rport);
+               break;
+
+       case RPSM_EVENT_SCN:
+       case RPSM_EVENT_ADDRESS_CHANGE:
+               bfa_sm_set_state(rport, bfa_fcs_rport_sm_nsdisc_sending);
+               bfa_timer_stop(&rport->timer);
+               rport->ns_retries = 0;
+               bfa_fcs_rport_send_gidpn(rport, NULL);
+               break;
+
+       case RPSM_EVENT_DELETE:
+               bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit);
+               bfa_timer_stop(&rport->timer);
+               bfa_fcs_rport_free(rport);
+               break;
+
+       case RPSM_EVENT_PLOGI_RCVD:
+               bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogiacc_sending);
+               bfa_timer_stop(&rport->timer);
+               bfa_fcs_rport_send_plogiacc(rport, NULL);
+               break;
+
+       case RPSM_EVENT_LOGO_RCVD:
+       case RPSM_EVENT_LOGO_IMP:
+               break;
+
+       case RPSM_EVENT_PLOGI_COMP:
+               bfa_sm_set_state(rport, bfa_fcs_rport_sm_hal_online);
+               bfa_timer_stop(&rport->timer);
+               bfa_fcs_rport_hal_online(rport);
+               break;
+
+       case RPSM_EVENT_PLOGI_SEND:
+               bfa_timer_stop(&rport->timer);
+               bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogi_sending);
+               rport->plogi_retries = 0;
+               bfa_fcs_rport_send_plogi(rport, NULL);
+               break;
+
+       default:
+               bfa_assert(0);
+       }
+}
+
+/**
+ *     Rport address has changed. Nameserver discovery request is being sent.
+ */
+static void
+bfa_fcs_rport_sm_nsdisc_sending(struct bfa_fcs_rport_s *rport,
+                               enum rport_event event)
+{
+       bfa_trc(rport->fcs, rport->pwwn);
+       bfa_trc(rport->fcs, rport->pid);
+       bfa_trc(rport->fcs, event);
+
+       switch (event) {
+       case RPSM_EVENT_FCXP_SENT:
+               bfa_sm_set_state(rport, bfa_fcs_rport_sm_nsdisc_sent);
+               break;
+
+       case RPSM_EVENT_DELETE:
+               bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit);
+               bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
+               bfa_fcs_rport_free(rport);
+               break;
+
+       case RPSM_EVENT_PLOGI_RCVD:
+               bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogiacc_sending);
+               bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
+               bfa_fcs_rport_send_plogiacc(rport, NULL);
+               break;
+
+       case RPSM_EVENT_SCN:
+       case RPSM_EVENT_LOGO_RCVD:
+       case RPSM_EVENT_PLOGI_SEND:
+               break;
+
+       case RPSM_EVENT_ADDRESS_CHANGE:
+               rport->ns_retries = 0;  /* reset the retry count */
+               break;
+
+       case RPSM_EVENT_LOGO_IMP:
+               bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);
+               bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
+               bfa_timer_start(rport->fcs->bfa, &rport->timer,
+                               bfa_fcs_rport_timeout, rport,
+                               bfa_fcs_rport_del_timeout);
+               break;
+
+       case RPSM_EVENT_PLOGI_COMP:
+               bfa_sm_set_state(rport, bfa_fcs_rport_sm_hal_online);
+               bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
+               bfa_fcs_rport_hal_online(rport);
+               break;
+
+       default:
+               bfa_assert(0);
+       }
+}
+
+/**
+ *             Nameserver discovery failed. Waiting for timeout to retry.
+ */
+static void
+bfa_fcs_rport_sm_nsdisc_retry(struct bfa_fcs_rport_s *rport,
+                             enum rport_event event)
+{
+       bfa_trc(rport->fcs, rport->pwwn);
+       bfa_trc(rport->fcs, rport->pid);
+       bfa_trc(rport->fcs, event);
+
+       switch (event) {
+       case RPSM_EVENT_TIMEOUT:
+               bfa_sm_set_state(rport, bfa_fcs_rport_sm_nsdisc_sending);
+               bfa_fcs_rport_send_gidpn(rport, NULL);
+               break;
+
+       case RPSM_EVENT_SCN:
+       case RPSM_EVENT_ADDRESS_CHANGE:
+               bfa_sm_set_state(rport, bfa_fcs_rport_sm_nsdisc_sending);
+               bfa_timer_stop(&rport->timer);
+               rport->ns_retries = 0;
+               bfa_fcs_rport_send_gidpn(rport, NULL);
+               break;
+
+       case RPSM_EVENT_DELETE:
+               bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit);
+               bfa_timer_stop(&rport->timer);
+               bfa_fcs_rport_free(rport);
+               break;
+
+       case RPSM_EVENT_PLOGI_RCVD:
+               bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogiacc_sending);
+               bfa_timer_stop(&rport->timer);
+               bfa_fcs_rport_send_plogiacc(rport, NULL);
+               break;
+
+       case RPSM_EVENT_LOGO_IMP:
+               rport->pid = 0;
+               bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);
+               bfa_timer_stop(&rport->timer);
+               bfa_timer_start(rport->fcs->bfa, &rport->timer,
+                               bfa_fcs_rport_timeout, rport,
+                               bfa_fcs_rport_del_timeout);
+               break;
+
+       case RPSM_EVENT_LOGO_RCVD:
+               bfa_fcs_rport_send_logo_acc(rport);
+               break;
+
+       case RPSM_EVENT_PLOGI_COMP:
+               bfa_sm_set_state(rport, bfa_fcs_rport_sm_hal_online);
+               bfa_timer_stop(&rport->timer);
+               bfa_fcs_rport_hal_online(rport);
+               break;
+
+       default:
+               bfa_assert(0);
+       }
+}
+
+/**
+ * Rport address has changed. Nameserver discovery request is sent.
+ */
+static void
+bfa_fcs_rport_sm_nsdisc_sent(struct bfa_fcs_rport_s *rport,
+                       enum rport_event event)
+{
+       bfa_trc(rport->fcs, rport->pwwn);
+       bfa_trc(rport->fcs, rport->pid);
+       bfa_trc(rport->fcs, event);
+
+       switch (event) {
+       case RPSM_EVENT_ACCEPTED:
+       case RPSM_EVENT_ADDRESS_CHANGE:
+               if (rport->pid) {
+                       bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogi_sending);
+                       bfa_fcs_rport_send_plogi(rport, NULL);
+               } else {
+                       bfa_sm_set_state(rport,
+                                        bfa_fcs_rport_sm_nsdisc_sending);
+                       rport->ns_retries = 0;
+                       bfa_fcs_rport_send_gidpn(rport, NULL);
+               }
+               break;
+
+       case RPSM_EVENT_FAILED:
+               rport->ns_retries++;
+               if (rport->ns_retries < BFA_FCS_RPORT_MAX_RETRIES) {
+                       bfa_sm_set_state(rport,
+                                        bfa_fcs_rport_sm_nsdisc_sending);
+                       bfa_fcs_rport_send_gidpn(rport, NULL);
+               } else {
+                       rport->pid = 0;
+                       bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);
+                       bfa_timer_start(rport->fcs->bfa, &rport->timer,
+                                       bfa_fcs_rport_timeout, rport,
+                                       bfa_fcs_rport_del_timeout);
+               };
+               break;
+
+       case RPSM_EVENT_DELETE:
+               bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit);
+               bfa_fcxp_discard(rport->fcxp);
+               bfa_fcs_rport_free(rport);
+               break;
+
+       case RPSM_EVENT_PLOGI_RCVD:
+               bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogiacc_sending);
+               bfa_fcxp_discard(rport->fcxp);
+               bfa_fcs_rport_send_plogiacc(rport, NULL);
+               break;
+
+       case RPSM_EVENT_LOGO_IMP:
+               rport->pid = 0;
+               bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);
+               bfa_fcxp_discard(rport->fcxp);
+               bfa_timer_start(rport->fcs->bfa, &rport->timer,
+                               bfa_fcs_rport_timeout, rport,
+                               bfa_fcs_rport_del_timeout);
+               break;
+
+       case RPSM_EVENT_SCN:
+               /**
+                * ignore, wait for NS query response
+                */
+               break;
+
+       case RPSM_EVENT_LOGO_RCVD:
+               /**
+                * Not logged-in yet. Accept LOGO.
+                */
+               bfa_fcs_rport_send_logo_acc(rport);
+               break;
+
+       case RPSM_EVENT_PLOGI_COMP:
+               bfa_sm_set_state(rport, bfa_fcs_rport_sm_hal_online);
+               bfa_fcxp_discard(rport->fcxp);
+               bfa_fcs_rport_hal_online(rport);
+               break;
+
+       default:
+               bfa_assert(0);
+       }
+}
+
+
+
+/**
+ *  fcs_rport_private FCS RPORT provate functions
+ */
+
+static void
+bfa_fcs_rport_send_plogi(void *rport_cbarg, struct bfa_fcxp_s *fcxp_alloced)
+{
+       struct bfa_fcs_rport_s *rport = rport_cbarg;
+       struct bfa_fcs_port_s *port = rport->port;
+       struct fchs_s          fchs;
+       int             len;
+       struct bfa_fcxp_s *fcxp;
+
+       bfa_trc(rport->fcs, rport->pwwn);
+
+       fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
+       if (!fcxp) {
+               bfa_fcxp_alloc_wait(port->fcs->bfa, &rport->fcxp_wqe,
+                                   bfa_fcs_rport_send_plogi, rport);
+               return;
+       }
+       rport->fcxp = fcxp;
+
+       len = fc_plogi_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), rport->pid,
+                            bfa_fcs_port_get_fcid(port), 0,
+                            port->port_cfg.pwwn, port->port_cfg.nwwn,
+                            bfa_pport_get_maxfrsize(port->fcs->bfa));
+
+       bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
+                     FC_CLASS_3, len, &fchs, bfa_fcs_rport_plogi_response,
+                     (void *)rport, FC_MAX_PDUSZ, FC_RA_TOV);
+
+       rport->stats.plogis++;
+       bfa_sm_send_event(rport, RPSM_EVENT_FCXP_SENT);
+}
+
+static void
+bfa_fcs_rport_plogi_response(void *fcsarg, struct bfa_fcxp_s *fcxp, void *cbarg,
+                            bfa_status_t req_status, u32 rsp_len,
+                            u32 resid_len, struct fchs_s *rsp_fchs)
+{
+       struct bfa_fcs_rport_s *rport = (struct bfa_fcs_rport_s *)cbarg;
+       struct fc_logi_s        *plogi_rsp;
+       struct fc_ls_rjt_s      *ls_rjt;
+       struct bfa_fcs_rport_s *twin;
+       struct list_head *qe;
+
+       bfa_trc(rport->fcs, rport->pwwn);
+
+       /*
+        * Sanity Checks
+        */
+       if (req_status != BFA_STATUS_OK) {
+               bfa_trc(rport->fcs, req_status);
+               rport->stats.plogi_failed++;
+               bfa_sm_send_event(rport, RPSM_EVENT_FAILED);
+               return;
+       }
+
+       plogi_rsp = (struct fc_logi_s *) BFA_FCXP_RSP_PLD(fcxp);
+
+       /**
+        * Check for failure first.
+        */
+       if (plogi_rsp->els_cmd.els_code != FC_ELS_ACC) {
+               ls_rjt = (struct fc_ls_rjt_s *) BFA_FCXP_RSP_PLD(fcxp);
+
+               bfa_trc(rport->fcs, ls_rjt->reason_code);
+               bfa_trc(rport->fcs, ls_rjt->reason_code_expl);
+
+               rport->stats.plogi_rejects++;
+               bfa_sm_send_event(rport, RPSM_EVENT_FAILED);
+               return;
+       }
+
+       /**
+        * PLOGI is complete. Make sure this device is not one of the known
+        * device with a new FC port address.
+        */
+       list_for_each(qe, &rport->port->rport_q) {
+               twin = (struct bfa_fcs_rport_s *)qe;
+               if (twin == rport)
+                       continue;
+               if (!rport->pwwn && (plogi_rsp->port_name == twin->pwwn)) {
+                       bfa_trc(rport->fcs, twin->pid);
+                       bfa_trc(rport->fcs, rport->pid);
+
+                       /*
+                        * Update plogi stats in twin
+                        */
+                       twin->stats.plogis += rport->stats.plogis;
+                       twin->stats.plogi_rejects += rport->stats.plogi_rejects;
+                       twin->stats.plogi_timeouts +=
+                               rport->stats.plogi_timeouts;
+                       twin->stats.plogi_failed += rport->stats.plogi_failed;
+                       twin->stats.plogi_rcvd += rport->stats.plogi_rcvd;
+                       twin->stats.plogi_accs++;
+
+                       bfa_fcs_rport_delete(rport);
+
+                       bfa_fcs_rport_update(twin, plogi_rsp);
+                       twin->pid = rsp_fchs->s_id;
+                       bfa_sm_send_event(twin, RPSM_EVENT_PLOGI_COMP);
+                       return;
+               }
+       }
+
+       /**
+        * Normal login path -- no evil twins.
+        */
+       rport->stats.plogi_accs++;
+       bfa_fcs_rport_update(rport, plogi_rsp);
+       bfa_sm_send_event(rport, RPSM_EVENT_ACCEPTED);
+}
+
+static void
+bfa_fcs_rport_send_plogiacc(void *rport_cbarg, struct bfa_fcxp_s *fcxp_alloced)
+{
+       struct bfa_fcs_rport_s *rport = rport_cbarg;
+       struct bfa_fcs_port_s *port = rport->port;
+       struct fchs_s          fchs;
+       int             len;
+       struct bfa_fcxp_s *fcxp;
+
+       bfa_trc(rport->fcs, rport->pwwn);
+       bfa_trc(rport->fcs, rport->reply_oxid);
+
+       fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
+       if (!fcxp) {
+               bfa_fcxp_alloc_wait(port->fcs->bfa, &rport->fcxp_wqe,
+                                   bfa_fcs_rport_send_plogiacc, rport);
+               return;
+       }
+       rport->fcxp = fcxp;
+
+       len = fc_plogi_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), rport->pid,
+                                bfa_fcs_port_get_fcid(port), rport->reply_oxid,
+                                port->port_cfg.pwwn, port->port_cfg.nwwn,
+                                bfa_pport_get_maxfrsize(port->fcs->bfa));
+
+       bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
+                     FC_CLASS_3, len, &fchs, NULL, NULL, FC_MAX_PDUSZ, 0);
+
+       bfa_sm_send_event(rport, RPSM_EVENT_FCXP_SENT);
+}
+
+static void
+bfa_fcs_rport_send_adisc(void *rport_cbarg, struct bfa_fcxp_s *fcxp_alloced)
+{
+       struct bfa_fcs_rport_s *rport = rport_cbarg;
+       struct bfa_fcs_port_s *port = rport->port;
+       struct fchs_s          fchs;
+       int             len;
+       struct bfa_fcxp_s *fcxp;
+
+       bfa_trc(rport->fcs, rport->pwwn);
+
+       fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
+       if (!fcxp) {
+               bfa_fcxp_alloc_wait(port->fcs->bfa, &rport->fcxp_wqe,
+                                   bfa_fcs_rport_send_adisc, rport);
+               return;
+       }
+       rport->fcxp = fcxp;
+
+       len = fc_adisc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), rport->pid,
+                            bfa_fcs_port_get_fcid(port), 0,
+                            port->port_cfg.pwwn, port->port_cfg.nwwn);
+
+       bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
+                     FC_CLASS_3, len, &fchs, bfa_fcs_rport_adisc_response,
+                     rport, FC_MAX_PDUSZ, FC_RA_TOV);
+
+       rport->stats.adisc_sent++;
+       bfa_sm_send_event(rport, RPSM_EVENT_FCXP_SENT);
+}
+
+static void
+bfa_fcs_rport_adisc_response(void *fcsarg, struct bfa_fcxp_s *fcxp, void *cbarg,
+                            bfa_status_t req_status, u32 rsp_len,
+                            u32 resid_len, struct fchs_s *rsp_fchs)
+{
+       struct bfa_fcs_rport_s *rport = (struct bfa_fcs_rport_s *)cbarg;
+       void           *pld = bfa_fcxp_get_rspbuf(fcxp);
+       struct fc_ls_rjt_s    *ls_rjt;
+
+       if (req_status != BFA_STATUS_OK) {
+               bfa_trc(rport->fcs, req_status);
+               rport->stats.adisc_failed++;
+               bfa_sm_send_event(rport, RPSM_EVENT_FAILED);
+               return;
+       }
+
+       if (fc_adisc_rsp_parse((struct fc_adisc_s *)pld, rsp_len, rport->pwwn,
+               rport->nwwn)  == FC_PARSE_OK) {
+               rport->stats.adisc_accs++;
+               bfa_sm_send_event(rport, RPSM_EVENT_ACCEPTED);
+               return;
+       }
+
+       rport->stats.adisc_rejects++;
+       ls_rjt = pld;
+       bfa_trc(rport->fcs, ls_rjt->els_cmd.els_code);
+       bfa_trc(rport->fcs, ls_rjt->reason_code);
+       bfa_trc(rport->fcs, ls_rjt->reason_code_expl);
+       bfa_sm_send_event(rport, RPSM_EVENT_FAILED);
+}
+
+static void
+bfa_fcs_rport_send_gidpn(void *rport_cbarg, struct bfa_fcxp_s *fcxp_alloced)
+{
+       struct bfa_fcs_rport_s *rport = rport_cbarg;
+       struct bfa_fcs_port_s *port = rport->port;
+       struct fchs_s          fchs;
+       struct bfa_fcxp_s *fcxp;
+       int             len;
+
+       bfa_trc(rport->fcs, rport->pid);
+
+       fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
+       if (!fcxp) {
+               bfa_fcxp_alloc_wait(port->fcs->bfa, &rport->fcxp_wqe,
+                                   bfa_fcs_rport_send_gidpn, rport);
+               return;
+       }
+       rport->fcxp = fcxp;
+
+       len = fc_gidpn_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
+                            bfa_fcs_port_get_fcid(port), 0, rport->pwwn);
+
+       bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
+                     FC_CLASS_3, len, &fchs, bfa_fcs_rport_gidpn_response,
+                     (void *)rport, FC_MAX_PDUSZ, FC_RA_TOV);
+
+       bfa_sm_send_event(rport, RPSM_EVENT_FCXP_SENT);
+}
+
+static void
+bfa_fcs_rport_gidpn_response(void *fcsarg, struct bfa_fcxp_s *fcxp, void *cbarg,
+                            bfa_status_t req_status, u32 rsp_len,
+                            u32 resid_len, struct fchs_s *rsp_fchs)
+{
+       struct bfa_fcs_rport_s *rport = (struct bfa_fcs_rport_s *)cbarg;
+       struct bfa_fcs_rport_s *twin;
+       struct list_head *qe;
+       struct ct_hdr_s         *cthdr;
+       struct fcgs_gidpn_resp_s        *gidpn_rsp;
+
+       bfa_trc(rport->fcs, rport->pwwn);
+
+       cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp);
+       cthdr->cmd_rsp_code = bfa_os_ntohs(cthdr->cmd_rsp_code);
+
+       if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) {
+               /*
+                * Check if the pid is the same as before.
+                */
+               gidpn_rsp = (struct fcgs_gidpn_resp_s *) (cthdr + 1);
+
+               if (gidpn_rsp->dap == rport->pid) {
+                       /*
+                        * Device is online
+                        */
+                       bfa_sm_send_event(rport, RPSM_EVENT_ACCEPTED);
+               } else {
+                       /*
+                        * Device's PID has changed. We need to cleanup and
+                        * re-login. If there is another device with the the
+                        * newly discovered pid, send an scn notice so that its
+                        * new pid can be discovered.
+                        */
+                       list_for_each(qe, &rport->port->rport_q) {
+                               twin = (struct bfa_fcs_rport_s *)qe;
+                               if (twin == rport)
+                                       continue;
+                               if (gidpn_rsp->dap == twin->pid) {
+                                       bfa_trc(rport->fcs, twin->pid);
+                                       bfa_trc(rport->fcs, rport->pid);
+
+                                       twin->pid = 0;
+                                       bfa_sm_send_event(twin,
+                                               RPSM_EVENT_ADDRESS_CHANGE);
+                               }
+                       }
+                       rport->pid = gidpn_rsp->dap;
+                       bfa_sm_send_event(rport, RPSM_EVENT_ADDRESS_CHANGE);
+               }
+               return;
+       }
+
+       /*
+        * Reject Response
+        */
+       switch (cthdr->reason_code) {
+       case CT_RSN_LOGICAL_BUSY:
+               /*
+                * Need to retry
+                */
+               bfa_sm_send_event(rport, RPSM_EVENT_TIMEOUT);
+               break;
+
+       case CT_RSN_UNABLE_TO_PERF:
+               /*
+                * device doesn't exist : Start timer to cleanup this later.
+                */
+               bfa_sm_send_event(rport, RPSM_EVENT_FAILED);
+               break;
+
+       default:
+               bfa_sm_send_event(rport, RPSM_EVENT_FAILED);
+               break;
+       }
+}
+
+/**
+ *    Called to send a logout to the rport.
+ */
+static void
+bfa_fcs_rport_send_logo(void *rport_cbarg, struct bfa_fcxp_s *fcxp_alloced)
+{
+       struct bfa_fcs_rport_s *rport = rport_cbarg;
+       struct bfa_fcs_port_s *port;
+       struct fchs_s          fchs;
+       struct bfa_fcxp_s *fcxp;
+       u16        len;
+
+       bfa_trc(rport->fcs, rport->pid);
+
+       port = rport->port;
+
+       fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
+       if (!fcxp) {
+               bfa_fcxp_alloc_wait(port->fcs->bfa, &rport->fcxp_wqe,
+                                   bfa_fcs_rport_send_logo, rport);
+               return;
+       }
+       rport->fcxp = fcxp;
+
+       len = fc_logo_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), rport->pid,
+                           bfa_fcs_port_get_fcid(port), 0,
+                           bfa_fcs_port_get_pwwn(port));
+
+       bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
+                     FC_CLASS_3, len, &fchs, NULL, rport, FC_MAX_PDUSZ,
+                     FC_ED_TOV);
+
+       rport->stats.logos++;
+       bfa_fcxp_discard(rport->fcxp);
+       bfa_sm_send_event(rport, RPSM_EVENT_FCXP_SENT);
+}
+
+/**
+ *    Send ACC for a LOGO received.
+ */
+static void
+bfa_fcs_rport_send_logo_acc(void *rport_cbarg)
+{
+       struct bfa_fcs_rport_s *rport = rport_cbarg;
+       struct bfa_fcs_port_s *port;
+       struct fchs_s          fchs;
+       struct bfa_fcxp_s *fcxp;
+       u16        len;
+
+       bfa_trc(rport->fcs, rport->pid);
+
+       port = rport->port;
+
+       fcxp = bfa_fcs_fcxp_alloc(port->fcs);
+       if (!fcxp)
+               return;
+
+       rport->stats.logo_rcvd++;
+       len = fc_logo_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), rport->pid,
+                               bfa_fcs_port_get_fcid(port), rport->reply_oxid);
+
+       bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
+                     FC_CLASS_3, len, &fchs, NULL, NULL, FC_MAX_PDUSZ, 0);
+}
+
+/**
+ *     This routine will be called by bfa_timer on timer timeouts.
+ *
+ *     param[in]       rport                   - pointer to bfa_fcs_port_ns_t.
+ *     param[out]      rport_status    - pointer to return vport status in
+ *
+ *     return
+ *             void
+ *
+*      Special Considerations:
+ *
+ *     note
+ */
+static void
+bfa_fcs_rport_timeout(void *arg)
+{
+       struct bfa_fcs_rport_s *rport = (struct bfa_fcs_rport_s *)arg;
+
+       rport->stats.plogi_timeouts++;
+       bfa_sm_send_event(rport, RPSM_EVENT_TIMEOUT);
+}
+
+static void
+bfa_fcs_rport_process_prli(struct bfa_fcs_rport_s *rport,
+                       struct fchs_s *rx_fchs, u16 len)
+{
+       struct bfa_fcxp_s *fcxp;
+       struct fchs_s          fchs;
+       struct bfa_fcs_port_s *port = rport->port;
+       struct fc_prli_s      *prli;
+
+       bfa_trc(port->fcs, rx_fchs->s_id);
+       bfa_trc(port->fcs, rx_fchs->d_id);
+
+       rport->stats.prli_rcvd++;
+
+       if (BFA_FCS_VPORT_IS_TARGET_MODE(port)) {
+               /*
+                * Target Mode : Let the fcptm handle it
+                */
+               bfa_fcs_tin_rx_prli(rport->tin, rx_fchs, len);
+               return;
+       }
+
+       /*
+        * We are either in Initiator or ipfc Mode
+        */
+       prli = (struct fc_prli_s *) (rx_fchs + 1);
+
+       if (prli->parampage.servparams.initiator) {
+               bfa_trc(rport->fcs, prli->parampage.type);
+               rport->scsi_function = BFA_RPORT_INITIATOR;
+               bfa_fcs_itnim_is_initiator(rport->itnim);
+       } else {
+               /*
+                * @todo: PRLI from a target ?
+                */
+               bfa_trc(port->fcs, rx_fchs->s_id);
+               rport->scsi_function = BFA_RPORT_TARGET;
+       }
+
+       fcxp = bfa_fcs_fcxp_alloc(port->fcs);
+       if (!fcxp)
+               return;
+
+       len = fc_prli_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), rx_fchs->s_id,
+                               bfa_fcs_port_get_fcid(port), rx_fchs->ox_id,
+                               port->port_cfg.roles);
+
+       bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
+                     FC_CLASS_3, len, &fchs, NULL, NULL, FC_MAX_PDUSZ, 0);
+}
+
+static void
+bfa_fcs_rport_process_rpsc(struct bfa_fcs_rport_s *rport,
+                       struct fchs_s *rx_fchs, u16 len)
+{
+       struct bfa_fcxp_s *fcxp;
+       struct fchs_s          fchs;
+       struct bfa_fcs_port_s *port = rport->port;
+       struct fc_rpsc_speed_info_s speeds;
+       struct bfa_pport_attr_s pport_attr;
+
+       bfa_trc(port->fcs, rx_fchs->s_id);
+       bfa_trc(port->fcs, rx_fchs->d_id);
+
+       rport->stats.rpsc_rcvd++;
+       speeds.port_speed_cap =
+               RPSC_SPEED_CAP_1G | RPSC_SPEED_CAP_2G | RPSC_SPEED_CAP_4G |
+               RPSC_SPEED_CAP_8G;
+
+       /*
+        * get curent speed from pport attributes from BFA
+        */
+       bfa_pport_get_attr(port->fcs->bfa, &pport_attr);
+
+       speeds.port_op_speed = fc_bfa_speed_to_rpsc_operspeed(pport_attr.speed);
+
+       fcxp = bfa_fcs_fcxp_alloc(port->fcs);
+       if (!fcxp)
+               return;
+
+       len = fc_rpsc_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), rx_fchs->s_id,
+                               bfa_fcs_port_get_fcid(port), rx_fchs->ox_id,
+                               &speeds);
+
+       bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
+                     FC_CLASS_3, len, &fchs, NULL, NULL, FC_MAX_PDUSZ, 0);
+}
+
+static void
+bfa_fcs_rport_process_adisc(struct bfa_fcs_rport_s *rport,
+                       struct fchs_s *rx_fchs, u16 len)
+{
+       struct bfa_fcxp_s *fcxp;
+       struct fchs_s          fchs;
+       struct bfa_fcs_port_s *port = rport->port;
+       struct fc_adisc_s      *adisc;
+
+       bfa_trc(port->fcs, rx_fchs->s_id);
+       bfa_trc(port->fcs, rx_fchs->d_id);
+
+       rport->stats.adisc_rcvd++;
+
+       if (BFA_FCS_VPORT_IS_TARGET_MODE(port)) {
+               /*
+                * @todo : Target Mode handling
+                */
+               bfa_trc(port->fcs, rx_fchs->d_id);
+               bfa_assert(0);
+               return;
+       }
+
+       adisc = (struct fc_adisc_s *) (rx_fchs + 1);
+
+       /*
+        * Accept if the itnim for this rport is online. Else reject the ADISC
+        */
+       if (bfa_fcs_itnim_get_online_state(rport->itnim) == BFA_STATUS_OK) {
+
+               fcxp = bfa_fcs_fcxp_alloc(port->fcs);
+               if (!fcxp)
+                       return;
+
+               len = fc_adisc_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
+                                        rx_fchs->s_id,
+                                        bfa_fcs_port_get_fcid(port),
+                                        rx_fchs->ox_id, port->port_cfg.pwwn,
+                                        port->port_cfg.nwwn);
+
+               bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag,
+                             BFA_FALSE, FC_CLASS_3, len, &fchs, NULL, NULL,
+                             FC_MAX_PDUSZ, 0);
+       } else {
+               rport->stats.adisc_rejected++;
+               bfa_fcs_rport_send_ls_rjt(rport, rx_fchs,
+                                         FC_LS_RJT_RSN_UNABLE_TO_PERF_CMD,
+                                         FC_LS_RJT_EXP_LOGIN_REQUIRED);
+       }
+
+}
+
+static void
+bfa_fcs_rport_hal_online(struct bfa_fcs_rport_s *rport)
+{
+       struct bfa_fcs_port_s *port = rport->port;
+       struct bfa_rport_info_s rport_info;
+
+       rport_info.pid = rport->pid;
+       rport_info.local_pid = port->pid;
+       rport_info.lp_tag = port->lp_tag;
+       rport_info.vf_id = port->fabric->vf_id;
+       rport_info.vf_en = port->fabric->is_vf;
+       rport_info.fc_class = rport->fc_cos;
+       rport_info.cisc = rport->cisc;
+       rport_info.max_frmsz = rport->maxfrsize;
+       bfa_rport_online(rport->bfa_rport, &rport_info);
+}
+
+static void
+bfa_fcs_rport_fc4_pause(struct bfa_fcs_rport_s *rport)
+{
+       if (bfa_fcs_port_is_initiator(rport->port))
+               bfa_fcs_itnim_pause(rport->itnim);
+
+       if (bfa_fcs_port_is_target(rport->port))
+               bfa_fcs_tin_pause(rport->tin);
+}
+
+static void
+bfa_fcs_rport_fc4_resume(struct bfa_fcs_rport_s *rport)
+{
+       if (bfa_fcs_port_is_initiator(rport->port))
+               bfa_fcs_itnim_resume(rport->itnim);
+
+       if (bfa_fcs_port_is_target(rport->port))
+               bfa_fcs_tin_resume(rport->tin);
+}
+
+static struct bfa_fcs_rport_s *
+bfa_fcs_rport_alloc(struct bfa_fcs_port_s *port, wwn_t pwwn, u32 rpid)
+{
+       struct bfa_fcs_s *fcs = port->fcs;
+       struct bfa_fcs_rport_s *rport;
+       struct bfad_rport_s *rport_drv;
+
+       /**
+        * allocate rport
+        */
+       if (bfa_fcb_rport_alloc(fcs->bfad, &rport, &rport_drv)
+           != BFA_STATUS_OK) {
+               bfa_trc(fcs, rpid);
+               return NULL;
+       }
+
+       /*
+        * Initialize r-port
+        */
+       rport->port = port;
+       rport->fcs = fcs;
+       rport->rp_drv = rport_drv;
+       rport->pid = rpid;
+       rport->pwwn = pwwn;
+
+       /**
+        * allocate BFA rport
+        */
+       rport->bfa_rport = bfa_rport_create(port->fcs->bfa, rport);
+       if (!rport->bfa_rport) {
+               bfa_trc(fcs, rpid);
+               kfree(rport_drv);
+               return NULL;
+       }
+
+       /**
+        * allocate FC-4s
+        */
+       bfa_assert(bfa_fcs_port_is_initiator(port) ^
+                  bfa_fcs_port_is_target(port));
+
+       if (bfa_fcs_port_is_initiator(port)) {
+               rport->itnim = bfa_fcs_itnim_create(rport);
+               if (!rport->itnim) {
+                       bfa_trc(fcs, rpid);
+                       bfa_rport_delete(rport->bfa_rport);
+                       kfree(rport_drv);
+                       return NULL;
+               }
+       }
+
+       if (bfa_fcs_port_is_target(port)) {
+               rport->tin = bfa_fcs_tin_create(rport);
+               if (!rport->tin) {
+                       bfa_trc(fcs, rpid);
+                       bfa_rport_delete(rport->bfa_rport);
+                       kfree(rport_drv);
+                       return NULL;
+               }
+       }
+
+       bfa_fcs_port_add_rport(port, rport);
+
+       bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit);
+
+       /*
+        * Initialize the Rport Features(RPF) Sub Module
+        */
+       if (!BFA_FCS_PID_IS_WKA(rport->pid))
+               bfa_fcs_rpf_init(rport);
+
+       return rport;
+}
+
+
+static void
+bfa_fcs_rport_free(struct bfa_fcs_rport_s *rport)
+{
+       struct bfa_fcs_port_s *port = rport->port;
+
+       /**
+        * - delete FC-4s
+        * - delete BFA rport
+        * - remove from queue of rports
+        */
+       if (bfa_fcs_port_is_initiator(port))
+               bfa_fcs_itnim_delete(rport->itnim);
+
+       if (bfa_fcs_port_is_target(port))
+               bfa_fcs_tin_delete(rport->tin);
+
+       bfa_rport_delete(rport->bfa_rport);
+       bfa_fcs_port_del_rport(port, rport);
+       kfree(rport->rp_drv);
+}
+
+static void
+bfa_fcs_rport_aen_post(struct bfa_fcs_rport_s *rport,
+                      enum bfa_rport_aen_event event,
+                      struct bfa_rport_aen_data_s *data)
+{
+       union bfa_aen_data_u aen_data;
+       struct bfa_log_mod_s *logmod = rport->fcs->logm;
+       wwn_t           lpwwn = bfa_fcs_port_get_pwwn(rport->port);
+       wwn_t           rpwwn = rport->pwwn;
+       char            lpwwn_ptr[BFA_STRING_32];
+       char            rpwwn_ptr[BFA_STRING_32];
+       char           *prio_str[] = { "unknown", "high", "medium", "low" };
+
+       wwn2str(lpwwn_ptr, lpwwn);
+       wwn2str(rpwwn_ptr, rpwwn);
+
+       switch (event) {
+       case BFA_RPORT_AEN_ONLINE:
+               bfa_log(logmod, BFA_AEN_RPORT_ONLINE, rpwwn_ptr, lpwwn_ptr);
+               break;
+       case BFA_RPORT_AEN_OFFLINE:
+               bfa_log(logmod, BFA_AEN_RPORT_OFFLINE, rpwwn_ptr, lpwwn_ptr);
+               break;
+       case BFA_RPORT_AEN_DISCONNECT:
+               bfa_log(logmod, BFA_AEN_RPORT_DISCONNECT, rpwwn_ptr, lpwwn_ptr);
+               break;
+       case BFA_RPORT_AEN_QOS_PRIO:
+               aen_data.rport.priv.qos = data->priv.qos;
+               bfa_log(logmod, BFA_AEN_RPORT_QOS_PRIO,
+                       prio_str[aen_data.rport.priv.qos.qos_priority],
+                       rpwwn_ptr, lpwwn_ptr);
+               break;
+       case BFA_RPORT_AEN_QOS_FLOWID:
+               aen_data.rport.priv.qos = data->priv.qos;
+               bfa_log(logmod, BFA_AEN_RPORT_QOS_FLOWID,
+                       aen_data.rport.priv.qos.qos_flow_id, rpwwn_ptr,
+                       lpwwn_ptr);
+               break;
+       default:
+               break;
+       }
+
+       aen_data.rport.vf_id = rport->port->fabric->vf_id;
+       aen_data.rport.ppwwn =
+               bfa_fcs_port_get_pwwn(bfa_fcs_get_base_port(rport->fcs));
+       aen_data.rport.lpwwn = lpwwn;
+       aen_data.rport.rpwwn = rpwwn;
+}
+
+static void
+bfa_fcs_rport_online_action(struct bfa_fcs_rport_s *rport)
+{
+       struct bfa_fcs_port_s *port = rport->port;
+
+       rport->stats.onlines++;
+
+       if (bfa_fcs_port_is_initiator(port)) {
+               bfa_fcs_itnim_rport_online(rport->itnim);
+               if (!BFA_FCS_PID_IS_WKA(rport->pid))
+                       bfa_fcs_rpf_rport_online(rport);
+       };
+
+       if (bfa_fcs_port_is_target(port))
+               bfa_fcs_tin_rport_online(rport->tin);
+
+       /*
+        * Don't post events for well known addresses
+        */
+       if (!BFA_FCS_PID_IS_WKA(rport->pid))
+               bfa_fcs_rport_aen_post(rport, BFA_RPORT_AEN_ONLINE, NULL);
+}
+
+static void
+bfa_fcs_rport_offline_action(struct bfa_fcs_rport_s *rport)
+{
+       struct bfa_fcs_port_s *port = rport->port;
+
+       rport->stats.offlines++;
+
+       /*
+        * Don't post events for well known addresses
+        */
+       if (!BFA_FCS_PID_IS_WKA(rport->pid)) {
+               if (bfa_fcs_port_is_online(rport->port) == BFA_TRUE) {
+                       bfa_fcs_rport_aen_post(rport, BFA_RPORT_AEN_DISCONNECT,
+                                              NULL);
+               } else {
+                       bfa_fcs_rport_aen_post(rport, BFA_RPORT_AEN_OFFLINE,
+                                              NULL);
+               }
+       }
+
+       if (bfa_fcs_port_is_initiator(port)) {
+               bfa_fcs_itnim_rport_offline(rport->itnim);
+               if (!BFA_FCS_PID_IS_WKA(rport->pid))
+                       bfa_fcs_rpf_rport_offline(rport);
+       }
+
+       if (bfa_fcs_port_is_target(port))
+               bfa_fcs_tin_rport_offline(rport->tin);
+}
+
+/**
+ * Update rport parameters from PLOGI or PLOGI accept.
+ */
+static void
+bfa_fcs_rport_update(struct bfa_fcs_rport_s *rport, struct fc_logi_s *plogi)
+{
+       struct bfa_fcs_port_s *port = rport->port;
+
+       /**
+        * - port name
+        * - node name
+        */
+       rport->pwwn = plogi->port_name;
+       rport->nwwn = plogi->node_name;
+
+       /**
+        * - class of service
+        */
+       rport->fc_cos = 0;
+       if (plogi->class3.class_valid)
+               rport->fc_cos = FC_CLASS_3;
+
+       if (plogi->class2.class_valid)
+               rport->fc_cos |= FC_CLASS_2;
+
+       /**
+        * - CISC
+        * - MAX receive frame size
+        */
+       rport->cisc = plogi->csp.cisc;
+       rport->maxfrsize = bfa_os_ntohs(plogi->class3.rxsz);
+
+       bfa_trc(port->fcs, bfa_os_ntohs(plogi->csp.bbcred));
+       bfa_trc(port->fcs, port->fabric->bb_credit);
+       /**
+        * Direct Attach P2P mode :
+        * This is to handle a bug (233476) in IBM targets in Direct Attach
+        * Mode. Basically, in FLOGI Accept the target would have erroneously
+        * set the BB Credit to the value used in the FLOGI sent by the HBA.
+        * It uses the correct value (its own BB credit) in PLOGI.
+        */
+       if ((!bfa_fcs_fabric_is_switched(port->fabric))
+           && (bfa_os_ntohs(plogi->csp.bbcred) < port->fabric->bb_credit)) {
+
+               bfa_trc(port->fcs, bfa_os_ntohs(plogi->csp.bbcred));
+               bfa_trc(port->fcs, port->fabric->bb_credit);
+
+               port->fabric->bb_credit = bfa_os_ntohs(plogi->csp.bbcred);
+               bfa_pport_set_tx_bbcredit(port->fcs->bfa,
+                                         port->fabric->bb_credit);
+       }
+
+}
+
+/**
+ *   Called to handle LOGO received from an existing remote port.
+ */
+static void
+bfa_fcs_rport_process_logo(struct bfa_fcs_rport_s *rport, struct fchs_s *fchs)
+{
+       rport->reply_oxid = fchs->ox_id;
+       bfa_trc(rport->fcs, rport->reply_oxid);
+
+       rport->stats.logo_rcvd++;
+       bfa_sm_send_event(rport, RPSM_EVENT_LOGO_RCVD);
+}
+
+
+
+/**
+ *  fcs_rport_public FCS rport public interfaces
+ */
+
+/**
+ *     Called by bport/vport to create a remote port instance for a discovered
+ *     remote device.
+ *
+ * @param[in] port     - base port or vport
+ * @param[in] rpid     - remote port ID
+ *
+ * @return None
+ */
+struct bfa_fcs_rport_s *
+bfa_fcs_rport_create(struct bfa_fcs_port_s *port, u32 rpid)
+{
+       struct bfa_fcs_rport_s *rport;
+
+       bfa_trc(port->fcs, rpid);
+       rport = bfa_fcs_rport_alloc(port, WWN_NULL, rpid);
+       if (!rport)
+               return NULL;
+
+       bfa_sm_send_event(rport, RPSM_EVENT_PLOGI_SEND);
+       return rport;
+}
+
+/**
+ * Called to create a rport for which only the wwn is known.
+ *
+ * @param[in] port     - base port
+ * @param[in] rpwwn    - remote port wwn
+ *
+ * @return None
+ */
+struct bfa_fcs_rport_s *
+bfa_fcs_rport_create_by_wwn(struct bfa_fcs_port_s *port, wwn_t rpwwn)
+{
+       struct bfa_fcs_rport_s *rport;
+
+       bfa_trc(port->fcs, rpwwn);
+       rport = bfa_fcs_rport_alloc(port, rpwwn, 0);
+       if (!rport)
+               return NULL;
+
+       bfa_sm_send_event(rport, RPSM_EVENT_ADDRESS_DISC);
+       return rport;
+}
+
+/**
+ * Called by bport in private loop topology to indicate that a
+ * rport has been discovered and plogi has been completed.
+ *
+ * @param[in] port     - base port or vport
+ * @param[in] rpid     - remote port ID
+ */
+void
+bfa_fcs_rport_start(struct bfa_fcs_port_s *port, struct fchs_s *fchs,
+                       struct fc_logi_s *plogi)
+{
+       struct bfa_fcs_rport_s *rport;
+
+       rport = bfa_fcs_rport_alloc(port, WWN_NULL, fchs->s_id);
+       if (!rport)
+               return;
+
+       bfa_fcs_rport_update(rport, plogi);
+
+       bfa_sm_send_event(rport, RPSM_EVENT_PLOGI_COMP);
+}
+
+/**
+ *   Called by bport/vport to handle PLOGI received from a new remote port.
+ *   If an existing rport does a plogi, it will be handled separately.
+ */
+void
+bfa_fcs_rport_plogi_create(struct bfa_fcs_port_s *port, struct fchs_s *fchs,
+                          struct fc_logi_s *plogi)
+{
+       struct bfa_fcs_rport_s *rport;
+
+       rport = bfa_fcs_rport_alloc(port, plogi->port_name, fchs->s_id);
+       if (!rport)
+               return;
+
+       bfa_fcs_rport_update(rport, plogi);
+
+       rport->reply_oxid = fchs->ox_id;
+       bfa_trc(rport->fcs, rport->reply_oxid);
+
+       rport->stats.plogi_rcvd++;
+       bfa_sm_send_event(rport, RPSM_EVENT_PLOGI_RCVD);
+}
+
+static int
+wwn_compare(wwn_t wwn1, wwn_t wwn2)
+{
+       u8        *b1 = (u8 *) &wwn1;
+       u8        *b2 = (u8 *) &wwn2;
+       int             i;
+
+       for (i = 0; i < sizeof(wwn_t); i++) {
+               if (b1[i] < b2[i])
+                       return -1;
+               if (b1[i] > b2[i])
+                       return 1;
+       }
+       return 0;
+}
+
+/**
+ *   Called by bport/vport to handle PLOGI received from an existing
+ *      remote port.
+ */
+void
+bfa_fcs_rport_plogi(struct bfa_fcs_rport_s *rport, struct fchs_s *rx_fchs,
+                   struct fc_logi_s *plogi)
+{
+       /**
+        * @todo Handle P2P and initiator-initiator.
+        */
+
+       bfa_fcs_rport_update(rport, plogi);
+
+       rport->reply_oxid = rx_fchs->ox_id;
+       bfa_trc(rport->fcs, rport->reply_oxid);
+
+       /**
+        * In Switched fabric topology,
+        * PLOGI to each other. If our pwwn is smaller, ignore it,
+        * if it is not a well known address.
+        * If the link topology is N2N,
+        * this Plogi should be accepted.
+        */
+       if ((wwn_compare(rport->port->port_cfg.pwwn, rport->pwwn) == -1)
+           && (bfa_fcs_fabric_is_switched(rport->port->fabric))
+           && (!BFA_FCS_PID_IS_WKA(rport->pid))) {
+               bfa_trc(rport->fcs, rport->pid);
+               return;
+       }
+
+       rport->stats.plogi_rcvd++;
+       bfa_sm_send_event(rport, RPSM_EVENT_PLOGI_RCVD);
+}
+
+/**
+ * Called by bport/vport to delete a remote port instance.
+ *
+* Rport delete is called under the following conditions:
+ *             - vport is deleted
+ *             - vf is deleted
+ *             - explicit request from OS to delete rport (vmware)
+ */
+void
+bfa_fcs_rport_delete(struct bfa_fcs_rport_s *rport)
+{
+       bfa_sm_send_event(rport, RPSM_EVENT_DELETE);
+}
+
+/**
+ * Called by bport/vport to  when a target goes offline.
+ *
+ */
+void
+bfa_fcs_rport_offline(struct bfa_fcs_rport_s *rport)
+{
+       bfa_sm_send_event(rport, RPSM_EVENT_LOGO_IMP);
+}
+
+/**
+ * Called by bport in n2n when a target (attached port) becomes online.
+ *
+ */
+void
+bfa_fcs_rport_online(struct bfa_fcs_rport_s *rport)
+{
+       bfa_sm_send_event(rport, RPSM_EVENT_PLOGI_SEND);
+}
+
+/**
+ *   Called by bport/vport to notify SCN for the remote port
+ */
+void
+bfa_fcs_rport_scn(struct bfa_fcs_rport_s *rport)
+{
+
+       rport->stats.rscns++;
+       bfa_sm_send_event(rport, RPSM_EVENT_SCN);
+}
+
+/**
+ *   Called by  fcpim to notify that the ITN cleanup is done.
+ */
+void
+bfa_fcs_rport_itnim_ack(struct bfa_fcs_rport_s *rport)
+{
+       bfa_sm_send_event(rport, RPSM_EVENT_FC4_OFFLINE);
+}
+
+/**
+ *   Called by fcptm to notify that the ITN cleanup is done.
+ */
+void
+bfa_fcs_rport_tin_ack(struct bfa_fcs_rport_s *rport)
+{
+       bfa_sm_send_event(rport, RPSM_EVENT_FC4_OFFLINE);
+}
+
+/**
+ *     This routine BFA callback for bfa_rport_online() call.
+ *
+ *     param[in]       cb_arg  -  rport struct.
+ *
+ *     return
+ *             void
+ *
+*      Special Considerations:
+ *
+ *     note
+ */
+void
+bfa_cb_rport_online(void *cbarg)
+{
+
+       struct bfa_fcs_rport_s *rport = (struct bfa_fcs_rport_s *)cbarg;
+
+       bfa_trc(rport->fcs, rport->pwwn);
+       bfa_sm_send_event(rport, RPSM_EVENT_HCB_ONLINE);
+}
+
+/**
+ *     This routine BFA callback for bfa_rport_offline() call.
+ *
+ *     param[in]       rport   -
+ *
+ *     return
+ *             void
+ *
+ *     Special Considerations:
+ *
+ *     note
+ */
+void
+bfa_cb_rport_offline(void *cbarg)
+{
+       struct bfa_fcs_rport_s *rport = (struct bfa_fcs_rport_s *)cbarg;
+
+       bfa_trc(rport->fcs, rport->pwwn);
+       bfa_sm_send_event(rport, RPSM_EVENT_HCB_OFFLINE);
+}
+
+/**
+ * This routine is a static BFA callback when there is a QoS flow_id
+ * change notification
+ *
+ * @param[in]  rport   -
+ *
+ * @return     void
+ *
+ * Special Considerations:
+ *
+ * @note
+ */
+void
+bfa_cb_rport_qos_scn_flowid(void *cbarg,
+                           struct bfa_rport_qos_attr_s old_qos_attr,
+                           struct bfa_rport_qos_attr_s new_qos_attr)
+{
+       struct bfa_fcs_rport_s *rport = (struct bfa_fcs_rport_s *)cbarg;
+       struct bfa_rport_aen_data_s aen_data;
+
+       bfa_trc(rport->fcs, rport->pwwn);
+       aen_data.priv.qos = new_qos_attr;
+       bfa_fcs_rport_aen_post(rport, BFA_RPORT_AEN_QOS_FLOWID, &aen_data);
+}
+
+/**
+ * This routine is a static BFA callback when there is a QoS priority
+ * change notification
+ *
+ * @param[in]  rport   -
+ *
+ * @return     void
+ *
+ * Special Considerations:
+ *
+ * @note
+ */
+void
+bfa_cb_rport_qos_scn_prio(void *cbarg, struct bfa_rport_qos_attr_s old_qos_attr,
+                         struct bfa_rport_qos_attr_s new_qos_attr)
+{
+       struct bfa_fcs_rport_s *rport = (struct bfa_fcs_rport_s *)cbarg;
+       struct bfa_rport_aen_data_s aen_data;
+
+       bfa_trc(rport->fcs, rport->pwwn);
+       aen_data.priv.qos = new_qos_attr;
+       bfa_fcs_rport_aen_post(rport, BFA_RPORT_AEN_QOS_PRIO, &aen_data);
+}
+
+/**
+ *             Called to process any unsolicted frames from this remote port
+ */
+void
+bfa_fcs_rport_logo_imp(struct bfa_fcs_rport_s *rport)
+{
+       bfa_sm_send_event(rport, RPSM_EVENT_LOGO_IMP);
+}
+
+/**
+ *             Called to process any unsolicted frames from this remote port
+ */
+void
+bfa_fcs_rport_uf_recv(struct bfa_fcs_rport_s *rport, struct fchs_s *fchs,
+                       u16 len)
+{
+       struct bfa_fcs_port_s *port = rport->port;
+       struct fc_els_cmd_s   *els_cmd;
+
+       bfa_trc(rport->fcs, fchs->s_id);
+       bfa_trc(rport->fcs, fchs->d_id);
+       bfa_trc(rport->fcs, fchs->type);
+
+       if (fchs->type != FC_TYPE_ELS)
+               return;
+
+       els_cmd = (struct fc_els_cmd_s *) (fchs + 1);
+
+       bfa_trc(rport->fcs, els_cmd->els_code);
+
+       switch (els_cmd->els_code) {
+       case FC_ELS_LOGO:
+               bfa_fcs_rport_process_logo(rport, fchs);
+               break;
+
+       case FC_ELS_ADISC:
+               bfa_fcs_rport_process_adisc(rport, fchs, len);
+               break;
+
+       case FC_ELS_PRLO:
+               if (bfa_fcs_port_is_initiator(port))
+                       bfa_fcs_fcpim_uf_recv(rport->itnim, fchs, len);
+
+               if (bfa_fcs_port_is_target(port))
+                       bfa_fcs_fcptm_uf_recv(rport->tin, fchs, len);
+               break;
+
+       case FC_ELS_PRLI:
+               bfa_fcs_rport_process_prli(rport, fchs, len);
+               break;
+
+       case FC_ELS_RPSC:
+               bfa_fcs_rport_process_rpsc(rport, fchs, len);
+               break;
+
+       default:
+               bfa_fcs_rport_send_ls_rjt(rport, fchs,
+                                         FC_LS_RJT_RSN_CMD_NOT_SUPP,
+                                         FC_LS_RJT_EXP_NO_ADDL_INFO);
+               break;
+       }
+}
+
+/*
+ * Send a LS reject
+ */
+static void
+bfa_fcs_rport_send_ls_rjt(struct bfa_fcs_rport_s *rport, struct fchs_s *rx_fchs,
+                         u8 reason_code, u8 reason_code_expl)
+{
+       struct bfa_fcs_port_s *port = rport->port;
+       struct fchs_s          fchs;
+       struct bfa_fcxp_s *fcxp;
+       int             len;
+
+       bfa_trc(rport->fcs, rx_fchs->s_id);
+
+       fcxp = bfa_fcs_fcxp_alloc(rport->fcs);
+       if (!fcxp)
+               return;
+
+       len = fc_ls_rjt_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), rx_fchs->s_id,
+                             bfa_fcs_port_get_fcid(port), rx_fchs->ox_id,
+                             reason_code, reason_code_expl);
+
+       bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
+                     FC_CLASS_3, len, &fchs, NULL, NULL, FC_MAX_PDUSZ, 0);
+}
+
+/**
+ *   Module initialization
+ */
+void
+bfa_fcs_rport_modinit(struct bfa_fcs_s *fcs)
+{
+}
+
+/**
+ *   Module cleanup
+ */
+void
+bfa_fcs_rport_modexit(struct bfa_fcs_s *fcs)
+{
+       bfa_fcs_modexit_comp(fcs);
+}
+
+/**
+ * Return state of rport.
+ */
+int
+bfa_fcs_rport_get_state(struct bfa_fcs_rport_s *rport)
+{
+       return bfa_sm_to_state(rport_sm_table, rport->sm);
+}
+
+/**
+ *              Called by the Driver to set rport delete/ageout timeout
+ *
+ *     param[in]               rport timeout value in seconds.
+ *
+ *     return None
+ */
+void
+bfa_fcs_rport_set_del_timeout(u8 rport_tmo)
+{
+       /*
+        * convert to Millisecs
+        */
+       if (rport_tmo > 0)
+               bfa_fcs_rport_del_timeout = rport_tmo * 1000;
+}
diff --git a/drivers/scsi/bfa/rport_api.c b/drivers/scsi/bfa/rport_api.c
new file mode 100644 (file)
index 0000000..3dae177
--- /dev/null
@@ -0,0 +1,180 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ */
+#include <bfa.h>
+#include <bfa_svc.h>
+#include "fcs_vport.h"
+#include "fcs_lport.h"
+#include "fcs_rport.h"
+#include "fcs_trcmod.h"
+
+BFA_TRC_FILE(FCS, RPORT_API);
+
+/**
+ *  rport_api.c Remote port implementation.
+ */
+
+/**
+ *  fcs_rport_api FCS rport API.
+ */
+
+/**
+ *     Direct API to add a target by port wwn. This interface is used, for
+ *     example, by bios when target pwwn is known from boot lun configuration.
+ */
+bfa_status_t
+bfa_fcs_rport_add(struct bfa_fcs_port_s *port, wwn_t *pwwn,
+                       struct bfa_fcs_rport_s *rport,
+                       struct bfad_rport_s *rport_drv)
+{
+       bfa_trc(port->fcs, *pwwn);
+
+       return BFA_STATUS_OK;
+}
+
+/**
+ *     Direct API to remove a target and its associated resources. This
+ *     interface is used, for example, by vmware driver to remove target
+ *     ports from the target list for a VM.
+ */
+bfa_status_t
+bfa_fcs_rport_remove(struct bfa_fcs_rport_s *rport_in)
+{
+
+       struct bfa_fcs_rport_s *rport;
+
+       bfa_trc(rport_in->fcs, rport_in->pwwn);
+
+       rport = bfa_fcs_port_get_rport_by_pwwn(rport_in->port, rport_in->pwwn);
+       if (rport == NULL) {
+               /*
+                * TBD Error handling
+                */
+               bfa_trc(rport_in->fcs, rport_in->pid);
+               return BFA_STATUS_UNKNOWN_RWWN;
+       }
+
+       /*
+        * TBD if this remote port is online, send a logo
+        */
+       return BFA_STATUS_OK;
+
+}
+
+/**
+ *     Remote device status for display/debug.
+ */
+void
+bfa_fcs_rport_get_attr(struct bfa_fcs_rport_s *rport,
+                       struct bfa_rport_attr_s *rport_attr)
+{
+       struct bfa_rport_qos_attr_s qos_attr;
+       struct bfa_fcs_port_s *port = rport->port;
+
+       bfa_os_memset(rport_attr, 0, sizeof(struct bfa_rport_attr_s));
+
+       rport_attr->pid = rport->pid;
+       rport_attr->pwwn = rport->pwwn;
+       rport_attr->nwwn = rport->nwwn;
+       rport_attr->cos_supported = rport->fc_cos;
+       rport_attr->df_sz = rport->maxfrsize;
+       rport_attr->state = bfa_fcs_rport_get_state(rport);
+       rport_attr->fc_cos = rport->fc_cos;
+       rport_attr->cisc = rport->cisc;
+       rport_attr->scsi_function = rport->scsi_function;
+       rport_attr->curr_speed  = rport->rpf.rpsc_speed;
+       rport_attr->assigned_speed  = rport->rpf.assigned_speed;
+
+       bfa_rport_get_qos_attr(rport->bfa_rport, &qos_attr);
+       rport_attr->qos_attr = qos_attr;
+
+       rport_attr->trl_enforced = BFA_FALSE;
+       if (bfa_pport_is_ratelim(port->fcs->bfa)) {
+               if ((rport->rpf.rpsc_speed == BFA_PPORT_SPEED_UNKNOWN) ||
+                       (rport->rpf.rpsc_speed <
+                       bfa_fcs_port_get_rport_max_speed(port)))
+                       rport_attr->trl_enforced = BFA_TRUE;
+       }
+
+       /*
+        * TODO
+        * rport->symname
+        */
+}
+
+/**
+ *     Per remote device statistics.
+ */
+void
+bfa_fcs_rport_get_stats(struct bfa_fcs_rport_s *rport,
+                       struct bfa_rport_stats_s *stats)
+{
+       *stats = rport->stats;
+}
+
+void
+bfa_fcs_rport_clear_stats(struct bfa_fcs_rport_s *rport)
+{
+       bfa_os_memset((char *)&rport->stats, 0,
+                       sizeof(struct bfa_rport_stats_s));
+}
+
+struct bfa_fcs_rport_s *
+bfa_fcs_rport_lookup(struct bfa_fcs_port_s *port, wwn_t rpwwn)
+{
+       struct bfa_fcs_rport_s *rport;
+
+       rport = bfa_fcs_port_get_rport_by_pwwn(port, rpwwn);
+       if (rport == NULL) {
+               /*
+                * TBD Error handling
+                */
+       }
+
+       return rport;
+}
+
+struct bfa_fcs_rport_s *
+bfa_fcs_rport_lookup_by_nwwn(struct bfa_fcs_port_s *port, wwn_t rnwwn)
+{
+       struct bfa_fcs_rport_s *rport;
+
+       rport = bfa_fcs_port_get_rport_by_nwwn(port, rnwwn);
+       if (rport == NULL) {
+               /*
+                * TBD Error handling
+                */
+       }
+
+       return rport;
+}
+
+/*
+ * This API is to set the Rport's speed. Should be used when RPSC is not
+ * supported by the rport.
+ */
+void
+bfa_fcs_rport_set_speed(struct bfa_fcs_rport_s *rport,
+                       enum bfa_pport_speed speed)
+{
+       rport->rpf.assigned_speed  = speed;
+
+       /* Set this speed in f/w only if the RPSC speed is not available */
+       if (rport->rpf.rpsc_speed == BFA_PPORT_SPEED_UNKNOWN)
+               bfa_rport_speed(rport->bfa_rport, speed);
+}
+
+
diff --git a/drivers/scsi/bfa/rport_ftrs.c b/drivers/scsi/bfa/rport_ftrs.c
new file mode 100644 (file)
index 0000000..8a1f59d
--- /dev/null
@@ -0,0 +1,375 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) 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.
+ */
+
+/**
+ *  rport_ftrs.c Remote port features (RPF) implementation.
+ */
+
+#include <bfa.h>
+#include <bfa_svc.h>
+#include "fcbuild.h"
+#include "fcs_rport.h"
+#include "fcs_lport.h"
+#include "fcs_trcmod.h"
+#include "fcs_fcxp.h"
+#include "fcs.h"
+
+BFA_TRC_FILE(FCS, RPORT_FTRS);
+
+#define BFA_FCS_RPF_RETRIES    (3)
+#define BFA_FCS_RPF_RETRY_TIMEOUT  (1000) /* 1 sec (In millisecs) */
+
+static void     bfa_fcs_rpf_send_rpsc2(void *rport_cbarg,
+                       struct bfa_fcxp_s *fcxp_alloced);
+static void     bfa_fcs_rpf_rpsc2_response(void *fcsarg,
+                       struct bfa_fcxp_s *fcxp, void *cbarg,
+                       bfa_status_t req_status, u32 rsp_len,
+                       u32 resid_len,
+                       struct fchs_s *rsp_fchs);
+static void     bfa_fcs_rpf_timeout(void *arg);
+
+/**
+ *  fcs_rport_ftrs_sm FCS rport state machine events
+ */
+
+enum rpf_event {
+       RPFSM_EVENT_RPORT_OFFLINE  = 1,     /*  Rport offline            */
+       RPFSM_EVENT_RPORT_ONLINE   = 2,     /*  Rport online            */
+       RPFSM_EVENT_FCXP_SENT      = 3,    /*  Frame from has been sent */
+       RPFSM_EVENT_TIMEOUT        = 4,    /*  Rport SM timeout event   */
+       RPFSM_EVENT_RPSC_COMP      = 5,
+       RPFSM_EVENT_RPSC_FAIL      = 6,
+       RPFSM_EVENT_RPSC_ERROR     = 7,
+};
+
+static void    bfa_fcs_rpf_sm_uninit(struct bfa_fcs_rpf_s *rpf,
+                                       enum rpf_event event);
+static void     bfa_fcs_rpf_sm_rpsc_sending(struct bfa_fcs_rpf_s *rpf,
+                                              enum rpf_event event);
+static void     bfa_fcs_rpf_sm_rpsc(struct bfa_fcs_rpf_s *rpf,
+                                              enum rpf_event event);
+static void    bfa_fcs_rpf_sm_rpsc_retry(struct bfa_fcs_rpf_s *rpf,
+                                                       enum rpf_event event);
+static void     bfa_fcs_rpf_sm_offline(struct bfa_fcs_rpf_s *rpf,
+                                                       enum rpf_event event);
+static void     bfa_fcs_rpf_sm_online(struct bfa_fcs_rpf_s *rpf,
+                                                       enum rpf_event event);
+
+static void
+bfa_fcs_rpf_sm_uninit(struct bfa_fcs_rpf_s *rpf, enum rpf_event event)
+{
+       struct bfa_fcs_rport_s *rport = rpf->rport;
+
+       bfa_trc(rport->fcs, rport->pwwn);
+       bfa_trc(rport->fcs, rport->pid);
+       bfa_trc(rport->fcs, event);
+
+       switch (event) {
+       case RPFSM_EVENT_RPORT_ONLINE :
+               if (!BFA_FCS_PID_IS_WKA(rport->pid)) {
+                       bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_rpsc_sending);
+                       rpf->rpsc_retries = 0;
+                       bfa_fcs_rpf_send_rpsc2(rpf, NULL);
+                       break;
+               };
+
+       case RPFSM_EVENT_RPORT_OFFLINE :
+               break;
+
+       default:
+               bfa_assert(0);
+       }
+}
+
+static void
+bfa_fcs_rpf_sm_rpsc_sending(struct bfa_fcs_rpf_s *rpf, enum rpf_event event)
+{
+       struct bfa_fcs_rport_s *rport = rpf->rport;
+
+       bfa_trc(rport->fcs, event);
+
+       switch (event) {
+       case RPFSM_EVENT_FCXP_SENT:
+               bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_rpsc);
+               break;
+
+       case RPFSM_EVENT_RPORT_OFFLINE :
+               bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_offline);
+               bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rpf->fcxp_wqe);
+               rpf->rpsc_retries = 0;
+               break;
+
+       default:
+               bfa_assert(0);
+       }
+}
+
+static void
+bfa_fcs_rpf_sm_rpsc(struct bfa_fcs_rpf_s *rpf, enum rpf_event event)
+{
+       struct bfa_fcs_rport_s *rport = rpf->rport;
+
+       bfa_trc(rport->fcs, rport->pid);
+       bfa_trc(rport->fcs, event);
+
+       switch (event) {
+       case RPFSM_EVENT_RPSC_COMP:
+               bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_online);
+               /* Update speed info in f/w via BFA */
+               if (rpf->rpsc_speed != BFA_PPORT_SPEED_UNKNOWN) {
+                       bfa_rport_speed(rport->bfa_rport, rpf->rpsc_speed);
+               } else if (rpf->assigned_speed != BFA_PPORT_SPEED_UNKNOWN) {
+                       bfa_rport_speed(rport->bfa_rport, rpf->assigned_speed);
+               }
+               break;
+
+       case RPFSM_EVENT_RPSC_FAIL:
+               /* RPSC not supported by rport */
+               bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_online);
+               break;
+
+       case RPFSM_EVENT_RPSC_ERROR:
+               /* need to retry...delayed a bit. */
+               if (rpf->rpsc_retries++ < BFA_FCS_RPF_RETRIES) {
+                       bfa_timer_start(rport->fcs->bfa, &rpf->timer,
+                                   bfa_fcs_rpf_timeout, rpf,
+                                   BFA_FCS_RPF_RETRY_TIMEOUT);
+                       bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_rpsc_retry);
+               } else {
+                       bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_online);
+               }
+               break;
+
+       case RPFSM_EVENT_RPORT_OFFLINE :
+               bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_offline);
+               bfa_fcxp_discard(rpf->fcxp);
+               rpf->rpsc_retries = 0;
+               break;
+
+       default:
+               bfa_assert(0);
+       }
+}
+
+static void
+bfa_fcs_rpf_sm_rpsc_retry(struct bfa_fcs_rpf_s *rpf, enum rpf_event event)
+{
+       struct bfa_fcs_rport_s *rport = rpf->rport;
+
+       bfa_trc(rport->fcs, rport->pid);
+       bfa_trc(rport->fcs, event);
+
+       switch (event) {
+       case RPFSM_EVENT_TIMEOUT :
+               /* re-send the RPSC */
+               bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_rpsc_sending);
+               bfa_fcs_rpf_send_rpsc2(rpf, NULL);
+               break;
+
+       case RPFSM_EVENT_RPORT_OFFLINE :
+               bfa_timer_stop(&rpf->timer);
+               bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_offline);
+               rpf->rpsc_retries = 0;
+               break;
+
+       default:
+               bfa_assert(0);
+       }
+}
+
+static void
+bfa_fcs_rpf_sm_online(struct bfa_fcs_rpf_s *rpf, enum rpf_event event)
+{
+       struct bfa_fcs_rport_s *rport = rpf->rport;
+
+       bfa_trc(rport->fcs, rport->pwwn);
+       bfa_trc(rport->fcs, rport->pid);
+       bfa_trc(rport->fcs, event);
+
+       switch (event) {
+       case RPFSM_EVENT_RPORT_OFFLINE :
+               bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_offline);
+               rpf->rpsc_retries = 0;
+               break;
+
+       default:
+               bfa_assert(0);
+       }
+}
+
+static void
+bfa_fcs_rpf_sm_offline(struct bfa_fcs_rpf_s *rpf, enum rpf_event event)
+{
+       struct bfa_fcs_rport_s *rport = rpf->rport;
+
+       bfa_trc(rport->fcs, rport->pwwn);
+       bfa_trc(rport->fcs, rport->pid);
+       bfa_trc(rport->fcs, event);
+
+       switch (event) {
+       case RPFSM_EVENT_RPORT_ONLINE :
+               bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_rpsc_sending);
+               bfa_fcs_rpf_send_rpsc2(rpf, NULL);
+               break;
+
+       case RPFSM_EVENT_RPORT_OFFLINE :
+               break;
+
+       default:
+               bfa_assert(0);
+       }
+}
+/**
+ * Called when Rport is created.
+ */
+void  bfa_fcs_rpf_init(struct bfa_fcs_rport_s *rport)
+{
+       struct bfa_fcs_rpf_s *rpf = &rport->rpf;
+
+       bfa_trc(rport->fcs, rport->pid);
+       rpf->rport = rport;
+
+       bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_uninit);
+}
+
+/**
+ * Called when Rport becomes online
+ */
+void  bfa_fcs_rpf_rport_online(struct bfa_fcs_rport_s *rport)
+{
+       bfa_trc(rport->fcs, rport->pid);
+
+       if (__fcs_min_cfg(rport->port->fcs))
+               return;
+
+       if (bfa_fcs_fabric_is_switched(rport->port->fabric))
+               bfa_sm_send_event(&rport->rpf, RPFSM_EVENT_RPORT_ONLINE);
+}
+
+/**
+ * Called when Rport becomes offline
+ */
+void  bfa_fcs_rpf_rport_offline(struct bfa_fcs_rport_s *rport)
+{
+       bfa_trc(rport->fcs, rport->pid);
+
+       if (__fcs_min_cfg(rport->port->fcs))
+               return;
+
+       bfa_sm_send_event(&rport->rpf, RPFSM_EVENT_RPORT_OFFLINE);
+}
+
+static void
+bfa_fcs_rpf_timeout(void *arg)
+{
+       struct bfa_fcs_rpf_s *rpf = (struct bfa_fcs_rpf_s *) arg;
+       struct bfa_fcs_rport_s *rport = rpf->rport;
+
+       bfa_trc(rport->fcs, rport->pid);
+       bfa_sm_send_event(rpf, RPFSM_EVENT_TIMEOUT);
+}
+
+static void
+bfa_fcs_rpf_send_rpsc2(void *rpf_cbarg, struct bfa_fcxp_s *fcxp_alloced)
+{
+       struct bfa_fcs_rpf_s *rpf       = (struct bfa_fcs_rpf_s *)rpf_cbarg;
+       struct bfa_fcs_rport_s *rport = rpf->rport;
+       struct bfa_fcs_port_s *port = rport->port;
+       struct fchs_s          fchs;
+       int             len;
+       struct bfa_fcxp_s *fcxp;
+
+       bfa_trc(rport->fcs, rport->pwwn);
+
+       fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
+       if (!fcxp) {
+               bfa_fcxp_alloc_wait(port->fcs->bfa, &rpf->fcxp_wqe,
+                                       bfa_fcs_rpf_send_rpsc2, rpf);
+               return;
+       }
+       rpf->fcxp = fcxp;
+
+       len = fc_rpsc2_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), rport->pid,
+                           bfa_fcs_port_get_fcid(port), &rport->pid, 1);
+
+       bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
+                         FC_CLASS_3, len, &fchs, bfa_fcs_rpf_rpsc2_response,
+                         rpf, FC_MAX_PDUSZ, FC_RA_TOV);
+       rport->stats.rpsc_sent++;
+       bfa_sm_send_event(rpf, RPFSM_EVENT_FCXP_SENT);
+
+}
+
+static void
+bfa_fcs_rpf_rpsc2_response(void *fcsarg, struct bfa_fcxp_s *fcxp, void *cbarg,
+                           bfa_status_t req_status, u32 rsp_len,
+                           u32 resid_len, struct fchs_s *rsp_fchs)
+{
+       struct bfa_fcs_rpf_s *rpf = (struct bfa_fcs_rpf_s *) cbarg;
+       struct bfa_fcs_rport_s *rport = rpf->rport;
+       struct fc_ls_rjt_s    *ls_rjt;
+       struct fc_rpsc2_acc_s  *rpsc2_acc;
+       u16        num_ents;
+
+       bfa_trc(rport->fcs, req_status);
+
+       if (req_status != BFA_STATUS_OK) {
+               bfa_trc(rport->fcs, req_status);
+               if (req_status == BFA_STATUS_ETIMER)
+                       rport->stats.rpsc_failed++;
+               bfa_sm_send_event(rpf, RPFSM_EVENT_RPSC_ERROR);
+               return;
+       }
+
+       rpsc2_acc = (struct fc_rpsc2_acc_s *) BFA_FCXP_RSP_PLD(fcxp);
+       if (rpsc2_acc->els_cmd == FC_ELS_ACC) {
+               rport->stats.rpsc_accs++;
+               num_ents = bfa_os_ntohs(rpsc2_acc->num_pids);
+               bfa_trc(rport->fcs, num_ents);
+               if (num_ents > 0) {
+                       bfa_assert(rpsc2_acc->port_info[0].pid != rport->pid);
+                       bfa_trc(rport->fcs,
+                               bfa_os_ntohs(rpsc2_acc->port_info[0].pid));
+                       bfa_trc(rport->fcs,
+                               bfa_os_ntohs(rpsc2_acc->port_info[0].speed));
+                       bfa_trc(rport->fcs,
+                               bfa_os_ntohs(rpsc2_acc->port_info[0].index));
+                       bfa_trc(rport->fcs,
+                               rpsc2_acc->port_info[0].type);
+
+                       if (rpsc2_acc->port_info[0].speed == 0) {
+                               bfa_sm_send_event(rpf, RPFSM_EVENT_RPSC_ERROR);
+                               return;
+                       }
+
+                       rpf->rpsc_speed = fc_rpsc_operspeed_to_bfa_speed(
+                               bfa_os_ntohs(rpsc2_acc->port_info[0].speed));
+
+                       bfa_sm_send_event(rpf, RPFSM_EVENT_RPSC_COMP);
+               }
+       } else {
+               ls_rjt = (struct fc_ls_rjt_s *) BFA_FCXP_RSP_PLD(fcxp);
+               bfa_trc(rport->fcs, ls_rjt->reason_code);
+               bfa_trc(rport->fcs, ls_rjt->reason_code_expl);
+               rport->stats.rpsc_rejects++;
+               if (ls_rjt->reason_code == FC_LS_RJT_RSN_CMD_NOT_SUPP) {
+                       bfa_sm_send_event(rpf, RPFSM_EVENT_RPSC_FAIL);
+               } else {
+                       bfa_sm_send_event(rpf, RPFSM_EVENT_RPSC_ERROR);
+               }
+       }
+}
diff --git a/drivers/scsi/bfa/scn.c b/drivers/scsi/bfa/scn.c
new file mode 100644 (file)
index 0000000..bd4771f
--- /dev/null
@@ -0,0 +1,482 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ */
+
+#include <bfa.h>
+#include <bfa_svc.h>
+#include "fcs_lport.h"
+#include "fcs_rport.h"
+#include "fcs_ms.h"
+#include "fcs_trcmod.h"
+#include "fcs_fcxp.h"
+#include "fcs.h"
+#include "lport_priv.h"
+
+BFA_TRC_FILE(FCS, SCN);
+
+#define FC_QOS_RSCN_EVENT              0x0c
+#define FC_FABRIC_NAME_RSCN_EVENT      0x0d
+
+/*
+ * forward declarations
+ */
+static void     bfa_fcs_port_scn_send_scr(void *scn_cbarg,
+                                         struct bfa_fcxp_s *fcxp_alloced);
+static void     bfa_fcs_port_scn_scr_response(void *fcsarg,
+                                             struct bfa_fcxp_s *fcxp,
+                                             void *cbarg,
+                                             bfa_status_t req_status,
+                                             u32 rsp_len,
+                                             u32 resid_len,
+                                             struct fchs_s *rsp_fchs);
+static void     bfa_fcs_port_scn_send_ls_acc(struct bfa_fcs_port_s *port,
+                                            struct fchs_s *rx_fchs);
+static void     bfa_fcs_port_scn_timeout(void *arg);
+
+/**
+ *  fcs_scm_sm FCS SCN state machine
+ */
+
+/**
+ * VPort SCN State Machine events
+ */
+enum port_scn_event {
+       SCNSM_EVENT_PORT_ONLINE = 1,
+       SCNSM_EVENT_PORT_OFFLINE = 2,
+       SCNSM_EVENT_RSP_OK = 3,
+       SCNSM_EVENT_RSP_ERROR = 4,
+       SCNSM_EVENT_TIMEOUT = 5,
+       SCNSM_EVENT_SCR_SENT = 6,
+};
+
+static void     bfa_fcs_port_scn_sm_offline(struct bfa_fcs_port_scn_s *scn,
+                                           enum port_scn_event event);
+static void     bfa_fcs_port_scn_sm_sending_scr(struct bfa_fcs_port_scn_s *scn,
+                                               enum port_scn_event event);
+static void     bfa_fcs_port_scn_sm_scr(struct bfa_fcs_port_scn_s *scn,
+                                       enum port_scn_event event);
+static void     bfa_fcs_port_scn_sm_scr_retry(struct bfa_fcs_port_scn_s *scn,
+                                             enum port_scn_event event);
+static void     bfa_fcs_port_scn_sm_online(struct bfa_fcs_port_scn_s *scn,
+                                          enum port_scn_event event);
+
+/**
+ *             Starting state - awaiting link up.
+ */
+static void
+bfa_fcs_port_scn_sm_offline(struct bfa_fcs_port_scn_s *scn,
+                           enum port_scn_event event)
+{
+       switch (event) {
+       case SCNSM_EVENT_PORT_ONLINE:
+               bfa_sm_set_state(scn, bfa_fcs_port_scn_sm_sending_scr);
+               bfa_fcs_port_scn_send_scr(scn, NULL);
+               break;
+
+       case SCNSM_EVENT_PORT_OFFLINE:
+               break;
+
+       default:
+               bfa_assert(0);
+       }
+}
+
+static void
+bfa_fcs_port_scn_sm_sending_scr(struct bfa_fcs_port_scn_s *scn,
+                               enum port_scn_event event)
+{
+       switch (event) {
+       case SCNSM_EVENT_SCR_SENT:
+               bfa_sm_set_state(scn, bfa_fcs_port_scn_sm_scr);
+               break;
+
+       case SCNSM_EVENT_PORT_OFFLINE:
+               bfa_sm_set_state(scn, bfa_fcs_port_scn_sm_offline);
+               bfa_fcxp_walloc_cancel(scn->port->fcs->bfa, &scn->fcxp_wqe);
+               break;
+
+       default:
+               bfa_assert(0);
+       }
+}
+
+static void
+bfa_fcs_port_scn_sm_scr(struct bfa_fcs_port_scn_s *scn,
+                       enum port_scn_event event)
+{
+       struct bfa_fcs_port_s *port = scn->port;
+
+       switch (event) {
+       case SCNSM_EVENT_RSP_OK:
+               bfa_sm_set_state(scn, bfa_fcs_port_scn_sm_online);
+               break;
+
+       case SCNSM_EVENT_RSP_ERROR:
+               bfa_sm_set_state(scn, bfa_fcs_port_scn_sm_scr_retry);
+               bfa_timer_start(port->fcs->bfa, &scn->timer,
+                               bfa_fcs_port_scn_timeout, scn,
+                               BFA_FCS_RETRY_TIMEOUT);
+               break;
+
+       case SCNSM_EVENT_PORT_OFFLINE:
+               bfa_sm_set_state(scn, bfa_fcs_port_scn_sm_offline);
+               bfa_fcxp_discard(scn->fcxp);
+               break;
+
+       default:
+               bfa_assert(0);
+       }
+}
+
+static void
+bfa_fcs_port_scn_sm_scr_retry(struct bfa_fcs_port_scn_s *scn,
+                             enum port_scn_event event)
+{
+       switch (event) {
+       case SCNSM_EVENT_TIMEOUT:
+               bfa_sm_set_state(scn, bfa_fcs_port_scn_sm_sending_scr);
+               bfa_fcs_port_scn_send_scr(scn, NULL);
+               break;
+
+       case SCNSM_EVENT_PORT_OFFLINE:
+               bfa_sm_set_state(scn, bfa_fcs_port_scn_sm_offline);
+               bfa_timer_stop(&scn->timer);
+               break;
+
+       default:
+               bfa_assert(0);
+       }
+}
+
+static void
+bfa_fcs_port_scn_sm_online(struct bfa_fcs_port_scn_s *scn,
+                          enum port_scn_event event)
+{
+       switch (event) {
+       case SCNSM_EVENT_PORT_OFFLINE:
+               bfa_sm_set_state(scn, bfa_fcs_port_scn_sm_offline);
+               break;
+
+       default:
+               bfa_assert(0);
+       }
+}
+
+
+
+/**
+ *  fcs_scn_private FCS SCN private functions
+ */
+
+/**
+ * This routine will be called to send a SCR command.
+ */
+static void
+bfa_fcs_port_scn_send_scr(void *scn_cbarg, struct bfa_fcxp_s *fcxp_alloced)
+{
+       struct bfa_fcs_port_scn_s *scn = scn_cbarg;
+       struct bfa_fcs_port_s *port = scn->port;
+       struct fchs_s          fchs;
+       int             len;
+       struct bfa_fcxp_s *fcxp;
+
+       bfa_trc(port->fcs, port->pid);
+       bfa_trc(port->fcs, port->port_cfg.pwwn);
+
+       fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
+       if (!fcxp) {
+               bfa_fcxp_alloc_wait(port->fcs->bfa, &scn->fcxp_wqe,
+                                   bfa_fcs_port_scn_send_scr, scn);
+               return;
+       }
+       scn->fcxp = fcxp;
+
+       /*
+        * Handle VU registrations for Base port only
+        */
+       if ((!port->vport) && bfa_ioc_get_fcmode(&port->fcs->bfa->ioc)) {
+               len = fc_scr_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
+                                  bfa_lps_is_brcd_fabric(port->fabric->lps),
+                                  port->pid, 0);
+       } else {
+               len = fc_scr_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), BFA_FALSE,
+                                  port->pid, 0);
+       }
+
+       bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
+                     FC_CLASS_3, len, &fchs, bfa_fcs_port_scn_scr_response,
+                     (void *)scn, FC_MAX_PDUSZ, FC_RA_TOV);
+
+       bfa_sm_send_event(scn, SCNSM_EVENT_SCR_SENT);
+}
+
+static void
+bfa_fcs_port_scn_scr_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
+                             void *cbarg, bfa_status_t req_status,
+                             u32 rsp_len, u32 resid_len,
+                             struct fchs_s *rsp_fchs)
+{
+       struct bfa_fcs_port_scn_s *scn = (struct bfa_fcs_port_scn_s *)cbarg;
+       struct bfa_fcs_port_s *port = scn->port;
+       struct fc_els_cmd_s   *els_cmd;
+       struct fc_ls_rjt_s    *ls_rjt;
+
+       bfa_trc(port->fcs, port->port_cfg.pwwn);
+
+       /*
+        * Sanity Checks
+        */
+       if (req_status != BFA_STATUS_OK) {
+               bfa_trc(port->fcs, req_status);
+               bfa_sm_send_event(scn, SCNSM_EVENT_RSP_ERROR);
+               return;
+       }
+
+       els_cmd = (struct fc_els_cmd_s *) BFA_FCXP_RSP_PLD(fcxp);
+
+       switch (els_cmd->els_code) {
+
+       case FC_ELS_ACC:
+               bfa_sm_send_event(scn, SCNSM_EVENT_RSP_OK);
+               break;
+
+       case FC_ELS_LS_RJT:
+
+               ls_rjt = (struct fc_ls_rjt_s *) BFA_FCXP_RSP_PLD(fcxp);
+
+               bfa_trc(port->fcs, ls_rjt->reason_code);
+               bfa_trc(port->fcs, ls_rjt->reason_code_expl);
+
+               bfa_sm_send_event(scn, SCNSM_EVENT_RSP_ERROR);
+               break;
+
+       default:
+               bfa_sm_send_event(scn, SCNSM_EVENT_RSP_ERROR);
+       }
+}
+
+/*
+ * Send a LS Accept
+ */
+static void
+bfa_fcs_port_scn_send_ls_acc(struct bfa_fcs_port_s *port,
+                       struct fchs_s *rx_fchs)
+{
+       struct fchs_s          fchs;
+       struct bfa_fcxp_s *fcxp;
+       struct bfa_rport_s *bfa_rport = NULL;
+       int             len;
+
+       bfa_trc(port->fcs, rx_fchs->s_id);
+
+       fcxp = bfa_fcs_fcxp_alloc(port->fcs);
+       if (!fcxp)
+               return;
+
+       len = fc_ls_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), rx_fchs->s_id,
+                             bfa_fcs_port_get_fcid(port), rx_fchs->ox_id);
+
+       bfa_fcxp_send(fcxp, bfa_rport, port->fabric->vf_id, port->lp_tag,
+                     BFA_FALSE, FC_CLASS_3, len, &fchs, NULL, NULL,
+                     FC_MAX_PDUSZ, 0);
+}
+
+/**
+ *     This routine will be called by bfa_timer on timer timeouts.
+ *
+ *     param[in]       vport                   - pointer to bfa_fcs_port_t.
+ *     param[out]      vport_status    - pointer to return vport status in
+ *
+ *     return
+ *             void
+ *
+*      Special Considerations:
+ *
+ *     note
+ */
+static void
+bfa_fcs_port_scn_timeout(void *arg)
+{
+       struct bfa_fcs_port_scn_s *scn = (struct bfa_fcs_port_scn_s *)arg;
+
+       bfa_sm_send_event(scn, SCNSM_EVENT_TIMEOUT);
+}
+
+
+
+/**
+ *  fcs_scn_public FCS state change notification public interfaces
+ */
+
+/*
+ * Functions called by port/fab
+ */
+void
+bfa_fcs_port_scn_init(struct bfa_fcs_port_s *port)
+{
+       struct bfa_fcs_port_scn_s *scn = BFA_FCS_GET_SCN_FROM_PORT(port);
+
+       scn->port = port;
+       bfa_sm_set_state(scn, bfa_fcs_port_scn_sm_offline);
+}
+
+void
+bfa_fcs_port_scn_offline(struct bfa_fcs_port_s *port)
+{
+       struct bfa_fcs_port_scn_s *scn = BFA_FCS_GET_SCN_FROM_PORT(port);
+
+       scn->port = port;
+       bfa_sm_send_event(scn, SCNSM_EVENT_PORT_OFFLINE);
+}
+
+void
+bfa_fcs_port_scn_online(struct bfa_fcs_port_s *port)
+{
+       struct bfa_fcs_port_scn_s *scn = BFA_FCS_GET_SCN_FROM_PORT(port);
+
+       scn->port = port;
+       bfa_sm_send_event(scn, SCNSM_EVENT_PORT_ONLINE);
+}
+
+static void
+bfa_fcs_port_scn_portid_rscn(struct bfa_fcs_port_s *port, u32 rpid)
+{
+       struct bfa_fcs_rport_s *rport;
+
+       bfa_trc(port->fcs, rpid);
+
+       /**
+        * If this is an unknown device, then it just came online.
+        * Otherwise let rport handle the RSCN event.
+        */
+       rport = bfa_fcs_port_get_rport_by_pid(port, rpid);
+       if (rport == NULL) {
+               /*
+                * If min cfg mode is enabled, we donot need to
+                * discover any new rports.
+                */
+               if (!__fcs_min_cfg(port->fcs))
+                       rport = bfa_fcs_rport_create(port, rpid);
+       } else {
+               bfa_fcs_rport_scn(rport);
+       }
+}
+
+/**
+ * rscn format based PID comparison
+ */
+#define __fc_pid_match(__c0, __c1, __fmt)              \
+       (((__fmt) == FC_RSCN_FORMAT_FABRIC) ||          \
+        (((__fmt) == FC_RSCN_FORMAT_DOMAIN) &&         \
+         ((__c0)[0] == (__c1)[0])) ||                  \
+        (((__fmt) == FC_RSCN_FORMAT_AREA) &&           \
+         ((__c0)[0] == (__c1)[0]) &&                   \
+         ((__c0)[1] == (__c1)[1])))
+
+static void
+bfa_fcs_port_scn_multiport_rscn(struct bfa_fcs_port_s *port,
+                       enum fc_rscn_format format, u32 rscn_pid)
+{
+       struct bfa_fcs_rport_s *rport;
+       struct list_head *qe, *qe_next;
+       u8        *c0, *c1;
+
+       bfa_trc(port->fcs, format);
+       bfa_trc(port->fcs, rscn_pid);
+
+       c0 = (u8 *) &rscn_pid;
+
+       list_for_each_safe(qe, qe_next, &port->rport_q) {
+               rport = (struct bfa_fcs_rport_s *)qe;
+               c1 = (u8 *) &rport->pid;
+               if (__fc_pid_match(c0, c1, format))
+                       bfa_fcs_rport_scn(rport);
+       }
+}
+
+void
+bfa_fcs_port_scn_process_rscn(struct bfa_fcs_port_s *port, struct fchs_s *fchs,
+                             u32 len)
+{
+       struct fc_rscn_pl_s   *rscn = (struct fc_rscn_pl_s *) (fchs + 1);
+       int             num_entries;
+       u32        rscn_pid;
+       bfa_boolean_t   nsquery = BFA_FALSE;
+       int             i = 0;
+
+       num_entries =
+               (bfa_os_ntohs(rscn->payldlen) -
+                sizeof(u32)) / sizeof(rscn->event[0]);
+
+       bfa_trc(port->fcs, num_entries);
+
+       port->stats.num_rscn++;
+
+       bfa_fcs_port_scn_send_ls_acc(port, fchs);
+
+       for (i = 0; i < num_entries; i++) {
+               rscn_pid = rscn->event[i].portid;
+
+               bfa_trc(port->fcs, rscn->event[i].format);
+               bfa_trc(port->fcs, rscn_pid);
+
+               switch (rscn->event[i].format) {
+               case FC_RSCN_FORMAT_PORTID:
+                       if (rscn->event[i].qualifier == FC_QOS_RSCN_EVENT) {
+                               /*
+                                * Ignore this event. f/w would have processed
+                                * it
+                                */
+                               bfa_trc(port->fcs, rscn_pid);
+                       } else {
+                               port->stats.num_portid_rscn++;
+                               bfa_fcs_port_scn_portid_rscn(port, rscn_pid);
+                       }
+                       break;
+
+               case FC_RSCN_FORMAT_FABRIC:
+                       if (rscn->event[i].qualifier ==
+                           FC_FABRIC_NAME_RSCN_EVENT) {
+                               bfa_fcs_port_ms_fabric_rscn(port);
+                               break;
+                       }
+                       /*
+                        * !!!!!!!!! Fall Through !!!!!!!!!!!!!
+                        */
+
+               case FC_RSCN_FORMAT_AREA:
+               case FC_RSCN_FORMAT_DOMAIN:
+                       nsquery = BFA_TRUE;
+                       bfa_fcs_port_scn_multiport_rscn(port,
+                                                       rscn->event[i].format,
+                                                       rscn_pid);
+                       break;
+
+               default:
+                       bfa_assert(0);
+                       nsquery = BFA_TRUE;
+               }
+       }
+
+       /**
+        * If any of area, domain or fabric RSCN is received, do a fresh discovery
+        * to find new devices.
+        */
+       if (nsquery)
+               bfa_fcs_port_ns_query(port);
+}
+
+
diff --git a/drivers/scsi/bfa/vfapi.c b/drivers/scsi/bfa/vfapi.c
new file mode 100644 (file)
index 0000000..31d81fe
--- /dev/null
@@ -0,0 +1,292 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) 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.
+ */
+
+/**
+ *  vfapi.c Fabric module implementation.
+ */
+
+#include "fcs_fabric.h"
+#include "fcs_trcmod.h"
+
+BFA_TRC_FILE(FCS, VFAPI);
+
+/**
+ *  fcs_vf_api virtual fabrics API
+ */
+
+/**
+ *             Enable VF mode.
+ *
+ * @param[in]          fcs             fcs module instance
+ * @param[in]          vf_id           default vf_id of port, FC_VF_ID_NULL
+ *                                     to use standard default vf_id of 1.
+ *
+ * @retval     BFA_STATUS_OK           vf mode is enabled
+ * @retval     BFA_STATUS_BUSY         Port is active. Port must be disabled
+ *                                     before VF mode can be enabled.
+ */
+bfa_status_t
+bfa_fcs_vf_mode_enable(struct bfa_fcs_s *fcs, u16 vf_id)
+{
+       return BFA_STATUS_OK;
+}
+
+/**
+ *             Disable VF mode.
+ *
+ * @param[in]          fcs             fcs module instance
+ *
+ * @retval     BFA_STATUS_OK           vf mode is disabled
+ * @retval     BFA_STATUS_BUSY         VFs are present and being used. All
+ *                                     VFs must be deleted before disabling
+ *                                     VF mode.
+ */
+bfa_status_t
+bfa_fcs_vf_mode_disable(struct bfa_fcs_s *fcs)
+{
+       return BFA_STATUS_OK;
+}
+
+/**
+ *             Create a new VF instance.
+ *
+ *  A new VF is created using the given VF configuration. A VF is identified
+ *  by VF id. No duplicate VF creation is allowed with the same VF id. Once
+ *  a VF is created, VF is automatically started after link initialization
+ *  and EVFP exchange is completed.
+ *
+ *     param[in] vf            -       FCS vf data structure. Memory is
+ *                                     allocated by caller (driver)
+ *     param[in] fcs           -       FCS module
+ *     param[in] vf_cfg        -       VF configuration
+ *     param[in] vf_drv        -       Opaque handle back to the driver's
+ *                                     virtual vf structure
+ *
+ *     retval BFA_STATUS_OK VF creation is successful
+ *     retval BFA_STATUS_FAILED VF creation failed
+ *     retval BFA_STATUS_EEXIST A VF exists with the given vf_id
+ */
+bfa_status_t
+bfa_fcs_vf_create(bfa_fcs_vf_t *vf, struct bfa_fcs_s *fcs, u16 vf_id,
+                 struct bfa_port_cfg_s *port_cfg, struct bfad_vf_s *vf_drv)
+{
+       bfa_trc(fcs, vf_id);
+       return BFA_STATUS_OK;
+}
+
+/**
+ *     Use this function to delete a BFA VF object. VF object should
+ *             be stopped before this function call.
+ *
+ *     param[in] vf - pointer to bfa_vf_t.
+ *
+ *     retval BFA_STATUS_OK    On vf deletion success
+ *     retval BFA_STATUS_BUSY VF is not in a stopped state
+ *     retval BFA_STATUS_INPROGRESS VF deletion in in progress
+ */
+bfa_status_t
+bfa_fcs_vf_delete(bfa_fcs_vf_t *vf)
+{
+       bfa_trc(vf->fcs, vf->vf_id);
+       return BFA_STATUS_OK;
+}
+
+/**
+ *     Start participation in VF. This triggers login to the virtual fabric.
+ *
+ *     param[in] vf - pointer to bfa_vf_t.
+ *
+ *     return None
+ */
+void
+bfa_fcs_vf_start(bfa_fcs_vf_t *vf)
+{
+       bfa_trc(vf->fcs, vf->vf_id);
+}
+
+/**
+ *     Logout with the virtual fabric.
+ *
+ *     param[in] vf - pointer to bfa_vf_t.
+ *
+ *     retval BFA_STATUS_OK    On success.
+ *     retval BFA_STATUS_INPROGRESS VF is being stopped.
+ */
+bfa_status_t
+bfa_fcs_vf_stop(bfa_fcs_vf_t *vf)
+{
+       bfa_trc(vf->fcs, vf->vf_id);
+       return BFA_STATUS_OK;
+}
+
+/**
+ *     Returns attributes of the given VF.
+ *
+ *     param[in]       vf                      pointer to bfa_vf_t.
+ *     param[out] vf_attr      vf attributes returned
+ *
+ *     return None
+ */
+void
+bfa_fcs_vf_get_attr(bfa_fcs_vf_t *vf, struct bfa_vf_attr_s *vf_attr)
+{
+       bfa_trc(vf->fcs, vf->vf_id);
+}
+
+/**
+ *             Return statistics associated with the given vf.
+ *
+ *     param[in]       vf                      pointer to bfa_vf_t.
+ *     param[out] vf_stats     vf statistics returned
+ *
+ *  @return None
+ */
+void
+bfa_fcs_vf_get_stats(bfa_fcs_vf_t *vf, struct bfa_vf_stats_s *vf_stats)
+{
+       bfa_os_memcpy(vf_stats, &vf->stats, sizeof(struct bfa_vf_stats_s));
+       return;
+}
+
+void
+/**
+ *             clear statistics associated with the given vf.
+ *
+ *     param[in]       vf                      pointer to bfa_vf_t.
+ *
+ *  @return None
+ */
+bfa_fcs_vf_clear_stats(bfa_fcs_vf_t *vf)
+{
+       bfa_os_memset(&vf->stats, 0, sizeof(struct bfa_vf_stats_s));
+       return;
+}
+
+/**
+ *     Returns FCS vf structure for a given vf_id.
+ *
+ *     param[in]       vf_id           - VF_ID
+ *
+ *     return
+ *             If lookup succeeds, retuns fcs vf object, otherwise returns NULL
+ */
+bfa_fcs_vf_t   *
+bfa_fcs_vf_lookup(struct bfa_fcs_s *fcs, u16 vf_id)
+{
+       bfa_trc(fcs, vf_id);
+       if (vf_id == FC_VF_ID_NULL)
+               return (&fcs->fabric);
+
+       /**
+        * @todo vf support
+        */
+
+       return NULL;
+}
+
+/**
+ *     Returns driver VF structure for a given FCS vf.
+ *
+ *     param[in]       vf              - pointer to bfa_vf_t
+ *
+ *     return Driver VF structure
+ */
+struct bfad_vf_s      *
+bfa_fcs_vf_get_drv_vf(bfa_fcs_vf_t *vf)
+{
+       bfa_assert(vf);
+       bfa_trc(vf->fcs, vf->vf_id);
+       return vf->vf_drv;
+}
+
+/**
+ *     Return the list of VFs configured.
+ *
+ *     param[in]       fcs     fcs module instance
+ *     param[out]      vf_ids  returned list of vf_ids
+ *     param[in,out]   nvfs    in:size of vf_ids array,
+ *                             out:total elements present,
+ *                             actual elements returned is limited by the size
+ *
+ *     return Driver VF structure
+ */
+void
+bfa_fcs_vf_list(struct bfa_fcs_s *fcs, u16 *vf_ids, int *nvfs)
+{
+       bfa_trc(fcs, *nvfs);
+}
+
+/**
+ *     Return the list of all VFs visible from fabric.
+ *
+ *     param[in]       fcs     fcs module instance
+ *     param[out]      vf_ids  returned list of vf_ids
+ *     param[in,out]   nvfs    in:size of vf_ids array,
+ *                             out:total elements present,
+ *                             actual elements returned is limited by the size
+ *
+ *     return Driver VF structure
+ */
+void
+bfa_fcs_vf_list_all(struct bfa_fcs_s *fcs, u16 *vf_ids, int *nvfs)
+{
+       bfa_trc(fcs, *nvfs);
+}
+
+/**
+ *             Return the list of local logical ports present in the given VF.
+ *
+ *     param[in]       vf      vf for which logical ports are returned
+ *     param[out]      lpwwn   returned logical port wwn list
+ *     param[in,out]   nlports in:size of lpwwn list;
+ *                             out:total elements present,
+ *                             actual elements returned is limited by the size
+ *
+ */
+void
+bfa_fcs_vf_get_ports(bfa_fcs_vf_t *vf, wwn_t lpwwn[], int *nlports)
+{
+       struct list_head        *qe;
+       struct bfa_fcs_vport_s *vport;
+       int             i;
+       struct bfa_fcs_s      *fcs;
+
+       if (vf == NULL || lpwwn == NULL || *nlports == 0)
+               return;
+
+       fcs = vf->fcs;
+
+       bfa_trc(fcs, vf->vf_id);
+       bfa_trc(fcs, (u32) *nlports);
+
+       i = 0;
+       lpwwn[i++] = vf->bport.port_cfg.pwwn;
+
+       list_for_each(qe, &vf->vport_q) {
+               if (i >= *nlports)
+                       break;
+
+               vport = (struct bfa_fcs_vport_s *) qe;
+               lpwwn[i++] = vport->lport.port_cfg.pwwn;
+       }
+
+       bfa_trc(fcs, i);
+       *nlports = i;
+       return;
+}
+
+
diff --git a/drivers/scsi/bfa/vport.c b/drivers/scsi/bfa/vport.c
new file mode 100644 (file)
index 0000000..c10af06
--- /dev/null
@@ -0,0 +1,891 @@
+/*
+ * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) 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.
+ */
+
+/**
+ *  bfa_fcs_vport.c FCS virtual port state machine
+ */
+
+#include <bfa.h>
+#include <bfa_svc.h>
+#include <fcbuild.h>
+#include "fcs_fabric.h"
+#include "fcs_lport.h"
+#include "fcs_vport.h"
+#include "fcs_trcmod.h"
+#include "fcs.h"
+#include <aen/bfa_aen_lport.h>
+
+BFA_TRC_FILE(FCS, VPORT);
+
+#define __vport_fcs(__vp)       (__vp)->lport.fcs
+#define __vport_pwwn(__vp)      (__vp)->lport.port_cfg.pwwn
+#define __vport_nwwn(__vp)      (__vp)->lport.port_cfg.nwwn
+#define __vport_bfa(__vp)       (__vp)->lport.fcs->bfa
+#define __vport_fcid(__vp)      (__vp)->lport.pid
+#define __vport_fabric(__vp)    (__vp)->lport.fabric
+#define __vport_vfid(__vp)      (__vp)->lport.fabric->vf_id
+
+#define BFA_FCS_VPORT_MAX_RETRIES  5
+/*
+ * Forward declarations
+ */
+static void     bfa_fcs_vport_do_fdisc(struct bfa_fcs_vport_s *vport);
+static void     bfa_fcs_vport_timeout(void *vport_arg);
+static void     bfa_fcs_vport_do_logo(struct bfa_fcs_vport_s *vport);
+static void     bfa_fcs_vport_free(struct bfa_fcs_vport_s *vport);
+
+/**
+ *  fcs_vport_sm FCS virtual port state machine
+ */
+
+/**
+ * VPort State Machine events
+ */
+enum bfa_fcs_vport_event {
+       BFA_FCS_VPORT_SM_CREATE = 1,    /*  vport create event */
+       BFA_FCS_VPORT_SM_DELETE = 2,    /*  vport delete event */
+       BFA_FCS_VPORT_SM_START = 3,     /*  vport start request */
+       BFA_FCS_VPORT_SM_STOP = 4,      /*  stop: unsupported */
+       BFA_FCS_VPORT_SM_ONLINE = 5,    /*  fabric online */
+       BFA_FCS_VPORT_SM_OFFLINE = 6,   /*  fabric offline event */
+       BFA_FCS_VPORT_SM_FRMSENT = 7,   /*  fdisc/logo sent events */
+       BFA_FCS_VPORT_SM_RSP_OK = 8,    /*  good response */
+       BFA_FCS_VPORT_SM_RSP_ERROR = 9, /*  error/bad response */
+       BFA_FCS_VPORT_SM_TIMEOUT = 10,  /*  delay timer event */
+       BFA_FCS_VPORT_SM_DELCOMP = 11,  /*  lport delete completion */
+       BFA_FCS_VPORT_SM_RSP_DUP_WWN = 12,      /*  Dup wnn error */
+       BFA_FCS_VPORT_SM_RSP_FAILED = 13,       /*  non-retryable failure */
+};
+
+static void     bfa_fcs_vport_sm_uninit(struct bfa_fcs_vport_s *vport,
+                                       enum bfa_fcs_vport_event event);
+static void     bfa_fcs_vport_sm_created(struct bfa_fcs_vport_s *vport,
+                                        enum bfa_fcs_vport_event event);
+static void     bfa_fcs_vport_sm_offline(struct bfa_fcs_vport_s *vport,
+                                        enum bfa_fcs_vport_event event);
+static void     bfa_fcs_vport_sm_fdisc(struct bfa_fcs_vport_s *vport,
+                                      enum bfa_fcs_vport_event event);
+static void     bfa_fcs_vport_sm_fdisc_retry(struct bfa_fcs_vport_s *vport,
+                                            enum bfa_fcs_vport_event event);
+static void     bfa_fcs_vport_sm_online(struct bfa_fcs_vport_s *vport,
+                                       enum bfa_fcs_vport_event event);
+static void     bfa_fcs_vport_sm_deleting(struct bfa_fcs_vport_s *vport,
+                                         enum bfa_fcs_vport_event event);
+static void     bfa_fcs_vport_sm_cleanup(struct bfa_fcs_vport_s *vport,
+                                        enum bfa_fcs_vport_event event);
+static void     bfa_fcs_vport_sm_logo(struct bfa_fcs_vport_s *vport,
+                                     enum bfa_fcs_vport_event event);
+static void     bfa_fcs_vport_sm_error(struct bfa_fcs_vport_s *vport,
+                                      enum bfa_fcs_vport_event event);
+
+static struct bfa_sm_table_s vport_sm_table[] = {
+       {BFA_SM(bfa_fcs_vport_sm_uninit), BFA_FCS_VPORT_UNINIT},
+       {BFA_SM(bfa_fcs_vport_sm_created), BFA_FCS_VPORT_CREATED},
+       {BFA_SM(bfa_fcs_vport_sm_offline), BFA_FCS_VPORT_OFFLINE},
+       {BFA_SM(bfa_fcs_vport_sm_fdisc), BFA_FCS_VPORT_FDISC},
+       {BFA_SM(bfa_fcs_vport_sm_fdisc_retry), BFA_FCS_VPORT_FDISC_RETRY},
+       {BFA_SM(bfa_fcs_vport_sm_online), BFA_FCS_VPORT_ONLINE},
+       {BFA_SM(bfa_fcs_vport_sm_deleting), BFA_FCS_VPORT_DELETING},
+       {BFA_SM(bfa_fcs_vport_sm_cleanup), BFA_FCS_VPORT_CLEANUP},
+       {BFA_SM(bfa_fcs_vport_sm_logo), BFA_FCS_VPORT_LOGO},
+       {BFA_SM(bfa_fcs_vport_sm_error), BFA_FCS_VPORT_ERROR}
+};
+
+/**
+ * Beginning state.
+ */
+static void
+bfa_fcs_vport_sm_uninit(struct bfa_fcs_vport_s *vport,
+                       enum bfa_fcs_vport_event event)
+{
+       bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
+       bfa_trc(__vport_fcs(vport), event);
+
+       switch (event) {
+       case BFA_FCS_VPORT_SM_CREATE:
+               bfa_sm_set_state(vport, bfa_fcs_vport_sm_created);
+               bfa_fcs_fabric_addvport(__vport_fabric(vport), vport);
+               break;
+
+       default:
+               bfa_assert(0);
+       }
+}
+
+/**
+ * Created state - a start event is required to start up the state machine.
+ */
+static void
+bfa_fcs_vport_sm_created(struct bfa_fcs_vport_s *vport,
+                        enum bfa_fcs_vport_event event)
+{
+       bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
+       bfa_trc(__vport_fcs(vport), event);
+
+       switch (event) {
+       case BFA_FCS_VPORT_SM_START:
+               if (bfa_fcs_fabric_is_online(__vport_fabric(vport))
+                   && bfa_fcs_fabric_npiv_capable(__vport_fabric(vport))) {
+                       bfa_sm_set_state(vport, bfa_fcs_vport_sm_fdisc);
+                       bfa_fcs_vport_do_fdisc(vport);
+               } else {
+                       /**
+                        * Fabric is offline or not NPIV capable, stay in
+                        * offline state.
+                        */
+                       vport->vport_stats.fab_no_npiv++;
+                       bfa_sm_set_state(vport, bfa_fcs_vport_sm_offline);
+               }
+               break;
+
+       case BFA_FCS_VPORT_SM_DELETE:
+               bfa_sm_set_state(vport, bfa_fcs_vport_sm_cleanup);
+               bfa_fcs_port_delete(&vport->lport);
+               break;
+
+       case BFA_FCS_VPORT_SM_ONLINE:
+       case BFA_FCS_VPORT_SM_OFFLINE:
+               /**
+                * Ignore ONLINE/OFFLINE events from fabric till vport is started.
+                */
+               break;
+
+       default:
+               bfa_assert(0);
+       }
+}
+
+/**
+ * Offline state - awaiting ONLINE event from fabric SM.
+ */
+static void
+bfa_fcs_vport_sm_offline(struct bfa_fcs_vport_s *vport,
+                        enum bfa_fcs_vport_event event)
+{
+       bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
+       bfa_trc(__vport_fcs(vport), event);
+
+       switch (event) {
+       case BFA_FCS_VPORT_SM_DELETE:
+               bfa_sm_set_state(vport, bfa_fcs_vport_sm_cleanup);
+               bfa_fcs_port_delete(&vport->lport);
+               break;
+
+       case BFA_FCS_VPORT_SM_ONLINE:
+               bfa_sm_set_state(vport, bfa_fcs_vport_sm_fdisc);
+               vport->fdisc_retries = 0;
+               bfa_fcs_vport_do_fdisc(vport);
+               break;
+
+       case BFA_FCS_VPORT_SM_OFFLINE:
+               /*
+                * This can happen if the vport couldn't be initialzied due
+                * the fact that the npiv was not enabled on the switch. In
+                * that case we will put the vport in offline state. However,
+                * the link can go down and cause the this event to be sent when
+                * we are already offline. Ignore it.
+                */
+               break;
+
+       default:
+               bfa_assert(0);
+       }
+}
+
+/**
+ * FDISC is sent and awaiting reply from fabric.
+ */
+static void
+bfa_fcs_vport_sm_fdisc(struct bfa_fcs_vport_s *vport,
+                      enum bfa_fcs_vport_event event)
+{
+       bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
+       bfa_trc(__vport_fcs(vport), event);
+
+       switch (event) {
+       case BFA_FCS_VPORT_SM_DELETE:
+               bfa_sm_set_state(vport, bfa_fcs_vport_sm_logo);
+               bfa_lps_discard(vport->lps);
+               bfa_fcs_vport_do_logo(vport);
+               break;
+
+       case BFA_FCS_VPORT_SM_OFFLINE:
+               bfa_sm_set_state(vport, bfa_fcs_vport_sm_offline);
+               bfa_lps_discard(vport->lps);
+               break;
+
+       case BFA_FCS_VPORT_SM_RSP_OK:
+               bfa_sm_set_state(vport, bfa_fcs_vport_sm_online);
+               bfa_fcs_port_online(&vport->lport);
+               break;
+
+       case BFA_FCS_VPORT_SM_RSP_ERROR:
+               bfa_sm_set_state(vport, bfa_fcs_vport_sm_fdisc_retry);
+               bfa_timer_start(__vport_bfa(vport), &vport->timer,
+                               bfa_fcs_vport_timeout, vport,
+                               BFA_FCS_RETRY_TIMEOUT);
+               break;
+
+       case BFA_FCS_VPORT_SM_RSP_FAILED:
+               bfa_sm_set_state(vport, bfa_fcs_vport_sm_offline);
+               break;
+
+       case BFA_FCS_VPORT_SM_RSP_DUP_WWN:
+               bfa_sm_set_state(vport, bfa_fcs_vport_sm_error);
+               break;
+
+       default:
+               bfa_assert(0);
+       }
+}
+
+/**
+ * FDISC attempt failed - a timer is active to retry FDISC.
+ */
+static void
+bfa_fcs_vport_sm_fdisc_retry(struct bfa_fcs_vport_s *vport,
+                            enum bfa_fcs_vport_event event)
+{
+       bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
+       bfa_trc(__vport_fcs(vport), event);
+
+       switch (event) {
+       case BFA_FCS_VPORT_SM_DELETE:
+               bfa_sm_set_state(vport, bfa_fcs_vport_sm_cleanup);
+               bfa_timer_stop(&vport->timer);
+               bfa_fcs_port_delete(&vport->lport);
+               break;
+
+       case BFA_FCS_VPORT_SM_OFFLINE:
+               bfa_sm_set_state(vport, bfa_fcs_vport_sm_offline);
+               bfa_timer_stop(&vport->timer);
+               break;
+
+       case BFA_FCS_VPORT_SM_TIMEOUT:
+               bfa_sm_set_state(vport, bfa_fcs_vport_sm_fdisc);
+               vport->vport_stats.fdisc_retries++;
+               vport->fdisc_retries++;
+               bfa_fcs_vport_do_fdisc(vport);
+               break;
+
+       default:
+               bfa_assert(0);
+       }
+}
+
+/**
+ * Vport is online (FDISC is complete).
+ */
+static void
+bfa_fcs_vport_sm_online(struct bfa_fcs_vport_s *vport,
+                       enum bfa_fcs_vport_event event)
+{
+       bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
+       bfa_trc(__vport_fcs(vport), event);
+
+       switch (event) {
+       case BFA_FCS_VPORT_SM_DELETE:
+               bfa_sm_set_state(vport, bfa_fcs_vport_sm_deleting);
+               bfa_fcs_port_delete(&vport->lport);
+               break;
+
+       case BFA_FCS_VPORT_SM_OFFLINE:
+               bfa_sm_set_state(vport, bfa_fcs_vport_sm_offline);
+               bfa_lps_discard(vport->lps);
+               bfa_fcs_port_offline(&vport->lport);
+               break;
+
+       default:
+               bfa_assert(0);
+       }
+}
+
+/**
+ * Vport is being deleted - awaiting lport delete completion to send
+ * LOGO to fabric.
+ */
+static void
+bfa_fcs_vport_sm_deleting(struct bfa_fcs_vport_s *vport,
+                         enum bfa_fcs_vport_event event)
+{
+       bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
+       bfa_trc(__vport_fcs(vport), event);
+
+       switch (event) {
+       case BFA_FCS_VPORT_SM_DELETE:
+               break;
+
+       case BFA_FCS_VPORT_SM_DELCOMP:
+               bfa_sm_set_state(vport, bfa_fcs_vport_sm_logo);
+               bfa_fcs_vport_do_logo(vport);
+               break;
+
+       case BFA_FCS_VPORT_SM_OFFLINE:
+               bfa_sm_set_state(vport, bfa_fcs_vport_sm_cleanup);
+               break;
+
+       default:
+               bfa_assert(0);
+       }
+}
+
+/**
+ * Error State.
+ * This state will be set when the Vport Creation fails due to errors like
+ * Dup WWN. In this state only operation allowed is a Vport Delete.
+ */
+static void
+bfa_fcs_vport_sm_error(struct bfa_fcs_vport_s *vport,
+                      enum bfa_fcs_vport_event event)
+{
+       bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
+       bfa_trc(__vport_fcs(vport), event);
+
+       switch (event) {
+       case BFA_FCS_VPORT_SM_DELETE:
+               bfa_sm_set_state(vport, bfa_fcs_vport_sm_uninit);
+               bfa_fcs_vport_free(vport);
+               break;
+
+       default:
+               bfa_trc(__vport_fcs(vport), event);
+       }
+}
+
+/**
+ * Lport cleanup is in progress since vport is being deleted. Fabric is
+ * offline, so no LOGO is needed to complete vport deletion.
+ */
+static void
+bfa_fcs_vport_sm_cleanup(struct bfa_fcs_vport_s *vport,
+                        enum bfa_fcs_vport_event event)
+{
+       bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
+       bfa_trc(__vport_fcs(vport), event);
+
+       switch (event) {
+       case BFA_FCS_VPORT_SM_DELCOMP:
+               bfa_sm_set_state(vport, bfa_fcs_vport_sm_uninit);
+               bfa_fcs_vport_free(vport);
+               break;
+
+       case BFA_FCS_VPORT_SM_DELETE:
+               break;
+
+       default:
+               bfa_assert(0);
+       }
+}
+
+/**
+ * LOGO is sent to fabric. Vport delete is in progress. Lport delete cleanup
+ * is done.
+ */
+static void
+bfa_fcs_vport_sm_logo(struct bfa_fcs_vport_s *vport,
+                     enum bfa_fcs_vport_event event)
+{
+       bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
+       bfa_trc(__vport_fcs(vport), event);
+
+       switch (event) {
+       case BFA_FCS_VPORT_SM_OFFLINE:
+               bfa_lps_discard(vport->lps);
+               /*
+                * !!! fall through !!!
+                */
+
+       case BFA_FCS_VPORT_SM_RSP_OK:
+       case BFA_FCS_VPORT_SM_RSP_ERROR:
+               bfa_sm_set_state(vport, bfa_fcs_vport_sm_uninit);
+               bfa_fcs_vport_free(vport);
+               break;
+
+       case BFA_FCS_VPORT_SM_DELETE:
+               break;
+
+       default:
+               bfa_assert(0);
+       }
+}
+
+
+
+/**
+ *  fcs_vport_private FCS virtual port private functions
+ */
+
+/**
+ * Send AEN notification
+ */
+static void
+bfa_fcs_vport_aen_post(bfa_fcs_lport_t *port, enum bfa_lport_aen_event event)
+{
+       union bfa_aen_data_u aen_data;
+       struct bfa_log_mod_s *logmod = port->fcs->logm;
+       enum bfa_port_role role = port->port_cfg.roles;
+       wwn_t           lpwwn = bfa_fcs_port_get_pwwn(port);
+       char            lpwwn_ptr[BFA_STRING_32];
+       char           *role_str[BFA_PORT_ROLE_FCP_MAX / 2 + 1] =
+               { "Initiator", "Target", "IPFC" };
+
+       wwn2str(lpwwn_ptr, lpwwn);
+
+       bfa_assert(role <= BFA_PORT_ROLE_FCP_MAX);
+
+       switch (event) {
+       case BFA_LPORT_AEN_NPIV_DUP_WWN:
+               bfa_log(logmod, BFA_AEN_LPORT_NPIV_DUP_WWN, lpwwn_ptr,
+                       role_str[role / 2]);
+               break;
+       case BFA_LPORT_AEN_NPIV_FABRIC_MAX:
+               bfa_log(logmod, BFA_AEN_LPORT_NPIV_FABRIC_MAX, lpwwn_ptr,
+                       role_str[role / 2]);
+               break;
+       case BFA_LPORT_AEN_NPIV_UNKNOWN:
+               bfa_log(logmod, BFA_AEN_LPORT_NPIV_UNKNOWN, lpwwn_ptr,
+                       role_str[role / 2]);
+               break;
+       default:
+               break;
+       }
+
+       aen_data.lport.vf_id = port->fabric->vf_id;
+       aen_data.lport.roles = role;
+       aen_data.lport.ppwwn =
+               bfa_fcs_port_get_pwwn(bfa_fcs_get_base_port(port->fcs));
+       aen_data.lport.lpwwn = lpwwn;
+}
+
+/**
+ * This routine will be called to send a FDISC command.
+ */
+static void
+bfa_fcs_vport_do_fdisc(struct bfa_fcs_vport_s *vport)
+{
+       bfa_lps_fdisc(vport->lps, vport,
+                     bfa_pport_get_maxfrsize(__vport_bfa(vport)),
+                     __vport_pwwn(vport), __vport_nwwn(vport));
+       vport->vport_stats.fdisc_sent++;
+}
+
+static void
+bfa_fcs_vport_fdisc_rejected(struct bfa_fcs_vport_s *vport)
+{
+       u8         lsrjt_rsn = bfa_lps_get_lsrjt_rsn(vport->lps);
+       u8         lsrjt_expl = bfa_lps_get_lsrjt_expl(vport->lps);
+
+       bfa_trc(__vport_fcs(vport), lsrjt_rsn);
+       bfa_trc(__vport_fcs(vport), lsrjt_expl);
+
+       /*
+        * For certain reason codes, we don't want to retry.
+        */
+       switch (bfa_lps_get_lsrjt_expl(vport->lps)) {
+       case FC_LS_RJT_EXP_INV_PORT_NAME:       /* by brocade */
+       case FC_LS_RJT_EXP_INVALID_NPORT_ID:    /* by Cisco */
+               if (vport->fdisc_retries < BFA_FCS_VPORT_MAX_RETRIES)
+                       bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_ERROR);
+               else {
+                       bfa_fcs_vport_aen_post(&vport->lport,
+                                              BFA_LPORT_AEN_NPIV_DUP_WWN);
+                       bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_DUP_WWN);
+               }
+               break;
+
+       case FC_LS_RJT_EXP_INSUFF_RES:
+               /*
+                * This means max logins per port/switch setting on the
+                * switch was exceeded.
+                */
+               if (vport->fdisc_retries < BFA_FCS_VPORT_MAX_RETRIES)
+                       bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_ERROR);
+               else {
+                       bfa_fcs_vport_aen_post(&vport->lport,
+                                              BFA_LPORT_AEN_NPIV_FABRIC_MAX);
+                       bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_FAILED);
+               }
+               break;
+
+       default:
+               if (vport->fdisc_retries == 0)  /* Print only once */
+                       bfa_fcs_vport_aen_post(&vport->lport,
+                                              BFA_LPORT_AEN_NPIV_UNKNOWN);
+               bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_ERROR);
+       }
+}
+
+/**
+ *     Called to send a logout to the fabric. Used when a V-Port is
+ *     deleted/stopped.
+ */
+static void
+bfa_fcs_vport_do_logo(struct bfa_fcs_vport_s *vport)
+{
+       bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
+
+       vport->vport_stats.logo_sent++;
+       bfa_lps_fdisclogo(vport->lps);
+}
+
+/**
+ *     This routine will be called by bfa_timer on timer timeouts.
+ *
+ *     param[in]       vport           - pointer to bfa_fcs_vport_t.
+ *     param[out]      vport_status    - pointer to return vport status in
+ *
+ *     return
+ *             void
+ *
+*      Special Considerations:
+ *
+ *     note
+ */
+static void
+bfa_fcs_vport_timeout(void *vport_arg)
+{
+       struct bfa_fcs_vport_s *vport = (struct bfa_fcs_vport_s *)vport_arg;
+
+       vport->vport_stats.fdisc_timeouts++;
+       bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_TIMEOUT);
+}
+
+static void
+bfa_fcs_vport_free(struct bfa_fcs_vport_s *vport)
+{
+       bfa_fcs_fabric_delvport(__vport_fabric(vport), vport);
+       bfa_fcb_vport_delete(vport->vport_drv);
+       bfa_lps_delete(vport->lps);
+}
+
+
+
+/**
+ *  fcs_vport_public FCS virtual port public interfaces
+ */
+
+/**
+ * Online notification from fabric SM.
+ */
+void
+bfa_fcs_vport_online(struct bfa_fcs_vport_s *vport)
+{
+       vport->vport_stats.fab_online++;
+       bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_ONLINE);
+}
+
+/**
+ * Offline notification from fabric SM.
+ */
+void
+bfa_fcs_vport_offline(struct bfa_fcs_vport_s *vport)
+{
+       vport->vport_stats.fab_offline++;
+       bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_OFFLINE);
+}
+
+/**
+ * Cleanup notification from fabric SM on link timer expiry.
+ */
+void
+bfa_fcs_vport_cleanup(struct bfa_fcs_vport_s *vport)
+{
+       vport->vport_stats.fab_cleanup++;
+}
+
+/**
+ * Delete completion callback from associated lport
+ */
+void
+bfa_fcs_vport_delete_comp(struct bfa_fcs_vport_s *vport)
+{
+       bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_DELCOMP);
+}
+
+/**
+ *   Module initialization
+ */
+void
+bfa_fcs_vport_modinit(struct bfa_fcs_s *fcs)
+{
+}
+
+/**
+ *   Module cleanup
+ */
+void
+bfa_fcs_vport_modexit(struct bfa_fcs_s *fcs)
+{
+       bfa_fcs_modexit_comp(fcs);
+}
+
+u32
+bfa_fcs_vport_get_max(struct bfa_fcs_s *fcs)
+{
+       struct bfa_ioc_attr_s ioc_attr;
+
+       bfa_get_attr(fcs->bfa, &ioc_attr);
+
+       if (ioc_attr.pci_attr.device_id == BFA_PCI_DEVICE_ID_CT)
+               return (BFA_FCS_MAX_VPORTS_SUPP_CT);
+       else
+               return (BFA_FCS_MAX_VPORTS_SUPP_CB);
+}
+
+
+
+/**
+ *  fcs_vport_api Virtual port API
+ */
+
+/**
+ *     Use this function to instantiate a new FCS vport object. This
+ *     function will not trigger any HW initialization process (which will be
+ *     done in vport_start() call)
+ *
+ *     param[in] vport -       pointer to bfa_fcs_vport_t. This space
+ *                                     needs to be allocated by the driver.
+ *     param[in] fcs           -       FCS instance
+ *     param[in] vport_cfg     -       vport configuration
+ *     param[in] vf_id         -       VF_ID if vport is created within a VF.
+ *                                     FC_VF_ID_NULL to specify base fabric.
+ *     param[in] vport_drv     -       Opaque handle back to the driver's vport
+ *                                     structure
+ *
+ *     retval BFA_STATUS_OK - on success.
+ *     retval BFA_STATUS_FAILED - on failure.
+ */
+bfa_status_t
+bfa_fcs_vport_create(struct bfa_fcs_vport_s *vport, struct bfa_fcs_s *fcs,
+                    u16 vf_id, struct bfa_port_cfg_s *vport_cfg,
+                    struct bfad_vport_s *vport_drv)
+{
+       if (vport_cfg->pwwn == 0)
+               return (BFA_STATUS_INVALID_WWN);
+
+       if (bfa_fcs_port_get_pwwn(&fcs->fabric.bport) == vport_cfg->pwwn)
+               return BFA_STATUS_VPORT_WWN_BP;
+
+       if (bfa_fcs_vport_lookup(fcs, vf_id, vport_cfg->pwwn) != NULL)
+               return BFA_STATUS_VPORT_EXISTS;
+
+       if (bfa_fcs_fabric_vport_count(&fcs->fabric) ==
+           bfa_fcs_vport_get_max(fcs))
+               return BFA_STATUS_VPORT_MAX;
+
+       vport->lps = bfa_lps_alloc(fcs->bfa);
+       if (!vport->lps)
+               return BFA_STATUS_VPORT_MAX;
+
+       vport->vport_drv = vport_drv;
+       bfa_sm_set_state(vport, bfa_fcs_vport_sm_uninit);
+
+       bfa_fcs_lport_init(&vport->lport, fcs, vf_id, vport_cfg, vport);
+
+       bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_CREATE);
+
+       return BFA_STATUS_OK;
+}
+
+/**
+ *     Use this function initialize the vport.
+ *
+ *  @param[in] vport - pointer to bfa_fcs_vport_t.
+ *
+ *  @returns None
+ */
+bfa_status_t
+bfa_fcs_vport_start(struct bfa_fcs_vport_s *vport)
+{
+       bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_START);
+
+       return BFA_STATUS_OK;
+}
+
+/**
+ *     Use this function quiese the vport object. This function will return
+ *     immediately, when the vport is actually stopped, the
+ *     bfa_drv_vport_stop_cb() will be called.
+ *
+ *     param[in] vport - pointer to bfa_fcs_vport_t.
+ *
+ *     return None
+ */
+bfa_status_t
+bfa_fcs_vport_stop(struct bfa_fcs_vport_s *vport)
+{
+       bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_STOP);
+
+       return BFA_STATUS_OK;
+}
+
+/**
+ *     Use this function to delete a vport object. Fabric object should
+ *             be stopped before this function call.
+ *
+ *     param[in] vport - pointer to bfa_fcs_vport_t.
+ *
+ *     return     None
+ */
+bfa_status_t
+bfa_fcs_vport_delete(struct bfa_fcs_vport_s *vport)
+{
+       bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_DELETE);
+
+       return BFA_STATUS_OK;
+}
+
+/**
+ *     Use this function to get vport's current status info.
+ *
+ *     param[in]       vport           pointer to bfa_fcs_vport_t.
+ *     param[out]      attr            pointer to return vport attributes
+ *
+ *     return None
+ */
+void
+bfa_fcs_vport_get_attr(struct bfa_fcs_vport_s *vport,
+                      struct bfa_vport_attr_s *attr)
+{
+       if (vport == NULL || attr == NULL)
+               return;
+
+       bfa_os_memset(attr, 0, sizeof(struct bfa_vport_attr_s));
+
+       bfa_fcs_port_get_attr(&vport->lport, &attr->port_attr);
+       attr->vport_state = bfa_sm_to_state(vport_sm_table, vport->sm);
+}
+
+/**
+ *     Use this function to get vport's statistics.
+ *
+ *     param[in]       vport           pointer to bfa_fcs_vport_t.
+ *     param[out]      stats           pointer to return vport statistics in
+ *
+ *     return None
+ */
+void
+bfa_fcs_vport_get_stats(struct bfa_fcs_vport_s *vport,
+                       struct bfa_vport_stats_s *stats)
+{
+       *stats = vport->vport_stats;
+}
+
+/**
+ *     Use this function to clear vport's statistics.
+ *
+ *     param[in]       vport           pointer to bfa_fcs_vport_t.
+ *
+ *     return None
+ */
+void
+bfa_fcs_vport_clr_stats(struct bfa_fcs_vport_s *vport)
+{
+       bfa_os_memset(&vport->vport_stats, 0, sizeof(struct bfa_vport_stats_s));
+}
+
+/**
+ *      Lookup a virtual port. Excludes base port from lookup.
+ */
+struct bfa_fcs_vport_s *
+bfa_fcs_vport_lookup(struct bfa_fcs_s *fcs, u16 vf_id, wwn_t vpwwn)
+{
+       struct bfa_fcs_vport_s *vport;
+       struct bfa_fcs_fabric_s *fabric;
+
+       bfa_trc(fcs, vf_id);
+       bfa_trc(fcs, vpwwn);
+
+       fabric = bfa_fcs_vf_lookup(fcs, vf_id);
+       if (!fabric) {
+               bfa_trc(fcs, vf_id);
+               return NULL;
+       }
+
+       vport = bfa_fcs_fabric_vport_lookup(fabric, vpwwn);
+       return vport;
+}
+
+/**
+ * FDISC Response
+ */
+void
+bfa_cb_lps_fdisc_comp(void *bfad, void *uarg, bfa_status_t status)
+{
+       struct bfa_fcs_vport_s *vport = uarg;
+
+       bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
+       bfa_trc(__vport_fcs(vport), status);
+
+       switch (status) {
+       case BFA_STATUS_OK:
+               /*
+                * Initialiaze the V-Port fields
+                */
+               __vport_fcid(vport) = bfa_lps_get_pid(vport->lps);
+               vport->vport_stats.fdisc_accepts++;
+               bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_OK);
+               break;
+
+       case BFA_STATUS_INVALID_MAC:
+               /*
+                * Only for CNA
+                */
+               vport->vport_stats.fdisc_acc_bad++;
+               bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_ERROR);
+
+               break;
+
+       case BFA_STATUS_EPROTOCOL:
+               switch (bfa_lps_get_extstatus(vport->lps)) {
+               case BFA_EPROTO_BAD_ACCEPT:
+                       vport->vport_stats.fdisc_acc_bad++;
+                       break;
+
+               case BFA_EPROTO_UNKNOWN_RSP:
+                       vport->vport_stats.fdisc_unknown_rsp++;
+                       break;
+
+               default:
+                       break;
+               }
+
+               bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_ERROR);
+               break;
+
+       case BFA_STATUS_FABRIC_RJT:
+               vport->vport_stats.fdisc_rejects++;
+               bfa_fcs_vport_fdisc_rejected(vport);
+               break;
+
+       default:
+               vport->vport_stats.fdisc_rsp_err++;
+               bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_ERROR);
+       }
+}
+
+/**
+ * LOGO response
+ */
+void
+bfa_cb_lps_fdisclogo_comp(void *bfad, void *uarg)
+{
+       struct bfa_fcs_vport_s *vport = uarg;
+       bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_OK);
+}
+
+
index d7576f2..5edde1a 100644 (file)
 #define CTX_OFFSET                     0x10000
 #define MAX_CID_CNT                    0x4000
 
+#define BNX2I_570X_PAGE_SIZE_DEFAULT   4096
+
 /* 5709 context registers */
 #define BNX2_MQ_CONFIG2                        0x00003d00
 #define BNX2_MQ_CONFIG2_CONT_SZ                (0x7L<<4)
index 41e1b0e..5c8d763 100644 (file)
@@ -2386,7 +2386,7 @@ int bnx2i_map_ep_dbell_regs(struct bnx2i_endpoint *ep)
                ctx_sz = (config2 & BNX2_MQ_CONFIG2_CONT_SZ) >> 3;
                if (ctx_sz)
                        reg_off = CTX_OFFSET + MAX_CID_CNT * MB_KERNEL_CTX_SIZE
-                                 + PAGE_SIZE *
+                                 + BNX2I_570X_PAGE_SIZE_DEFAULT *
                                  (((cid_num - first_l4l5) / ctx_sz) + 256);
                else
                        reg_off = CTX_OFFSET + (MB_KERNEL_CTX_SIZE * cid_num);
index 9a7ba71..cafb888 100644 (file)
@@ -1243,7 +1243,7 @@ bnx2i_session_create(struct iscsi_endpoint *ep,
                cmds_max = BNX2I_SQ_WQES_MIN;
 
        cls_session = iscsi_session_setup(&bnx2i_iscsi_transport, shost,
-                                         cmds_max, sizeof(struct bnx2i_cmd),
+                                         cmds_max, 0, sizeof(struct bnx2i_cmd),
                                          initial_cmdsn, ISCSI_MAX_TARGET);
        if (!cls_session)
                return NULL;
index c399f48..2631bdd 100644 (file)
@@ -422,7 +422,7 @@ cxgb3i_session_create(struct iscsi_endpoint *ep, u16 cmds_max, u16 qdepth,
        BUG_ON(hba != iscsi_host_priv(shost));
 
        cls_session = iscsi_session_setup(&cxgb3i_iscsi_transport, shost,
-                                         cmds_max,
+                                         cmds_max, 0,
                                          sizeof(struct iscsi_tcp_task) +
                                          sizeof(struct cxgb3i_task_data),
                                          initial_cmdsn, ISCSI_MAX_TARGET);
index 11c8931..268189d 100644 (file)
@@ -500,8 +500,6 @@ static int mode_select_handle_sense(struct scsi_device *sdev,
        if (!ret)
                goto done;
 
-       err = SCSI_DH_OK;
-
        switch (sense_hdr.sense_key) {
        case NO_SENSE:
        case ABORTED_COMMAND:
index b6af63c..4967643 100644 (file)
@@ -1918,6 +1918,10 @@ static int adpt_i2o_passthru(adpt_hba* pHba, u32 __user *arg)
                }
                size = size>>16;
                size *= 4;
+               if (size > MAX_MESSAGE_SIZE) {
+                       rcode = -EINVAL;
+                       goto cleanup;
+               }
                /* Copy in the user's I2O command */
                if (copy_from_user (msg, user_msg, size)) {
                        rcode = -EFAULT;
index c596ab5..a0e7e71 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * HighPoint RR3xxx/4xxx controller driver for Linux
- * Copyright (C) 2006-2007 HighPoint Technologies, Inc. All Rights Reserved.
+ * Copyright (C) 2006-2009 HighPoint Technologies, 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
@@ -41,7 +41,7 @@ MODULE_DESCRIPTION("HighPoint RocketRAID 3xxx/4xxx Controller Driver");
 
 static char driver_name[] = "hptiop";
 static const char driver_name_long[] = "RocketRAID 3xxx/4xxx Controller driver";
-static const char driver_ver[] = "v1.3 (071203)";
+static const char driver_ver[] = "v1.6 (090910)";
 
 static int iop_send_sync_msg(struct hptiop_hba *hba, u32 msg, u32 millisec);
 static void hptiop_finish_scsi_req(struct hptiop_hba *hba, u32 tag,
@@ -115,9 +115,13 @@ static void hptiop_drain_outbound_queue_itl(struct hptiop_hba *hba)
 static int iop_intr_itl(struct hptiop_hba *hba)
 {
        struct hpt_iopmu_itl __iomem *iop = hba->u.itl.iop;
+       void __iomem *plx = hba->u.itl.plx;
        u32 status;
        int ret = 0;
 
+       if (plx && readl(plx + 0x11C5C) & 0xf)
+               writel(1, plx + 0x11C60);
+
        status = readl(&iop->outbound_intstatus);
 
        if (status & IOPMU_OUTBOUND_INT_MSG0) {
@@ -460,15 +464,25 @@ static void __iomem *hptiop_map_pci_bar(struct hptiop_hba *hba, int index)
 
 static int hptiop_map_pci_bar_itl(struct hptiop_hba *hba)
 {
+       struct pci_dev *pcidev = hba->pcidev;
        hba->u.itl.iop = hptiop_map_pci_bar(hba, 0);
-       if (hba->u.itl.iop)
-               return 0;
-       else
+       if (hba->u.itl.iop == NULL)
                return -1;
+       if ((pcidev->device & 0xff00) == 0x4400) {
+               hba->u.itl.plx = hba->u.itl.iop;
+               hba->u.itl.iop = hptiop_map_pci_bar(hba, 2);
+               if (hba->u.itl.iop == NULL) {
+                       iounmap(hba->u.itl.plx);
+                       return -1;
+               }
+       }
+       return 0;
 }
 
 static void hptiop_unmap_pci_bar_itl(struct hptiop_hba *hba)
 {
+       if (hba->u.itl.plx)
+               iounmap(hba->u.itl.plx);
        iounmap(hba->u.itl.iop);
 }
 
@@ -1239,22 +1253,23 @@ static struct hptiop_adapter_ops hptiop_mv_ops = {
 static struct pci_device_id hptiop_id_table[] = {
        { PCI_VDEVICE(TTI, 0x3220), (kernel_ulong_t)&hptiop_itl_ops },
        { PCI_VDEVICE(TTI, 0x3320), (kernel_ulong_t)&hptiop_itl_ops },
-       { PCI_VDEVICE(TTI, 0x3520), (kernel_ulong_t)&hptiop_itl_ops },
-       { PCI_VDEVICE(TTI, 0x4320), (kernel_ulong_t)&hptiop_itl_ops },
+       { PCI_VDEVICE(TTI, 0x3410), (kernel_ulong_t)&hptiop_itl_ops },
        { PCI_VDEVICE(TTI, 0x3510), (kernel_ulong_t)&hptiop_itl_ops },
        { PCI_VDEVICE(TTI, 0x3511), (kernel_ulong_t)&hptiop_itl_ops },
+       { PCI_VDEVICE(TTI, 0x3520), (kernel_ulong_t)&hptiop_itl_ops },
        { PCI_VDEVICE(TTI, 0x3521), (kernel_ulong_t)&hptiop_itl_ops },
        { PCI_VDEVICE(TTI, 0x3522), (kernel_ulong_t)&hptiop_itl_ops },
-       { PCI_VDEVICE(TTI, 0x3410), (kernel_ulong_t)&hptiop_itl_ops },
-       { PCI_VDEVICE(TTI, 0x3540), (kernel_ulong_t)&hptiop_itl_ops },
        { PCI_VDEVICE(TTI, 0x3530), (kernel_ulong_t)&hptiop_itl_ops },
+       { PCI_VDEVICE(TTI, 0x3540), (kernel_ulong_t)&hptiop_itl_ops },
        { PCI_VDEVICE(TTI, 0x3560), (kernel_ulong_t)&hptiop_itl_ops },
-       { PCI_VDEVICE(TTI, 0x4322), (kernel_ulong_t)&hptiop_itl_ops },
-       { PCI_VDEVICE(TTI, 0x4321), (kernel_ulong_t)&hptiop_itl_ops },
        { PCI_VDEVICE(TTI, 0x4210), (kernel_ulong_t)&hptiop_itl_ops },
        { PCI_VDEVICE(TTI, 0x4211), (kernel_ulong_t)&hptiop_itl_ops },
        { PCI_VDEVICE(TTI, 0x4310), (kernel_ulong_t)&hptiop_itl_ops },
        { PCI_VDEVICE(TTI, 0x4311), (kernel_ulong_t)&hptiop_itl_ops },
+       { PCI_VDEVICE(TTI, 0x4320), (kernel_ulong_t)&hptiop_itl_ops },
+       { PCI_VDEVICE(TTI, 0x4321), (kernel_ulong_t)&hptiop_itl_ops },
+       { PCI_VDEVICE(TTI, 0x4322), (kernel_ulong_t)&hptiop_itl_ops },
+       { PCI_VDEVICE(TTI, 0x4400), (kernel_ulong_t)&hptiop_itl_ops },
        { PCI_VDEVICE(TTI, 0x3120), (kernel_ulong_t)&hptiop_mv_ops },
        { PCI_VDEVICE(TTI, 0x3122), (kernel_ulong_t)&hptiop_mv_ops },
        { PCI_VDEVICE(TTI, 0x3020), (kernel_ulong_t)&hptiop_mv_ops },
index a0289f2..0b871c0 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * HighPoint RR3xxx/4xxx controller driver for Linux
- * Copyright (C) 2006-2007 HighPoint Technologies, Inc. All Rights Reserved.
+ * Copyright (C) 2006-2009 HighPoint Technologies, 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
@@ -228,6 +228,7 @@ struct hptiop_hba {
        union {
                struct {
                        struct hpt_iopmu_itl __iomem *iop;
+                       void __iomem *plx;
                } itl;
                struct {
                        struct hpt_iopmv_regs *regs;
index 2b1b834..edc49ca 100644 (file)
@@ -811,7 +811,7 @@ iscsi_sw_tcp_session_create(struct iscsi_endpoint *ep, uint16_t cmds_max,
                goto free_host;
 
        cls_session = iscsi_session_setup(&iscsi_sw_tcp_transport, shost,
-                                         cmds_max,
+                                         cmds_max, 0,
                                          sizeof(struct iscsi_tcp_task) +
                                          sizeof(struct iscsi_sw_tcp_hdrbuf),
                                          initial_cmdsn, 0);
index 8dc73c4..f1a4246 100644 (file)
@@ -2436,7 +2436,7 @@ static void iscsi_host_dec_session_cnt(struct Scsi_Host *shost)
  */
 struct iscsi_cls_session *
 iscsi_session_setup(struct iscsi_transport *iscsit, struct Scsi_Host *shost,
-                   uint16_t cmds_max, int cmd_task_size,
+                   uint16_t cmds_max, int dd_size, int cmd_task_size,
                    uint32_t initial_cmdsn, unsigned int id)
 {
        struct iscsi_host *ihost = shost_priv(shost);
@@ -2486,7 +2486,8 @@ iscsi_session_setup(struct iscsi_transport *iscsit, struct Scsi_Host *shost,
        scsi_cmds = total_cmds - ISCSI_MGMT_CMDS_MAX;
 
        cls_session = iscsi_alloc_session(shost, iscsit,
-                                         sizeof(struct iscsi_session));
+                                         sizeof(struct iscsi_session) +
+                                         dd_size);
        if (!cls_session)
                goto dec_session_count;
        session = cls_session->dd_data;
@@ -2503,6 +2504,7 @@ iscsi_session_setup(struct iscsi_transport *iscsit, struct Scsi_Host *shost,
        session->max_cmdsn = initial_cmdsn + 1;
        session->max_r2t = 1;
        session->tt = iscsit;
+       session->dd_data = cls_session->dd_data + sizeof(*session);
        mutex_init(&session->eh_mutex);
        spin_lock_init(&session->lock);
 
index 61d0897..c88f59f 100644 (file)
@@ -56,8 +56,6 @@ static char *dif_op_str[] = {
        "SCSI_PROT_WRITE_INSERT",
        "SCSI_PROT_READ_PASS",
        "SCSI_PROT_WRITE_PASS",
-       "SCSI_PROT_READ_CONVERT",
-       "SCSI_PROT_WRITE_CONVERT"
 };
 static void
 lpfc_release_scsi_buf_s4(struct lpfc_hba *phba, struct lpfc_scsi_buf *psb);
@@ -1131,13 +1129,11 @@ lpfc_sc_to_sli_prof(struct scsi_cmnd *sc)
                        ret_prof = LPFC_PROF_A1;
                        break;
 
-               case SCSI_PROT_READ_CONVERT:
-               case SCSI_PROT_WRITE_CONVERT:
+               case SCSI_PROT_READ_PASS:
+               case SCSI_PROT_WRITE_PASS:
                        ret_prof = LPFC_PROF_AST1;
                        break;
 
-               case SCSI_PROT_READ_PASS:
-               case SCSI_PROT_WRITE_PASS:
                case SCSI_PROT_NORMAL:
                default:
                        printk(KERN_ERR "Bad op/guard:%d/%d combination\n",
@@ -1157,8 +1153,6 @@ lpfc_sc_to_sli_prof(struct scsi_cmnd *sc)
                        ret_prof = LPFC_PROF_C1;
                        break;
 
-               case SCSI_PROT_READ_CONVERT:
-               case SCSI_PROT_WRITE_CONVERT:
                case SCSI_PROT_READ_INSERT:
                case SCSI_PROT_WRITE_STRIP:
                case SCSI_PROT_NORMAL:
@@ -1209,8 +1203,7 @@ lpfc_get_cmd_dif_parms(struct scsi_cmnd *sc, uint16_t *apptagmask,
        static int cnt;
 
        if (protcnt && (op == SCSI_PROT_WRITE_STRIP ||
-                               op == SCSI_PROT_WRITE_PASS ||
-                               op == SCSI_PROT_WRITE_CONVERT)) {
+                               op == SCSI_PROT_WRITE_PASS)) {
 
                cnt++;
                spt = page_address(sg_page(scsi_prot_sglist(sc))) +
@@ -1501,8 +1494,6 @@ lpfc_prot_group_type(struct lpfc_hba *phba, struct scsi_cmnd *sc)
        case SCSI_PROT_WRITE_STRIP:
        case SCSI_PROT_READ_PASS:
        case SCSI_PROT_WRITE_PASS:
-       case SCSI_PROT_WRITE_CONVERT:
-       case SCSI_PROT_READ_CONVERT:
                ret = LPFC_PG_TYPE_DIF_BUF;
                break;
        default:
index 4a86855..70c4c24 100644 (file)
@@ -2,7 +2,7 @@
 # Kernel configuration file for the MPT2SAS
 #
 # This code is based on drivers/scsi/mpt2sas/Kconfig
-# Copyright (C) 2007-2008  LSI Corporation
+# Copyright (C) 2007-2009  LSI Corporation
 #  (mailto:DL-MPTFusionLinux@lsi.com)
 
 # This program is free software; you can redistribute it and/or
index 7bb2ece..f9f6c08 100644 (file)
@@ -8,7 +8,7 @@
  *                  scatter/gather formats.
  *  Creation Date:  June 21, 2006
  *
- *  mpi2.h Version:  02.00.11
+ *  mpi2.h Version:  02.00.12
  *
  *  Version History
  *  ---------------
  *  10-02-08  02.00.10  Bumped MPI2_HEADER_VERSION_UNIT.
  *                      Moved LUN field defines from mpi2_init.h.
  *  01-19-09  02.00.11  Bumped MPI2_HEADER_VERSION_UNIT.
+ *  05-06-09  02.00.12  Bumped MPI2_HEADER_VERSION_UNIT.
+ *                      In all request and reply descriptors, replaced VF_ID
+ *                      field with MSIxIndex field.
+ *                      Removed DevHandle field from
+ *                      MPI2_SCSI_IO_SUCCESS_REPLY_DESCRIPTOR and made those
+ *                      bytes reserved.
+ *                      Added RAID Accelerator functionality.
  *  --------------------------------------------------------------------------
  */
 
@@ -70,7 +77,7 @@
 #define MPI2_VERSION_02_00                  (0x0200)
 
 /* versioning for this MPI header set */
-#define MPI2_HEADER_VERSION_UNIT            (0x0B)
+#define MPI2_HEADER_VERSION_UNIT            (0x0C)
 #define MPI2_HEADER_VERSION_DEV             (0x00)
 #define MPI2_HEADER_VERSION_UNIT_MASK       (0xFF00)
 #define MPI2_HEADER_VERSION_UNIT_SHIFT      (8)
@@ -257,7 +264,7 @@ typedef volatile struct _MPI2_SYSTEM_INTERFACE_REGS
 typedef struct _MPI2_DEFAULT_REQUEST_DESCRIPTOR
 {
     U8              RequestFlags;               /* 0x00 */
-    U8              VF_ID;                      /* 0x01 */
+    U8              MSIxIndex;                  /* 0x01 */
     U16             SMID;                       /* 0x02 */
     U16             LMID;                       /* 0x04 */
     U16             DescriptorTypeDependent;    /* 0x06 */
@@ -271,6 +278,7 @@ typedef struct _MPI2_DEFAULT_REQUEST_DESCRIPTOR
 #define MPI2_REQ_DESCRIPT_FLAGS_SCSI_TARGET             (0x02)
 #define MPI2_REQ_DESCRIPT_FLAGS_HIGH_PRIORITY           (0x06)
 #define MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE            (0x08)
+#define MPI2_REQ_DESCRIPT_FLAGS_RAID_ACCELERATOR        (0x0A)
 
 #define MPI2_REQ_DESCRIPT_FLAGS_IOC_FIFO_MARKER (0x01)
 
@@ -279,7 +287,7 @@ typedef struct _MPI2_DEFAULT_REQUEST_DESCRIPTOR
 typedef struct _MPI2_HIGH_PRIORITY_REQUEST_DESCRIPTOR
 {
     U8              RequestFlags;               /* 0x00 */
-    U8              VF_ID;                      /* 0x01 */
+    U8              MSIxIndex;                  /* 0x01 */
     U16             SMID;                       /* 0x02 */
     U16             LMID;                       /* 0x04 */
     U16             Reserved1;                  /* 0x06 */
@@ -293,7 +301,7 @@ typedef struct _MPI2_HIGH_PRIORITY_REQUEST_DESCRIPTOR
 typedef struct _MPI2_SCSI_IO_REQUEST_DESCRIPTOR
 {
     U8              RequestFlags;               /* 0x00 */
-    U8              VF_ID;                      /* 0x01 */
+    U8              MSIxIndex;                  /* 0x01 */
     U16             SMID;                       /* 0x02 */
     U16             LMID;                       /* 0x04 */
     U16             DevHandle;                  /* 0x06 */
@@ -306,7 +314,7 @@ typedef struct _MPI2_SCSI_IO_REQUEST_DESCRIPTOR
 typedef struct _MPI2_SCSI_TARGET_REQUEST_DESCRIPTOR
 {
     U8              RequestFlags;               /* 0x00 */
-    U8              VF_ID;                      /* 0x01 */
+    U8              MSIxIndex;                  /* 0x01 */
     U16             SMID;                       /* 0x02 */
     U16             LMID;                       /* 0x04 */
     U16             IoIndex;                    /* 0x06 */
@@ -315,14 +323,29 @@ typedef struct _MPI2_SCSI_TARGET_REQUEST_DESCRIPTOR
   Mpi2SCSITargetRequestDescriptor_t,
   MPI2_POINTER pMpi2SCSITargetRequestDescriptor_t;
 
+
+/* RAID Accelerator Request Descriptor */
+typedef struct _MPI2_RAID_ACCEL_REQUEST_DESCRIPTOR {
+    U8              RequestFlags;               /* 0x00 */
+    U8              MSIxIndex;                  /* 0x01 */
+    U16             SMID;                       /* 0x02 */
+    U16             LMID;                       /* 0x04 */
+    U16             Reserved;                   /* 0x06 */
+} MPI2_RAID_ACCEL_REQUEST_DESCRIPTOR,
+  MPI2_POINTER PTR_MPI2_RAID_ACCEL_REQUEST_DESCRIPTOR,
+  Mpi2RAIDAcceleratorRequestDescriptor_t,
+  MPI2_POINTER pMpi2RAIDAcceleratorRequestDescriptor_t;
+
+
 /* union of Request Descriptors */
 typedef union _MPI2_REQUEST_DESCRIPTOR_UNION
 {
-    MPI2_DEFAULT_REQUEST_DESCRIPTOR         Default;
-    MPI2_HIGH_PRIORITY_REQUEST_DESCRIPTOR   HighPriority;
-    MPI2_SCSI_IO_REQUEST_DESCRIPTOR         SCSIIO;
-    MPI2_SCSI_TARGET_REQUEST_DESCRIPTOR     SCSITarget;
-    U64                                     Words;
+    MPI2_DEFAULT_REQUEST_DESCRIPTOR             Default;
+    MPI2_HIGH_PRIORITY_REQUEST_DESCRIPTOR       HighPriority;
+    MPI2_SCSI_IO_REQUEST_DESCRIPTOR             SCSIIO;
+    MPI2_SCSI_TARGET_REQUEST_DESCRIPTOR         SCSITarget;
+    MPI2_RAID_ACCEL_REQUEST_DESCRIPTOR          RAIDAccelerator;
+    U64                                         Words;
 } MPI2_REQUEST_DESCRIPTOR_UNION, MPI2_POINTER PTR_MPI2_REQUEST_DESCRIPTOR_UNION,
   Mpi2RequestDescriptorUnion_t, MPI2_POINTER pMpi2RequestDescriptorUnion_t;
 
@@ -333,19 +356,20 @@ typedef union _MPI2_REQUEST_DESCRIPTOR_UNION
 typedef struct _MPI2_DEFAULT_REPLY_DESCRIPTOR
 {
     U8              ReplyFlags;                 /* 0x00 */
-    U8              VF_ID;                      /* 0x01 */
+    U8              MSIxIndex;                  /* 0x01 */
     U16             DescriptorTypeDependent1;   /* 0x02 */
     U32             DescriptorTypeDependent2;   /* 0x04 */
 } MPI2_DEFAULT_REPLY_DESCRIPTOR, MPI2_POINTER PTR_MPI2_DEFAULT_REPLY_DESCRIPTOR,
   Mpi2DefaultReplyDescriptor_t, MPI2_POINTER pMpi2DefaultReplyDescriptor_t;
 
 /* defines for the ReplyFlags field */
-#define MPI2_RPY_DESCRIPT_FLAGS_TYPE_MASK               (0x0F)
-#define MPI2_RPY_DESCRIPT_FLAGS_SCSI_IO_SUCCESS         (0x00)
-#define MPI2_RPY_DESCRIPT_FLAGS_ADDRESS_REPLY           (0x01)
-#define MPI2_RPY_DESCRIPT_FLAGS_TARGETASSIST_SUCCESS    (0x02)
-#define MPI2_RPY_DESCRIPT_FLAGS_TARGET_COMMAND_BUFFER   (0x03)
-#define MPI2_RPY_DESCRIPT_FLAGS_UNUSED                  (0x0F)
+#define MPI2_RPY_DESCRIPT_FLAGS_TYPE_MASK                   (0x0F)
+#define MPI2_RPY_DESCRIPT_FLAGS_SCSI_IO_SUCCESS             (0x00)
+#define MPI2_RPY_DESCRIPT_FLAGS_ADDRESS_REPLY               (0x01)
+#define MPI2_RPY_DESCRIPT_FLAGS_TARGETASSIST_SUCCESS        (0x02)
+#define MPI2_RPY_DESCRIPT_FLAGS_TARGET_COMMAND_BUFFER       (0x03)
+#define MPI2_RPY_DESCRIPT_FLAGS_RAID_ACCELERATOR_SUCCESS    (0x05)
+#define MPI2_RPY_DESCRIPT_FLAGS_UNUSED                      (0x0F)
 
 /* values for marking a reply descriptor as unused */
 #define MPI2_RPY_DESCRIPT_UNUSED_WORD0_MARK             (0xFFFFFFFF)
@@ -355,7 +379,7 @@ typedef struct _MPI2_DEFAULT_REPLY_DESCRIPTOR
 typedef struct _MPI2_ADDRESS_REPLY_DESCRIPTOR
 {
     U8              ReplyFlags;                 /* 0x00 */
-    U8              VF_ID;                      /* 0x01 */
+    U8              MSIxIndex;                  /* 0x01 */
     U16             SMID;                       /* 0x02 */
     U32             ReplyFrameAddress;          /* 0x04 */
 } MPI2_ADDRESS_REPLY_DESCRIPTOR, MPI2_POINTER PTR_MPI2_ADDRESS_REPLY_DESCRIPTOR,
@@ -368,10 +392,10 @@ typedef struct _MPI2_ADDRESS_REPLY_DESCRIPTOR
 typedef struct _MPI2_SCSI_IO_SUCCESS_REPLY_DESCRIPTOR
 {
     U8              ReplyFlags;                 /* 0x00 */
-    U8              VF_ID;                      /* 0x01 */
+    U8              MSIxIndex;                  /* 0x01 */
     U16             SMID;                       /* 0x02 */
     U16             TaskTag;                    /* 0x04 */
-    U16             DevHandle;                  /* 0x06 */
+    U16             Reserved1;                  /* 0x06 */
 } MPI2_SCSI_IO_SUCCESS_REPLY_DESCRIPTOR,
   MPI2_POINTER PTR_MPI2_SCSI_IO_SUCCESS_REPLY_DESCRIPTOR,
   Mpi2SCSIIOSuccessReplyDescriptor_t,
@@ -382,7 +406,7 @@ typedef struct _MPI2_SCSI_IO_SUCCESS_REPLY_DESCRIPTOR
 typedef struct _MPI2_TARGETASSIST_SUCCESS_REPLY_DESCRIPTOR
 {
     U8              ReplyFlags;                 /* 0x00 */
-    U8              VF_ID;                      /* 0x01 */
+    U8              MSIxIndex;                  /* 0x01 */
     U16             SMID;                       /* 0x02 */
     U8              SequenceNumber;             /* 0x04 */
     U8              Reserved1;                  /* 0x05 */
@@ -397,7 +421,7 @@ typedef struct _MPI2_TARGETASSIST_SUCCESS_REPLY_DESCRIPTOR
 typedef struct _MPI2_TARGET_COMMAND_BUFFER_REPLY_DESCRIPTOR
 {
     U8              ReplyFlags;                 /* 0x00 */
-    U8              VF_ID;                      /* 0x01 */
+    U8              MSIxIndex;                  /* 0x01 */
     U8              VP_ID;                      /* 0x02 */
     U8              Flags;                      /* 0x03 */
     U16             InitiatorDevHandle;         /* 0x04 */
@@ -411,15 +435,28 @@ typedef struct _MPI2_TARGET_COMMAND_BUFFER_REPLY_DESCRIPTOR
 #define MPI2_RPY_DESCRIPT_TCB_FLAGS_PHYNUM_MASK     (0x3F)
 
 
+/* RAID Accelerator Success Reply Descriptor */
+typedef struct _MPI2_RAID_ACCELERATOR_SUCCESS_REPLY_DESCRIPTOR {
+    U8              ReplyFlags;                 /* 0x00 */
+    U8              MSIxIndex;                  /* 0x01 */
+    U16             SMID;                       /* 0x02 */
+    U32             Reserved;                   /* 0x04 */
+} MPI2_RAID_ACCELERATOR_SUCCESS_REPLY_DESCRIPTOR,
+  MPI2_POINTER PTR_MPI2_RAID_ACCELERATOR_SUCCESS_REPLY_DESCRIPTOR,
+  Mpi2RAIDAcceleratorSuccessReplyDescriptor_t,
+  MPI2_POINTER pMpi2RAIDAcceleratorSuccessReplyDescriptor_t;
+
+
 /* union of Reply Descriptors */
 typedef union _MPI2_REPLY_DESCRIPTORS_UNION
 {
-    MPI2_DEFAULT_REPLY_DESCRIPTOR               Default;
-    MPI2_ADDRESS_REPLY_DESCRIPTOR               AddressReply;
-    MPI2_SCSI_IO_SUCCESS_REPLY_DESCRIPTOR       SCSIIOSuccess;
-    MPI2_TARGETASSIST_SUCCESS_REPLY_DESCRIPTOR  TargetAssistSuccess;
-    MPI2_TARGET_COMMAND_BUFFER_REPLY_DESCRIPTOR TargetCommandBuffer;
-    U64                                         Words;
+    MPI2_DEFAULT_REPLY_DESCRIPTOR                   Default;
+    MPI2_ADDRESS_REPLY_DESCRIPTOR                   AddressReply;
+    MPI2_SCSI_IO_SUCCESS_REPLY_DESCRIPTOR           SCSIIOSuccess;
+    MPI2_TARGETASSIST_SUCCESS_REPLY_DESCRIPTOR      TargetAssistSuccess;
+    MPI2_TARGET_COMMAND_BUFFER_REPLY_DESCRIPTOR     TargetCommandBuffer;
+    MPI2_RAID_ACCELERATOR_SUCCESS_REPLY_DESCRIPTOR  RAIDAcceleratorSuccess;
+    U64                                             Words;
 } MPI2_REPLY_DESCRIPTORS_UNION, MPI2_POINTER PTR_MPI2_REPLY_DESCRIPTORS_UNION,
   Mpi2ReplyDescriptorsUnion_t, MPI2_POINTER pMpi2ReplyDescriptorsUnion_t;
 
@@ -458,6 +495,7 @@ typedef union _MPI2_REPLY_DESCRIPTORS_UNION
 #define MPI2_FUNCTION_DIAG_RELEASE                  (0x1E) /* Diagnostic Release */
 #define MPI2_FUNCTION_TARGET_CMD_BUF_BASE_POST      (0x24) /* Target Command Buffer Post Base */
 #define MPI2_FUNCTION_TARGET_CMD_BUF_LIST_POST      (0x25) /* Target Command Buffer Post List */
+#define MPI2_FUNCTION_RAID_ACCELERATOR              (0x2C) /* RAID Accelerator*/
 
 
 
@@ -555,12 +593,17 @@ typedef union _MPI2_REPLY_DESCRIPTORS_UNION
 
 #define MPI2_IOCSTATUS_DIAGNOSTIC_RELEASED          (0x00A0)
 
+/****************************************************************************
+*  RAID Accelerator values
+****************************************************************************/
+
+#define MPI2_IOCSTATUS_RAID_ACCEL_ERROR             (0x00B0)
 
 /****************************************************************************
 *  IOCStatus flag to indicate that log info is available
 ****************************************************************************/
 
-#define MPI2_IOCSTATUS_FLAG_LOG_INFO_AVAILABLE  (0x8000)
+#define MPI2_IOCSTATUS_FLAG_LOG_INFO_AVAILABLE      (0x8000)
 
 /****************************************************************************
 *  IOCLogInfo Types
index 2f27cf6..ab47c46 100644 (file)
@@ -6,7 +6,7 @@
  *          Title:  MPI Configuration messages and pages
  *  Creation Date:  November 10, 2006
  *
- *    mpi2_cnfg.h Version:  02.00.10
+ *    mpi2_cnfg.h Version:  02.00.11
  *
  *  Version History
  *  ---------------
  *                      Added MPI2_SAS_DEVICE0_ASTATUS_DEVICE_BLOCKED define.
  *                      Added PortGroups, DmaGroup, and ControlGroup fields to
  *                      SAS Device Page 0.
+ *  05-06-09  02.00.11  Added structures and defines for IO Unit Page 5 and IO
+ *                      Unit Page 6.
+ *                      Added expander reduced functionality data to SAS
+ *                      Expander Page 0.
+ *                      Added SAS PHY Page 2 and SAS PHY Page 3.
  *  --------------------------------------------------------------------------
  */
 
@@ -723,6 +728,65 @@ typedef struct _MPI2_CONFIG_PAGE_IO_UNIT_3
 #define MPI2_IOUNITPAGE3_GPIO_SETTING_ON                (0x0001)
 
 
+/* IO Unit Page 5 */
+
+/*
+ * Upper layer code (drivers, utilities, etc.) should leave this define set to
+ * one and check Header.PageLength or NumDmaEngines at runtime.
+ */
+#ifndef MPI2_IOUNITPAGE5_DMAENGINE_ENTRIES
+#define MPI2_IOUNITPAGE5_DMAENGINE_ENTRIES      (1)
+#endif
+
+typedef struct _MPI2_CONFIG_PAGE_IO_UNIT_5 {
+    MPI2_CONFIG_PAGE_HEADER Header;                            /* 0x00 */
+    U64                     RaidAcceleratorBufferBaseAddress;  /* 0x04 */
+    U64                     RaidAcceleratorBufferSize;         /* 0x0C */
+    U64                     RaidAcceleratorControlBaseAddress; /* 0x14 */
+    U8                      RAControlSize;                     /* 0x1C */
+    U8                      NumDmaEngines;                     /* 0x1D */
+    U8                      RAMinControlSize;                  /* 0x1E */
+    U8                      RAMaxControlSize;                  /* 0x1F */
+    U32                     Reserved1;                         /* 0x20 */
+    U32                     Reserved2;                         /* 0x24 */
+    U32                     Reserved3;                         /* 0x28 */
+    U32                     DmaEngineCapabilities
+                               [MPI2_IOUNITPAGE5_DMAENGINE_ENTRIES]; /* 0x2C */
+} MPI2_CONFIG_PAGE_IO_UNIT_5, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_IO_UNIT_5,
+  Mpi2IOUnitPage5_t, MPI2_POINTER pMpi2IOUnitPage5_t;
+
+#define MPI2_IOUNITPAGE5_PAGEVERSION                    (0x00)
+
+/* defines for IO Unit Page 5 DmaEngineCapabilities field */
+#define MPI2_IOUNITPAGE5_DMA_CAP_MASK_MAX_REQUESTS      (0xFF00)
+#define MPI2_IOUNITPAGE5_DMA_CAP_SHIFT_MAX_REQUESTS     (16)
+
+#define MPI2_IOUNITPAGE5_DMA_CAP_EEDP                   (0x0008)
+#define MPI2_IOUNITPAGE5_DMA_CAP_PARITY_GENERATION      (0x0004)
+#define MPI2_IOUNITPAGE5_DMA_CAP_HASHING                (0x0002)
+#define MPI2_IOUNITPAGE5_DMA_CAP_ENCRYPTION             (0x0001)
+
+
+/* IO Unit Page 6 */
+
+typedef struct _MPI2_CONFIG_PAGE_IO_UNIT_6 {
+    MPI2_CONFIG_PAGE_HEADER Header;                                 /* 0x00 */
+    U16                     Flags;                                  /* 0x04 */
+    U8                      RAHostControlSize;                      /* 0x06 */
+    U8                      Reserved0;                              /* 0x07 */
+    U64                     RaidAcceleratorHostControlBaseAddress;  /* 0x08 */
+    U32                     Reserved1;                              /* 0x10 */
+    U32                     Reserved2;                              /* 0x14 */
+    U32                     Reserved3;                              /* 0x18 */
+} MPI2_CONFIG_PAGE_IO_UNIT_6, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_IO_UNIT_6,
+  Mpi2IOUnitPage6_t, MPI2_POINTER pMpi2IOUnitPage6_t;
+
+#define MPI2_IOUNITPAGE6_PAGEVERSION                    (0x00)
+
+/* defines for IO Unit Page 6 Flags field */
+#define MPI2_IOUNITPAGE6_FLAGS_ENABLE_RAID_ACCELERATOR  (0x0001)
+
+
 /****************************************************************************
 *   IOC Config Pages
 ****************************************************************************/
@@ -1709,10 +1773,14 @@ typedef struct _MPI2_CONFIG_PAGE_EXPANDER_0
     U64                                 ActiveZoneManagerSASAddress;/* 0x2C */
     U16                                 ZoneLockInactivityLimit;    /* 0x34 */
     U16                                 Reserved1;                  /* 0x36 */
+    U8                                  TimeToReducedFunc;          /* 0x38 */
+    U8                                  InitialTimeToReducedFunc;   /* 0x39 */
+    U8                                  MaxReducedFuncTime;         /* 0x3A */
+    U8                                  Reserved2;                  /* 0x3B */
 } MPI2_CONFIG_PAGE_EXPANDER_0, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_EXPANDER_0,
   Mpi2ExpanderPage0_t, MPI2_POINTER pMpi2ExpanderPage0_t;
 
-#define MPI2_SASEXPANDER0_PAGEVERSION       (0x05)
+#define MPI2_SASEXPANDER0_PAGEVERSION       (0x06)
 
 /* values for SAS Expander Page 0 DiscoveryStatus field */
 #define MPI2_SAS_EXPANDER0_DS_MAX_ENCLOSURES_EXCEED         (0x80000000)
@@ -1737,6 +1805,7 @@ typedef struct _MPI2_CONFIG_PAGE_EXPANDER_0
 #define MPI2_SAS_EXPANDER0_DS_LOOP_DETECTED                 (0x00000001)
 
 /* values for SAS Expander Page 0 Flags field */
+#define MPI2_SAS_EXPANDER0_FLAGS_REDUCED_FUNCTIONALITY      (0x2000)
 #define MPI2_SAS_EXPANDER0_FLAGS_ZONE_LOCKED                (0x1000)
 #define MPI2_SAS_EXPANDER0_FLAGS_SUPPORTED_PHYSICAL_PRES    (0x0800)
 #define MPI2_SAS_EXPANDER0_FLAGS_ASSERTED_PHYSICAL_PRES     (0x0400)
@@ -1944,6 +2013,133 @@ typedef struct _MPI2_CONFIG_PAGE_SAS_PHY_1
 #define MPI2_SASPHY1_PAGEVERSION            (0x01)
 
 
+/* SAS PHY Page 2 */
+
+typedef struct _MPI2_SASPHY2_PHY_EVENT {
+    U8          PhyEventCode;       /* 0x00 */
+    U8          Reserved1;          /* 0x01 */
+    U16         Reserved2;          /* 0x02 */
+    U32         PhyEventInfo;       /* 0x04 */
+} MPI2_SASPHY2_PHY_EVENT, MPI2_POINTER PTR_MPI2_SASPHY2_PHY_EVENT,
+  Mpi2SasPhy2PhyEvent_t, MPI2_POINTER pMpi2SasPhy2PhyEvent_t;
+
+/* use MPI2_SASPHY3_EVENT_CODE_ for the PhyEventCode field */
+
+
+/*
+ * Host code (drivers, BIOS, utilities, etc.) should leave this define set to
+ * one and check Header.ExtPageLength or NumPhyEvents at runtime.
+ */
+#ifndef MPI2_SASPHY2_PHY_EVENT_MAX
+#define MPI2_SASPHY2_PHY_EVENT_MAX      (1)
+#endif
+
+typedef struct _MPI2_CONFIG_PAGE_SAS_PHY_2 {
+    MPI2_CONFIG_EXTENDED_PAGE_HEADER    Header;                     /* 0x00 */
+    U32                                 Reserved1;                  /* 0x08 */
+    U8                                  NumPhyEvents;               /* 0x0C */
+    U8                                  Reserved2;                  /* 0x0D */
+    U16                                 Reserved3;                  /* 0x0E */
+    MPI2_SASPHY2_PHY_EVENT              PhyEvent[MPI2_SASPHY2_PHY_EVENT_MAX];
+                                                               /* 0x10 */
+} MPI2_CONFIG_PAGE_SAS_PHY_2, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_SAS_PHY_2,
+  Mpi2SasPhyPage2_t, MPI2_POINTER pMpi2SasPhyPage2_t;
+
+#define MPI2_SASPHY2_PAGEVERSION            (0x00)
+
+
+/* SAS PHY Page 3 */
+
+typedef struct _MPI2_SASPHY3_PHY_EVENT_CONFIG {
+    U8          PhyEventCode;       /* 0x00 */
+    U8          Reserved1;          /* 0x01 */
+    U16         Reserved2;          /* 0x02 */
+    U8          CounterType;        /* 0x04 */
+    U8          ThresholdWindow;    /* 0x05 */
+    U8          TimeUnits;          /* 0x06 */
+    U8          Reserved3;          /* 0x07 */
+    U32         EventThreshold;     /* 0x08 */
+    U16         ThresholdFlags;     /* 0x0C */
+    U16         Reserved4;          /* 0x0E */
+} MPI2_SASPHY3_PHY_EVENT_CONFIG, MPI2_POINTER PTR_MPI2_SASPHY3_PHY_EVENT_CONFIG,
+  Mpi2SasPhy3PhyEventConfig_t, MPI2_POINTER pMpi2SasPhy3PhyEventConfig_t;
+
+/* values for PhyEventCode field */
+#define MPI2_SASPHY3_EVENT_CODE_NO_EVENT                    (0x00)
+#define MPI2_SASPHY3_EVENT_CODE_INVALID_DWORD               (0x01)
+#define MPI2_SASPHY3_EVENT_CODE_RUNNING_DISPARITY_ERROR     (0x02)
+#define MPI2_SASPHY3_EVENT_CODE_LOSS_DWORD_SYNC             (0x03)
+#define MPI2_SASPHY3_EVENT_CODE_PHY_RESET_PROBLEM           (0x04)
+#define MPI2_SASPHY3_EVENT_CODE_ELASTICITY_BUF_OVERFLOW     (0x05)
+#define MPI2_SASPHY3_EVENT_CODE_RX_ERROR                    (0x06)
+#define MPI2_SASPHY3_EVENT_CODE_RX_ADDR_FRAME_ERROR         (0x20)
+#define MPI2_SASPHY3_EVENT_CODE_TX_AC_OPEN_REJECT           (0x21)
+#define MPI2_SASPHY3_EVENT_CODE_RX_AC_OPEN_REJECT           (0x22)
+#define MPI2_SASPHY3_EVENT_CODE_TX_RC_OPEN_REJECT           (0x23)
+#define MPI2_SASPHY3_EVENT_CODE_RX_RC_OPEN_REJECT           (0x24)
+#define MPI2_SASPHY3_EVENT_CODE_RX_AIP_PARTIAL_WAITING_ON   (0x25)
+#define MPI2_SASPHY3_EVENT_CODE_RX_AIP_CONNECT_WAITING_ON   (0x26)
+#define MPI2_SASPHY3_EVENT_CODE_TX_BREAK                    (0x27)
+#define MPI2_SASPHY3_EVENT_CODE_RX_BREAK                    (0x28)
+#define MPI2_SASPHY3_EVENT_CODE_BREAK_TIMEOUT               (0x29)
+#define MPI2_SASPHY3_EVENT_CODE_CONNECTION                  (0x2A)
+#define MPI2_SASPHY3_EVENT_CODE_PEAKTX_PATHWAY_BLOCKED      (0x2B)
+#define MPI2_SASPHY3_EVENT_CODE_PEAKTX_ARB_WAIT_TIME        (0x2C)
+#define MPI2_SASPHY3_EVENT_CODE_PEAK_ARB_WAIT_TIME          (0x2D)
+#define MPI2_SASPHY3_EVENT_CODE_PEAK_CONNECT_TIME           (0x2E)
+#define MPI2_SASPHY3_EVENT_CODE_TX_SSP_FRAMES               (0x40)
+#define MPI2_SASPHY3_EVENT_CODE_RX_SSP_FRAMES               (0x41)
+#define MPI2_SASPHY3_EVENT_CODE_TX_SSP_ERROR_FRAMES         (0x42)
+#define MPI2_SASPHY3_EVENT_CODE_RX_SSP_ERROR_FRAMES         (0x43)
+#define MPI2_SASPHY3_EVENT_CODE_TX_CREDIT_BLOCKED           (0x44)
+#define MPI2_SASPHY3_EVENT_CODE_RX_CREDIT_BLOCKED           (0x45)
+#define MPI2_SASPHY3_EVENT_CODE_TX_SATA_FRAMES              (0x50)
+#define MPI2_SASPHY3_EVENT_CODE_RX_SATA_FRAMES              (0x51)
+#define MPI2_SASPHY3_EVENT_CODE_SATA_OVERFLOW               (0x52)
+#define MPI2_SASPHY3_EVENT_CODE_TX_SMP_FRAMES               (0x60)
+#define MPI2_SASPHY3_EVENT_CODE_RX_SMP_FRAMES               (0x61)
+#define MPI2_SASPHY3_EVENT_CODE_RX_SMP_ERROR_FRAMES         (0x63)
+#define MPI2_SASPHY3_EVENT_CODE_HOTPLUG_TIMEOUT             (0xD0)
+#define MPI2_SASPHY3_EVENT_CODE_MISALIGNED_MUX_PRIMITIVE    (0xD1)
+#define MPI2_SASPHY3_EVENT_CODE_RX_AIP                      (0xD2)
+
+/* values for the CounterType field */
+#define MPI2_SASPHY3_COUNTER_TYPE_WRAPPING                  (0x00)
+#define MPI2_SASPHY3_COUNTER_TYPE_SATURATING                (0x01)
+#define MPI2_SASPHY3_COUNTER_TYPE_PEAK_VALUE                (0x02)
+
+/* values for the TimeUnits field */
+#define MPI2_SASPHY3_TIME_UNITS_10_MICROSECONDS             (0x00)
+#define MPI2_SASPHY3_TIME_UNITS_100_MICROSECONDS            (0x01)
+#define MPI2_SASPHY3_TIME_UNITS_1_MILLISECOND               (0x02)
+#define MPI2_SASPHY3_TIME_UNITS_10_MILLISECONDS             (0x03)
+
+/* values for the ThresholdFlags field */
+#define MPI2_SASPHY3_TFLAGS_PHY_RESET                       (0x0002)
+#define MPI2_SASPHY3_TFLAGS_EVENT_NOTIFY                    (0x0001)
+
+/*
+ * Host code (drivers, BIOS, utilities, etc.) should leave this define set to
+ * one and check Header.ExtPageLength or NumPhyEvents at runtime.
+ */
+#ifndef MPI2_SASPHY3_PHY_EVENT_MAX
+#define MPI2_SASPHY3_PHY_EVENT_MAX      (1)
+#endif
+
+typedef struct _MPI2_CONFIG_PAGE_SAS_PHY_3 {
+    MPI2_CONFIG_EXTENDED_PAGE_HEADER    Header;                     /* 0x00 */
+    U32                                 Reserved1;                  /* 0x08 */
+    U8                                  NumPhyEvents;               /* 0x0C */
+    U8                                  Reserved2;                  /* 0x0D */
+    U16                                 Reserved3;                  /* 0x0E */
+    MPI2_SASPHY3_PHY_EVENT_CONFIG       PhyEventConfig
+                                       [MPI2_SASPHY3_PHY_EVENT_MAX]; /* 0x10 */
+} MPI2_CONFIG_PAGE_SAS_PHY_3, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_SAS_PHY_3,
+  Mpi2SasPhyPage3_t, MPI2_POINTER pMpi2SasPhyPage3_t;
+
+#define MPI2_SASPHY3_PAGEVERSION            (0x00)
+
+
 /****************************************************************************
 *   SAS Port Config Pages
 ****************************************************************************/
diff --git a/drivers/scsi/mpt2sas/mpi/mpi2_history.txt b/drivers/scsi/mpt2sas/mpi/mpi2_history.txt
new file mode 100644 (file)
index 0000000..65fcaa3
--- /dev/null
@@ -0,0 +1,334 @@
+ ==============================
+ Fusion-MPT MPI 2.0 Header File Change History
+ ==============================
+
+ Copyright (c) 2000-2009 LSI Corporation.
+
+ ---------------------------------------
+ Header Set Release Version:    02.00.12
+ Header Set Release Date:       05-06-09
+ ---------------------------------------
+
+ Filename               Current version     Prior version
+ ----------             ---------------     -------------
+ mpi2.h                 02.00.12            02.00.11
+ mpi2_cnfg.h            02.00.11            02.00.10
+ mpi2_init.h            02.00.07            02.00.06
+ mpi2_ioc.h             02.00.11            02.00.10
+ mpi2_raid.h            02.00.03            02.00.03
+ mpi2_sas.h             02.00.02            02.00.02
+ mpi2_targ.h            02.00.03            02.00.03
+ mpi2_tool.h            02.00.03            02.00.02
+ mpi2_type.h            02.00.00            02.00.00
+ mpi2_ra.h              02.00.00
+ mpi2_history.txt       02.00.11            02.00.12
+
+
+ *  Date      Version   Description
+ *  --------  --------  ------------------------------------------------------
+
+mpi2.h
+ *  04-30-07  02.00.00  Corresponds to Fusion-MPT MPI Specification Rev A.
+ *  06-04-07  02.00.01  Bumped MPI2_HEADER_VERSION_UNIT.
+ *  06-26-07  02.00.02  Bumped MPI2_HEADER_VERSION_UNIT.
+ *  08-31-07  02.00.03  Bumped MPI2_HEADER_VERSION_UNIT.
+ *                      Moved ReplyPostHostIndex register to offset 0x6C of the
+ *                      MPI2_SYSTEM_INTERFACE_REGS and modified the define for
+ *                      MPI2_REPLY_POST_HOST_INDEX_OFFSET.
+ *                      Added union of request descriptors.
+ *                      Added union of reply descriptors.
+ *  10-31-07  02.00.04  Bumped MPI2_HEADER_VERSION_UNIT.
+ *                      Added define for MPI2_VERSION_02_00.
+ *                      Fixed the size of the FunctionDependent5 field in the
+ *                      MPI2_DEFAULT_REPLY structure.
+ *  12-18-07  02.00.05  Bumped MPI2_HEADER_VERSION_UNIT.
+ *                      Removed the MPI-defined Fault Codes and extended the
+ *                      product specific codes up to 0xEFFF.
+ *                      Added a sixth key value for the WriteSequence register
+ *                      and changed the flush value to 0x0.
+ *                      Added message function codes for Diagnostic Buffer Post
+ *                      and Diagnsotic Release.
+ *                      New IOCStatus define: MPI2_IOCSTATUS_DIAGNOSTIC_RELEASED
+ *                      Moved MPI2_VERSION_UNION from mpi2_ioc.h.
+ *  02-29-08  02.00.06  Bumped MPI2_HEADER_VERSION_UNIT.
+ *  03-03-08  02.00.07  Bumped MPI2_HEADER_VERSION_UNIT.
+ *  05-21-08  02.00.08  Bumped MPI2_HEADER_VERSION_UNIT.
+ *                      Added #defines for marking a reply descriptor as unused.
+ *  06-27-08  02.00.09  Bumped MPI2_HEADER_VERSION_UNIT.
+ *  10-02-08  02.00.10  Bumped MPI2_HEADER_VERSION_UNIT.
+ *                      Moved LUN field defines from mpi2_init.h.
+ *  01-19-09  02.00.11  Bumped MPI2_HEADER_VERSION_UNIT.
+ *  05-06-09  02.00.12  Bumped MPI2_HEADER_VERSION_UNIT.
+ *                      In all request and reply descriptors, replaced VF_ID
+ *                      field with MSIxIndex field.
+ *                      Removed DevHandle field from
+ *                      MPI2_SCSI_IO_SUCCESS_REPLY_DESCRIPTOR and made those
+ *                      bytes reserved.
+ *                      Added RAID Accelerator functionality.
+ *  --------------------------------------------------------------------------
+
+mpi2_cnfg.h
+ *  04-30-07  02.00.00  Corresponds to Fusion-MPT MPI Specification Rev A.
+ *  06-04-07  02.00.01  Added defines for SAS IO Unit Page 2 PhyFlags.
+ *                      Added Manufacturing Page 11.
+ *                      Added MPI2_SAS_EXPANDER0_FLAGS_CONNECTOR_END_DEVICE
+ *                      define.
+ *  06-26-07  02.00.02  Adding generic structure for product-specific
+ *                      Manufacturing pages: MPI2_CONFIG_PAGE_MANUFACTURING_PS.
+ *                      Rework of BIOS Page 2 configuration page.
+ *                      Fixed MPI2_BIOSPAGE2_BOOT_DEVICE to be a union of the
+ *                      forms.
+ *                      Added configuration pages IOC Page 8 and Driver
+ *                      Persistent Mapping Page 0.
+ *  08-31-07  02.00.03  Modified configuration pages dealing with Integrated
+ *                      RAID (Manufacturing Page 4, RAID Volume Pages 0 and 1,
+ *                      RAID Physical Disk Pages 0 and 1, RAID Configuration
+ *                      Page 0).
+ *                      Added new value for AccessStatus field of SAS Device
+ *                      Page 0 (_SATA_NEEDS_INITIALIZATION).
+ *  10-31-07  02.00.04  Added missing SEPDevHandle field to
+ *                      MPI2_CONFIG_PAGE_SAS_ENCLOSURE_0.
+ *  12-18-07  02.00.05  Modified IO Unit Page 0 to use 32-bit version fields for
+ *                      NVDATA.
+ *                      Modified IOC Page 7 to use masks and added field for
+ *                      SASBroadcastPrimitiveMasks.
+ *                      Added MPI2_CONFIG_PAGE_BIOS_4.
+ *                      Added MPI2_CONFIG_PAGE_LOG_0.
+ *  02-29-08  02.00.06  Modified various names to make them 32-character unique.
+ *                      Added SAS Device IDs.
+ *                      Updated Integrated RAID configuration pages including
+ *                      Manufacturing Page 4, IOC Page 6, and RAID Configuration
+ *                      Page 0.
+ *  05-21-08  02.00.07  Added define MPI2_MANPAGE4_MIX_SSD_SAS_SATA.
+ *                      Added define MPI2_MANPAGE4_PHYSDISK_128MB_COERCION.
+ *                      Fixed define MPI2_IOCPAGE8_FLAGS_ENCLOSURE_SLOT_MAPPING.
+ *                      Added missing MaxNumRoutedSasAddresses field to
+ *                      MPI2_CONFIG_PAGE_EXPANDER_0.
+ *                      Added SAS Port Page 0.
+ *                      Modified structure layout for
+ *                      MPI2_CONFIG_PAGE_DRIVER_MAPPING_0.
+ *  06-27-08  02.00.08  Changed MPI2_CONFIG_PAGE_RD_PDISK_1 to use
+ *                      MPI2_RAID_PHYS_DISK1_PATH_MAX to size the array.
+ *  10-02-08  02.00.09  Changed MPI2_RAID_PGAD_CONFIGNUM_MASK from 0x0000FFFF
+ *                      to 0x000000FF.
+ *                      Added two new values for the Physical Disk Coercion Size
+ *                      bits in the Flags field of Manufacturing Page 4.
+ *                      Added product-specific Manufacturing pages 16 to 31.
+ *                      Modified Flags bits for controlling write cache on SATA
+ *                      drives in IO Unit Page 1.
+ *                      Added new bit to AdditionalControlFlags of SAS IO Unit
+ *                      Page 1 to control Invalid Topology Correction.
+ *                      Added SupportedPhysDisks field to RAID Volume Page 1 and
+ *                      added related defines.
+ *                      Added additional defines for RAID Volume Page 0
+ *                      VolumeStatusFlags field.
+ *                      Modified meaning of RAID Volume Page 0 VolumeSettings
+ *                      define for auto-configure of hot-swap drives.
+ *                      Added PhysDiskAttributes field (and related defines) to
+ *                      RAID Physical Disk Page 0.
+ *                      Added MPI2_SAS_PHYINFO_PHY_VACANT define.
+ *                      Added three new DiscoveryStatus bits for SAS IO Unit
+ *                      Page 0 and SAS Expander Page 0.
+ *                      Removed multiplexing information from SAS IO Unit pages.
+ *                      Added BootDeviceWaitTime field to SAS IO Unit Page 4.
+ *                      Removed Zone Address Resolved bit from PhyInfo and from
+ *                      Expander Page 0 Flags field.
+ *                      Added two new AccessStatus values to SAS Device Page 0
+ *                      for indicating routing problems. Added 3 reserved words
+ *                      to this page.
+ *  01-19-09  02.00.10  Fixed defines for GPIOVal field of IO Unit Page 3.
+ *                      Inserted missing reserved field into structure for IOC
+ *                      Page 6.
+ *                      Added more pending task bits to RAID Volume Page 0
+ *                      VolumeStatusFlags defines.
+ *                      Added MPI2_PHYSDISK0_STATUS_FLAG_NOT_CERTIFIED define.
+ *                      Added a new DiscoveryStatus bit for SAS IO Unit Page 0
+ *                      and SAS Expander Page 0 to flag a downstream initiator
+ *                      when in simplified routing mode.
+ *                      Removed SATA Init Failure defines for DiscoveryStatus
+ *                      fields of SAS IO Unit Page 0 and SAS Expander Page 0.
+ *                      Added MPI2_SAS_DEVICE0_ASTATUS_DEVICE_BLOCKED define.
+ *                      Added PortGroups, DmaGroup, and ControlGroup fields to
+ *                      SAS Device Page 0.
+ *  05-06-09  02.00.11  Added structures and defines for IO Unit Page 5 and IO
+ *                      Unit Page 6.
+ *                      Added expander reduced functionality data to SAS
+ *                      Expander Page 0.
+ *                      Added SAS PHY Page 2 and SAS PHY Page 3.
+ *  --------------------------------------------------------------------------
+
+mpi2_init.h
+ *  04-30-07  02.00.00  Corresponds to Fusion-MPT MPI Specification Rev A.
+ *  10-31-07  02.00.01  Fixed name for pMpi2SCSITaskManagementRequest_t.
+ *  12-18-07  02.00.02  Modified Task Management Target Reset Method defines.
+ *  02-29-08  02.00.03  Added Query Task Set and Query Unit Attention.
+ *  03-03-08  02.00.04  Fixed name of struct _MPI2_SCSI_TASK_MANAGE_REPLY.
+ *  05-21-08  02.00.05  Fixed typo in name of Mpi2SepRequest_t.
+ *  10-02-08  02.00.06  Removed Untagged and No Disconnect values from SCSI IO
+ *                      Control field Task Attribute flags.
+ *                      Moved LUN field defines to mpi2.h becasue they are
+ *                      common to many structures.
+ *  05-06-09  02.00.07  Changed task management type of Query Unit Attention to
+ *                      Query Asynchronous Event.
+ *                      Defined two new bits in the SlotStatus field of the SCSI
+ *                      Enclosure Processor Request and Reply.
+ *  --------------------------------------------------------------------------
+
+mpi2_ioc.h
+ *  04-30-07  02.00.00  Corresponds to Fusion-MPT MPI Specification Rev A.
+ *  06-04-07  02.00.01  In IOCFacts Reply structure, renamed MaxDevices to
+ *                      MaxTargets.
+ *                      Added TotalImageSize field to FWDownload Request.
+ *                      Added reserved words to FWUpload Request.
+ *  06-26-07  02.00.02  Added IR Configuration Change List Event.
+ *  08-31-07  02.00.03  Removed SystemReplyQueueDepth field from the IOCInit
+ *                      request and replaced it with
+ *                      ReplyDescriptorPostQueueDepth and ReplyFreeQueueDepth.
+ *                      Replaced the MinReplyQueueDepth field of the IOCFacts
+ *                      reply with MaxReplyDescriptorPostQueueDepth.
+ *                      Added MPI2_RDPQ_DEPTH_MIN define to specify the minimum
+ *                      depth for the Reply Descriptor Post Queue.
+ *                      Added SASAddress field to Initiator Device Table
+ *                      Overflow Event data.
+ *  10-31-07  02.00.04  Added ReasonCode MPI2_EVENT_SAS_INIT_RC_NOT_RESPONDING
+ *                      for SAS Initiator Device Status Change Event data.
+ *                      Modified Reason Code defines for SAS Topology Change
+ *                      List Event data, including adding a bit for PHY Vacant
+ *                      status, and adding a mask for the Reason Code.
+ *                      Added define for
+ *                      MPI2_EVENT_SAS_TOPO_ES_DELAY_NOT_RESPONDING.
+ *                      Added define for MPI2_EXT_IMAGE_TYPE_MEGARAID.
+ *  12-18-07  02.00.05  Added Boot Status defines for the IOCExceptions field of
+ *                      the IOCFacts Reply.
+ *                      Removed MPI2_IOCFACTS_CAPABILITY_EXTENDED_BUFFER define.
+ *                      Moved MPI2_VERSION_UNION to mpi2.h.
+ *                      Changed MPI2_EVENT_NOTIFICATION_REQUEST to use masks
+ *                      instead of enables, and added SASBroadcastPrimitiveMasks
+ *                      field.
+ *                      Added Log Entry Added Event and related structure.
+ *  02-29-08  02.00.06  Added define MPI2_IOCFACTS_CAPABILITY_INTEGRATED_RAID.
+ *                      Removed define MPI2_IOCFACTS_PROTOCOL_SMP_TARGET.
+ *                      Added MaxVolumes and MaxPersistentEntries fields to
+ *                      IOCFacts reply.
+ *                      Added ProtocalFlags and IOCCapabilities fields to
+ *                      MPI2_FW_IMAGE_HEADER.
+ *                      Removed MPI2_PORTENABLE_FLAGS_ENABLE_SINGLE_PORT.
+ *  03-03-08  02.00.07  Fixed MPI2_FW_IMAGE_HEADER by changing Reserved26 to
+ *                      a U16 (from a U32).
+ *                      Removed extra 's' from EventMasks name.
+ *  06-27-08  02.00.08  Fixed an offset in a comment.
+ *  10-02-08  02.00.09  Removed SystemReplyFrameSize from MPI2_IOC_INIT_REQUEST.
+ *                      Removed CurReplyFrameSize from MPI2_IOC_FACTS_REPLY and
+ *                      renamed MinReplyFrameSize to ReplyFrameSize.
+ *                      Added MPI2_IOCFACTS_EXCEPT_IR_FOREIGN_CONFIG_MAX.
+ *                      Added two new RAIDOperation values for Integrated RAID
+ *                      Operations Status Event data.
+ *                      Added four new IR Configuration Change List Event data
+ *                      ReasonCode values.
+ *                      Added two new ReasonCode defines for SAS Device Status
+ *                      Change Event data.
+ *                      Added three new DiscoveryStatus bits for the SAS
+ *                      Discovery event data.
+ *                      Added Multiplexing Status Change bit to the PhyStatus
+ *                      field of the SAS Topology Change List event data.
+ *                      Removed define for MPI2_INIT_IMAGE_BOOTFLAGS_XMEMCOPY.
+ *                      BootFlags are now product-specific.
+ *                      Added defines for the indivdual signature bytes
+ *                      for MPI2_INIT_IMAGE_FOOTER.
+ *  01-19-09  02.00.10  Added MPI2_IOCFACTS_CAPABILITY_EVENT_REPLAY define.
+ *                      Added MPI2_EVENT_SAS_DISC_DS_DOWNSTREAM_INITIATOR
+ *                      define.
+ *                      Added MPI2_EVENT_SAS_DEV_STAT_RC_SATA_INIT_FAILURE
+ *                      define.
+ *                      Removed MPI2_EVENT_SAS_DISC_DS_SATA_INIT_FAILURE define.
+ *  05-06-09  02.00.11  Added MPI2_IOCFACTS_CAPABILITY_RAID_ACCELERATOR define.
+ *                      Added MPI2_IOCFACTS_CAPABILITY_MSI_X_INDEX define.
+ *                      Added two new reason codes for SAS Device Status Change
+ *                      Event.
+ *                      Added new event: SAS PHY Counter.
+ *  --------------------------------------------------------------------------
+
+mpi2_raid.h
+ *  04-30-07  02.00.00  Corresponds to Fusion-MPT MPI Specification Rev A.
+ *  08-31-07  02.00.01  Modifications to RAID Action request and reply,
+ *                      including the Actions and ActionData.
+ *  02-29-08  02.00.02  Added MPI2_RAID_ACTION_ADATA_DISABL_FULL_REBUILD.
+ *  05-21-08  02.00.03  Added MPI2_RAID_VOL_CREATION_NUM_PHYSDISKS so that
+ *                      the PhysDisk array in MPI2_RAID_VOLUME_CREATION_STRUCT
+ *                      can be sized by the build environment.
+ *  --------------------------------------------------------------------------
+
+mpi2_sas.h
+ *  04-30-07  02.00.00  Corresponds to Fusion-MPT MPI Specification Rev A.
+ *  06-26-07  02.00.01  Added Clear All Persistent Operation to SAS IO Unit
+ *                      Control Request.
+ *  10-02-08  02.00.02  Added Set IOC Parameter Operation to SAS IO Unit Control
+ *                      Request.
+ *  --------------------------------------------------------------------------
+
+mpi2_targ.h
+ *  04-30-07  02.00.00  Corresponds to Fusion-MPT MPI Specification Rev A.
+ *  08-31-07  02.00.01  Added Command Buffer Data Location Address Space bits to
+ *                      BufferPostFlags field of CommandBufferPostBase Request.
+ *  02-29-08  02.00.02  Modified various names to make them 32-character unique.
+ *  10-02-08  02.00.03  Removed NextCmdBufferOffset from
+ *                      MPI2_TARGET_CMD_BUF_POST_BASE_REQUEST.
+ *                      Target Status Send Request only takes a single SGE for
+ *                      response data.
+ *  --------------------------------------------------------------------------
+
+mpi2_tool.h
+ *  04-30-07  02.00.00  Corresponds to Fusion-MPT MPI Specification Rev A.
+ *  12-18-07  02.00.01  Added Diagnostic Buffer Post and Diagnostic Release
+ *                      structures and defines.
+ *  02-29-08  02.00.02  Modified various names to make them 32-character unique.
+ *  05-06-09  02.00.03  Added ISTWI Read Write Tool and Diagnostic CLI Tool.
+ *  --------------------------------------------------------------------------
+
+mpi2_type.h
+ *  04-30-07  02.00.00  Corresponds to Fusion-MPT MPI Specification Rev A.
+ *  --------------------------------------------------------------------------
+
+mpi2_ra.h
+ *  05-06-09  02.00.00  Initial version.
+ *  --------------------------------------------------------------------------
+
+mpi2_history.txt         Parts list history
+
+Filename     02.00.12
+----------   --------
+mpi2.h       02.00.12
+mpi2_cnfg.h  02.00.11
+mpi2_init.h  02.00.07
+mpi2_ioc.h   02.00.11
+mpi2_raid.h  02.00.03
+mpi2_sas.h   02.00.02
+mpi2_targ.h  02.00.03
+mpi2_tool.h  02.00.03
+mpi2_type.h  02.00.00
+mpi2_ra.h    02.00.00
+
+Filename     02.00.11  02.00.10  02.00.09  02.00.08  02.00.07  02.00.06
+----------   --------  --------  --------  --------  --------  --------
+mpi2.h       02.00.11  02.00.10  02.00.09  02.00.08  02.00.07  02.00.06
+mpi2_cnfg.h  02.00.10  02.00.09  02.00.08  02.00.07  02.00.06  02.00.06
+mpi2_init.h  02.00.06  02.00.06  02.00.05  02.00.05  02.00.04  02.00.03
+mpi2_ioc.h   02.00.10  02.00.09  02.00.08  02.00.07  02.00.07  02.00.06
+mpi2_raid.h  02.00.03  02.00.03  02.00.03  02.00.03  02.00.02  02.00.02
+mpi2_sas.h   02.00.02  02.00.02  02.00.01  02.00.01  02.00.01  02.00.01
+mpi2_targ.h  02.00.03  02.00.03  02.00.02  02.00.02  02.00.02  02.00.02
+mpi2_tool.h  02.00.02  02.00.02  02.00.02  02.00.02  02.00.02  02.00.02
+mpi2_type.h  02.00.00  02.00.00  02.00.00  02.00.00  02.00.00  02.00.00
+
+Filename     02.00.05  02.00.04  02.00.03  02.00.02  02.00.01  02.00.00
+----------   --------  --------  --------  --------  --------  --------
+mpi2.h       02.00.05  02.00.04  02.00.03  02.00.02  02.00.01  02.00.00
+mpi2_cnfg.h  02.00.05  02.00.04  02.00.03  02.00.02  02.00.01  02.00.00
+mpi2_init.h  02.00.02  02.00.01  02.00.00  02.00.00  02.00.00  02.00.00
+mpi2_ioc.h   02.00.05  02.00.04  02.00.03  02.00.02  02.00.01  02.00.00
+mpi2_raid.h  02.00.01  02.00.01  02.00.01  02.00.00  02.00.00  02.00.00
+mpi2_sas.h   02.00.01  02.00.01  02.00.01  02.00.01  02.00.00  02.00.00
+mpi2_targ.h  02.00.01  02.00.01  02.00.01  02.00.00  02.00.00  02.00.00
+mpi2_tool.h  02.00.01  02.00.00  02.00.00  02.00.00  02.00.00  02.00.00
+mpi2_type.h  02.00.00  02.00.00  02.00.00  02.00.00  02.00.00  02.00.00
+
index f1115f0..563e56d 100644 (file)
@@ -1,12 +1,12 @@
 /*
- *  Copyright (c) 2000-2008 LSI Corporation.
+ *  Copyright (c) 2000-2009 LSI Corporation.
  *
  *
  *           Name:  mpi2_init.h
  *          Title:  MPI SCSI initiator mode messages and structures
  *  Creation Date:  June 23, 2006
  *
- *    mpi2_init.h Version:  02.00.06
+ *    mpi2_init.h Version:  02.00.07
  *
  *  Version History
  *  ---------------
  *                      Control field Task Attribute flags.
  *                      Moved LUN field defines to mpi2.h becasue they are
  *                      common to many structures.
+ *  05-06-09  02.00.07  Changed task management type of Query Unit Attention to
+ *                      Query Asynchronous Event.
+ *                      Defined two new bits in the SlotStatus field of the SCSI
+ *                      Enclosure Processor Request and Reply.
  *  --------------------------------------------------------------------------
  */
 
@@ -289,7 +293,11 @@ typedef struct _MPI2_SCSI_TASK_MANAGE_REQUEST
 #define MPI2_SCSITASKMGMT_TASKTYPE_QUERY_TASK           (0x07)
 #define MPI2_SCSITASKMGMT_TASKTYPE_CLR_ACA              (0x08)
 #define MPI2_SCSITASKMGMT_TASKTYPE_QRY_TASK_SET         (0x09)
-#define MPI2_SCSITASKMGMT_TASKTYPE_QRY_UNIT_ATTENTION   (0x0A)
+#define MPI2_SCSITASKMGMT_TASKTYPE_QRY_ASYNC_EVENT      (0x0A)
+
+/* obsolete TaskType name */
+#define MPI2_SCSITASKMGMT_TASKTYPE_QRY_UNIT_ATTENTION  \
+       (MPI2_SCSITASKMGMT_TASKTYPE_QRY_ASYNC_EVENT)
 
 /* MsgFlags bits */
 
@@ -375,6 +383,8 @@ typedef struct _MPI2_SEP_REQUEST
 #define MPI2_SEP_REQ_SLOTSTATUS_HOT_SPARE               (0x00000100)
 #define MPI2_SEP_REQ_SLOTSTATUS_UNCONFIGURED            (0x00000080)
 #define MPI2_SEP_REQ_SLOTSTATUS_PREDICTED_FAULT         (0x00000040)
+#define MPI2_SEP_REQ_SLOTSTATUS_IN_CRITICAL_ARRAY       (0x00000010)
+#define MPI2_SEP_REQ_SLOTSTATUS_IN_FAILED_ARRAY         (0x00000008)
 #define MPI2_SEP_REQ_SLOTSTATUS_DEV_REBUILDING          (0x00000004)
 #define MPI2_SEP_REQ_SLOTSTATUS_DEV_FAULTY              (0x00000002)
 #define MPI2_SEP_REQ_SLOTSTATUS_NO_ERROR                (0x00000001)
@@ -410,6 +420,8 @@ typedef struct _MPI2_SEP_REPLY
 #define MPI2_SEP_REPLY_SLOTSTATUS_HOT_SPARE             (0x00000100)
 #define MPI2_SEP_REPLY_SLOTSTATUS_UNCONFIGURED          (0x00000080)
 #define MPI2_SEP_REPLY_SLOTSTATUS_PREDICTED_FAULT       (0x00000040)
+#define MPI2_SEP_REPLY_SLOTSTATUS_IN_CRITICAL_ARRAY     (0x00000010)
+#define MPI2_SEP_REPLY_SLOTSTATUS_IN_FAILED_ARRAY       (0x00000008)
 #define MPI2_SEP_REPLY_SLOTSTATUS_DEV_REBUILDING        (0x00000004)
 #define MPI2_SEP_REPLY_SLOTSTATUS_DEV_FAULTY            (0x00000002)
 #define MPI2_SEP_REPLY_SLOTSTATUS_NO_ERROR              (0x00000001)
index 8c5d818..c294128 100644 (file)
@@ -6,7 +6,7 @@
  *          Title:  MPI IOC, Port, Event, FW Download, and FW Upload messages
  *  Creation Date:  October 11, 2006
  *
- *  mpi2_ioc.h Version:  02.00.10
+ *  mpi2_ioc.h Version:  02.00.11
  *
  *  Version History
  *  ---------------
  *                      Added MPI2_EVENT_SAS_DEV_STAT_RC_SATA_INIT_FAILURE
  *                      define.
  *                      Removed MPI2_EVENT_SAS_DISC_DS_SATA_INIT_FAILURE define.
+ *  05-06-09  02.00.11  Added MPI2_IOCFACTS_CAPABILITY_RAID_ACCELERATOR define.
+ *                      Added MPI2_IOCFACTS_CAPABILITY_MSI_X_INDEX define.
+ *                      Added two new reason codes for SAS Device Status Change
+ *                      Event.
+ *                      Added new event: SAS PHY Counter.
  *  --------------------------------------------------------------------------
  */
 
@@ -261,6 +266,8 @@ typedef struct _MPI2_IOC_FACTS_REPLY
 /* ProductID field uses MPI2_FW_HEADER_PID_ */
 
 /* IOCCapabilities */
+#define MPI2_IOCFACTS_CAPABILITY_MSI_X_INDEX            (0x00008000)
+#define MPI2_IOCFACTS_CAPABILITY_RAID_ACCELERATOR       (0x00004000)
 #define MPI2_IOCFACTS_CAPABILITY_EVENT_REPLAY           (0x00002000)
 #define MPI2_IOCFACTS_CAPABILITY_INTEGRATED_RAID        (0x00001000)
 #define MPI2_IOCFACTS_CAPABILITY_TLR                    (0x00000800)
@@ -440,6 +447,7 @@ typedef struct _MPI2_EVENT_NOTIFICATION_REPLY
 #define MPI2_EVENT_IR_PHYSICAL_DISK                 (0x001F)
 #define MPI2_EVENT_IR_CONFIGURATION_CHANGE_LIST     (0x0020)
 #define MPI2_EVENT_LOG_ENTRY_ADDED                  (0x0021)
+#define MPI2_EVENT_SAS_PHY_COUNTER                  (0x0022)
 
 
 /* Log Entry Added Event data */
@@ -502,17 +510,19 @@ typedef struct _MPI2_EVENT_DATA_SAS_DEVICE_STATUS_CHANGE
   MPI2_POINTER pMpi2EventDataSasDeviceStatusChange_t;
 
 /* SAS Device Status Change Event data ReasonCode values */
-#define MPI2_EVENT_SAS_DEV_STAT_RC_SMART_DATA               (0x05)
-#define MPI2_EVENT_SAS_DEV_STAT_RC_UNSUPPORTED              (0x07)
-#define MPI2_EVENT_SAS_DEV_STAT_RC_INTERNAL_DEVICE_RESET    (0x08)
-#define MPI2_EVENT_SAS_DEV_STAT_RC_TASK_ABORT_INTERNAL      (0x09)
-#define MPI2_EVENT_SAS_DEV_STAT_RC_ABORT_TASK_SET_INTERNAL  (0x0A)
-#define MPI2_EVENT_SAS_DEV_STAT_RC_CLEAR_TASK_SET_INTERNAL  (0x0B)
-#define MPI2_EVENT_SAS_DEV_STAT_RC_QUERY_TASK_INTERNAL      (0x0C)
-#define MPI2_EVENT_SAS_DEV_STAT_RC_ASYNC_NOTIFICATION       (0x0D)
-#define MPI2_EVENT_SAS_DEV_STAT_RC_CMP_INTERNAL_DEV_RESET   (0x0E)
-#define MPI2_EVENT_SAS_DEV_STAT_RC_CMP_TASK_ABORT_INTERNAL  (0x0F)
-#define MPI2_EVENT_SAS_DEV_STAT_RC_SATA_INIT_FAILURE        (0x10)
+#define MPI2_EVENT_SAS_DEV_STAT_RC_SMART_DATA                           (0x05)
+#define MPI2_EVENT_SAS_DEV_STAT_RC_UNSUPPORTED                          (0x07)
+#define MPI2_EVENT_SAS_DEV_STAT_RC_INTERNAL_DEVICE_RESET                (0x08)
+#define MPI2_EVENT_SAS_DEV_STAT_RC_TASK_ABORT_INTERNAL                  (0x09)
+#define MPI2_EVENT_SAS_DEV_STAT_RC_ABORT_TASK_SET_INTERNAL              (0x0A)
+#define MPI2_EVENT_SAS_DEV_STAT_RC_CLEAR_TASK_SET_INTERNAL              (0x0B)
+#define MPI2_EVENT_SAS_DEV_STAT_RC_QUERY_TASK_INTERNAL                  (0x0C)
+#define MPI2_EVENT_SAS_DEV_STAT_RC_ASYNC_NOTIFICATION                   (0x0D)
+#define MPI2_EVENT_SAS_DEV_STAT_RC_CMP_INTERNAL_DEV_RESET               (0x0E)
+#define MPI2_EVENT_SAS_DEV_STAT_RC_CMP_TASK_ABORT_INTERNAL              (0x0F)
+#define MPI2_EVENT_SAS_DEV_STAT_RC_SATA_INIT_FAILURE                    (0x10)
+#define MPI2_EVENT_SAS_DEV_STAT_RC_EXPANDER_REDUCED_FUNCTIONALITY       (0x11)
+#define MPI2_EVENT_SAS_DEV_STAT_RC_CMP_EXPANDER_REDUCED_FUNCTIONALITY   (0x12)
 
 
 /* Integrated RAID Operation Status Event data */
@@ -822,6 +832,37 @@ typedef struct _MPI2_EVENT_DATA_SAS_ENCL_DEV_STATUS_CHANGE
 #define MPI2_EVENT_SAS_ENCL_RC_NOT_RESPONDING       (0x02)
 
 
+/* SAS PHY Counter Event data */
+
+typedef struct _MPI2_EVENT_DATA_SAS_PHY_COUNTER {
+    U64         TimeStamp;          /* 0x00 */
+    U32         Reserved1;          /* 0x08 */
+    U8          PhyEventCode;       /* 0x0C */
+    U8          PhyNum;             /* 0x0D */
+    U16         Reserved2;          /* 0x0E */
+    U32         PhyEventInfo;       /* 0x10 */
+    U8          CounterType;        /* 0x14 */
+    U8          ThresholdWindow;    /* 0x15 */
+    U8          TimeUnits;          /* 0x16 */
+    U8          Reserved3;          /* 0x17 */
+    U32         EventThreshold;     /* 0x18 */
+    U16         ThresholdFlags;     /* 0x1C */
+    U16         Reserved4;          /* 0x1E */
+} MPI2_EVENT_DATA_SAS_PHY_COUNTER,
+  MPI2_POINTER PTR_MPI2_EVENT_DATA_SAS_PHY_COUNTER,
+  Mpi2EventDataSasPhyCounter_t, MPI2_POINTER pMpi2EventDataSasPhyCounter_t;
+
+/* use MPI2_SASPHY3_EVENT_CODE_ values from mpi2_cnfg.h for the
+ * PhyEventCode field
+ * use MPI2_SASPHY3_COUNTER_TYPE_ values from mpi2_cnfg.h for the
+ * CounterType field
+ * use MPI2_SASPHY3_TIME_UNITS_ values from mpi2_cnfg.h for the
+ * TimeUnits field
+ * use MPI2_SASPHY3_TFLAGS_ values from mpi2_cnfg.h for the
+ * ThresholdFlags field
+ * */
+
+
 /****************************************************************************
 *  EventAck message
 ****************************************************************************/
index 2ff4e93..007e950 100644 (file)
@@ -1,12 +1,12 @@
 /*
- *  Copyright (c) 2000-2008 LSI Corporation.
+ *  Copyright (c) 2000-2009 LSI Corporation.
  *
  *
  *           Name:  mpi2_tool.h
  *          Title:  MPI diagnostic tool structures and definitions
  *  Creation Date:  March 26, 2007
  *
- *    mpi2_tool.h Version:  02.00.02
+ *    mpi2_tool.h Version:  02.00.03
  *
  *  Version History
  *  ---------------
@@ -17,6 +17,7 @@
  *  12-18-07  02.00.01  Added Diagnostic Buffer Post and Diagnostic Release
  *                      structures and defines.
  *  02-29-08  02.00.02  Modified various names to make them 32-character unique.
+ *  05-06-09  02.00.03  Added ISTWI Read Write Tool and Diagnostic CLI Tool.
  *  --------------------------------------------------------------------------
  */
 
 /* defines for the Tools */
 #define MPI2_TOOLBOX_CLEAN_TOOL                     (0x00)
 #define MPI2_TOOLBOX_MEMORY_MOVE_TOOL               (0x01)
+#define MPI2_TOOLBOX_ISTWI_READ_WRITE_TOOL          (0x03)
 #define MPI2_TOOLBOX_BEACON_TOOL                    (0x05)
+#define MPI2_TOOLBOX_DIAGNOSTIC_CLI_TOOL            (0x06)
+
 
 /****************************************************************************
 *  Toolbox reply
@@ -112,6 +116,77 @@ typedef struct _MPI2_TOOLBOX_MEM_MOVE_REQUEST
 
 
 /****************************************************************************
+*  Toolbox ISTWI Read Write Tool
+****************************************************************************/
+
+/* Toolbox ISTWI Read Write Tool request message */
+typedef struct _MPI2_TOOLBOX_ISTWI_READ_WRITE_REQUEST {
+    U8                      Tool;                       /* 0x00 */
+    U8                      Reserved1;                  /* 0x01 */
+    U8                      ChainOffset;                /* 0x02 */
+    U8                      Function;                   /* 0x03 */
+    U16                     Reserved2;                  /* 0x04 */
+    U8                      Reserved3;                  /* 0x06 */
+    U8                      MsgFlags;                   /* 0x07 */
+    U8                      VP_ID;                      /* 0x08 */
+    U8                      VF_ID;                      /* 0x09 */
+    U16                     Reserved4;                  /* 0x0A */
+    U32                     Reserved5;                  /* 0x0C */
+    U32                     Reserved6;                  /* 0x10 */
+    U8                      DevIndex;                   /* 0x14 */
+    U8                      Action;                     /* 0x15 */
+    U8                      SGLFlags;                   /* 0x16 */
+    U8                      Reserved7;                  /* 0x17 */
+    U16                     TxDataLength;               /* 0x18 */
+    U16                     RxDataLength;               /* 0x1A */
+    U32                     Reserved8;                  /* 0x1C */
+    U32                     Reserved9;                  /* 0x20 */
+    U32                     Reserved10;                 /* 0x24 */
+    U32                     Reserved11;                 /* 0x28 */
+    U32                     Reserved12;                 /* 0x2C */
+    MPI2_SGE_SIMPLE_UNION   SGL;                        /* 0x30 */
+} MPI2_TOOLBOX_ISTWI_READ_WRITE_REQUEST,
+  MPI2_POINTER PTR_MPI2_TOOLBOX_ISTWI_READ_WRITE_REQUEST,
+  Mpi2ToolboxIstwiReadWriteRequest_t,
+  MPI2_POINTER pMpi2ToolboxIstwiReadWriteRequest_t;
+
+/* values for the Action field */
+#define MPI2_TOOL_ISTWI_ACTION_READ_DATA            (0x01)
+#define MPI2_TOOL_ISTWI_ACTION_WRITE_DATA           (0x02)
+#define MPI2_TOOL_ISTWI_ACTION_SEQUENCE             (0x03)
+#define MPI2_TOOL_ISTWI_ACTION_RESERVE_BUS          (0x10)
+#define MPI2_TOOL_ISTWI_ACTION_RELEASE_BUS          (0x11)
+#define MPI2_TOOL_ISTWI_ACTION_RESET                (0x12)
+
+/* values for SGLFlags field are in the SGL section of mpi2.h */
+
+
+/* Toolbox ISTWI Read Write Tool reply message */
+typedef struct _MPI2_TOOLBOX_ISTWI_REPLY {
+    U8                      Tool;                       /* 0x00 */
+    U8                      Reserved1;                  /* 0x01 */
+    U8                      MsgLength;                  /* 0x02 */
+    U8                      Function;                   /* 0x03 */
+    U16                     Reserved2;                  /* 0x04 */
+    U8                      Reserved3;                  /* 0x06 */
+    U8                      MsgFlags;                   /* 0x07 */
+    U8                      VP_ID;                      /* 0x08 */
+    U8                      VF_ID;                      /* 0x09 */
+    U16                     Reserved4;                  /* 0x0A */
+    U16                     Reserved5;                  /* 0x0C */
+    U16                     IOCStatus;                  /* 0x0E */
+    U32                     IOCLogInfo;                 /* 0x10 */
+    U8                      DevIndex;                   /* 0x14 */
+    U8                      Action;                     /* 0x15 */
+    U8                      IstwiStatus;                /* 0x16 */
+    U8                      Reserved6;                  /* 0x17 */
+    U16                     TxDataCount;                /* 0x18 */
+    U16                     RxDataCount;                /* 0x1A */
+} MPI2_TOOLBOX_ISTWI_REPLY, MPI2_POINTER PTR_MPI2_TOOLBOX_ISTWI_REPLY,
+  Mpi2ToolboxIstwiReply_t, MPI2_POINTER pMpi2ToolboxIstwiReply_t;
+
+
+/****************************************************************************
 *  Toolbox Beacon Tool request
 ****************************************************************************/
 
@@ -139,6 +214,61 @@ typedef struct _MPI2_TOOLBOX_BEACON_REQUEST
 #define MPI2_TOOLBOX_FLAGS_BEACONMODE_ON        (0x01)
 
 
+/****************************************************************************
+*  Toolbox Diagnostic CLI Tool
+****************************************************************************/
+
+#define MPI2_TOOLBOX_DIAG_CLI_CMD_LENGTH    (0x5C)
+
+/* Toolbox Diagnostic CLI Tool request message */
+typedef struct _MPI2_TOOLBOX_DIAGNOSTIC_CLI_REQUEST {
+    U8                      Tool;                       /* 0x00 */
+    U8                      Reserved1;                  /* 0x01 */
+    U8                      ChainOffset;                /* 0x02 */
+    U8                      Function;                   /* 0x03 */
+    U16                     Reserved2;                  /* 0x04 */
+    U8                      Reserved3;                  /* 0x06 */
+    U8                      MsgFlags;                   /* 0x07 */
+    U8                      VP_ID;                      /* 0x08 */
+    U8                      VF_ID;                      /* 0x09 */
+    U16                     Reserved4;                  /* 0x0A */
+    U8                      SGLFlags;                   /* 0x0C */
+    U8                      Reserved5;                  /* 0x0D */
+    U16                     Reserved6;                  /* 0x0E */
+    U32                     DataLength;                 /* 0x10 */
+    U8                      DiagnosticCliCommand
+               [MPI2_TOOLBOX_DIAG_CLI_CMD_LENGTH];     /* 0x14 */
+    MPI2_SGE_SIMPLE_UNION   SGL;                        /* 0x70 */
+} MPI2_TOOLBOX_DIAGNOSTIC_CLI_REQUEST,
+  MPI2_POINTER PTR_MPI2_TOOLBOX_DIAGNOSTIC_CLI_REQUEST,
+  Mpi2ToolboxDiagnosticCliRequest_t,
+  MPI2_POINTER pMpi2ToolboxDiagnosticCliRequest_t;
+
+/* values for SGLFlags field are in the SGL section of mpi2.h */
+
+
+/* Toolbox Diagnostic CLI Tool reply message */
+typedef struct _MPI2_TOOLBOX_DIAGNOSTIC_CLI_REPLY {
+    U8                      Tool;                       /* 0x00 */
+    U8                      Reserved1;                  /* 0x01 */
+    U8                      MsgLength;                  /* 0x02 */
+    U8                      Function;                   /* 0x03 */
+    U16                     Reserved2;                  /* 0x04 */
+    U8                      Reserved3;                  /* 0x06 */
+    U8                      MsgFlags;                   /* 0x07 */
+    U8                      VP_ID;                      /* 0x08 */
+    U8                      VF_ID;                      /* 0x09 */
+    U16                     Reserved4;                  /* 0x0A */
+    U16                     Reserved5;                  /* 0x0C */
+    U16                     IOCStatus;                  /* 0x0E */
+    U32                     IOCLogInfo;                 /* 0x10 */
+    U32                     ReturnedDataLength;         /* 0x14 */
+} MPI2_TOOLBOX_DIAGNOSTIC_CLI_REPLY,
+  MPI2_POINTER PTR_MPI2_TOOLBOX_DIAG_CLI_REPLY,
+  Mpi2ToolboxDiagnosticCliReply_t,
+  MPI2_POINTER pMpi2ToolboxDiagnosticCliReply_t;
+
+
 /*****************************************************************************
 *
 *       Diagnostic Buffer Messages
index d95d2f2..670241e 100644 (file)
@@ -3,7 +3,7 @@
  * for access to MPT (Message Passing Technology) firmware.
  *
  * This code is based on drivers/scsi/mpt2sas/mpt2_base.c
- * Copyright (C) 2007-2008  LSI Corporation
+ * Copyright (C) 2007-2009  LSI Corporation
  *  (mailto:DL-MPTFusionLinux@lsi.com)
  *
  * This program is free software; you can redistribute it and/or
@@ -63,7 +63,7 @@
 static MPT_CALLBACK    mpt_callbacks[MPT_MAX_CALLBACKS];
 
 #define FAULT_POLLING_INTERVAL 1000 /* in milliseconds */
-#define MPT2SAS_MAX_REQUEST_QUEUE 500 /* maximum controller queue depth */
+#define MPT2SAS_MAX_REQUEST_QUEUE 600 /* maximum controller queue depth */
 
 static int max_queue_depth = -1;
 module_param(max_queue_depth, int, 0);
@@ -543,13 +543,13 @@ mpt2sas_base_fault_info(struct MPT2SAS_ADAPTER *ioc , u16 fault_code)
  * _base_display_reply_info -
  * @ioc: pointer to scsi command object
  * @smid: system request message index
- * @VF_ID: virtual function id
+ * @msix_index: MSIX table index supplied by the OS
  * @reply: reply message frame(lower 32bit addr)
  *
  * Return nothing.
  */
 static void
-_base_display_reply_info(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 VF_ID,
+_base_display_reply_info(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 msix_index,
     u32 reply)
 {
        MPI2DefaultReply_t *mpi_reply;
@@ -572,22 +572,24 @@ _base_display_reply_info(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 VF_ID,
  * mpt2sas_base_done - base internal command completion routine
  * @ioc: pointer to scsi command object
  * @smid: system request message index
- * @VF_ID: virtual function id
+ * @msix_index: MSIX table index supplied by the OS
  * @reply: reply message frame(lower 32bit addr)
  *
- * Return nothing.
+ * Return 1 meaning mf should be freed from _base_interrupt
+ *        0 means the mf is freed from this function.
  */
-void
-mpt2sas_base_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 VF_ID, u32 reply)
+u8
+mpt2sas_base_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 msix_index,
+    u32 reply)
 {
        MPI2DefaultReply_t *mpi_reply;
 
        mpi_reply = mpt2sas_base_get_reply_virt_addr(ioc, reply);
        if (mpi_reply && mpi_reply->Function == MPI2_FUNCTION_EVENT_ACK)
-               return;
+               return 1;
 
        if (ioc->base_cmds.status == MPT2_CMD_NOT_USED)
-               return;
+               return 1;
 
        ioc->base_cmds.status |= MPT2_CMD_COMPLETE;
        if (mpi_reply) {
@@ -596,18 +598,20 @@ mpt2sas_base_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 VF_ID, u32 reply)
        }
        ioc->base_cmds.status &= ~MPT2_CMD_PENDING;
        complete(&ioc->base_cmds.done);
+       return 1;
 }
 
 /**
  * _base_async_event - main callback handler for firmware asyn events
  * @ioc: pointer to scsi command object
- * @VF_ID: virtual function id
+ * @msix_index: MSIX table index supplied by the OS
  * @reply: reply message frame(lower 32bit addr)
  *
- * Return nothing.
+ * Return 1 meaning mf should be freed from _base_interrupt
+ *        0 means the mf is freed from this function.
  */
-static void
-_base_async_event(struct MPT2SAS_ADAPTER *ioc, u8 VF_ID, u32 reply)
+static u8
+_base_async_event(struct MPT2SAS_ADAPTER *ioc, u8 msix_index, u32 reply)
 {
        Mpi2EventNotificationReply_t *mpi_reply;
        Mpi2EventAckRequest_t *ack_request;
@@ -615,9 +619,9 @@ _base_async_event(struct MPT2SAS_ADAPTER *ioc, u8 VF_ID, u32 reply)
 
        mpi_reply = mpt2sas_base_get_reply_virt_addr(ioc, reply);
        if (!mpi_reply)
-               return;
+               return 1;
        if (mpi_reply->Function != MPI2_FUNCTION_EVENT_NOTIFICATION)
-               return;
+               return 1;
 #ifdef CONFIG_SCSI_MPT2SAS_LOGGING
        _base_display_event_data(ioc, mpi_reply);
 #endif
@@ -635,16 +639,47 @@ _base_async_event(struct MPT2SAS_ADAPTER *ioc, u8 VF_ID, u32 reply)
        ack_request->Function = MPI2_FUNCTION_EVENT_ACK;
        ack_request->Event = mpi_reply->Event;
        ack_request->EventContext = mpi_reply->EventContext;
-       ack_request->VF_ID = VF_ID;
-       mpt2sas_base_put_smid_default(ioc, smid, VF_ID);
+       ack_request->VF_ID = 0;  /* TODO */
+       ack_request->VP_ID = 0;
+       mpt2sas_base_put_smid_default(ioc, smid);
 
  out:
 
        /* scsih callback handler */
-       mpt2sas_scsih_event_callback(ioc, VF_ID, reply);
+       mpt2sas_scsih_event_callback(ioc, msix_index, reply);
 
        /* ctl callback handler */
-       mpt2sas_ctl_event_callback(ioc, VF_ID, reply);
+       mpt2sas_ctl_event_callback(ioc, msix_index, reply);
+
+       return 1;
+}
+
+/**
+ * _base_get_cb_idx - obtain the callback index
+ * @ioc: per adapter object
+ * @smid: system request message index
+ *
+ * Return callback index.
+ */
+static u8
+_base_get_cb_idx(struct MPT2SAS_ADAPTER *ioc, u16 smid)
+{
+       int i;
+       u8 cb_idx = 0xFF;
+
+       if (smid >= ioc->hi_priority_smid) {
+               if (smid < ioc->internal_smid) {
+                       i = smid - ioc->hi_priority_smid;
+                       cb_idx = ioc->hpr_lookup[i].cb_idx;
+               } else {
+                       i = smid - ioc->internal_smid;
+                       cb_idx = ioc->internal_lookup[i].cb_idx;
+               }
+       } else {
+               i = smid - 1;
+               cb_idx = ioc->scsi_lookup[i].cb_idx;
+       }
+       return cb_idx;
 }
 
 /**
@@ -680,7 +715,6 @@ _base_unmask_interrupts(struct MPT2SAS_ADAPTER *ioc)
 {
        u32 him_register;
 
-       writel(0, &ioc->chip->HostInterruptStatus);
        him_register = readl(&ioc->chip->HostInterruptMask);
        him_register &= ~MPI2_HIM_RIM;
        writel(him_register, &ioc->chip->HostInterruptMask);
@@ -712,9 +746,10 @@ _base_interrupt(int irq, void *bus_id)
        u16 smid;
        u8 cb_idx;
        u32 reply;
-       u8 VF_ID;
+       u8 msix_index;
        struct MPT2SAS_ADAPTER *ioc = bus_id;
        Mpi2ReplyDescriptorsUnion_t *rpf;
+       u8 rc;
 
        if (ioc->mask_interrupts)
                return IRQ_NONE;
@@ -733,7 +768,7 @@ _base_interrupt(int irq, void *bus_id)
                reply = 0;
                cb_idx = 0xFF;
                smid = le16_to_cpu(rpf->Default.DescriptorTypeDependent1);
-               VF_ID = rpf->Default.VF_ID;
+               msix_index = rpf->Default.MSIxIndex;
                if (request_desript_type ==
                    MPI2_RPY_DESCRIPT_FLAGS_ADDRESS_REPLY) {
                        reply = le32_to_cpu
@@ -745,16 +780,18 @@ _base_interrupt(int irq, void *bus_id)
                    MPI2_RPY_DESCRIPT_FLAGS_TARGETASSIST_SUCCESS)
                        goto next;
                if (smid)
-                       cb_idx = ioc->scsi_lookup[smid - 1].cb_idx;
+                       cb_idx = _base_get_cb_idx(ioc, smid);
                if (smid && cb_idx != 0xFF) {
-                       mpt_callbacks[cb_idx](ioc, smid, VF_ID, reply);
+                       rc = mpt_callbacks[cb_idx](ioc, smid, msix_index,
+                           reply);
                        if (reply)
-                               _base_display_reply_info(ioc, smid, VF_ID,
+                               _base_display_reply_info(ioc, smid, msix_index,
                                    reply);
-                       mpt2sas_base_free_smid(ioc, smid);
+                       if (rc)
+                               mpt2sas_base_free_smid(ioc, smid);
                }
                if (!smid)
-                       _base_async_event(ioc, VF_ID, reply);
+                       _base_async_event(ioc, msix_index, reply);
 
                /* reply free queue handling */
                if (reply) {
@@ -1191,19 +1228,6 @@ mpt2sas_base_map_resources(struct MPT2SAS_ADAPTER *ioc)
 }
 
 /**
- * mpt2sas_base_get_msg_frame_dma - obtain request mf pointer phys addr
- * @ioc: per adapter object
- * @smid: system request message index(smid zero is invalid)
- *
- * Returns phys pointer to message frame.
- */
-dma_addr_t
-mpt2sas_base_get_msg_frame_dma(struct MPT2SAS_ADAPTER *ioc, u16 smid)
-{
-       return ioc->request_dma + (smid * ioc->request_sz);
-}
-
-/**
  * mpt2sas_base_get_msg_frame - obtain request mf pointer
  * @ioc: per adapter object
  * @smid: system request message index(smid zero is invalid)
@@ -1258,7 +1282,7 @@ mpt2sas_base_get_reply_virt_addr(struct MPT2SAS_ADAPTER *ioc, u32 phys_addr)
 }
 
 /**
- * mpt2sas_base_get_smid - obtain a free smid
+ * mpt2sas_base_get_smid - obtain a free smid from internal queue
  * @ioc: per adapter object
  * @cb_idx: callback index
  *
@@ -1272,6 +1296,39 @@ mpt2sas_base_get_smid(struct MPT2SAS_ADAPTER *ioc, u8 cb_idx)
        u16 smid;
 
        spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
+       if (list_empty(&ioc->internal_free_list)) {
+               spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
+               printk(MPT2SAS_ERR_FMT "%s: smid not available\n",
+                   ioc->name, __func__);
+               return 0;
+       }
+
+       request = list_entry(ioc->internal_free_list.next,
+           struct request_tracker, tracker_list);
+       request->cb_idx = cb_idx;
+       smid = request->smid;
+       list_del(&request->tracker_list);
+       spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
+       return smid;
+}
+
+/**
+ * mpt2sas_base_get_smid_scsiio - obtain a free smid from scsiio queue
+ * @ioc: per adapter object
+ * @cb_idx: callback index
+ * @scmd: pointer to scsi command object
+ *
+ * Returns smid (zero is invalid)
+ */
+u16
+mpt2sas_base_get_smid_scsiio(struct MPT2SAS_ADAPTER *ioc, u8 cb_idx,
+    struct scsi_cmnd *scmd)
+{
+       unsigned long flags;
+       struct request_tracker *request;
+       u16 smid;
+
+       spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
        if (list_empty(&ioc->free_list)) {
                spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
                printk(MPT2SAS_ERR_FMT "%s: smid not available\n",
@@ -1281,6 +1338,36 @@ mpt2sas_base_get_smid(struct MPT2SAS_ADAPTER *ioc, u8 cb_idx)
 
        request = list_entry(ioc->free_list.next,
            struct request_tracker, tracker_list);
+       request->scmd = scmd;
+       request->cb_idx = cb_idx;
+       smid = request->smid;
+       list_del(&request->tracker_list);
+       spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
+       return smid;
+}
+
+/**
+ * mpt2sas_base_get_smid_hpr - obtain a free smid from hi-priority queue
+ * @ioc: per adapter object
+ * @cb_idx: callback index
+ *
+ * Returns smid (zero is invalid)
+ */
+u16
+mpt2sas_base_get_smid_hpr(struct MPT2SAS_ADAPTER *ioc, u8 cb_idx)
+{
+       unsigned long flags;
+       struct request_tracker *request;
+       u16 smid;
+
+       spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
+       if (list_empty(&ioc->hpr_free_list)) {
+               spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
+               return 0;
+       }
+
+       request = list_entry(ioc->hpr_free_list.next,
+           struct request_tracker, tracker_list);
        request->cb_idx = cb_idx;
        smid = request->smid;
        list_del(&request->tracker_list);
@@ -1300,10 +1387,32 @@ void
 mpt2sas_base_free_smid(struct MPT2SAS_ADAPTER *ioc, u16 smid)
 {
        unsigned long flags;
+       int i;
 
        spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
-       ioc->scsi_lookup[smid - 1].cb_idx = 0xFF;
-       list_add_tail(&ioc->scsi_lookup[smid - 1].tracker_list,
+       if (smid >= ioc->hi_priority_smid) {
+               if (smid < ioc->internal_smid) {
+                       /* hi-priority */
+                       i = smid - ioc->hi_priority_smid;
+                       ioc->hpr_lookup[i].cb_idx = 0xFF;
+                       list_add_tail(&ioc->hpr_lookup[i].tracker_list,
+                           &ioc->hpr_free_list);
+               } else {
+                       /* internal queue */
+                       i = smid - ioc->internal_smid;
+                       ioc->internal_lookup[i].cb_idx = 0xFF;
+                       list_add_tail(&ioc->internal_lookup[i].tracker_list,
+                           &ioc->internal_free_list);
+               }
+               spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
+               return;
+       }
+
+       /* scsiio queue */
+       i = smid - 1;
+       ioc->scsi_lookup[i].cb_idx = 0xFF;
+       ioc->scsi_lookup[i].scmd = NULL;
+       list_add_tail(&ioc->scsi_lookup[i].tracker_list,
            &ioc->free_list);
        spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
 
@@ -1352,21 +1461,19 @@ static inline void _base_writeq(__u64 b, volatile void __iomem *addr,
  * mpt2sas_base_put_smid_scsi_io - send SCSI_IO request to firmware
  * @ioc: per adapter object
  * @smid: system request message index
- * @vf_id: virtual function id
  * @handle: device handle
  *
  * Return nothing.
  */
 void
-mpt2sas_base_put_smid_scsi_io(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 vf_id,
-    u16 handle)
+mpt2sas_base_put_smid_scsi_io(struct MPT2SAS_ADAPTER *ioc, u16 smid, u16 handle)
 {
        Mpi2RequestDescriptorUnion_t descriptor;
        u64 *request = (u64 *)&descriptor;
 
 
        descriptor.SCSIIO.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_SCSI_IO;
-       descriptor.SCSIIO.VF_ID = vf_id;
+       descriptor.SCSIIO.MSIxIndex = 0; /* TODO */
        descriptor.SCSIIO.SMID = cpu_to_le16(smid);
        descriptor.SCSIIO.DevHandle = cpu_to_le16(handle);
        descriptor.SCSIIO.LMID = 0;
@@ -1379,20 +1486,18 @@ mpt2sas_base_put_smid_scsi_io(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 vf_id,
  * mpt2sas_base_put_smid_hi_priority - send Task Managment request to firmware
  * @ioc: per adapter object
  * @smid: system request message index
- * @vf_id: virtual function id
  *
  * Return nothing.
  */
 void
-mpt2sas_base_put_smid_hi_priority(struct MPT2SAS_ADAPTER *ioc, u16 smid,
-    u8 vf_id)
+mpt2sas_base_put_smid_hi_priority(struct MPT2SAS_ADAPTER *ioc, u16 smid)
 {
        Mpi2RequestDescriptorUnion_t descriptor;
        u64 *request = (u64 *)&descriptor;
 
        descriptor.HighPriority.RequestFlags =
            MPI2_REQ_DESCRIPT_FLAGS_HIGH_PRIORITY;
-       descriptor.HighPriority.VF_ID = vf_id;
+       descriptor.HighPriority.MSIxIndex = 0; /* TODO */
        descriptor.HighPriority.SMID = cpu_to_le16(smid);
        descriptor.HighPriority.LMID = 0;
        descriptor.HighPriority.Reserved1 = 0;
@@ -1404,18 +1509,17 @@ mpt2sas_base_put_smid_hi_priority(struct MPT2SAS_ADAPTER *ioc, u16 smid,
  * mpt2sas_base_put_smid_default - Default, primarily used for config pages
  * @ioc: per adapter object
  * @smid: system request message index
- * @vf_id: virtual function id
  *
  * Return nothing.
  */
 void
-mpt2sas_base_put_smid_default(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 vf_id)
+mpt2sas_base_put_smid_default(struct MPT2SAS_ADAPTER *ioc, u16 smid)
 {
        Mpi2RequestDescriptorUnion_t descriptor;
        u64 *request = (u64 *)&descriptor;
 
        descriptor.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
-       descriptor.Default.VF_ID = vf_id;
+       descriptor.Default.MSIxIndex = 0; /* TODO */
        descriptor.Default.SMID = cpu_to_le16(smid);
        descriptor.Default.LMID = 0;
        descriptor.Default.DescriptorTypeDependent = 0;
@@ -1427,21 +1531,20 @@ mpt2sas_base_put_smid_default(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 vf_id)
  * mpt2sas_base_put_smid_target_assist - send Target Assist/Status to firmware
  * @ioc: per adapter object
  * @smid: system request message index
- * @vf_id: virtual function id
  * @io_index: value used to track the IO
  *
  * Return nothing.
  */
 void
 mpt2sas_base_put_smid_target_assist(struct MPT2SAS_ADAPTER *ioc, u16 smid,
-    u8 vf_id, u16 io_index)
+    u16 io_index)
 {
        Mpi2RequestDescriptorUnion_t descriptor;
        u64 *request = (u64 *)&descriptor;
 
        descriptor.SCSITarget.RequestFlags =
            MPI2_REQ_DESCRIPT_FLAGS_SCSI_TARGET;
-       descriptor.SCSITarget.VF_ID = vf_id;
+       descriptor.SCSITarget.MSIxIndex = 0; /* TODO */
        descriptor.SCSITarget.SMID = cpu_to_le16(smid);
        descriptor.SCSITarget.LMID = 0;
        descriptor.SCSITarget.IoIndex = cpu_to_le16(io_index);
@@ -1717,6 +1820,8 @@ _base_release_memory_pools(struct MPT2SAS_ADAPTER *ioc)
        }
 
        kfree(ioc->scsi_lookup);
+       kfree(ioc->hpr_lookup);
+       kfree(ioc->internal_lookup);
 }
 
 
@@ -1736,7 +1841,6 @@ _base_allocate_memory_pools(struct MPT2SAS_ADAPTER *ioc,  int sleep_flag)
        u16 num_of_reply_frames;
        u16 chains_needed_per_io;
        u32 sz, total_sz;
-       u16 i;
        u32 retry_sz;
        u16 max_request_credit;
 
@@ -1764,7 +1868,10 @@ _base_allocate_memory_pools(struct MPT2SAS_ADAPTER *ioc,  int sleep_flag)
                    MPT2SAS_MAX_REQUEST_QUEUE) ? MPT2SAS_MAX_REQUEST_QUEUE :
                    facts->RequestCredit;
        }
-       ioc->request_depth = max_request_credit;
+
+       ioc->hba_queue_depth = max_request_credit;
+       ioc->hi_priority_depth = facts->HighPriorityCredit;
+       ioc->internal_depth = ioc->hi_priority_depth + 5;
 
        /* request frame size */
        ioc->request_sz = facts->IOCRequestFrameSize * 4;
@@ -1802,7 +1909,7 @@ _base_allocate_memory_pools(struct MPT2SAS_ADAPTER *ioc,  int sleep_flag)
        ioc->chains_needed_per_io = chains_needed_per_io;
 
        /* reply free queue sizing - taking into account for events */
-       num_of_reply_frames = ioc->request_depth + 32;
+       num_of_reply_frames = ioc->hba_queue_depth + 32;
 
        /* number of replies frames can't be a multiple of 16 */
        /* decrease number of reply frames by 1 */
@@ -1823,7 +1930,7 @@ _base_allocate_memory_pools(struct MPT2SAS_ADAPTER *ioc,  int sleep_flag)
         * frames
         */
 
-       queue_size = ioc->request_depth + num_of_reply_frames + 1;
+       queue_size = ioc->hba_queue_depth + num_of_reply_frames + 1;
        /* round up to 16 byte boundary */
        if (queue_size % 16)
                queue_size += 16 - (queue_size % 16);
@@ -1837,60 +1944,85 @@ _base_allocate_memory_pools(struct MPT2SAS_ADAPTER *ioc,  int sleep_flag)
                if (queue_diff % 16)
                        queue_diff += 16 - (queue_diff % 16);
 
-               /* adjust request_depth, reply_free_queue_depth,
+               /* adjust hba_queue_depth, reply_free_queue_depth,
                 * and queue_size
                 */
-               ioc->request_depth -= queue_diff;
+               ioc->hba_queue_depth -= queue_diff;
                ioc->reply_free_queue_depth -= queue_diff;
                queue_size -= queue_diff;
        }
        ioc->reply_post_queue_depth = queue_size;
 
-       /* max scsi host queue depth */
-       ioc->shost->can_queue = ioc->request_depth - INTERNAL_CMDS_COUNT;
-       dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "scsi host queue: depth"
-           "(%d)\n", ioc->name, ioc->shost->can_queue));
-
        dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "scatter gather: "
            "sge_in_main_msg(%d), sge_per_chain(%d), sge_per_io(%d), "
            "chains_per_io(%d)\n", ioc->name, ioc->max_sges_in_main_message,
            ioc->max_sges_in_chain_message, ioc->shost->sg_tablesize,
            ioc->chains_needed_per_io));
 
+       ioc->scsiio_depth = ioc->hba_queue_depth -
+           ioc->hi_priority_depth - ioc->internal_depth;
+
+       /* set the scsi host can_queue depth
+        * with some internal commands that could be outstanding
+        */
+       ioc->shost->can_queue = ioc->scsiio_depth - (2);
+       dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "scsi host: "
+           "can_queue depth (%d)\n", ioc->name, ioc->shost->can_queue));
+
        /* contiguous pool for request and chains, 16 byte align, one extra "
         * "frame for smid=0
         */
-       ioc->chain_depth = ioc->chains_needed_per_io * ioc->request_depth;
-       sz = ((ioc->request_depth + 1 + ioc->chain_depth) * ioc->request_sz);
+       ioc->chain_depth = ioc->chains_needed_per_io * ioc->scsiio_depth;
+       sz = ((ioc->scsiio_depth + 1 + ioc->chain_depth) * ioc->request_sz);
+
+       /* hi-priority queue */
+       sz += (ioc->hi_priority_depth * ioc->request_sz);
+
+       /* internal queue */
+       sz += (ioc->internal_depth * ioc->request_sz);
 
        ioc->request_dma_sz = sz;
        ioc->request = pci_alloc_consistent(ioc->pdev, sz, &ioc->request_dma);
        if (!ioc->request) {
                printk(MPT2SAS_ERR_FMT "request pool: pci_alloc_consistent "
-                   "failed: req_depth(%d), chains_per_io(%d), frame_sz(%d), "
-                   "total(%d kB)\n", ioc->name, ioc->request_depth,
+                   "failed: hba_depth(%d), chains_per_io(%d), frame_sz(%d), "
+                   "total(%d kB)\n", ioc->name, ioc->hba_queue_depth,
                    ioc->chains_needed_per_io, ioc->request_sz, sz/1024);
-               if (ioc->request_depth < MPT2SAS_SAS_QUEUE_DEPTH)
+               if (ioc->scsiio_depth < MPT2SAS_SAS_QUEUE_DEPTH)
                        goto out;
                retry_sz += 64;
-               ioc->request_depth = max_request_credit - retry_sz;
+               ioc->hba_queue_depth = max_request_credit - retry_sz;
                goto retry_allocation;
        }
 
        if (retry_sz)
                printk(MPT2SAS_ERR_FMT "request pool: pci_alloc_consistent "
-                   "succeed: req_depth(%d), chains_per_io(%d), frame_sz(%d), "
-                   "total(%d kb)\n", ioc->name, ioc->request_depth,
+                   "succeed: hba_depth(%d), chains_per_io(%d), frame_sz(%d), "
+                   "total(%d kb)\n", ioc->name, ioc->hba_queue_depth,
                    ioc->chains_needed_per_io, ioc->request_sz, sz/1024);
 
-       ioc->chain = ioc->request + ((ioc->request_depth + 1) *
+
+       /* hi-priority queue */
+       ioc->hi_priority = ioc->request + ((ioc->scsiio_depth + 1) *
+           ioc->request_sz);
+       ioc->hi_priority_dma = ioc->request_dma + ((ioc->scsiio_depth + 1) *
+           ioc->request_sz);
+
+       /* internal queue */
+       ioc->internal = ioc->hi_priority + (ioc->hi_priority_depth *
+           ioc->request_sz);
+       ioc->internal_dma = ioc->hi_priority_dma + (ioc->hi_priority_depth *
+           ioc->request_sz);
+
+       ioc->chain = ioc->internal + (ioc->internal_depth *
            ioc->request_sz);
-       ioc->chain_dma = ioc->request_dma + ((ioc->request_depth + 1) *
+       ioc->chain_dma = ioc->internal_dma + (ioc->internal_depth *
            ioc->request_sz);
+
        dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "request pool(0x%p): "
            "depth(%d), frame_size(%d), pool_size(%d kB)\n", ioc->name,
-           ioc->request, ioc->request_depth, ioc->request_sz,
-           ((ioc->request_depth + 1) * ioc->request_sz)/1024));
+           ioc->request, ioc->hba_queue_depth, ioc->request_sz,
+           (ioc->hba_queue_depth * ioc->request_sz)/1024));
        dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "chain pool(0x%p): depth"
            "(%d), frame_size(%d), pool_size(%d kB)\n", ioc->name, ioc->chain,
            ioc->chain_depth, ioc->request_sz, ((ioc->chain_depth *
@@ -1899,7 +2031,7 @@ _base_allocate_memory_pools(struct MPT2SAS_ADAPTER *ioc,  int sleep_flag)
            ioc->name, (unsigned long long) ioc->request_dma));
        total_sz += sz;
 
-       ioc->scsi_lookup = kcalloc(ioc->request_depth,
+       ioc->scsi_lookup = kcalloc(ioc->scsiio_depth,
            sizeof(struct request_tracker), GFP_KERNEL);
        if (!ioc->scsi_lookup) {
                printk(MPT2SAS_ERR_FMT "scsi_lookup: kcalloc failed\n",
@@ -1907,12 +2039,38 @@ _base_allocate_memory_pools(struct MPT2SAS_ADAPTER *ioc,  int sleep_flag)
                goto out;
        }
 
-        /* initialize some bits */
-       for (i = 0; i < ioc->request_depth; i++)
-               ioc->scsi_lookup[i].smid = i + 1;
+       dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "scsiio(0x%p): "
+           "depth(%d)\n", ioc->name, ioc->request,
+           ioc->scsiio_depth));
+
+       /* initialize hi-priority queue smid's */
+       ioc->hpr_lookup = kcalloc(ioc->hi_priority_depth,
+           sizeof(struct request_tracker), GFP_KERNEL);
+       if (!ioc->hpr_lookup) {
+               printk(MPT2SAS_ERR_FMT "hpr_lookup: kcalloc failed\n",
+                   ioc->name);
+               goto out;
+       }
+       ioc->hi_priority_smid = ioc->scsiio_depth + 1;
+       dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "hi_priority(0x%p): "
+           "depth(%d), start smid(%d)\n", ioc->name, ioc->hi_priority,
+           ioc->hi_priority_depth, ioc->hi_priority_smid));
+
+       /* initialize internal queue smid's */
+       ioc->internal_lookup = kcalloc(ioc->internal_depth,
+           sizeof(struct request_tracker), GFP_KERNEL);
+       if (!ioc->internal_lookup) {
+               printk(MPT2SAS_ERR_FMT "internal_lookup: kcalloc failed\n",
+                   ioc->name);
+               goto out;
+       }
+       ioc->internal_smid = ioc->hi_priority_smid + ioc->hi_priority_depth;
+       dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "internal(0x%p): "
+           "depth(%d), start smid(%d)\n", ioc->name, ioc->internal,
+            ioc->internal_depth, ioc->internal_smid));
 
        /* sense buffers, 4 byte align */
-       sz = ioc->request_depth * SCSI_SENSE_BUFFERSIZE;
+       sz = ioc->scsiio_depth * SCSI_SENSE_BUFFERSIZE;
        ioc->sense_dma_pool = pci_pool_create("sense pool", ioc->pdev, sz, 4,
            0);
        if (!ioc->sense_dma_pool) {
@@ -1929,7 +2087,7 @@ _base_allocate_memory_pools(struct MPT2SAS_ADAPTER *ioc,  int sleep_flag)
        }
        dinitprintk(ioc, printk(MPT2SAS_INFO_FMT
            "sense pool(0x%p): depth(%d), element_size(%d), pool_size"
-           "(%d kB)\n", ioc->name, ioc->sense, ioc->request_depth,
+           "(%d kB)\n", ioc->name, ioc->sense, ioc->scsiio_depth,
            SCSI_SENSE_BUFFERSIZE, sz/1024));
        dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "sense_dma(0x%llx)\n",
            ioc->name, (unsigned long long)ioc->sense_dma));
@@ -2304,7 +2462,7 @@ _base_handshake_req_reply_wait(struct MPT2SAS_ADAPTER *ioc, int request_bytes,
            ((request_bytes/4)<<MPI2_DOORBELL_ADD_DWORDS_SHIFT)),
            &ioc->chip->Doorbell);
 
-       if ((_base_wait_for_doorbell_int(ioc, 5, sleep_flag))) {
+       if ((_base_wait_for_doorbell_int(ioc, 5, NO_SLEEP))) {
                printk(MPT2SAS_ERR_FMT "doorbell handshake "
                   "int failed (line=%d)\n", ioc->name, __LINE__);
                return -EFAULT;
@@ -2454,7 +2612,8 @@ mpt2sas_base_sas_iounit_control(struct MPT2SAS_ADAPTER *ioc,
        if (mpi_request->Operation == MPI2_SAS_OP_PHY_HARD_RESET ||
            mpi_request->Operation == MPI2_SAS_OP_PHY_LINK_RESET)
                ioc->ioc_link_reset_in_progress = 1;
-       mpt2sas_base_put_smid_default(ioc, smid, mpi_request->VF_ID);
+       mpt2sas_base_put_smid_default(ioc, smid);
+       init_completion(&ioc->base_cmds.done);
        timeleft = wait_for_completion_timeout(&ioc->base_cmds.done,
            msecs_to_jiffies(10000));
        if ((mpi_request->Operation == MPI2_SAS_OP_PHY_HARD_RESET ||
@@ -2555,7 +2714,8 @@ mpt2sas_base_scsi_enclosure_processor(struct MPT2SAS_ADAPTER *ioc,
        request = mpt2sas_base_get_msg_frame(ioc, smid);
        ioc->base_cmds.smid = smid;
        memcpy(request, mpi_request, sizeof(Mpi2SepReply_t));
-       mpt2sas_base_put_smid_default(ioc, smid, mpi_request->VF_ID);
+       mpt2sas_base_put_smid_default(ioc, smid);
+       init_completion(&ioc->base_cmds.done);
        timeleft = wait_for_completion_timeout(&ioc->base_cmds.done,
            msecs_to_jiffies(10000));
        if (!(ioc->base_cmds.status & MPT2_CMD_COMPLETE)) {
@@ -2701,13 +2861,12 @@ _base_get_ioc_facts(struct MPT2SAS_ADAPTER *ioc, int sleep_flag)
 /**
  * _base_send_ioc_init - send ioc_init to firmware
  * @ioc: per adapter object
- * @VF_ID: virtual function id
  * @sleep_flag: CAN_SLEEP or NO_SLEEP
  *
  * Returns 0 for success, non-zero for failure.
  */
 static int
-_base_send_ioc_init(struct MPT2SAS_ADAPTER *ioc, u8 VF_ID, int sleep_flag)
+_base_send_ioc_init(struct MPT2SAS_ADAPTER *ioc, int sleep_flag)
 {
        Mpi2IOCInitRequest_t mpi_request;
        Mpi2IOCInitReply_t mpi_reply;
@@ -2719,7 +2878,8 @@ _base_send_ioc_init(struct MPT2SAS_ADAPTER *ioc, u8 VF_ID, int sleep_flag)
        memset(&mpi_request, 0, sizeof(Mpi2IOCInitRequest_t));
        mpi_request.Function = MPI2_FUNCTION_IOC_INIT;
        mpi_request.WhoInit = MPI2_WHOINIT_HOST_DRIVER;
-       mpi_request.VF_ID = VF_ID;
+       mpi_request.VF_ID = 0; /* TODO */
+       mpi_request.VP_ID = 0;
        mpi_request.MsgVersion = cpu_to_le16(MPI2_VERSION);
        mpi_request.HeaderVersion = cpu_to_le16(MPI2_HEADER_VERSION);
 
@@ -2795,13 +2955,12 @@ _base_send_ioc_init(struct MPT2SAS_ADAPTER *ioc, u8 VF_ID, int sleep_flag)
 /**
  * _base_send_port_enable - send port_enable(discovery stuff) to firmware
  * @ioc: per adapter object
- * @VF_ID: virtual function id
  * @sleep_flag: CAN_SLEEP or NO_SLEEP
  *
  * Returns 0 for success, non-zero for failure.
  */
 static int
-_base_send_port_enable(struct MPT2SAS_ADAPTER *ioc, u8 VF_ID, int sleep_flag)
+_base_send_port_enable(struct MPT2SAS_ADAPTER *ioc, int sleep_flag)
 {
        Mpi2PortEnableRequest_t *mpi_request;
        u32 ioc_state;
@@ -2829,9 +2988,11 @@ _base_send_port_enable(struct MPT2SAS_ADAPTER *ioc, u8 VF_ID, int sleep_flag)
        ioc->base_cmds.smid = smid;
        memset(mpi_request, 0, sizeof(Mpi2PortEnableRequest_t));
        mpi_request->Function = MPI2_FUNCTION_PORT_ENABLE;
-       mpi_request->VF_ID = VF_ID;
+       mpi_request->VF_ID = 0; /* TODO */
+       mpi_request->VP_ID = 0;
 
-       mpt2sas_base_put_smid_default(ioc, smid, VF_ID);
+       mpt2sas_base_put_smid_default(ioc, smid);
+       init_completion(&ioc->base_cmds.done);
        timeleft = wait_for_completion_timeout(&ioc->base_cmds.done,
            300*HZ);
        if (!(ioc->base_cmds.status & MPT2_CMD_COMPLETE)) {
@@ -2892,13 +3053,12 @@ _base_unmask_events(struct MPT2SAS_ADAPTER *ioc, u16 event)
 /**
  * _base_event_notification - send event notification
  * @ioc: per adapter object
- * @VF_ID: virtual function id
  * @sleep_flag: CAN_SLEEP or NO_SLEEP
  *
  * Returns 0 for success, non-zero for failure.
  */
 static int
-_base_event_notification(struct MPT2SAS_ADAPTER *ioc, u8 VF_ID, int sleep_flag)
+_base_event_notification(struct MPT2SAS_ADAPTER *ioc, int sleep_flag)
 {
        Mpi2EventNotificationRequest_t *mpi_request;
        unsigned long timeleft;
@@ -2926,11 +3086,13 @@ _base_event_notification(struct MPT2SAS_ADAPTER *ioc, u8 VF_ID, int sleep_flag)
        ioc->base_cmds.smid = smid;
        memset(mpi_request, 0, sizeof(Mpi2EventNotificationRequest_t));
        mpi_request->Function = MPI2_FUNCTION_EVENT_NOTIFICATION;
-       mpi_request->VF_ID = VF_ID;
+       mpi_request->VF_ID = 0; /* TODO */
+       mpi_request->VP_ID = 0;
        for (i = 0; i < MPI2_EVENT_NOTIFY_EVENTMASK_WORDS; i++)
                mpi_request->EventMasks[i] =
                    le32_to_cpu(ioc->event_masks[i]);
-       mpt2sas_base_put_smid_default(ioc, smid, VF_ID);
+       mpt2sas_base_put_smid_default(ioc, smid);
+       init_completion(&ioc->base_cmds.done);
        timeleft = wait_for_completion_timeout(&ioc->base_cmds.done, 30*HZ);
        if (!(ioc->base_cmds.status & MPT2_CMD_COMPLETE)) {
                printk(MPT2SAS_ERR_FMT "%s: timeout\n",
@@ -2981,7 +3143,7 @@ mpt2sas_base_validate_event_type(struct MPT2SAS_ADAPTER *ioc, u32 *event_type)
                return;
 
        mutex_lock(&ioc->base_cmds.mutex);
-       _base_event_notification(ioc, 0, CAN_SLEEP);
+       _base_event_notification(ioc, CAN_SLEEP);
        mutex_unlock(&ioc->base_cmds.mutex);
 }
 
@@ -3006,7 +3168,6 @@ _base_diag_reset(struct MPT2SAS_ADAPTER *ioc, int sleep_flag)
 
        drsprintk(ioc, printk(MPT2SAS_DEBUG_FMT "clear interrupts\n",
            ioc->name));
-       writel(0, &ioc->chip->HostInterruptStatus);
 
        count = 0;
        do {
@@ -3160,30 +3321,60 @@ _base_make_ioc_ready(struct MPT2SAS_ADAPTER *ioc, int sleep_flag,
 /**
  * _base_make_ioc_operational - put controller in OPERATIONAL state
  * @ioc: per adapter object
- * @VF_ID: virtual function id
  * @sleep_flag: CAN_SLEEP or NO_SLEEP
  *
  * Returns 0 for success, non-zero for failure.
  */
 static int
-_base_make_ioc_operational(struct MPT2SAS_ADAPTER *ioc, u8 VF_ID,
-    int sleep_flag)
+_base_make_ioc_operational(struct MPT2SAS_ADAPTER *ioc, int sleep_flag)
 {
        int r, i;
        unsigned long   flags;
        u32 reply_address;
+       u16 smid;
+       struct _tr_list *delayed_tr, *delayed_tr_next;
 
        dinitprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s\n", ioc->name,
            __func__));
 
+       /* clean the delayed target reset list */
+       list_for_each_entry_safe(delayed_tr, delayed_tr_next,
+           &ioc->delayed_tr_list, list) {
+               list_del(&delayed_tr->list);
+               kfree(delayed_tr);
+       }
+
        /* initialize the scsi lookup free list */
        spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
        INIT_LIST_HEAD(&ioc->free_list);
-       for (i = 0; i < ioc->request_depth; i++) {
+       smid = 1;
+       for (i = 0; i < ioc->scsiio_depth; i++, smid++) {
                ioc->scsi_lookup[i].cb_idx = 0xFF;
+               ioc->scsi_lookup[i].smid = smid;
+               ioc->scsi_lookup[i].scmd = NULL;
                list_add_tail(&ioc->scsi_lookup[i].tracker_list,
                    &ioc->free_list);
        }
+
+       /* hi-priority queue */
+       INIT_LIST_HEAD(&ioc->hpr_free_list);
+       smid = ioc->hi_priority_smid;
+       for (i = 0; i < ioc->hi_priority_depth; i++, smid++) {
+               ioc->hpr_lookup[i].cb_idx = 0xFF;
+               ioc->hpr_lookup[i].smid = smid;
+               list_add_tail(&ioc->hpr_lookup[i].tracker_list,
+                   &ioc->hpr_free_list);
+       }
+
+       /* internal queue */
+       INIT_LIST_HEAD(&ioc->internal_free_list);
+       smid = ioc->internal_smid;
+       for (i = 0; i < ioc->internal_depth; i++, smid++) {
+               ioc->internal_lookup[i].cb_idx = 0xFF;
+               ioc->internal_lookup[i].smid = smid;
+               list_add_tail(&ioc->internal_lookup[i].tracker_list,
+                   &ioc->internal_free_list);
+       }
        spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
 
        /* initialize Reply Free Queue */
@@ -3196,7 +3387,7 @@ _base_make_ioc_operational(struct MPT2SAS_ADAPTER *ioc, u8 VF_ID,
        for (i = 0; i < ioc->reply_post_queue_depth; i++)
                ioc->reply_post_free[i].Words = ULLONG_MAX;
 
-       r = _base_send_ioc_init(ioc, VF_ID, sleep_flag);
+       r = _base_send_ioc_init(ioc, sleep_flag);
        if (r)
                return r;
 
@@ -3207,14 +3398,14 @@ _base_make_ioc_operational(struct MPT2SAS_ADAPTER *ioc, u8 VF_ID,
        writel(0, &ioc->chip->ReplyPostHostIndex);
 
        _base_unmask_interrupts(ioc);
-       r = _base_event_notification(ioc, VF_ID, sleep_flag);
+       r = _base_event_notification(ioc, sleep_flag);
        if (r)
                return r;
 
        if (sleep_flag == CAN_SLEEP)
                _base_static_config_pages(ioc);
 
-       r = _base_send_port_enable(ioc, VF_ID, sleep_flag);
+       r = _base_send_port_enable(ioc, sleep_flag);
        if (r)
                return r;
 
@@ -3278,6 +3469,17 @@ mpt2sas_base_attach(struct MPT2SAS_ADAPTER *ioc)
        if (r)
                goto out_free_resources;
 
+       ioc->pfacts = kcalloc(ioc->facts.NumberOfPorts,
+           sizeof(Mpi2PortFactsReply_t), GFP_KERNEL);
+       if (!ioc->pfacts)
+               goto out_free_resources;
+
+       for (i = 0 ; i < ioc->facts.NumberOfPorts; i++) {
+               r = _base_get_port_facts(ioc, i, CAN_SLEEP);
+               if (r)
+                       goto out_free_resources;
+       }
+
        r = _base_allocate_memory_pools(ioc, CAN_SLEEP);
        if (r)
                goto out_free_resources;
@@ -3286,7 +3488,6 @@ mpt2sas_base_attach(struct MPT2SAS_ADAPTER *ioc)
 
        /* base internal command bits */
        mutex_init(&ioc->base_cmds.mutex);
-       init_completion(&ioc->base_cmds.done);
        ioc->base_cmds.reply = kzalloc(ioc->reply_sz, GFP_KERNEL);
        ioc->base_cmds.status = MPT2_CMD_NOT_USED;
 
@@ -3294,7 +3495,6 @@ mpt2sas_base_attach(struct MPT2SAS_ADAPTER *ioc)
        ioc->transport_cmds.reply = kzalloc(ioc->reply_sz, GFP_KERNEL);
        ioc->transport_cmds.status = MPT2_CMD_NOT_USED;
        mutex_init(&ioc->transport_cmds.mutex);
-       init_completion(&ioc->transport_cmds.done);
 
        /* task management internal command bits */
        ioc->tm_cmds.reply = kzalloc(ioc->reply_sz, GFP_KERNEL);
@@ -3310,7 +3510,6 @@ mpt2sas_base_attach(struct MPT2SAS_ADAPTER *ioc)
        ioc->ctl_cmds.reply = kzalloc(ioc->reply_sz, GFP_KERNEL);
        ioc->ctl_cmds.status = MPT2_CMD_NOT_USED;
        mutex_init(&ioc->ctl_cmds.mutex);
-       init_completion(&ioc->ctl_cmds.done);
 
        for (i = 0; i < MPI2_EVENT_NOTIFY_EVENTMASK_WORDS; i++)
                ioc->event_masks[i] = -1;
@@ -3327,18 +3526,7 @@ mpt2sas_base_attach(struct MPT2SAS_ADAPTER *ioc)
        _base_unmask_events(ioc, MPI2_EVENT_IR_OPERATION_STATUS);
        _base_unmask_events(ioc, MPI2_EVENT_TASK_SET_FULL);
        _base_unmask_events(ioc, MPI2_EVENT_LOG_ENTRY_ADDED);
-
-       ioc->pfacts = kcalloc(ioc->facts.NumberOfPorts,
-           sizeof(Mpi2PortFactsReply_t), GFP_KERNEL);
-       if (!ioc->pfacts)
-               goto out_free_resources;
-
-       for (i = 0 ; i < ioc->facts.NumberOfPorts; i++) {
-               r = _base_get_port_facts(ioc, i, CAN_SLEEP);
-               if (r)
-                       goto out_free_resources;
-       }
-       r = _base_make_ioc_operational(ioc, 0, CAN_SLEEP);
+       r = _base_make_ioc_operational(ioc, CAN_SLEEP);
        if (r)
                goto out_free_resources;
 
@@ -3466,7 +3654,7 @@ _wait_for_commands_to_complete(struct MPT2SAS_ADAPTER *ioc, int sleep_flag)
 
        /* pending command count */
        spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
-       for (i = 0; i < ioc->request_depth; i++)
+       for (i = 0; i < ioc->scsiio_depth; i++)
                if (ioc->scsi_lookup[i].cb_idx != 0xFF)
                        ioc->pending_io_count++;
        spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
@@ -3490,7 +3678,7 @@ int
 mpt2sas_base_hard_reset_handler(struct MPT2SAS_ADAPTER *ioc, int sleep_flag,
     enum reset_type type)
 {
-       int r, i;
+       int r;
        unsigned long flags;
 
        dtmprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: enter\n", ioc->name,
@@ -3513,9 +3701,7 @@ mpt2sas_base_hard_reset_handler(struct MPT2SAS_ADAPTER *ioc, int sleep_flag,
        if (r)
                goto out;
        _base_reset_handler(ioc, MPT2_IOC_AFTER_RESET);
-       for (i = 0 ; i < ioc->facts.NumberOfPorts; i++)
-               r = _base_make_ioc_operational(ioc, ioc->pfacts[i].VF_ID,
-                   sleep_flag);
+       r = _base_make_ioc_operational(ioc, sleep_flag);
        if (!r)
                _base_reset_handler(ioc, MPT2_IOC_DONE_RESET);
  out:
index 2faab1e..0cf6bc2 100644 (file)
@@ -3,7 +3,7 @@
  * for access to MPT (Message Passing Technology) firmware.
  *
  * This code is based on drivers/scsi/mpt2sas/mpt2_base.h
- * Copyright (C) 2007-2008  LSI Corporation
+ * Copyright (C) 2007-2009  LSI Corporation
  *  (mailto:DL-MPTFusionLinux@lsi.com)
  *
  * This program is free software; you can redistribute it and/or
 #define MPT2SAS_DRIVER_NAME            "mpt2sas"
 #define MPT2SAS_AUTHOR "LSI Corporation <DL-MPTFusionLinux@lsi.com>"
 #define MPT2SAS_DESCRIPTION    "LSI MPT Fusion SAS 2.0 Device Driver"
-#define MPT2SAS_DRIVER_VERSION         "01.100.06.00"
-#define MPT2SAS_MAJOR_VERSION          01
+#define MPT2SAS_DRIVER_VERSION         "02.100.03.00"
+#define MPT2SAS_MAJOR_VERSION          02
 #define MPT2SAS_MINOR_VERSION          100
-#define MPT2SAS_BUILD_VERSION          06
+#define MPT2SAS_BUILD_VERSION          03
 #define MPT2SAS_RELEASE_VERSION                00
 
 /*
@@ -264,6 +264,13 @@ struct _internal_cmd {
  * SAS Topology Structures
  */
 
+#define MPTSAS_STATE_TR_SEND           0x0001
+#define MPTSAS_STATE_TR_COMPLETE       0x0002
+#define MPTSAS_STATE_CNTRL_SEND                0x0004
+#define MPTSAS_STATE_CNTRL_COMPLETE    0x0008
+
+#define MPT2SAS_REQ_SAS_CNTRL          0x0010
+
 /**
  * struct _sas_device - attached device information
  * @list: sas device list
@@ -300,6 +307,7 @@ struct _sas_device {
        u16     slot;
        u8      hidden_raid_component;
        u8      responding;
+       u16     state;
 };
 
 /**
@@ -436,6 +444,17 @@ struct request_tracker {
        struct list_head tracker_list;
 };
 
+/**
+ * struct _tr_list - target reset list
+ * @handle: device handle
+ * @state: state machine
+ */
+struct _tr_list {
+       struct list_head list;
+       u16     handle;
+       u16     state;
+};
+
 typedef void (*MPT_ADD_SGE)(void *paddr, u32 flags_length, dma_addr_t dma_addr);
 
 /**
@@ -510,8 +529,9 @@ typedef void (*MPT_ADD_SGE)(void *paddr, u32 flags_length, dma_addr_t dma_addr);
  * @config_page_sz: config page size
  * @config_page: reserve memory for config page payload
  * @config_page_dma:
+ * @hba_queue_depth: hba request queue depth
  * @sge_size: sg element size for either 32/64 bit
- * @request_depth: hba request queue depth
+ * @scsiio_depth: SCSI_IO queue depth
  * @request_sz: per request frame size
  * @request: pool of request frames
  * @request_dma:
@@ -528,6 +548,18 @@ typedef void (*MPT_ADD_SGE)(void *paddr, u32 flags_length, dma_addr_t dma_addr);
  * @chains_needed_per_io: max chains per io
  * @chain_offset_value_for_main_message: location 1st sg in main
  * @chain_depth: total chains allocated
+ * @hi_priority_smid:
+ * @hi_priority:
+ * @hi_priority_dma:
+ * @hi_priority_depth:
+ * @hpr_lookup:
+ * @hpr_free_list:
+ * @internal_smid:
+ * @internal:
+ * @internal_dma:
+ * @internal_depth:
+ * @internal_lookup:
+ * @internal_free_list:
  * @sense: pool of sense
  * @sense_dma:
  * @sense_dma_pool:
@@ -597,6 +629,8 @@ struct MPT2SAS_ADAPTER {
        u8              ctl_cb_idx;
        u8              base_cb_idx;
        u8              config_cb_idx;
+       u8              tm_tr_cb_idx;
+       u8              tm_sas_control_cb_idx;
        struct _internal_cmd base_cmds;
        struct _internal_cmd transport_cmds;
        struct _internal_cmd tm_cmds;
@@ -643,9 +677,10 @@ struct MPT2SAS_ADAPTER {
        void            *config_page;
        dma_addr_t      config_page_dma;
 
-       /* request */
+       /* scsiio request */
+       u16             hba_queue_depth;
        u16             sge_size;
-       u16             request_depth;
+       u16             scsiio_depth;
        u16             request_sz;
        u8              *request;
        dma_addr_t      request_dma;
@@ -665,6 +700,22 @@ struct MPT2SAS_ADAPTER {
        u16             chain_offset_value_for_main_message;
        u16             chain_depth;
 
+       /* hi-priority queue */
+       u16             hi_priority_smid;
+       u8              *hi_priority;
+       dma_addr_t      hi_priority_dma;
+       u16             hi_priority_depth;
+       struct request_tracker *hpr_lookup;
+       struct list_head hpr_free_list;
+
+       /* internal queue */
+       u16             internal_smid;
+       u8              *internal;
+       dma_addr_t      internal_dma;
+       u16             internal_depth;
+       struct request_tracker *internal_lookup;
+       struct list_head internal_free_list;
+
        /* sense */
        u8              *sense;
        dma_addr_t      sense_dma;
@@ -690,6 +741,8 @@ struct MPT2SAS_ADAPTER {
        struct dma_pool *reply_post_free_dma_pool;
        u32             reply_post_host_index;
 
+       struct list_head delayed_tr_list;
+
        /* diag buffer support */
        u8              *diag_buffer[MPI2_DIAG_BUF_TYPE_COUNT];
        u32             diag_buffer_sz[MPI2_DIAG_BUF_TYPE_COUNT];
@@ -701,7 +754,7 @@ struct MPT2SAS_ADAPTER {
        u32             diagnostic_flags[MPI2_DIAG_BUF_TYPE_COUNT];
 };
 
-typedef void (*MPT_CALLBACK)(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 VF_ID,
+typedef u8 (*MPT_CALLBACK)(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 msix_index,
     u32 reply);
 
 
@@ -720,22 +773,28 @@ int mpt2sas_base_hard_reset_handler(struct MPT2SAS_ADAPTER *ioc, int sleep_flag,
 void *mpt2sas_base_get_msg_frame(struct MPT2SAS_ADAPTER *ioc, u16 smid);
 void *mpt2sas_base_get_sense_buffer(struct MPT2SAS_ADAPTER *ioc, u16 smid);
 void mpt2sas_base_build_zero_len_sge(struct MPT2SAS_ADAPTER *ioc, void *paddr);
-dma_addr_t mpt2sas_base_get_msg_frame_dma(struct MPT2SAS_ADAPTER *ioc, u16 smid);
-dma_addr_t mpt2sas_base_get_sense_buffer_dma(struct MPT2SAS_ADAPTER *ioc, u16 smid);
+dma_addr_t mpt2sas_base_get_sense_buffer_dma(struct MPT2SAS_ADAPTER *ioc,
+    u16 smid);
+
+/* hi-priority queue */
+u16 mpt2sas_base_get_smid_hpr(struct MPT2SAS_ADAPTER *ioc, u8 cb_idx);
+u16 mpt2sas_base_get_smid_scsiio(struct MPT2SAS_ADAPTER *ioc, u8 cb_idx,
+    struct scsi_cmnd *scmd);
 
 u16 mpt2sas_base_get_smid(struct MPT2SAS_ADAPTER *ioc, u8 cb_idx);
 void mpt2sas_base_free_smid(struct MPT2SAS_ADAPTER *ioc, u16 smid);
-void mpt2sas_base_put_smid_scsi_io(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 vf_id,
+void mpt2sas_base_put_smid_scsi_io(struct MPT2SAS_ADAPTER *ioc, u16 smid,
     u16 handle);
-void mpt2sas_base_put_smid_hi_priority(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 vf_id);
+void mpt2sas_base_put_smid_hi_priority(struct MPT2SAS_ADAPTER *ioc, u16 smid);
 void mpt2sas_base_put_smid_target_assist(struct MPT2SAS_ADAPTER *ioc, u16 smid,
-    u8 vf_id, u16 io_index);
-void mpt2sas_base_put_smid_default(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 vf_id);
+    u16 io_index);
+void mpt2sas_base_put_smid_default(struct MPT2SAS_ADAPTER *ioc, u16 smid);
 void mpt2sas_base_initialize_callback_handler(void);
 u8 mpt2sas_base_register_callback_handler(MPT_CALLBACK cb_func);
 void mpt2sas_base_release_callback_handler(u8 cb_idx);
 
-void mpt2sas_base_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 VF_ID, u32 reply);
+u8 mpt2sas_base_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 msix_index,
+    u32 reply);
 void *mpt2sas_base_get_reply_virt_addr(struct MPT2SAS_ADAPTER *ioc, u32 phys_addr);
 
 u32 mpt2sas_base_get_iocstate(struct MPT2SAS_ADAPTER *ioc, int cooked);
@@ -749,6 +808,8 @@ int mpt2sas_base_scsi_enclosure_processor(struct MPT2SAS_ADAPTER *ioc,
 void mpt2sas_base_validate_event_type(struct MPT2SAS_ADAPTER *ioc, u32 *event_type);
 
 /* scsih shared API */
+u8 mpt2sas_scsih_event_callback(struct MPT2SAS_ADAPTER *ioc, u8 msix_index,
+    u32 reply);
 void mpt2sas_scsih_issue_tm(struct MPT2SAS_ADAPTER *ioc, u16 handle, uint lun,
     u8 type, u16 smid_task, ulong timeout);
 void mpt2sas_scsih_set_tm_flag(struct MPT2SAS_ADAPTER *ioc, u16 handle);
@@ -760,11 +821,11 @@ struct _sas_node *mpt2sas_scsih_expander_find_by_sas_address(struct MPT2SAS_ADAP
 struct _sas_device *mpt2sas_scsih_sas_device_find_by_sas_address(
     struct MPT2SAS_ADAPTER *ioc, u64 sas_address);
 
-void mpt2sas_scsih_event_callback(struct MPT2SAS_ADAPTER *ioc, u8 VF_ID, u32 reply);
 void mpt2sas_scsih_reset_handler(struct MPT2SAS_ADAPTER *ioc, int reset_phase);
 
 /* config shared API */
-void mpt2sas_config_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 VF_ID, u32 reply);
+u8 mpt2sas_config_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 msix_index,
+    u32 reply);
 int mpt2sas_config_get_number_hba_phys(struct MPT2SAS_ADAPTER *ioc, u8 *num_phys);
 int mpt2sas_config_get_manufacturing_pg0(struct MPT2SAS_ADAPTER *ioc,
     Mpi2ConfigReply_t *mpi_reply, Mpi2ManufacturingPage0_t *config_page);
@@ -817,14 +878,17 @@ extern struct device_attribute *mpt2sas_host_attrs[];
 extern struct device_attribute *mpt2sas_dev_attrs[];
 void mpt2sas_ctl_init(void);
 void mpt2sas_ctl_exit(void);
-void mpt2sas_ctl_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 VF_ID, u32 reply);
+u8 mpt2sas_ctl_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 msix_index,
+    u32 reply);
 void mpt2sas_ctl_reset_handler(struct MPT2SAS_ADAPTER *ioc, int reset_phase);
-void mpt2sas_ctl_event_callback(struct MPT2SAS_ADAPTER *ioc, u8 VF_ID, u32 reply);
+u8 mpt2sas_ctl_event_callback(struct MPT2SAS_ADAPTER *ioc, u8 msix_index,
+    u32 reply);
 void mpt2sas_ctl_add_to_event_log(struct MPT2SAS_ADAPTER *ioc,
     Mpi2EventNotificationReply_t *mpi_reply);
 
 /* transport shared API */
-void mpt2sas_transport_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 VF_ID, u32 reply);
+u8 mpt2sas_transport_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 msix_index,
+    u32 reply);
 struct _sas_port *mpt2sas_transport_port_add(struct MPT2SAS_ADAPTER *ioc,
     u16 handle, u16 parent_handle);
 void mpt2sas_transport_port_remove(struct MPT2SAS_ADAPTER *ioc, u64 sas_address,
@@ -838,6 +902,8 @@ void mpt2sas_transport_update_links(struct MPT2SAS_ADAPTER *ioc, u16 handle,
 extern struct sas_function_template mpt2sas_transport_functions;
 extern struct scsi_transport_template *mpt2sas_transport_template;
 extern int scsi_internal_device_block(struct scsi_device *sdev);
+extern u8 mpt2sas_stm_zero_smid_handler(struct MPT2SAS_ADAPTER *ioc,
+    u8 msix_index, u32 reply);
 extern int scsi_internal_device_unblock(struct scsi_device *sdev);
 
 #endif /* MPT2SAS_BASE_H_INCLUDED */
index ab8c560..594a389 100644 (file)
@@ -2,7 +2,7 @@
  * This module provides common API for accessing firmware configuration pages
  *
  * This code is based on drivers/scsi/mpt2sas/mpt2_base.c
- * Copyright (C) 2007-2008  LSI Corporation
+ * Copyright (C) 2007-2009  LSI Corporation
  *  (mailto:DL-MPTFusionLinux@lsi.com)
  *
  * This program is free software; you can redistribute it and/or
@@ -227,23 +227,25 @@ _config_free_config_dma_memory(struct MPT2SAS_ADAPTER *ioc,
  * mpt2sas_config_done - config page completion routine
  * @ioc: per adapter object
  * @smid: system request message index
- * @VF_ID: virtual function id
+ * @msix_index: MSIX table index supplied by the OS
  * @reply: reply message frame(lower 32bit addr)
  * Context: none.
  *
  * The callback handler when using _config_request.
  *
- * Return nothing.
+ * Return 1 meaning mf should be freed from _base_interrupt
+ *        0 means the mf is freed from this function.
  */
-void
-mpt2sas_config_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 VF_ID, u32 reply)
+u8
+mpt2sas_config_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 msix_index,
+    u32 reply)
 {
        MPI2DefaultReply_t *mpi_reply;
 
        if (ioc->config_cmds.status == MPT2_CMD_NOT_USED)
-               return;
+               return 1;
        if (ioc->config_cmds.smid != smid)
-               return;
+               return 1;
        ioc->config_cmds.status |= MPT2_CMD_COMPLETE;
        mpi_reply =  mpt2sas_base_get_reply_virt_addr(ioc, reply);
        if (mpi_reply) {
@@ -257,6 +259,7 @@ mpt2sas_config_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 VF_ID, u32 reply)
 #endif
        ioc->config_cmds.smid = USHORT_MAX;
        complete(&ioc->config_cmds.done);
+       return 1;
 }
 
 /**
@@ -303,6 +306,9 @@ _config_request(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigRequest_t
        retry_count = 0;
        memset(&mem, 0, sizeof(struct config_request));
 
+       mpi_request->VF_ID = 0; /* TODO */
+       mpi_request->VP_ID = 0;
+
        if (config_page) {
                mpi_request->Header.PageVersion = mpi_reply->Header.PageVersion;
                mpi_request->Header.PageNumber = mpi_reply->Header.PageNumber;
@@ -380,7 +386,7 @@ _config_request(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigRequest_t
        _config_display_some_debug(ioc, smid, "config_request", NULL);
 #endif
        init_completion(&ioc->config_cmds.done);
-       mpt2sas_base_put_smid_default(ioc, smid, config_request->VF_ID);
+       mpt2sas_base_put_smid_default(ioc, smid);
        timeleft = wait_for_completion_timeout(&ioc->config_cmds.done,
            timeout*HZ);
        if (!(ioc->config_cmds.status & MPT2_CMD_COMPLETE)) {
index c2a5101..57d7246 100644 (file)
@@ -3,7 +3,7 @@
  * controllers
  *
  * This code is based on drivers/scsi/mpt2sas/mpt2_ctl.c
- * Copyright (C) 2007-2008  LSI Corporation
+ * Copyright (C) 2007-2009  LSI Corporation
  *  (mailto:DL-MPTFusionLinux@lsi.com)
  *
  * This program is free software; you can redistribute it and/or
@@ -219,23 +219,25 @@ _ctl_display_some_debug(struct MPT2SAS_ADAPTER *ioc, u16 smid,
  * mpt2sas_ctl_done - ctl module completion routine
  * @ioc: per adapter object
  * @smid: system request message index
- * @VF_ID: virtual function id
+ * @msix_index: MSIX table index supplied by the OS
  * @reply: reply message frame(lower 32bit addr)
  * Context: none.
  *
  * The callback handler when using ioc->ctl_cb_idx.
  *
- * Return nothing.
+ * Return 1 meaning mf should be freed from _base_interrupt
+ *        0 means the mf is freed from this function.
  */
-void
-mpt2sas_ctl_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 VF_ID, u32 reply)
+u8
+mpt2sas_ctl_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 msix_index,
+       u32 reply)
 {
        MPI2DefaultReply_t *mpi_reply;
 
        if (ioc->ctl_cmds.status == MPT2_CMD_NOT_USED)
-               return;
+               return 1;
        if (ioc->ctl_cmds.smid != smid)
-               return;
+               return 1;
        ioc->ctl_cmds.status |= MPT2_CMD_COMPLETE;
        mpi_reply = mpt2sas_base_get_reply_virt_addr(ioc, reply);
        if (mpi_reply) {
@@ -247,6 +249,7 @@ mpt2sas_ctl_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 VF_ID, u32 reply)
 #endif
        ioc->ctl_cmds.status &= ~MPT2_CMD_PENDING;
        complete(&ioc->ctl_cmds.done);
+       return 1;
 }
 
 /**
@@ -328,22 +331,25 @@ mpt2sas_ctl_add_to_event_log(struct MPT2SAS_ADAPTER *ioc,
 /**
  * mpt2sas_ctl_event_callback - firmware event handler (called at ISR time)
  * @ioc: per adapter object
- * @VF_ID: virtual function id
+ * @msix_index: MSIX table index supplied by the OS
  * @reply: reply message frame(lower 32bit addr)
  * Context: interrupt.
  *
  * This function merely adds a new work task into ioc->firmware_event_thread.
  * The tasks are worked from _firmware_event_work in user context.
  *
- * Return nothing.
+ * Return 1 meaning mf should be freed from _base_interrupt
+ *        0 means the mf is freed from this function.
  */
-void
-mpt2sas_ctl_event_callback(struct MPT2SAS_ADAPTER *ioc, u8 VF_ID, u32 reply)
+u8
+mpt2sas_ctl_event_callback(struct MPT2SAS_ADAPTER *ioc, u8 msix_index,
+       u32 reply)
 {
        Mpi2EventNotificationReply_t *mpi_reply;
 
        mpi_reply = mpt2sas_base_get_reply_virt_addr(ioc, reply);
        mpt2sas_ctl_add_to_event_log(ioc, mpi_reply);
+       return 1;
 }
 
 /**
@@ -507,7 +513,7 @@ _ctl_set_task_mid(struct MPT2SAS_ADAPTER *ioc, struct mpt2_ioctl_command *karg,
 
        handle = le16_to_cpu(tm_request->DevHandle);
        spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
-       for (i = ioc->request_depth; i && !found; i--) {
+       for (i = ioc->scsiio_depth; i && !found; i--) {
                scmd = ioc->scsi_lookup[i - 1].scmd;
                if (scmd == NULL || scmd->device == NULL ||
                    scmd->device->hostdata == NULL)
@@ -614,7 +620,7 @@ _ctl_do_mpt_command(struct MPT2SAS_ADAPTER *ioc,
                printk(MPT2SAS_INFO_FMT "%s: ioc is operational\n",
                    ioc->name, __func__);
 
-       smid = mpt2sas_base_get_smid(ioc, ioc->ctl_cb_idx);
+       smid = mpt2sas_base_get_smid_scsiio(ioc, ioc->ctl_cb_idx, NULL);
        if (!smid) {
                printk(MPT2SAS_ERR_FMT "%s: failed obtaining a smid\n",
                    ioc->name, __func__);
@@ -737,7 +743,7 @@ _ctl_do_mpt_command(struct MPT2SAS_ADAPTER *ioc,
                    (u32)mpt2sas_base_get_sense_buffer_dma(ioc, smid);
                priv_sense = mpt2sas_base_get_sense_buffer(ioc, smid);
                memset(priv_sense, 0, SCSI_SENSE_BUFFERSIZE);
-               mpt2sas_base_put_smid_scsi_io(ioc, smid, 0,
+               mpt2sas_base_put_smid_scsi_io(ioc, smid,
                    le16_to_cpu(mpi_request->FunctionDependent1));
                break;
        }
@@ -759,8 +765,7 @@ _ctl_do_mpt_command(struct MPT2SAS_ADAPTER *ioc,
                mutex_lock(&ioc->tm_cmds.mutex);
                mpt2sas_scsih_set_tm_flag(ioc, le16_to_cpu(
                    tm_request->DevHandle));
-               mpt2sas_base_put_smid_hi_priority(ioc, smid,
-                   mpi_request->VF_ID);
+               mpt2sas_base_put_smid_hi_priority(ioc, smid);
                break;
        }
        case MPI2_FUNCTION_SMP_PASSTHROUGH:
@@ -781,7 +786,7 @@ _ctl_do_mpt_command(struct MPT2SAS_ADAPTER *ioc,
                        ioc->ioc_link_reset_in_progress = 1;
                        ioc->ignore_loginfos = 1;
                }
-               mpt2sas_base_put_smid_default(ioc, smid, mpi_request->VF_ID);
+               mpt2sas_base_put_smid_default(ioc, smid);
                break;
        }
        case MPI2_FUNCTION_SAS_IO_UNIT_CONTROL:
@@ -795,11 +800,11 @@ _ctl_do_mpt_command(struct MPT2SAS_ADAPTER *ioc,
                        ioc->ioc_link_reset_in_progress = 1;
                        ioc->ignore_loginfos = 1;
                }
-               mpt2sas_base_put_smid_default(ioc, smid, mpi_request->VF_ID);
+               mpt2sas_base_put_smid_default(ioc, smid);
                break;
        }
        default:
-               mpt2sas_base_put_smid_default(ioc, smid, mpi_request->VF_ID);
+               mpt2sas_base_put_smid_default(ioc, smid);
                break;
        }
 
@@ -807,6 +812,7 @@ _ctl_do_mpt_command(struct MPT2SAS_ADAPTER *ioc,
                timeout = MPT2_IOCTL_DEFAULT_TIMEOUT;
        else
                timeout = karg.timeout;
+       init_completion(&ioc->ctl_cmds.done);
        timeleft = wait_for_completion_timeout(&ioc->ctl_cmds.done,
            timeout*HZ);
        if (mpi_request->Function == MPI2_FUNCTION_SCSI_TASK_MGMT) {
@@ -1371,6 +1377,8 @@ _ctl_diag_register(void __user *arg, enum block_state state)
        mpi_request->Flags = cpu_to_le32(karg.diagnostic_flags);
        mpi_request->BufferAddress = cpu_to_le64(request_data_dma);
        mpi_request->BufferLength = cpu_to_le32(request_data_sz);
+       mpi_request->VF_ID = 0; /* TODO */
+       mpi_request->VP_ID = 0;
 
        dctlprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: diag_buffer(0x%p), "
            "dma(0x%llx), sz(%d)\n", ioc->name, __func__, request_data,
@@ -1380,7 +1388,8 @@ _ctl_diag_register(void __user *arg, enum block_state state)
                mpi_request->ProductSpecific[i] =
                        cpu_to_le32(ioc->product_specific[buffer_type][i]);
 
-       mpt2sas_base_put_smid_default(ioc, smid, mpi_request->VF_ID);
+       mpt2sas_base_put_smid_default(ioc, smid);
+       init_completion(&ioc->ctl_cmds.done);
        timeleft = wait_for_completion_timeout(&ioc->ctl_cmds.done,
            MPT2_IOCTL_DEFAULT_TIMEOUT*HZ);
 
@@ -1643,8 +1652,11 @@ _ctl_send_release(struct MPT2SAS_ADAPTER *ioc, u8 buffer_type, u8 *issue_reset)
 
        mpi_request->Function = MPI2_FUNCTION_DIAG_RELEASE;
        mpi_request->BufferType = buffer_type;
+       mpi_request->VF_ID = 0; /* TODO */
+       mpi_request->VP_ID = 0;
 
-       mpt2sas_base_put_smid_default(ioc, smid, mpi_request->VF_ID);
+       mpt2sas_base_put_smid_default(ioc, smid);
+       init_completion(&ioc->ctl_cmds.done);
        timeleft = wait_for_completion_timeout(&ioc->ctl_cmds.done,
            MPT2_IOCTL_DEFAULT_TIMEOUT*HZ);
 
@@ -1902,8 +1914,11 @@ _ctl_diag_read_buffer(void __user *arg, enum block_state state)
        for (i = 0; i < MPT2_PRODUCT_SPECIFIC_DWORDS; i++)
                mpi_request->ProductSpecific[i] =
                        cpu_to_le32(ioc->product_specific[buffer_type][i]);
+       mpi_request->VF_ID = 0; /* TODO */
+       mpi_request->VP_ID = 0;
 
-       mpt2sas_base_put_smid_default(ioc, smid, mpi_request->VF_ID);
+       mpt2sas_base_put_smid_default(ioc, smid);
+       init_completion(&ioc->ctl_cmds.done);
        timeleft = wait_for_completion_timeout(&ioc->ctl_cmds.done,
            MPT2_IOCTL_DEFAULT_TIMEOUT*HZ);
 
@@ -2069,6 +2084,7 @@ static long
 _ctl_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 {
        long ret;
+
        lock_kernel();
        ret = _ctl_ioctl_main(file, cmd, (void __user *)arg);
        unlock_kernel();
@@ -2143,6 +2159,7 @@ static long
 _ctl_ioctl_compat(struct file *file, unsigned cmd, unsigned long arg)
 {
        long ret;
+
        lock_kernel();
        if (cmd == MPT2COMMAND32)
                ret = _ctl_compat_mpt_command(file, cmd, arg);
index 4da1143..211f296 100644 (file)
@@ -3,7 +3,7 @@
  * controllers
  *
  * This code is based on drivers/scsi/mpt2sas/mpt2_ctl.h
- * Copyright (C) 2007-2008  LSI Corporation
+ * Copyright (C) 2007-2009  LSI Corporation
  *  (mailto:DL-MPTFusionLinux@lsi.com)
  *
  * This program is free software; you can redistribute it and/or
index ad32509..5308a25 100644 (file)
@@ -2,7 +2,7 @@
  * Logging Support for MPT (Message Passing Technology) based controllers
  *
  * This code is based on drivers/scsi/mpt2sas/mpt2_debug.c
- * Copyright (C) 2007-2008  LSI Corporation
+ * Copyright (C) 2007-2009  LSI Corporation
  *  (mailto:DL-MPTFusionLinux@lsi.com)
  *
  * This program is free software; you can redistribute it and/or
index 774b345..86ab32d 100644 (file)
@@ -2,7 +2,7 @@
  * Scsi Host Layer for MPT (Message Passing Technology) based controllers
  *
  * This code is based on drivers/scsi/mpt2sas/mpt2_scsih.c
- * Copyright (C) 2007-2008  LSI Corporation
+ * Copyright (C) 2007-2009  LSI Corporation
  *  (mailto:DL-MPTFusionLinux@lsi.com)
  *
  * This program is free software; you can redistribute it and/or
@@ -79,6 +79,9 @@ static u8 transport_cb_idx = -1;
 static u8 config_cb_idx = -1;
 static int mpt_ids;
 
+static u8 tm_tr_cb_idx = -1 ;
+static u8 tm_sas_control_cb_idx = -1;
+
 /* command line options */
 static u32 logging_level;
 MODULE_PARM_DESC(logging_level, " bits for enabling additional logging info "
@@ -109,6 +112,7 @@ struct sense_info {
  * @work: work object (ioc->fault_reset_work_q)
  * @ioc: per adapter object
  * @VF_ID: virtual function id
+ * @VP_ID: virtual port id
  * @host_reset_handling: handling events during host reset
  * @ignore: flag meaning this event has been marked to ignore
  * @event: firmware event MPI2_EVENT_XXX defined in mpt2_ioc.h
@@ -121,6 +125,7 @@ struct fw_event_work {
        struct work_struct      work;
        struct MPT2SAS_ADAPTER *ioc;
        u8                      VF_ID;
+       u8                      VP_ID;
        u8                      host_reset_handling;
        u8                      ignore;
        u16                     event;
@@ -138,8 +143,10 @@ struct fw_event_work {
  * @lun: lun number
  * @cdb_length: cdb length
  * @cdb: cdb contents
- * @valid_reply: flag set for reply message
  * @timeout: timeout for this command
+ * @VF_ID: virtual function id
+ * @VP_ID: virtual port id
+ * @valid_reply: flag set for reply message
  * @sense_length: sense length
  * @ioc_status: ioc status
  * @scsi_state: scsi state
@@ -161,6 +168,8 @@ struct _scsi_io_transfer {
        u8      cdb_length;
        u8      cdb[32];
        u8      timeout;
+       u8      VF_ID;
+       u8      VP_ID;
        u8      valid_reply;
   /* the following bits are only valid when 'valid_reply = 1' */
        u32     sense_length;
@@ -756,66 +765,16 @@ _scsih_is_end_device(u32 device_info)
 }
 
 /**
- * _scsih_scsi_lookup_get - returns scmd entry
+ * mptscsih_get_scsi_lookup - returns scmd entry
  * @ioc: per adapter object
  * @smid: system request message index
- * Context: This function will acquire ioc->scsi_lookup_lock.
  *
  * Returns the smid stored scmd pointer.
  */
 static struct scsi_cmnd *
 _scsih_scsi_lookup_get(struct MPT2SAS_ADAPTER *ioc, u16 smid)
 {
-       unsigned long   flags;
-       struct scsi_cmnd *scmd;
-
-       spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
-       scmd = ioc->scsi_lookup[smid - 1].scmd;
-       spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
-       return scmd;
-}
-
-/**
- * mptscsih_getclear_scsi_lookup - returns scmd entry
- * @ioc: per adapter object
- * @smid: system request message index
- * Context: This function will acquire ioc->scsi_lookup_lock.
- *
- * Returns the smid stored scmd pointer, as well as clearing the scmd pointer.
- */
-static struct scsi_cmnd *
-_scsih_scsi_lookup_getclear(struct MPT2SAS_ADAPTER *ioc, u16 smid)
-{
-       unsigned long   flags;
-       struct scsi_cmnd *scmd;
-
-       spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
-       scmd = ioc->scsi_lookup[smid - 1].scmd;
-       ioc->scsi_lookup[smid - 1].scmd = NULL;
-       spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
-       return scmd;
-}
-
-/**
- * _scsih_scsi_lookup_set - updates scmd entry in lookup
- * @ioc: per adapter object
- * @smid: system request message index
- * @scmd: pointer to scsi command object
- * Context: This function will acquire ioc->scsi_lookup_lock.
- *
- * This will save scmd pointer in the scsi_lookup array.
- *
- * Return nothing.
- */
-static void
-_scsih_scsi_lookup_set(struct MPT2SAS_ADAPTER *ioc, u16 smid,
-    struct scsi_cmnd *scmd)
-{
-       unsigned long   flags;
-
-       spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
-       ioc->scsi_lookup[smid - 1].scmd = scmd;
-       spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
+       return ioc->scsi_lookup[smid - 1].scmd;
 }
 
 /**
@@ -838,9 +797,9 @@ _scsih_scsi_lookup_find_by_scmd(struct MPT2SAS_ADAPTER *ioc, struct scsi_cmnd
 
        spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
        smid = 0;
-       for (i = 0; i < ioc->request_depth; i++) {
+       for (i = 0; i < ioc->scsiio_depth; i++) {
                if (ioc->scsi_lookup[i].scmd == scmd) {
-                       smid = i + 1;
+                       smid = ioc->scsi_lookup[i].smid;
                        goto out;
                }
        }
@@ -869,7 +828,7 @@ _scsih_scsi_lookup_find_by_target(struct MPT2SAS_ADAPTER *ioc, int id,
 
        spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
        found = 0;
-       for (i = 0 ; i < ioc->request_depth; i++) {
+       for (i = 0 ; i < ioc->scsiio_depth; i++) {
                if (ioc->scsi_lookup[i].scmd &&
                    (ioc->scsi_lookup[i].scmd->device->id == id &&
                    ioc->scsi_lookup[i].scmd->device->channel == channel)) {
@@ -903,7 +862,7 @@ _scsih_scsi_lookup_find_by_lun(struct MPT2SAS_ADAPTER *ioc, int id,
 
        spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
        found = 0;
-       for (i = 0 ; i < ioc->request_depth; i++) {
+       for (i = 0 ; i < ioc->scsiio_depth; i++) {
                if (ioc->scsi_lookup[i].scmd &&
                    (ioc->scsi_lookup[i].scmd->device->id == id &&
                    ioc->scsi_lookup[i].scmd->device->channel == channel &&
@@ -1113,7 +1072,7 @@ _scsih_change_queue_depth(struct scsi_device *sdev, int qdepth)
 }
 
 /**
- * _scsih_change_queue_depth - changing device queue tag type
+ * _scsih_change_queue_type - changing device queue tag type
  * @sdev: scsi device struct
  * @tag_type: requested tag type
  *
@@ -1679,23 +1638,24 @@ _scsih_response_code(struct MPT2SAS_ADAPTER *ioc, u8 response_code)
  * _scsih_tm_done - tm completion routine
  * @ioc: per adapter object
  * @smid: system request message index
- * @VF_ID: virtual function id
+ * @msix_index: MSIX table index supplied by the OS
  * @reply: reply message frame(lower 32bit addr)
  * Context: none.
  *
  * The callback handler when using scsih_issue_tm.
  *
- * Return nothing.
+ * Return 1 meaning mf should be freed from _base_interrupt
+ *        0 means the mf is freed from this function.
  */
-static void
-_scsih_tm_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 VF_ID, u32 reply)
+static u8
+_scsih_tm_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 msix_index, u32 reply)
 {
        MPI2DefaultReply_t *mpi_reply;
 
        if (ioc->tm_cmds.status == MPT2_CMD_NOT_USED)
-               return;
+               return 1;
        if (ioc->tm_cmds.smid != smid)
-               return;
+               return 1;
        ioc->tm_cmds.status |= MPT2_CMD_COMPLETE;
        mpi_reply =  mpt2sas_base_get_reply_virt_addr(ioc, reply);
        if (mpi_reply) {
@@ -1704,6 +1664,7 @@ _scsih_tm_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 VF_ID, u32 reply)
        }
        ioc->tm_cmds.status &= ~MPT2_CMD_PENDING;
        complete(&ioc->tm_cmds.done);
+       return 1;
 }
 
 /**
@@ -1790,7 +1751,6 @@ mpt2sas_scsih_issue_tm(struct MPT2SAS_ADAPTER *ioc, u16 handle, uint lun,
        u16 smid = 0;
        u32 ioc_state;
        unsigned long timeleft;
-       u8 VF_ID = 0;
 
        if (ioc->tm_cmds.status != MPT2_CMD_NOT_USED) {
                printk(MPT2SAS_INFO_FMT "%s: tm_cmd busy!!!\n",
@@ -1817,7 +1777,7 @@ mpt2sas_scsih_issue_tm(struct MPT2SAS_ADAPTER *ioc, u16 handle, uint lun,
                goto issue_host_reset;
        }
 
-       smid = mpt2sas_base_get_smid(ioc, ioc->tm_cb_idx);
+       smid = mpt2sas_base_get_smid_hpr(ioc, ioc->tm_cb_idx);
        if (!smid) {
                printk(MPT2SAS_ERR_FMT "%s: failed obtaining a smid\n",
                    ioc->name, __func__);
@@ -1825,7 +1785,8 @@ mpt2sas_scsih_issue_tm(struct MPT2SAS_ADAPTER *ioc, u16 handle, uint lun,
        }
 
        dtmprintk(ioc, printk(MPT2SAS_INFO_FMT "sending tm: handle(0x%04x),"
-           " task_type(0x%02x), smid(%d)\n", ioc->name, handle, type, smid));
+           " task_type(0x%02x), smid(%d)\n", ioc->name, handle, type,
+           smid_task));
        ioc->tm_cmds.status = MPT2_CMD_PENDING;
        mpi_request = mpt2sas_base_get_msg_frame(ioc, smid);
        ioc->tm_cmds.smid = smid;
@@ -1834,10 +1795,12 @@ mpt2sas_scsih_issue_tm(struct MPT2SAS_ADAPTER *ioc, u16 handle, uint lun,
        mpi_request->DevHandle = cpu_to_le16(handle);
        mpi_request->TaskType = type;
        mpi_request->TaskMID = cpu_to_le16(smid_task);
+       mpi_request->VP_ID = 0;  /* TODO */
+       mpi_request->VF_ID = 0;
        int_to_scsilun(lun, (struct scsi_lun *)mpi_request->LUN);
        mpt2sas_scsih_set_tm_flag(ioc, handle);
        init_completion(&ioc->tm_cmds.done);
-       mpt2sas_base_put_smid_hi_priority(ioc, smid, VF_ID);
+       mpt2sas_base_put_smid_hi_priority(ioc, smid);
        timeleft = wait_for_completion_timeout(&ioc->tm_cmds.done, timeout*HZ);
        mpt2sas_scsih_clear_tm_flag(ioc, handle);
        if (!(ioc->tm_cmds.status & MPT2_CMD_COMPLETE)) {
@@ -2075,7 +2038,7 @@ _scsih_target_reset(struct scsi_cmnd *scmd)
 }
 
 /**
- * _scsih_abort - eh threads main host reset routine
+ * _scsih_host_reset - eh threads main host reset routine
  * @sdev: scsi device struct
  *
  * Returns SUCCESS if command aborted else FAILED
@@ -2354,6 +2317,231 @@ _scsih_block_io_to_children_attached_directly(struct MPT2SAS_ADAPTER *ioc,
 }
 
 /**
+ * _scsih_tm_tr_send - send task management request
+ * @ioc: per adapter object
+ * @handle: device handle
+ * Context: interrupt time.
+ *
+ * This code is to initiate the device removal handshake protocal
+ * with controller firmware.  This function will issue target reset
+ * using high priority request queue.  It will send a sas iounit
+ * controll request (MPI2_SAS_OP_REMOVE_DEVICE) from this completion.
+ *
+ * This is designed to send muliple task management request at the same
+ * time to the fifo. If the fifo is full, we will append the request,
+ * and process it in a future completion.
+ */
+static void
+_scsih_tm_tr_send(struct MPT2SAS_ADAPTER *ioc, u16 handle)
+{
+       Mpi2SCSITaskManagementRequest_t *mpi_request;
+       struct MPT2SAS_TARGET *sas_target_priv_data;
+       u16 smid;
+       struct _sas_device *sas_device;
+       unsigned long flags;
+       struct _tr_list *delayed_tr;
+
+       if (ioc->shost_recovery) {
+               printk(MPT2SAS_INFO_FMT "%s: host reset in progress!\n",
+                   __func__, ioc->name);
+               return;
+       }
+
+       spin_lock_irqsave(&ioc->sas_device_lock, flags);
+       sas_device = _scsih_sas_device_find_by_handle(ioc, handle);
+       if (!sas_device) {
+               spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
+               printk(MPT2SAS_ERR_FMT "%s: failed finding sas_device\n",
+                   ioc->name, __func__);
+               return;
+       }
+       spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
+
+       /* skip is hidden raid component */
+       if (sas_device->hidden_raid_component)
+               return;
+
+       smid = mpt2sas_base_get_smid_hpr(ioc, ioc->tm_tr_cb_idx);
+       if (!smid) {
+               delayed_tr = kzalloc(sizeof(*delayed_tr), GFP_ATOMIC);
+               if (!delayed_tr)
+                       return;
+               INIT_LIST_HEAD(&delayed_tr->list);
+               delayed_tr->handle = handle;
+               delayed_tr->state = MPT2SAS_REQ_SAS_CNTRL;
+               list_add_tail(&delayed_tr->list,
+                   &ioc->delayed_tr_list);
+               if (sas_device->starget)
+                       dewtprintk(ioc, starget_printk(KERN_INFO,
+                           sas_device->starget, "DELAYED:tr:handle(0x%04x), "
+                           "(open)\n", sas_device->handle));
+               return;
+       }
+
+       if (sas_device->starget && sas_device->starget->hostdata) {
+               sas_target_priv_data = sas_device->starget->hostdata;
+               sas_target_priv_data->tm_busy = 1;
+               dewtprintk(ioc, starget_printk(KERN_INFO, sas_device->starget,
+                   "tr:handle(0x%04x), (open)\n", sas_device->handle));
+       }
+
+       mpi_request = mpt2sas_base_get_msg_frame(ioc, smid);
+       memset(mpi_request, 0, sizeof(Mpi2SCSITaskManagementRequest_t));
+       mpi_request->Function = MPI2_FUNCTION_SCSI_TASK_MGMT;
+       mpi_request->DevHandle = cpu_to_le16(handle);
+       mpi_request->TaskType = MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET;
+       sas_device->state |= MPTSAS_STATE_TR_SEND;
+       sas_device->state |= MPT2SAS_REQ_SAS_CNTRL;
+       mpt2sas_base_put_smid_hi_priority(ioc, smid);
+}
+
+
+
+/**
+ * _scsih_sas_control_complete - completion routine
+ * @ioc: per adapter object
+ * @smid: system request message index
+ * @msix_index: MSIX table index supplied by the OS
+ * @reply: reply message frame(lower 32bit addr)
+ * Context: interrupt time.
+ *
+ * This is the sas iounit controll completion routine.
+ * This code is part of the code to initiate the device removal
+ * handshake protocal with controller firmware.
+ *
+ * Return 1 meaning mf should be freed from _base_interrupt
+ *        0 means the mf is freed from this function.
+ */
+static u8
+_scsih_sas_control_complete(struct MPT2SAS_ADAPTER *ioc, u16 smid,
+    u8 msix_index, u32 reply)
+{
+       unsigned long flags;
+       u16 handle;
+       struct _sas_device *sas_device;
+       Mpi2SasIoUnitControlReply_t *mpi_reply =
+           mpt2sas_base_get_reply_virt_addr(ioc, reply);
+
+       handle = le16_to_cpu(mpi_reply->DevHandle);
+
+       spin_lock_irqsave(&ioc->sas_device_lock, flags);
+       sas_device = _scsih_sas_device_find_by_handle(ioc, handle);
+       if (!sas_device) {
+               spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
+               printk(MPT2SAS_ERR_FMT "%s: failed finding sas_device\n",
+                   ioc->name, __func__);
+               return 1;
+       }
+       sas_device->state |= MPTSAS_STATE_CNTRL_COMPLETE;
+       spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
+
+       if (sas_device->starget)
+               dewtprintk(ioc, starget_printk(KERN_INFO, sas_device->starget,
+                   "sc_complete:handle(0x%04x), "
+                   "ioc_status(0x%04x), loginfo(0x%08x)\n",
+                   handle, le16_to_cpu(mpi_reply->IOCStatus),
+                   le32_to_cpu(mpi_reply->IOCLogInfo)));
+       return 1;
+}
+
+/**
+ * _scsih_tm_tr_complete -
+ * @ioc: per adapter object
+ * @smid: system request message index
+ * @msix_index: MSIX table index supplied by the OS
+ * @reply: reply message frame(lower 32bit addr)
+ * Context: interrupt time.
+ *
+ * This is the target reset completion routine.
+ * This code is part of the code to initiate the device removal
+ * handshake protocal with controller firmware.
+ * It will send a sas iounit controll request (MPI2_SAS_OP_REMOVE_DEVICE)
+ *
+ * Return 1 meaning mf should be freed from _base_interrupt
+ *        0 means the mf is freed from this function.
+ */
+static u8
+_scsih_tm_tr_complete(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 msix_index,
+    u32 reply)
+{
+       unsigned long flags;
+       u16 handle;
+       struct _sas_device *sas_device;
+       Mpi2SCSITaskManagementReply_t *mpi_reply =
+           mpt2sas_base_get_reply_virt_addr(ioc, reply);
+       Mpi2SasIoUnitControlRequest_t *mpi_request;
+       u16 smid_sas_ctrl;
+       struct MPT2SAS_TARGET *sas_target_priv_data;
+       struct _tr_list *delayed_tr;
+       u8 rc;
+
+       handle = le16_to_cpu(mpi_reply->DevHandle);
+       spin_lock_irqsave(&ioc->sas_device_lock, flags);
+       sas_device = _scsih_sas_device_find_by_handle(ioc, handle);
+       if (!sas_device) {
+               spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
+               printk(MPT2SAS_ERR_FMT "%s: failed finding sas_device\n",
+                   ioc->name, __func__);
+               return 1;
+       }
+       sas_device->state |= MPTSAS_STATE_TR_COMPLETE;
+       spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
+
+       if (sas_device->starget)
+               dewtprintk(ioc, starget_printk(KERN_INFO, sas_device->starget,
+                   "tr_complete:handle(0x%04x), (%s) ioc_status(0x%04x), "
+                   "loginfo(0x%08x), completed(%d)\n",
+                   sas_device->handle, (sas_device->state &
+                   MPT2SAS_REQ_SAS_CNTRL) ? "open" : "active",
+                   le16_to_cpu(mpi_reply->IOCStatus),
+                   le32_to_cpu(mpi_reply->IOCLogInfo),
+                   le32_to_cpu(mpi_reply->TerminationCount)));
+
+       if (sas_device->starget && sas_device->starget->hostdata) {
+               sas_target_priv_data = sas_device->starget->hostdata;
+               sas_target_priv_data->tm_busy = 0;
+       }
+
+       if (!list_empty(&ioc->delayed_tr_list)) {
+               delayed_tr = list_entry(ioc->delayed_tr_list.next,
+                   struct _tr_list, list);
+               mpt2sas_base_free_smid(ioc, smid);
+               if (delayed_tr->state & MPT2SAS_REQ_SAS_CNTRL)
+                       _scsih_tm_tr_send(ioc, delayed_tr->handle);
+               list_del(&delayed_tr->list);
+               kfree(delayed_tr);
+               rc = 0; /* tells base_interrupt not to free mf */
+       } else
+               rc = 1;
+
+
+       if (!(sas_device->state & MPT2SAS_REQ_SAS_CNTRL))
+               return rc;
+
+       if (ioc->shost_recovery) {
+               printk(MPT2SAS_INFO_FMT "%s: host reset in progress!\n",
+                   __func__, ioc->name);
+               return rc;
+       }
+
+       smid_sas_ctrl = mpt2sas_base_get_smid(ioc, ioc->tm_sas_control_cb_idx);
+       if (!smid_sas_ctrl) {
+               printk(MPT2SAS_ERR_FMT "%s: failed obtaining a smid\n",
+                   ioc->name, __func__);
+               return rc;
+       }
+
+       mpi_request = mpt2sas_base_get_msg_frame(ioc, smid_sas_ctrl);
+       memset(mpi_request, 0, sizeof(Mpi2SasIoUnitControlRequest_t));
+       mpi_request->Function = MPI2_FUNCTION_SAS_IO_UNIT_CONTROL;
+       mpi_request->Operation = MPI2_SAS_OP_REMOVE_DEVICE;
+       mpi_request->DevHandle = mpi_reply->DevHandle;
+       sas_device->state |= MPTSAS_STATE_CNTRL_SEND;
+       mpt2sas_base_put_smid_default(ioc, smid_sas_ctrl);
+       return rc;
+}
+
+/**
  * _scsih_check_topo_delete_events - sanity check on topo events
  * @ioc: per adapter object
  * @event_data: the event data payload
@@ -2375,6 +2563,21 @@ _scsih_check_topo_delete_events(struct MPT2SAS_ADAPTER *ioc,
        u16 expander_handle;
        struct _sas_node *sas_expander;
        unsigned long flags;
+       int i, reason_code;
+       u16 handle;
+
+       for (i = 0 ; i < event_data->NumEntries; i++) {
+               if (event_data->PHY[i].PhyStatus &
+                   MPI2_EVENT_SAS_TOPO_PHYSTATUS_VACANT)
+                       continue;
+               handle = le16_to_cpu(event_data->PHY[i].AttachedDevHandle);
+               if (!handle)
+                       continue;
+               reason_code = event_data->PHY[i].PhyStatus &
+                   MPI2_EVENT_SAS_TOPO_RC_MASK;
+               if (reason_code == MPI2_EVENT_SAS_TOPO_RC_TARG_NOT_RESPONDING)
+                       _scsih_tm_tr_send(ioc, handle);
+       }
 
        expander_handle = le16_to_cpu(event_data->ExpanderDevHandle);
        if (expander_handle < ioc->sas_hba.num_phys) {
@@ -2433,8 +2636,8 @@ _scsih_flush_running_cmds(struct MPT2SAS_ADAPTER *ioc)
        u16 smid;
        u16 count = 0;
 
-       for (smid = 1; smid <= ioc->request_depth; smid++) {
-               scmd = _scsih_scsi_lookup_getclear(ioc, smid);
+       for (smid = 1; smid <= ioc->scsiio_depth; smid++) {
+               scmd = _scsih_scsi_lookup_get(ioc, smid);
                if (!scmd)
                        continue;
                count++;
@@ -2616,7 +2819,7 @@ _scsih_qcmd(struct scsi_cmnd *scmd, void (*done)(struct scsi_cmnd *))
        if ((sas_device_priv_data->flags & MPT_DEVICE_TLR_ON))
                mpi_control |= MPI2_SCSIIO_CONTROL_TLR_ON;
 
-       smid = mpt2sas_base_get_smid(ioc, ioc->scsi_io_cb_idx);
+       smid = mpt2sas_base_get_smid_scsiio(ioc, ioc->scsi_io_cb_idx, scmd);
        if (!smid) {
                printk(MPT2SAS_ERR_FMT "%s: failed obtaining a smid\n",
                    ioc->name, __func__);
@@ -2643,7 +2846,8 @@ _scsih_qcmd(struct scsi_cmnd *scmd, void (*done)(struct scsi_cmnd *))
        mpi_request->SGLOffset0 = offsetof(Mpi2SCSIIORequest_t, SGL) / 4;
        mpi_request->SGLFlags = cpu_to_le16(MPI2_SCSIIO_SGLFLAGS_TYPE_MPI +
            MPI2_SCSIIO_SGLFLAGS_SYSTEM_ADDR);
-
+       mpi_request->VF_ID = 0; /* TODO */
+       mpi_request->VP_ID = 0;
        int_to_scsilun(sas_device_priv_data->lun, (struct scsi_lun *)
            mpi_request->LUN);
        memcpy(mpi_request->CDB.CDB32, scmd->cmnd, scmd->cmd_len);
@@ -2657,8 +2861,7 @@ _scsih_qcmd(struct scsi_cmnd *scmd, void (*done)(struct scsi_cmnd *))
                }
        }
 
-       _scsih_scsi_lookup_set(ioc, smid, scmd);
-       mpt2sas_base_put_smid_scsi_io(ioc, smid, 0,
+       mpt2sas_base_put_smid_scsi_io(ioc, smid,
            sas_device_priv_data->sas_target->handle);
        return 0;
 
@@ -2954,15 +3157,16 @@ _scsih_smart_predicted_fault(struct MPT2SAS_ADAPTER *ioc, u16 handle)
  * _scsih_io_done - scsi request callback
  * @ioc: per adapter object
  * @smid: system request message index
- * @VF_ID: virtual function id
+ * @msix_index: MSIX table index supplied by the OS
  * @reply: reply message frame(lower 32bit addr)
  *
- * Callback handler when using scsih_qcmd.
+ * Callback handler when using _scsih_qcmd.
  *
- * Return nothing.
+ * Return 1 meaning mf should be freed from _base_interrupt
+ *        0 means the mf is freed from this function.
  */
-static void
-_scsih_io_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 VF_ID, u32 reply)
+static u8
+_scsih_io_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 msix_index, u32 reply)
 {
        Mpi2SCSIIORequest_t *mpi_request;
        Mpi2SCSIIOReply_t *mpi_reply;
@@ -2976,9 +3180,9 @@ _scsih_io_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 VF_ID, u32 reply)
        u32 response_code;
 
        mpi_reply = mpt2sas_base_get_reply_virt_addr(ioc, reply);
-       scmd = _scsih_scsi_lookup_getclear(ioc, smid);
+       scmd = _scsih_scsi_lookup_get(ioc, smid);
        if (scmd == NULL)
-               return;
+               return 1;
 
        mpi_request = mpt2sas_base_get_msg_frame(ioc, smid);
 
@@ -3134,6 +3338,7 @@ _scsih_io_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 VF_ID, u32 reply)
  out:
        scsi_dma_unmap(scmd);
        scmd->scsi_done(scmd);
+       return 1;
 }
 
 /**
@@ -3398,9 +3603,8 @@ _scsih_expander_add(struct MPT2SAS_ADAPTER *ioc, u16 handle)
                }
        }
 
-       sas_address = le64_to_cpu(expander_pg0.SASAddress);
-
        spin_lock_irqsave(&ioc->sas_node_lock, flags);
+       sas_address = le64_to_cpu(expander_pg0.SASAddress);
        sas_expander = mpt2sas_scsih_expander_find_by_sas_address(ioc,
            sas_address);
        spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
@@ -3666,6 +3870,12 @@ _scsih_remove_device(struct MPT2SAS_ADAPTER *ioc, u16 handle)
        if (ioc->remove_host)
                goto out;
 
+       if ((sas_device->state & MPTSAS_STATE_TR_COMPLETE)) {
+               dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "\tskip "
+                  "target_reset handle(0x%04x)\n", ioc->name, handle));
+               goto skip_tr;
+       }
+
        /* Target Reset to flush out all the outstanding IO */
        device_handle = (sas_device->hidden_raid_component) ?
            sas_device->volume_handle : handle;
@@ -3682,6 +3892,13 @@ _scsih_remove_device(struct MPT2SAS_ADAPTER *ioc, u16 handle)
                if (ioc->shost_recovery)
                        goto out;
        }
+ skip_tr:
+
+       if ((sas_device->state & MPTSAS_STATE_CNTRL_COMPLETE)) {
+               dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "\tskip "
+                  "sas_cntrl handle(0x%04x)\n", ioc->name, handle));
+               goto out;
+       }
 
        /* SAS_IO_UNIT_CNTR - send REMOVE_DEVICE */
        dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "sas_iounit: handle"
@@ -3690,7 +3907,8 @@ _scsih_remove_device(struct MPT2SAS_ADAPTER *ioc, u16 handle)
        mpi_request.Function = MPI2_FUNCTION_SAS_IO_UNIT_CONTROL;
        mpi_request.Operation = MPI2_SAS_OP_REMOVE_DEVICE;
        mpi_request.DevHandle = handle;
-       mpi_request.VF_ID = 0;
+       mpi_request.VF_ID = 0; /* TODO */
+       mpi_request.VP_ID = 0;
        if ((mpt2sas_base_sas_iounit_control(ioc, &mpi_reply,
            &mpi_request)) != 0) {
                printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
@@ -3800,15 +4018,12 @@ _scsih_sas_topology_change_event_debug(struct MPT2SAS_ADAPTER *ioc,
 /**
  * _scsih_sas_topology_change_event - handle topology changes
  * @ioc: per adapter object
- * @VF_ID:
- * @event_data: event data payload
- * fw_event:
+ * @fw_event: The fw_event_work object
  * Context: user.
  *
  */
 static void
-_scsih_sas_topology_change_event(struct MPT2SAS_ADAPTER *ioc, u8 VF_ID,
-    Mpi2EventDataSasTopologyChangeList_t *event_data,
+_scsih_sas_topology_change_event(struct MPT2SAS_ADAPTER *ioc,
     struct fw_event_work *fw_event)
 {
        int i;
@@ -3818,6 +4033,7 @@ _scsih_sas_topology_change_event(struct MPT2SAS_ADAPTER *ioc, u8 VF_ID,
        struct _sas_node *sas_expander;
        unsigned long flags;
        u8 link_rate_;
+       Mpi2EventDataSasTopologyChangeList_t *event_data = fw_event->event_data;
 
 #ifdef CONFIG_SCSI_MPT2SAS_LOGGING
        if (ioc->logging_level & MPT_DEBUG_EVENT_WORK_TASK)
@@ -3851,15 +4067,16 @@ _scsih_sas_topology_change_event(struct MPT2SAS_ADAPTER *ioc, u8 VF_ID,
                }
                if (ioc->shost_recovery)
                        return;
-               if (event_data->PHY[i].PhyStatus &
-                   MPI2_EVENT_SAS_TOPO_PHYSTATUS_VACANT)
+               phy_number = event_data->StartPhyNum + i;
+               reason_code = event_data->PHY[i].PhyStatus &
+                   MPI2_EVENT_SAS_TOPO_RC_MASK;
+               if ((event_data->PHY[i].PhyStatus &
+                   MPI2_EVENT_SAS_TOPO_PHYSTATUS_VACANT) && (reason_code !=
+                   MPI2_EVENT_SAS_TOPO_RC_TARG_NOT_RESPONDING))
                        continue;
                handle = le16_to_cpu(event_data->PHY[i].AttachedDevHandle);
                if (!handle)
                        continue;
-               phy_number = event_data->StartPhyNum + i;
-               reason_code = event_data->PHY[i].PhyStatus &
-                   MPI2_EVENT_SAS_TOPO_RC_MASK;
                link_rate_ = event_data->PHY[i].LinkRate >> 4;
                switch (reason_code) {
                case MPI2_EVENT_SAS_TOPO_RC_PHY_CHANGED:
@@ -3971,19 +4188,19 @@ _scsih_sas_device_status_change_event_debug(struct MPT2SAS_ADAPTER *ioc,
 /**
  * _scsih_sas_device_status_change_event - handle device status change
  * @ioc: per adapter object
- * @VF_ID:
- * @event_data: event data payload
+ * @fw_event: The fw_event_work object
  * Context: user.
  *
  * Return nothing.
  */
 static void
-_scsih_sas_device_status_change_event(struct MPT2SAS_ADAPTER *ioc, u8 VF_ID,
-    Mpi2EventDataSasDeviceStatusChange_t *event_data)
+_scsih_sas_device_status_change_event(struct MPT2SAS_ADAPTER *ioc,
+    struct fw_event_work *fw_event)
 {
 #ifdef CONFIG_SCSI_MPT2SAS_LOGGING
        if (ioc->logging_level & MPT_DEBUG_EVENT_WORK_TASK)
-               _scsih_sas_device_status_change_event_debug(ioc, event_data);
+               _scsih_sas_device_status_change_event_debug(ioc,
+                    fw_event->event_data);
 #endif
 }
 
@@ -4026,34 +4243,33 @@ _scsih_sas_enclosure_dev_status_change_event_debug(struct MPT2SAS_ADAPTER *ioc,
 /**
  * _scsih_sas_enclosure_dev_status_change_event - handle enclosure events
  * @ioc: per adapter object
- * @VF_ID:
- * @event_data: event data payload
+ * @fw_event: The fw_event_work object
  * Context: user.
  *
  * Return nothing.
  */
 static void
 _scsih_sas_enclosure_dev_status_change_event(struct MPT2SAS_ADAPTER *ioc,
-    u8 VF_ID, Mpi2EventDataSasEnclDevStatusChange_t *event_data)
+    struct fw_event_work *fw_event)
 {
 #ifdef CONFIG_SCSI_MPT2SAS_LOGGING
        if (ioc->logging_level & MPT_DEBUG_EVENT_WORK_TASK)
                _scsih_sas_enclosure_dev_status_change_event_debug(ioc,
-                    event_data);
+                    fw_event->event_data);
 #endif
 }
 
 /**
  * _scsih_sas_broadcast_primative_event - handle broadcast events
  * @ioc: per adapter object
- * @event_data: event data payload
+ * @fw_event: The fw_event_work object
  * Context: user.
  *
  * Return nothing.
  */
 static void
-_scsih_sas_broadcast_primative_event(struct MPT2SAS_ADAPTER *ioc, u8 VF_ID,
-    Mpi2EventDataSasBroadcastPrimitive_t *event_data)
+_scsih_sas_broadcast_primative_event(struct MPT2SAS_ADAPTER *ioc,
+    struct fw_event_work *fw_event)
 {
        struct scsi_cmnd *scmd;
        u16 smid, handle;
@@ -4062,11 +4278,12 @@ _scsih_sas_broadcast_primative_event(struct MPT2SAS_ADAPTER *ioc, u8 VF_ID,
        u32 termination_count;
        u32 query_count;
        Mpi2SCSITaskManagementReply_t *mpi_reply;
-
+#ifdef CONFIG_SCSI_MPT2SAS_LOGGING
+       Mpi2EventDataSasBroadcastPrimitive_t *event_data = fw_event->event_data;
+#endif
        dewtprintk(ioc, printk(MPT2SAS_DEBUG_FMT "broadcast primative: "
            "phy number(%d), width(%d)\n", ioc->name, event_data->PhyNum,
            event_data->PortWidth));
-
        dtmprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: enter\n", ioc->name,
            __func__));
 
@@ -4074,7 +4291,7 @@ _scsih_sas_broadcast_primative_event(struct MPT2SAS_ADAPTER *ioc, u8 VF_ID,
        termination_count = 0;
        query_count = 0;
        mpi_reply = ioc->tm_cmds.reply;
-       for (smid = 1; smid <= ioc->request_depth; smid++) {
+       for (smid = 1; smid <= ioc->scsiio_depth; smid++) {
                scmd = _scsih_scsi_lookup_get(ioc, smid);
                if (!scmd)
                        continue;
@@ -4121,23 +4338,25 @@ _scsih_sas_broadcast_primative_event(struct MPT2SAS_ADAPTER *ioc, u8 VF_ID,
 /**
  * _scsih_sas_discovery_event - handle discovery events
  * @ioc: per adapter object
- * @event_data: event data payload
+ * @fw_event: The fw_event_work object
  * Context: user.
  *
  * Return nothing.
  */
 static void
-_scsih_sas_discovery_event(struct MPT2SAS_ADAPTER *ioc, u8 VF_ID,
-    Mpi2EventDataSasDiscovery_t *event_data)
+_scsih_sas_discovery_event(struct MPT2SAS_ADAPTER *ioc,
+    struct fw_event_work *fw_event)
 {
+       Mpi2EventDataSasDiscovery_t *event_data = fw_event->event_data;
+
 #ifdef CONFIG_SCSI_MPT2SAS_LOGGING
        if (ioc->logging_level & MPT_DEBUG_EVENT_WORK_TASK) {
                printk(MPT2SAS_DEBUG_FMT "discovery event: (%s)", ioc->name,
                    (event_data->ReasonCode == MPI2_EVENT_SAS_DISC_RC_STARTED) ?
                    "start" : "stop");
        if (event_data->DiscoveryStatus)
-               printk(MPT2SAS_DEBUG_FMT ", discovery_status(0x%08x)",
-                   ioc->name, le32_to_cpu(event_data->DiscoveryStatus));
+               printk("discovery_status(0x%08x)",
+                   le32_to_cpu(event_data->DiscoveryStatus));
        printk("\n");
        }
 #endif
@@ -4488,19 +4707,19 @@ _scsih_sas_ir_config_change_event_debug(struct MPT2SAS_ADAPTER *ioc,
 /**
  * _scsih_sas_ir_config_change_event - handle ir configuration change events
  * @ioc: per adapter object
- * @VF_ID:
- * @event_data: event data payload
+ * @fw_event: The fw_event_work object
  * Context: user.
  *
  * Return nothing.
  */
 static void
-_scsih_sas_ir_config_change_event(struct MPT2SAS_ADAPTER *ioc, u8 VF_ID,
-    Mpi2EventDataIrConfigChangeList_t *event_data)
+_scsih_sas_ir_config_change_event(struct MPT2SAS_ADAPTER *ioc,
+    struct fw_event_work *fw_event)
 {
        Mpi2EventIrConfigElement_t *element;
        int i;
        u8 foreign_config;
+       Mpi2EventDataIrConfigChangeList_t *event_data = fw_event->event_data;
 
 #ifdef CONFIG_SCSI_MPT2SAS_LOGGING
        if (ioc->logging_level & MPT_DEBUG_EVENT_WORK_TASK)
@@ -4543,14 +4762,14 @@ _scsih_sas_ir_config_change_event(struct MPT2SAS_ADAPTER *ioc, u8 VF_ID,
 /**
  * _scsih_sas_ir_volume_event - IR volume event
  * @ioc: per adapter object
- * @event_data: event data payload
+ * @fw_event: The fw_event_work object
  * Context: user.
  *
  * Return nothing.
  */
 static void
-_scsih_sas_ir_volume_event(struct MPT2SAS_ADAPTER *ioc, u8 VF_ID,
-    Mpi2EventDataIrVolume_t *event_data)
+_scsih_sas_ir_volume_event(struct MPT2SAS_ADAPTER *ioc,
+    struct fw_event_work *fw_event)
 {
        u64 wwid;
        unsigned long flags;
@@ -4559,6 +4778,7 @@ _scsih_sas_ir_volume_event(struct MPT2SAS_ADAPTER *ioc, u8 VF_ID,
        u32 state;
        int rc;
        struct MPT2SAS_TARGET *sas_target_priv_data;
+       Mpi2EventDataIrVolume_t *event_data = fw_event->event_data;
 
        if (event_data->ReasonCode != MPI2_EVENT_IR_VOLUME_RC_STATE_CHANGED)
                return;
@@ -4628,14 +4848,14 @@ _scsih_sas_ir_volume_event(struct MPT2SAS_ADAPTER *ioc, u8 VF_ID,
 /**
  * _scsih_sas_ir_physical_disk_event - PD event
  * @ioc: per adapter object
- * @event_data: event data payload
+ * @fw_event: The fw_event_work object
  * Context: user.
  *
  * Return nothing.
  */
 static void
-_scsih_sas_ir_physical_disk_event(struct MPT2SAS_ADAPTER *ioc, u8 VF_ID,
-   Mpi2EventDataIrPhysicalDisk_t *event_data)
+_scsih_sas_ir_physical_disk_event(struct MPT2SAS_ADAPTER *ioc,
+    struct fw_event_work *fw_event)
 {
        u16 handle;
        u32 state;
@@ -4644,6 +4864,7 @@ _scsih_sas_ir_physical_disk_event(struct MPT2SAS_ADAPTER *ioc, u8 VF_ID,
        Mpi2ConfigReply_t mpi_reply;
        Mpi2SasDevicePage0_t sas_device_pg0;
        u32 ioc_status;
+       Mpi2EventDataIrPhysicalDisk_t *event_data = fw_event->event_data;
 
        if (event_data->ReasonCode != MPI2_EVENT_IR_PHYSDISK_RC_STATE_CHANGED)
                return;
@@ -4743,33 +4964,33 @@ _scsih_sas_ir_operation_status_event_debug(struct MPT2SAS_ADAPTER *ioc,
 /**
  * _scsih_sas_ir_operation_status_event - handle RAID operation events
  * @ioc: per adapter object
- * @VF_ID:
- * @event_data: event data payload
+ * @fw_event: The fw_event_work object
  * Context: user.
  *
  * Return nothing.
  */
 static void
-_scsih_sas_ir_operation_status_event(struct MPT2SAS_ADAPTER *ioc, u8 VF_ID,
-    Mpi2EventDataIrOperationStatus_t *event_data)
+_scsih_sas_ir_operation_status_event(struct MPT2SAS_ADAPTER *ioc,
+    struct fw_event_work *fw_event)
 {
 #ifdef CONFIG_SCSI_MPT2SAS_LOGGING
        if (ioc->logging_level & MPT_DEBUG_EVENT_WORK_TASK)
-               _scsih_sas_ir_operation_status_event_debug(ioc, event_data);
+               _scsih_sas_ir_operation_status_event_debug(ioc,
+                    fw_event->event_data);
 #endif
 }
 
 /**
  * _scsih_task_set_full - handle task set full
  * @ioc: per adapter object
- * @event_data: event data payload
+ * @fw_event: The fw_event_work object
  * Context: user.
  *
  * Throttle back qdepth.
  */
 static void
-_scsih_task_set_full(struct MPT2SAS_ADAPTER *ioc, u8 VF_ID,
-    Mpi2EventDataTaskSetFull_t *event_data)
+_scsih_task_set_full(struct MPT2SAS_ADAPTER *ioc, struct fw_event_work
+       *fw_event)
 {
        unsigned long flags;
        struct _sas_device *sas_device;
@@ -4780,6 +5001,7 @@ _scsih_task_set_full(struct MPT2SAS_ADAPTER *ioc, u8 VF_ID,
        u16 handle;
        int id, channel;
        u64 sas_address;
+       Mpi2EventDataTaskSetFull_t *event_data = fw_event->event_data;
 
        current_depth = le16_to_cpu(event_data->CurrentDepth);
        handle = le16_to_cpu(event_data->DevHandle);
@@ -4868,6 +5090,10 @@ _scsih_mark_responding_sas_device(struct MPT2SAS_ADAPTER *ioc, u64 sas_address,
                if (sas_device->sas_address == sas_address &&
                    sas_device->slot == slot && sas_device->starget) {
                        sas_device->responding = 1;
+                       sas_device->state = 0;
+                       starget = sas_device->starget;
+                       sas_target_priv_data = starget->hostdata;
+                       sas_target_priv_data->tm_busy = 0;
                        starget_printk(KERN_INFO, sas_device->starget,
                            "handle(0x%04x), sas_addr(0x%016llx), enclosure "
                            "logical id(0x%016llx), slot(%d)\n", handle,
@@ -4880,8 +5106,6 @@ _scsih_mark_responding_sas_device(struct MPT2SAS_ADAPTER *ioc, u64 sas_address,
                        printk(KERN_INFO "\thandle changed from(0x%04x)!!!\n",
                            sas_device->handle);
                        sas_device->handle = handle;
-                       starget = sas_device->starget;
-                       sas_target_priv_data = starget->hostdata;
                        sas_target_priv_data->handle = handle;
                        goto out;
                }
@@ -5227,44 +5451,38 @@ _firmware_event_work(struct work_struct *work)
 
        switch (fw_event->event) {
        case MPI2_EVENT_SAS_TOPOLOGY_CHANGE_LIST:
-               _scsih_sas_topology_change_event(ioc, fw_event->VF_ID,
-                   fw_event->event_data, fw_event);
+               _scsih_sas_topology_change_event(ioc, fw_event);
                break;
        case MPI2_EVENT_SAS_DEVICE_STATUS_CHANGE:
-               _scsih_sas_device_status_change_event(ioc, fw_event->VF_ID,
-                   fw_event->event_data);
+               _scsih_sas_device_status_change_event(ioc,
+                   fw_event);
                break;
        case MPI2_EVENT_SAS_DISCOVERY:
-               _scsih_sas_discovery_event(ioc, fw_event->VF_ID,
-                   fw_event->event_data);
+               _scsih_sas_discovery_event(ioc,
+                   fw_event);
                break;
        case MPI2_EVENT_SAS_BROADCAST_PRIMITIVE:
-               _scsih_sas_broadcast_primative_event(ioc, fw_event->VF_ID,
-                   fw_event->event_data);
+               _scsih_sas_broadcast_primative_event(ioc,
+                   fw_event);
                break;
        case MPI2_EVENT_SAS_ENCL_DEVICE_STATUS_CHANGE:
                _scsih_sas_enclosure_dev_status_change_event(ioc,
-                   fw_event->VF_ID, fw_event->event_data);
+                   fw_event);
                break;
        case MPI2_EVENT_IR_CONFIGURATION_CHANGE_LIST:
-               _scsih_sas_ir_config_change_event(ioc, fw_event->VF_ID,
-                   fw_event->event_data);
+               _scsih_sas_ir_config_change_event(ioc, fw_event);
                break;
        case MPI2_EVENT_IR_VOLUME:
-               _scsih_sas_ir_volume_event(ioc, fw_event->VF_ID,
-                   fw_event->event_data);
+               _scsih_sas_ir_volume_event(ioc, fw_event);
                break;
        case MPI2_EVENT_IR_PHYSICAL_DISK:
-               _scsih_sas_ir_physical_disk_event(ioc, fw_event->VF_ID,
-                   fw_event->event_data);
+               _scsih_sas_ir_physical_disk_event(ioc, fw_event);
                break;
        case MPI2_EVENT_IR_OPERATION_STATUS:
-               _scsih_sas_ir_operation_status_event(ioc, fw_event->VF_ID,
-                   fw_event->event_data);
+               _scsih_sas_ir_operation_status_event(ioc, fw_event);
                break;
        case MPI2_EVENT_TASK_SET_FULL:
-               _scsih_task_set_full(ioc, fw_event->VF_ID,
-                   fw_event->event_data);
+               _scsih_task_set_full(ioc, fw_event);
                break;
        }
        _scsih_fw_event_free(ioc, fw_event);
@@ -5273,17 +5491,19 @@ _firmware_event_work(struct work_struct *work)
 /**
  * mpt2sas_scsih_event_callback - firmware event handler (called at ISR time)
  * @ioc: per adapter object
- * @VF_ID: virtual function id
+ * @msix_index: MSIX table index supplied by the OS
  * @reply: reply message frame(lower 32bit addr)
  * Context: interrupt.
  *
  * This function merely adds a new work task into ioc->firmware_event_thread.
  * The tasks are worked from _firmware_event_work in user context.
  *
- * Return nothing.
+ * Return 1 meaning mf should be freed from _base_interrupt
+ *        0 means the mf is freed from this function.
  */
-void
-mpt2sas_scsih_event_callback(struct MPT2SAS_ADAPTER *ioc, u8 VF_ID, u32 reply)
+u8
+mpt2sas_scsih_event_callback(struct MPT2SAS_ADAPTER *ioc, u8 msix_index,
+       u32 reply)
 {
        struct fw_event_work *fw_event;
        Mpi2EventNotificationReply_t *mpi_reply;
@@ -5294,11 +5514,11 @@ mpt2sas_scsih_event_callback(struct MPT2SAS_ADAPTER *ioc, u8 VF_ID, u32 reply)
        spin_lock_irqsave(&ioc->fw_event_lock, flags);
        if (ioc->fw_events_off || ioc->remove_host) {
                spin_unlock_irqrestore(&ioc->fw_event_lock, flags);
-               return;
+               return 1;
        }
        spin_unlock_irqrestore(&ioc->fw_event_lock, flags);
 
-       mpi_reply =  mpt2sas_base_get_reply_virt_addr(ioc, reply);
+       mpi_reply = mpt2sas_base_get_reply_virt_addr(ioc, reply);
        event = le16_to_cpu(mpi_reply->Event);
 
        switch (event) {
@@ -5312,7 +5532,7 @@ mpt2sas_scsih_event_callback(struct MPT2SAS_ADAPTER *ioc, u8 VF_ID, u32 reply)
                if (baen_data->Primitive !=
                    MPI2_EVENT_PRIMITIVE_ASYNCHRONOUS_EVENT ||
                    ioc->broadcast_aen_busy)
-                       return;
+                       return 1;
                ioc->broadcast_aen_busy = 1;
                break;
        }
@@ -5334,14 +5554,14 @@ mpt2sas_scsih_event_callback(struct MPT2SAS_ADAPTER *ioc, u8 VF_ID, u32 reply)
                break;
 
        default: /* ignore the rest */
-               return;
+               return 1;
        }
 
        fw_event = kzalloc(sizeof(struct fw_event_work), GFP_ATOMIC);
        if (!fw_event) {
                printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
                    ioc->name, __FILE__, __LINE__, __func__);
-               return;
+               return 1;
        }
        fw_event->event_data =
            kzalloc(mpi_reply->EventDataLength*4, GFP_ATOMIC);
@@ -5349,15 +5569,17 @@ mpt2sas_scsih_event_callback(struct MPT2SAS_ADAPTER *ioc, u8 VF_ID, u32 reply)
                printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
                    ioc->name, __FILE__, __LINE__, __func__);
                kfree(fw_event);
-               return;
+               return 1;
        }
 
        memcpy(fw_event->event_data, mpi_reply->EventData,
            mpi_reply->EventDataLength*4);
        fw_event->ioc = ioc;
-       fw_event->VF_ID = VF_ID;
+       fw_event->VF_ID = mpi_reply->VF_ID;
+       fw_event->VP_ID = mpi_reply->VP_ID;
        fw_event->event = event;
        _scsih_fw_event_add(ioc, fw_event);
+       return 1;
 }
 
 /* shost template */
@@ -5617,7 +5839,7 @@ _scsih_probe_raid(struct MPT2SAS_ADAPTER *ioc)
 }
 
 /**
- * _scsih_probe_sas - reporting raid volumes to sas transport
+ * _scsih_probe_sas - reporting sas devices to sas transport
  * @ioc: per adapter object
  *
  * Called during initial loading of the driver.
@@ -5714,6 +5936,8 @@ _scsih_probe(struct pci_dev *pdev, const struct pci_device_id *id)
        ioc->base_cb_idx = base_cb_idx;
        ioc->transport_cb_idx = transport_cb_idx;
        ioc->config_cb_idx = config_cb_idx;
+       ioc->tm_tr_cb_idx = tm_tr_cb_idx;
+       ioc->tm_sas_control_cb_idx = tm_sas_control_cb_idx;
        ioc->logging_level = logging_level;
        /* misc semaphores and spin locks */
        spin_lock_init(&ioc->ioc_reset_in_progress_lock);
@@ -5729,6 +5953,7 @@ _scsih_probe(struct pci_dev *pdev, const struct pci_device_id *id)
        INIT_LIST_HEAD(&ioc->fw_event_list);
        INIT_LIST_HEAD(&ioc->raid_device_list);
        INIT_LIST_HEAD(&ioc->sas_hba.sas_port_list);
+       INIT_LIST_HEAD(&ioc->delayed_tr_list);
 
        /* init shost parameters */
        shost->max_cmd_len = 16;
@@ -5745,6 +5970,7 @@ _scsih_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 
        scsi_host_set_prot(shost, SHOST_DIF_TYPE1_PROTECTION
            | SHOST_DIF_TYPE3_PROTECTION);
+       scsi_host_set_guard(shost, SHOST_DIX_GUARD_CRC);
 
        /* event thread */
        snprintf(ioc->firmware_event_name, sizeof(ioc->firmware_event_name),
@@ -5894,6 +6120,11 @@ _scsih_init(void)
        /* ctl module callback handler */
        ctl_cb_idx = mpt2sas_base_register_callback_handler(mpt2sas_ctl_done);
 
+       tm_tr_cb_idx = mpt2sas_base_register_callback_handler(
+           _scsih_tm_tr_complete);
+       tm_sas_control_cb_idx = mpt2sas_base_register_callback_handler(
+           _scsih_sas_control_complete);
+
        mpt2sas_ctl_init();
 
        error = pci_register_driver(&scsih_driver);
@@ -5924,6 +6155,9 @@ _scsih_exit(void)
        mpt2sas_base_release_callback_handler(config_cb_idx);
        mpt2sas_base_release_callback_handler(ctl_cb_idx);
 
+       mpt2sas_base_release_callback_handler(tm_tr_cb_idx);
+       mpt2sas_base_release_callback_handler(tm_sas_control_cb_idx);
+
        mpt2sas_ctl_exit();
 }
 
index 742324a..eb98188 100644 (file)
@@ -2,7 +2,7 @@
  * SAS Transport Layer for MPT (Message Passing Technology) based controllers
  *
  * This code is based on drivers/scsi/mpt2sas/mpt2_transport.c
- * Copyright (C) 2007-2008  LSI Corporation
+ * Copyright (C) 2007-2009  LSI Corporation
  *  (mailto:DL-MPTFusionLinux@lsi.com)
  *
  * This program is free software; you can redistribute it and/or
@@ -212,25 +212,26 @@ _transport_set_identify(struct MPT2SAS_ADAPTER *ioc, u16 handle,
  * mpt2sas_transport_done -  internal transport layer callback handler.
  * @ioc: per adapter object
  * @smid: system request message index
- * @VF_ID: virtual function id
+ * @msix_index: MSIX table index supplied by the OS
  * @reply: reply message frame(lower 32bit addr)
  *
  * Callback handler when sending internal generated transport cmds.
  * The callback index passed is `ioc->transport_cb_idx`
  *
- * Return nothing.
+ * Return 1 meaning mf should be freed from _base_interrupt
+ *        0 means the mf is freed from this function.
  */
-void
-mpt2sas_transport_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 VF_ID,
+u8
+mpt2sas_transport_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 msix_index,
     u32 reply)
 {
        MPI2DefaultReply_t *mpi_reply;
 
        mpi_reply =  mpt2sas_base_get_reply_virt_addr(ioc, reply);
        if (ioc->transport_cmds.status == MPT2_CMD_NOT_USED)
-               return;
+               return 1;
        if (ioc->transport_cmds.smid != smid)
-               return;
+               return 1;
        ioc->transport_cmds.status |= MPT2_CMD_COMPLETE;
        if (mpi_reply) {
                memcpy(ioc->transport_cmds.reply, mpi_reply,
@@ -239,6 +240,7 @@ mpt2sas_transport_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 VF_ID,
        }
        ioc->transport_cmds.status &= ~MPT2_CMD_PENDING;
        complete(&ioc->transport_cmds.done);
+       return 1;
 }
 
 /* report manufacture request structure */
@@ -369,6 +371,8 @@ _transport_expander_report_manufacture(struct MPT2SAS_ADAPTER *ioc,
        memset(mpi_request, 0, sizeof(Mpi2SmpPassthroughRequest_t));
        mpi_request->Function = MPI2_FUNCTION_SMP_PASSTHROUGH;
        mpi_request->PhysicalPort = 0xFF;
+       mpi_request->VF_ID = 0; /* TODO */
+       mpi_request->VP_ID = 0;
        sas_address_le = (u64 *)&mpi_request->SASAddress;
        *sas_address_le = cpu_to_le64(sas_address);
        mpi_request->RequestDataLength = sizeof(struct rep_manu_request);
@@ -396,7 +400,8 @@ _transport_expander_report_manufacture(struct MPT2SAS_ADAPTER *ioc,
        dtransportprintk(ioc, printk(MPT2SAS_DEBUG_FMT "report_manufacture - "
            "send to sas_addr(0x%016llx)\n", ioc->name,
            (unsigned long long)sas_address));
-       mpt2sas_base_put_smid_default(ioc, smid, 0 /* VF_ID */);
+       mpt2sas_base_put_smid_default(ioc, smid);
+       init_completion(&ioc->transport_cmds.done);
        timeleft = wait_for_completion_timeout(&ioc->transport_cmds.done,
            10*HZ);
 
@@ -1106,6 +1111,8 @@ _transport_smp_handler(struct Scsi_Host *shost, struct sas_rphy *rphy,
        memset(mpi_request, 0, sizeof(Mpi2SmpPassthroughRequest_t));
        mpi_request->Function = MPI2_FUNCTION_SMP_PASSTHROUGH;
        mpi_request->PhysicalPort = 0xFF;
+       mpi_request->VF_ID = 0; /* TODO */
+       mpi_request->VP_ID = 0;
        *((u64 *)&mpi_request->SASAddress) = (rphy) ?
            cpu_to_le64(rphy->identify.sas_address) :
            cpu_to_le64(ioc->sas_hba.sas_address);
@@ -1147,7 +1154,8 @@ _transport_smp_handler(struct Scsi_Host *shost, struct sas_rphy *rphy,
        dtransportprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s - "
            "sending smp request\n", ioc->name, __func__));
 
-       mpt2sas_base_put_smid_default(ioc, smid, 0 /* VF_ID */);
+       mpt2sas_base_put_smid_default(ioc, smid);
+       init_completion(&ioc->transport_cmds.done);
        timeleft = wait_for_completion_timeout(&ioc->transport_cmds.done,
            10*HZ);
 
index f8cb9de..1849da1 100644 (file)
@@ -25,6 +25,8 @@
 #ifndef _MV_DEFS_H_
 #define _MV_DEFS_H_
 
+#define PCI_DEVICE_ID_ARECA_1300       0x1300
+#define PCI_DEVICE_ID_ARECA_1320       0x1320
 
 enum chip_flavors {
        chip_6320,
@@ -32,6 +34,8 @@ enum chip_flavors {
        chip_6485,
        chip_9480,
        chip_9180,
+       chip_1300,
+       chip_1320
 };
 
 /* driver compile-time configuration */
index 8646a19..c790d45 100644 (file)
@@ -32,6 +32,8 @@ static const struct mvs_chip_info mvs_chips[] = {
        [chip_6485] =   { 1, 8, 0x800, 33, 32, 10, &mvs_64xx_dispatch, },
        [chip_9180] =   { 2, 4, 0x800, 17, 64,  9, &mvs_94xx_dispatch, },
        [chip_9480] =   { 2, 4, 0x800, 17, 64,  9, &mvs_94xx_dispatch, },
+       [chip_1300] =   { 1, 4, 0x400, 17, 16,  9, &mvs_64xx_dispatch, },
+       [chip_1320] =   { 2, 4, 0x800, 17, 64,  9, &mvs_94xx_dispatch, },
 };
 
 #define SOC_SAS_NUM 2
@@ -653,6 +655,8 @@ static struct pci_device_id __devinitdata mvs_pci_table[] = {
        { PCI_VDEVICE(MARVELL, 0x6485), chip_6485 },
        { PCI_VDEVICE(MARVELL, 0x9480), chip_9480 },
        { PCI_VDEVICE(MARVELL, 0x9180), chip_9180 },
+       { PCI_VDEVICE(ARECA, PCI_DEVICE_ID_ARECA_1300), chip_1300 },
+       { PCI_VDEVICE(ARECA, PCI_DEVICE_ID_ARECA_1320), chip_1320 },
 
        { }     /* terminate list */
 };
index 4302f06..f7c70e2 100644 (file)
@@ -46,6 +46,7 @@
 #include <linux/mutex.h>
 #include <scsi/scsi.h>
 #include <scsi/scsi_host.h>
+#include <scsi/scsi_device.h>
 #include <scsi/scsi_tcq.h>
 #include <scsi/scsi_eh.h>
 #include <scsi/scsi_cmnd.h>
@@ -684,7 +685,7 @@ static void pmcraid_timeout_handler(struct pmcraid_cmd *cmd)
        struct pmcraid_instance *pinstance = cmd->drv_inst;
        unsigned long lock_flags;
 
-       dev_err(&pinstance->pdev->dev,
+       dev_info(&pinstance->pdev->dev,
                "Adapter being reset due to command timeout.\n");
 
        /* Command timeouts result in hard reset sequence. The command that got
@@ -815,8 +816,9 @@ static void pmcraid_erp_done(struct pmcraid_cmd *cmd)
 
        if (PMCRAID_IOASC_SENSE_KEY(ioasc) > 0) {
                scsi_cmd->result |= (DID_ERROR << 16);
-               pmcraid_err("command CDB[0] = %x failed with IOASC: 0x%08X\n",
-                            cmd->ioa_cb->ioarcb.cdb[0], ioasc);
+               scmd_printk(KERN_INFO, scsi_cmd,
+                           "command CDB[0] = %x failed with IOASC: 0x%08X\n",
+                           cmd->ioa_cb->ioarcb.cdb[0], ioasc);
        }
 
        /* if we had allocated sense buffers for request sense, copy the sense
@@ -1541,13 +1543,13 @@ static void pmcraid_handle_error_log(struct pmcraid_instance *pinstance)
 
        if (pinstance->ldn.hcam->notification_lost ==
            HOSTRCB_NOTIFICATIONS_LOST)
-               dev_err(&pinstance->pdev->dev, "Error notifications lost\n");
+               dev_info(&pinstance->pdev->dev, "Error notifications lost\n");
 
        ioasc = le32_to_cpu(hcam_ldn->error_log.fd_ioasc);
 
        if (ioasc == PMCRAID_IOASC_UA_BUS_WAS_RESET ||
                ioasc == PMCRAID_IOASC_UA_BUS_WAS_RESET_BY_OTHER) {
-               dev_err(&pinstance->pdev->dev,
+               dev_info(&pinstance->pdev->dev,
                        "UnitAttention due to IOA Bus Reset\n");
                scsi_report_bus_reset(
                        pinstance->host,
@@ -1584,7 +1586,7 @@ static void pmcraid_process_ccn(struct pmcraid_cmd *cmd)
            atomic_read(&pinstance->ccn.ignore) == 1) {
                return;
        } else if (ioasc) {
-               dev_err(&pinstance->pdev->dev,
+               dev_info(&pinstance->pdev->dev,
                        "Host RCB (CCN) failed with IOASC: 0x%08X\n", ioasc);
                spin_lock_irqsave(pinstance->host->host_lock, lock_flags);
                pmcraid_send_hcam(pinstance, PMCRAID_HCAM_CODE_CONFIG_CHANGE);
@@ -1634,7 +1636,7 @@ static void pmcraid_process_ldn(struct pmcraid_cmd *cmd)
                        return;
                }
        } else {
-               dev_err(&pinstance->pdev->dev,
+               dev_info(&pinstance->pdev->dev,
                        "Host RCB(LDN) failed with IOASC: 0x%08X\n", ioasc);
        }
        /* send netlink message for HCAM notification if enabled */
@@ -1822,7 +1824,6 @@ static void pmcraid_fail_outstanding_cmds(struct pmcraid_instance *pinstance)
                        scsi_dma_unmap(scsi_cmd);
                        pmcraid_return_cmd(cmd);
 
-
                        pmcraid_info("failing(%d) CDB[0] = %x result: %x\n",
                                     le32_to_cpu(resp) >> 2,
                                     cmd->ioa_cb->ioarcb.cdb[0],
@@ -2514,7 +2515,8 @@ static int pmcraid_reset_device(
        res = scsi_cmd->device->hostdata;
 
        if (!res) {
-               pmcraid_err("reset_device: NULL resource pointer\n");
+               sdev_printk(KERN_ERR, scsi_cmd->device,
+                           "reset_device: NULL resource pointer\n");
                return FAILED;
        }
 
@@ -2752,8 +2754,8 @@ static int pmcraid_eh_abort_handler(struct scsi_cmnd *scsi_cmd)
        pinstance =
                (struct pmcraid_instance *)scsi_cmd->device->host->hostdata;
 
-       dev_err(&pinstance->pdev->dev,
-               "I/O command timed out, aborting it.\n");
+       scmd_printk(KERN_INFO, scsi_cmd,
+                   "I/O command timed out, aborting it.\n");
 
        res = scsi_cmd->device->hostdata;
 
@@ -2824,7 +2826,8 @@ static int pmcraid_eh_abort_handler(struct scsi_cmnd *scsi_cmd)
  */
 static int pmcraid_eh_device_reset_handler(struct scsi_cmnd *scmd)
 {
-       pmcraid_err("Doing device reset due to an I/O command timeout.\n");
+       scmd_printk(KERN_INFO, scmd,
+                   "resetting device due to an I/O command timeout.\n");
        return pmcraid_reset_device(scmd,
                                    PMCRAID_INTERNAL_TIMEOUT,
                                    RESET_DEVICE_LUN);
@@ -2832,7 +2835,8 @@ static int pmcraid_eh_device_reset_handler(struct scsi_cmnd *scmd)
 
 static int pmcraid_eh_bus_reset_handler(struct scsi_cmnd *scmd)
 {
-       pmcraid_err("Doing bus reset due to an I/O command timeout.\n");
+       scmd_printk(KERN_INFO, scmd,
+                   "Doing bus reset due to an I/O command timeout.\n");
        return pmcraid_reset_device(scmd,
                                    PMCRAID_RESET_BUS_TIMEOUT,
                                    RESET_DEVICE_BUS);
@@ -2840,7 +2844,8 @@ static int pmcraid_eh_bus_reset_handler(struct scsi_cmnd *scmd)
 
 static int pmcraid_eh_target_reset_handler(struct scsi_cmnd *scmd)
 {
-       pmcraid_err("Doing target reset due to an I/O command timeout.\n");
+       scmd_printk(KERN_INFO, scmd,
+                   "Doing target reset due to an I/O command timeout.\n");
        return pmcraid_reset_device(scmd,
                                    PMCRAID_INTERNAL_TIMEOUT,
                                    RESET_DEVICE_TARGET);
@@ -2988,11 +2993,11 @@ static int pmcraid_build_ioadl(
        nseg = scsi_dma_map(scsi_cmd);
 
        if (nseg < 0) {
-               dev_err(&pinstance->pdev->dev, "scsi_map_dma failed!\n");
+               scmd_printk(KERN_ERR, scsi_cmd, "scsi_map_dma failed!\n");
                return -1;
        } else if (nseg > PMCRAID_MAX_IOADLS) {
                scsi_dma_unmap(scsi_cmd);
-               dev_err(&pinstance->pdev->dev,
+               scmd_printk(KERN_ERR, scsi_cmd,
                        "sg count is (%d) more than allowed!\n", nseg);
                return -1;
        }
@@ -5040,7 +5045,7 @@ static int pmcraid_resume(struct pci_dev *pdev)
        rc = pci_enable_device(pdev);
 
        if (rc) {
-               pmcraid_err("pmcraid: Enable device failed\n");
+               dev_err(&pdev->dev, "resume: Enable device failed\n");
                return rc;
        }
 
@@ -5054,7 +5059,7 @@ static int pmcraid_resume(struct pci_dev *pdev)
                rc = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32));
 
        if (rc != 0) {
-               dev_err(&pdev->dev, "Failed to set PCI DMA mask\n");
+               dev_err(&pdev->dev, "resume: Failed to set PCI DMA mask\n");
                goto disable_device;
        }
 
@@ -5063,7 +5068,8 @@ static int pmcraid_resume(struct pci_dev *pdev)
        rc = pmcraid_register_interrupt_handler(pinstance);
 
        if (rc) {
-               pmcraid_err("resume: couldn't register interrupt handlers\n");
+               dev_err(&pdev->dev,
+                       "resume: couldn't register interrupt handlers\n");
                rc = -ENODEV;
                goto release_host;
        }
@@ -5080,7 +5086,7 @@ static int pmcraid_resume(struct pci_dev *pdev)
         * state.
         */
        if (pmcraid_reset_bringup(pinstance)) {
-               pmcraid_err("couldn't initialize IOA \n");
+               dev_err(&pdev->dev, "couldn't initialize IOA \n");
                rc = -ENODEV;
                goto release_tasklets;
        }
@@ -5187,7 +5193,7 @@ static void pmcraid_init_res_table(struct pmcraid_cmd *cmd)
        LIST_HEAD(old_res);
 
        if (pinstance->cfg_table->flags & MICROCODE_UPDATE_REQUIRED)
-               dev_err(&pinstance->pdev->dev, "Require microcode download\n");
+               pmcraid_err("IOA requires microcode download\n");
 
        /* resource list is protected by pinstance->resource_lock.
         * init_res_table can be called from probe (user-thread) or runtime
@@ -5224,8 +5230,7 @@ static void pmcraid_init_res_table(struct pmcraid_cmd *cmd)
                if (!found) {
 
                        if (list_empty(&pinstance->free_res_q)) {
-                               dev_err(&pinstance->pdev->dev,
-                                       "Too many devices attached\n");
+                               pmcraid_err("Too many devices attached\n");
                                break;
                        }
 
@@ -5442,7 +5447,7 @@ static int __devinit pmcraid_probe(
        rc = pmcraid_register_interrupt_handler(pinstance);
 
        if (rc) {
-               pmcraid_err("couldn't register interrupt handler\n");
+               dev_err(&pdev->dev, "couldn't register interrupt handler\n");
                goto out_scsi_host_put;
        }
 
@@ -5466,7 +5471,7 @@ static int __devinit pmcraid_probe(
         */
        pmcraid_info("starting IOA initialization sequence\n");
        if (pmcraid_reset_bringup(pinstance)) {
-               pmcraid_err("couldn't initialize IOA \n");
+               dev_err(&pdev->dev, "couldn't initialize IOA \n");
                rc = 1;
                goto out_release_bufs;
        }
@@ -5534,7 +5539,6 @@ static struct pci_driver pmcraid_driver = {
        .shutdown = pmcraid_shutdown
 };
 
-
 /**
  * pmcraid_init - module load entry point
  */
@@ -5566,7 +5570,6 @@ static int __init pmcraid_init(void)
                goto out_unreg_chrdev;
        }
 
-
        error = pmcraid_netlink_init();
 
        if (error)
@@ -5584,6 +5587,7 @@ static int __init pmcraid_init(void)
 
 out_unreg_chrdev:
        unregister_chrdev_region(MKDEV(pmcraid_major, 0), PMCRAID_MAX_ADAPTERS);
+
 out_init:
        return error;
 }
index 42b799a..e07b361 100644 (file)
@@ -568,7 +568,7 @@ qla25xx_create_req_que(struct qla_hw_data *ha, uint16_t options,
        if (req == NULL) {
                qla_printk(KERN_WARNING, ha, "could not allocate memory"
                        "for request que\n");
-               goto que_failed;
+               goto failed;
        }
 
        req->length = REQUEST_ENTRY_CNT_24XX;
@@ -632,6 +632,7 @@ qla25xx_create_req_que(struct qla_hw_data *ha, uint16_t options,
 
 que_failed:
        qla25xx_free_req_que(base_vha, req);
+failed:
        return 0;
 }
 
@@ -659,7 +660,7 @@ qla25xx_create_rsp_que(struct qla_hw_data *ha, uint16_t options,
        if (rsp == NULL) {
                qla_printk(KERN_WARNING, ha, "could not allocate memory for"
                                " response que\n");
-               goto que_failed;
+               goto failed;
        }
 
        rsp->length = RESPONSE_ENTRY_CNT_MQ;
@@ -728,6 +729,7 @@ qla25xx_create_rsp_que(struct qla_hw_data *ha, uint16_t options,
 
 que_failed:
        qla25xx_free_rsp_que(base_vha, rsp);
+failed:
        return 0;
 }
 
index b6e0307..dd098ca 100644 (file)
@@ -241,10 +241,7 @@ scsi_host_alloc_command(struct Scsi_Host *shost, gfp_t gfp_mask)
  */
 struct scsi_cmnd *__scsi_get_command(struct Scsi_Host *shost, gfp_t gfp_mask)
 {
-       struct scsi_cmnd *cmd;
-       unsigned char *buf;
-
-       cmd = scsi_host_alloc_command(shost, gfp_mask);
+       struct scsi_cmnd *cmd = scsi_host_alloc_command(shost, gfp_mask);
 
        if (unlikely(!cmd)) {
                unsigned long flags;
@@ -258,9 +255,15 @@ struct scsi_cmnd *__scsi_get_command(struct Scsi_Host *shost, gfp_t gfp_mask)
                spin_unlock_irqrestore(&shost->free_list_lock, flags);
 
                if (cmd) {
+                       void *buf, *prot;
+
                        buf = cmd->sense_buffer;
+                       prot = cmd->prot_sdb;
+
                        memset(cmd, 0, sizeof(*cmd));
+
                        cmd->sense_buffer = buf;
+                       cmd->prot_sdb = prot;
                }
        }
 
index fb9af20..c4103be 100644 (file)
@@ -50,6 +50,7 @@
 #include <scsi/scsi_host.h>
 #include <scsi/scsicam.h>
 #include <scsi/scsi_eh.h>
+#include <scsi/scsi_dbg.h>
 
 #include "sd.h"
 #include "scsi_logging.h"
@@ -64,6 +65,7 @@ static const char * scsi_debug_version_date = "20070104";
 #define PARAMETER_LIST_LENGTH_ERR 0x1a
 #define INVALID_OPCODE 0x20
 #define ADDR_OUT_OF_RANGE 0x21
+#define INVALID_COMMAND_OPCODE 0x20
 #define INVALID_FIELD_IN_CDB 0x24
 #define INVALID_FIELD_IN_PARAM_LIST 0x26
 #define POWERON_RESET 0x29
@@ -180,7 +182,7 @@ static int sdebug_sectors_per;              /* sectors per cylinder */
 #define SDEBUG_SENSE_LEN 32
 
 #define SCSI_DEBUG_CANQUEUE  255
-#define SCSI_DEBUG_MAX_CMD_LEN 16
+#define SCSI_DEBUG_MAX_CMD_LEN 32
 
 struct sdebug_dev_info {
        struct list_head dev_list;
@@ -296,9 +298,25 @@ static void mk_sense_buffer(struct sdebug_dev_info *devip, int key,
 }
 
 static void get_data_transfer_info(unsigned char *cmd,
-                                  unsigned long long *lba, unsigned int *num)
+                                  unsigned long long *lba, unsigned int *num,
+                                  u32 *ei_lba)
 {
+       *ei_lba = 0;
+
        switch (*cmd) {
+       case VARIABLE_LENGTH_CMD:
+               *lba = (u64)cmd[19] | (u64)cmd[18] << 8 |
+                       (u64)cmd[17] << 16 | (u64)cmd[16] << 24 |
+                       (u64)cmd[15] << 32 | (u64)cmd[14] << 40 |
+                       (u64)cmd[13] << 48 | (u64)cmd[12] << 56;
+
+               *ei_lba = (u32)cmd[23] | (u32)cmd[22] << 8 |
+                       (u32)cmd[21] << 16 | (u32)cmd[20] << 24;
+
+               *num = (u32)cmd[31] | (u32)cmd[30] << 8 | (u32)cmd[29] << 16 |
+                       (u32)cmd[28] << 24;
+               break;
+
        case WRITE_16:
        case READ_16:
                *lba = (u64)cmd[9] | (u64)cmd[8] << 8 |
@@ -1589,7 +1607,7 @@ static int do_device_access(struct scsi_cmnd *scmd,
 }
 
 static int prot_verify_read(struct scsi_cmnd *SCpnt, sector_t start_sec,
-                           unsigned int sectors)
+                           unsigned int sectors, u32 ei_lba)
 {
        unsigned int i, resid;
        struct scatterlist *psgl;
@@ -1636,13 +1654,23 @@ static int prot_verify_read(struct scsi_cmnd *SCpnt, sector_t start_sec,
                        return 0x01;
                }
 
-               if (scsi_debug_dif != SD_DIF_TYPE3_PROTECTION &&
+               if (scsi_debug_dif == SD_DIF_TYPE1_PROTECTION &&
                    be32_to_cpu(sdt[i].ref_tag) != (sector & 0xffffffff)) {
                        printk(KERN_ERR "%s: REF check failed on sector %lu\n",
                               __func__, (unsigned long)sector);
                        dif_errors++;
                        return 0x03;
                }
+
+               if (scsi_debug_dif == SD_DIF_TYPE2_PROTECTION &&
+                   be32_to_cpu(sdt[i].ref_tag) != ei_lba) {
+                       printk(KERN_ERR "%s: REF check failed on sector %lu\n",
+                              __func__, (unsigned long)sector);
+                       dif_errors++;
+                       return 0x03;
+               }
+
+               ei_lba++;
        }
 
        resid = sectors * 8; /* Bytes of protection data to copy into sgl */
@@ -1670,7 +1698,8 @@ static int prot_verify_read(struct scsi_cmnd *SCpnt, sector_t start_sec,
 }
 
 static int resp_read(struct scsi_cmnd *SCpnt, unsigned long long lba,
-                    unsigned int num, struct sdebug_dev_info *devip)
+                    unsigned int num, struct sdebug_dev_info *devip,
+                    u32 ei_lba)
 {
        unsigned long iflags;
        int ret;
@@ -1699,7 +1728,7 @@ static int resp_read(struct scsi_cmnd *SCpnt, unsigned long long lba,
 
        /* DIX + T10 DIF */
        if (scsi_debug_dix && scsi_prot_sg_count(SCpnt)) {
-               int prot_ret = prot_verify_read(SCpnt, lba, num);
+               int prot_ret = prot_verify_read(SCpnt, lba, num, ei_lba);
 
                if (prot_ret) {
                        mk_sense_buffer(devip, ABORTED_COMMAND, 0x10, prot_ret);
@@ -1735,7 +1764,7 @@ void dump_sector(unsigned char *buf, int len)
 }
 
 static int prot_verify_write(struct scsi_cmnd *SCpnt, sector_t start_sec,
-                            unsigned int sectors)
+                            unsigned int sectors, u32 ei_lba)
 {
        int i, j, ret;
        struct sd_dif_tuple *sdt;
@@ -1749,11 +1778,6 @@ static int prot_verify_write(struct scsi_cmnd *SCpnt, sector_t start_sec,
 
        sector = do_div(tmp_sec, sdebug_store_sectors);
 
-       if (((SCpnt->cmnd[1] >> 5) & 7) != 1) {
-               printk(KERN_WARNING "scsi_debug: WRPROTECT != 1\n");
-               return 0;
-       }
-
        BUG_ON(scsi_sg_count(SCpnt) == 0);
        BUG_ON(scsi_prot_sg_count(SCpnt) == 0);
 
@@ -1808,7 +1832,7 @@ static int prot_verify_write(struct scsi_cmnd *SCpnt, sector_t start_sec,
                                goto out;
                        }
 
-                       if (scsi_debug_dif != SD_DIF_TYPE3_PROTECTION &&
+                       if (scsi_debug_dif == SD_DIF_TYPE1_PROTECTION &&
                            be32_to_cpu(sdt->ref_tag)
                            != (start_sec & 0xffffffff)) {
                                printk(KERN_ERR
@@ -1819,6 +1843,16 @@ static int prot_verify_write(struct scsi_cmnd *SCpnt, sector_t start_sec,
                                goto out;
                        }
 
+                       if (scsi_debug_dif == SD_DIF_TYPE2_PROTECTION &&
+                           be32_to_cpu(sdt->ref_tag) != ei_lba) {
+                               printk(KERN_ERR
+                                      "%s: REF check failed on sector %lu\n",
+                                      __func__, (unsigned long)sector);
+                               ret = 0x03;
+                               dump_sector(daddr, scsi_debug_sector_size);
+                               goto out;
+                       }
+
                        /* Would be great to copy this in bigger
                         * chunks.  However, for the sake of
                         * correctness we need to verify each sector
@@ -1832,6 +1866,7 @@ static int prot_verify_write(struct scsi_cmnd *SCpnt, sector_t start_sec,
                                sector = 0;     /* Force wrap */
 
                        start_sec++;
+                       ei_lba++;
                        daddr += scsi_debug_sector_size;
                        ppage_offset += sizeof(struct sd_dif_tuple);
                }
@@ -1853,7 +1888,8 @@ out:
 }
 
 static int resp_write(struct scsi_cmnd *SCpnt, unsigned long long lba,
-                     unsigned int num, struct sdebug_dev_info *devip)
+                     unsigned int num, struct sdebug_dev_info *devip,
+                     u32 ei_lba)
 {
        unsigned long iflags;
        int ret;
@@ -1864,7 +1900,7 @@ static int resp_write(struct scsi_cmnd *SCpnt, unsigned long long lba,
 
        /* DIX + T10 DIF */
        if (scsi_debug_dix && scsi_prot_sg_count(SCpnt)) {
-               int prot_ret = prot_verify_write(SCpnt, lba, num);
+               int prot_ret = prot_verify_write(SCpnt, lba, num, ei_lba);
 
                if (prot_ret) {
                        mk_sense_buffer(devip, ILLEGAL_REQUEST, 0x10, prot_ret);
@@ -2872,11 +2908,12 @@ static int __init scsi_debug_init(void)
 
        case SD_DIF_TYPE0_PROTECTION:
        case SD_DIF_TYPE1_PROTECTION:
+       case SD_DIF_TYPE2_PROTECTION:
        case SD_DIF_TYPE3_PROTECTION:
                break;
 
        default:
-               printk(KERN_ERR "scsi_debug_init: dif must be 0, 1 or 3\n");
+               printk(KERN_ERR "scsi_debug_init: dif must be 0, 1, 2 or 3\n");
                return -EINVAL;
        }
 
@@ -3121,6 +3158,7 @@ int scsi_debug_queuecommand(struct scsi_cmnd *SCpnt, done_funct_t done)
        int len, k;
        unsigned int num;
        unsigned long long lba;
+       u32 ei_lba;
        int errsts = 0;
        int target = SCpnt->device->id;
        struct sdebug_dev_info *devip = NULL;
@@ -3254,14 +3292,30 @@ int scsi_debug_queuecommand(struct scsi_cmnd *SCpnt, done_funct_t done)
        case READ_16:
        case READ_12:
        case READ_10:
+               /* READ{10,12,16} and DIF Type 2 are natural enemies */
+               if (scsi_debug_dif == SD_DIF_TYPE2_PROTECTION &&
+                   cmd[1] & 0xe0) {
+                       mk_sense_buffer(devip, ILLEGAL_REQUEST,
+                                       INVALID_COMMAND_OPCODE, 0);
+                       errsts = check_condition_result;
+                       break;
+               }
+
+               if ((scsi_debug_dif == SD_DIF_TYPE1_PROTECTION ||
+                    scsi_debug_dif == SD_DIF_TYPE3_PROTECTION) &&
+                   (cmd[1] & 0xe0) == 0)
+                       printk(KERN_ERR "Unprotected RD/WR to DIF device\n");
+
+               /* fall through */
        case READ_6:
+read:
                errsts = check_readiness(SCpnt, 0, devip);
                if (errsts)
                        break;
                if (scsi_debug_fake_rw)
                        break;
-               get_data_transfer_info(cmd, &lba, &num);
-               errsts = resp_read(SCpnt, lba, num, devip);
+               get_data_transfer_info(cmd, &lba, &num, &ei_lba);
+               errsts = resp_read(SCpnt, lba, num, devip, ei_lba);
                if (inj_recovered && (0 == errsts)) {
                        mk_sense_buffer(devip, RECOVERED_ERROR,
                                        THRESHOLD_EXCEEDED, 0);
@@ -3288,14 +3342,30 @@ int scsi_debug_queuecommand(struct scsi_cmnd *SCpnt, done_funct_t done)
        case WRITE_16:
        case WRITE_12:
        case WRITE_10:
+               /* WRITE{10,12,16} and DIF Type 2 are natural enemies */
+               if (scsi_debug_dif == SD_DIF_TYPE2_PROTECTION &&
+                   cmd[1] & 0xe0) {
+                       mk_sense_buffer(devip, ILLEGAL_REQUEST,
+                                       INVALID_COMMAND_OPCODE, 0);
+                       errsts = check_condition_result;
+                       break;
+               }
+
+               if ((scsi_debug_dif == SD_DIF_TYPE1_PROTECTION ||
+                    scsi_debug_dif == SD_DIF_TYPE3_PROTECTION) &&
+                   (cmd[1] & 0xe0) == 0)
+                       printk(KERN_ERR "Unprotected RD/WR to DIF device\n");
+
+               /* fall through */
        case WRITE_6:
+write:
                errsts = check_readiness(SCpnt, 0, devip);
                if (errsts)
                        break;
                if (scsi_debug_fake_rw)
                        break;
-               get_data_transfer_info(cmd, &lba, &num);
-               errsts = resp_write(SCpnt, lba, num, devip);
+               get_data_transfer_info(cmd, &lba, &num, &ei_lba);
+               errsts = resp_write(SCpnt, lba, num, devip, ei_lba);
                if (inj_recovered && (0 == errsts)) {
                        mk_sense_buffer(devip, RECOVERED_ERROR,
                                        THRESHOLD_EXCEEDED, 0);
@@ -3341,15 +3411,38 @@ int scsi_debug_queuecommand(struct scsi_cmnd *SCpnt, done_funct_t done)
                        break;
                if (scsi_debug_fake_rw)
                        break;
-               get_data_transfer_info(cmd, &lba, &num);
-               errsts = resp_read(SCpnt, lba, num, devip);
+               get_data_transfer_info(cmd, &lba, &num, &ei_lba);
+               errsts = resp_read(SCpnt, lba, num, devip, ei_lba);
                if (errsts)
                        break;
-               errsts = resp_write(SCpnt, lba, num, devip);
+               errsts = resp_write(SCpnt, lba, num, devip, ei_lba);
                if (errsts)
                        break;
                errsts = resp_xdwriteread(SCpnt, lba, num, devip);
                break;
+       case VARIABLE_LENGTH_CMD:
+               if (scsi_debug_dif == SD_DIF_TYPE2_PROTECTION) {
+
+                       if ((cmd[10] & 0xe0) == 0)
+                               printk(KERN_ERR
+                                      "Unprotected RD/WR to DIF device\n");
+
+                       if (cmd[9] == READ_32) {
+                               BUG_ON(SCpnt->cmd_len < 32);
+                               goto read;
+                       }
+
+                       if (cmd[9] == WRITE_32) {
+                               BUG_ON(SCpnt->cmd_len < 32);
+                               goto write;
+                       }
+               }
+
+               mk_sense_buffer(devip, ILLEGAL_REQUEST,
+                               INVALID_FIELD_IN_CDB, 0);
+               errsts = check_condition_result;
+               break;
+
        default:
                if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts)
                        printk(KERN_INFO "scsi_debug: Opcode: 0x%x not "
index 877204d..1b0060b 100644 (file)
@@ -725,6 +725,9 @@ static int scsi_send_eh_cmnd(struct scsi_cmnd *scmd, unsigned char *cmnd,
                case NEEDS_RETRY:
                case FAILED:
                        break;
+               case ADD_TO_MLQUEUE:
+                       rtn = NEEDS_RETRY;
+                       break;
                default:
                        rtn = FAILED;
                        break;
index c447838..0547a7f 100644 (file)
@@ -317,6 +317,7 @@ static struct scsi_device *scsi_alloc_sdev(struct scsi_target *starget,
 out_device_destroy:
        scsi_device_set_state(sdev, SDEV_DEL);
        transport_destroy_device(&sdev->sdev_gendev);
+       put_device(&sdev->sdev_dev);
        put_device(&sdev->sdev_gendev);
 out:
        if (display_failure_msg)
@@ -957,6 +958,7 @@ static inline void scsi_destroy_sdev(struct scsi_device *sdev)
        if (sdev->host->hostt->slave_destroy)
                sdev->host->hostt->slave_destroy(sdev);
        transport_destroy_device(&sdev->sdev_gendev);
+       put_device(&sdev->sdev_dev);
        put_device(&sdev->sdev_gendev);
 }
 
index fde5453..5c7eb63 100644 (file)
@@ -864,10 +864,6 @@ int scsi_sysfs_add_sdev(struct scsi_device *sdev)
                goto clean_device;
        }
 
-       /* take a reference for the sdev_dev; this is
-        * released by the sdev_class .release */
-       get_device(&sdev->sdev_gendev);
-
        /* create queue files, which may be writable, depending on the host */
        if (sdev->host->hostt->change_queue_depth)
                error = device_create_file(&sdev->sdev_gendev, &sdev_attr_queue_depth_rw);
@@ -917,6 +913,7 @@ int scsi_sysfs_add_sdev(struct scsi_device *sdev)
 
        device_del(&sdev->sdev_gendev);
        transport_destroy_device(&sdev->sdev_gendev);
+       put_device(&sdev->sdev_dev);
        put_device(&sdev->sdev_gendev);
 
        return error;
@@ -1065,7 +1062,7 @@ void scsi_sysfs_device_initialize(struct scsi_device *sdev)
                     sdev->host->host_no, sdev->channel, sdev->id, sdev->lun);
 
        device_initialize(&sdev->sdev_dev);
-       sdev->sdev_dev.parent = &sdev->sdev_gendev;
+       sdev->sdev_dev.parent = get_device(&sdev->sdev_gendev);
        sdev->sdev_dev.class = &sdev_class;
        dev_set_name(&sdev->sdev_dev, "%d:%d:%d:%d",
                     sdev->host->host_no, sdev->channel, sdev->id, sdev->lun);
index b98885d..a67fed1 100644 (file)
@@ -3586,6 +3586,7 @@ enum fc_dispatch_result {
 
 /**
  * fc_bsg_host_dispatch - process fc host bsg requests and dispatch to LLDD
+ * @q:         fc host request queue
  * @shost:     scsi host rport attached to
  * @job:       bsg job to be processed
  */
@@ -3693,6 +3694,7 @@ fc_bsg_goose_queue(struct fc_rport *rport)
 
 /**
  * fc_bsg_rport_dispatch - process rport bsg requests and dispatch to LLDD
+ * @q:         rport request queue
  * @shost:     scsi host rport attached to
  * @rport:     rport request destined to
  * @job:       bsg job to be processed
index 8dd96dc..9093c72 100644 (file)
@@ -116,6 +116,9 @@ static DEFINE_IDA(sd_index_ida);
  * object after last put) */
 static DEFINE_MUTEX(sd_ref_mutex);
 
+struct kmem_cache *sd_cdb_cache;
+mempool_t *sd_cdb_pool;
+
 static const char *sd_cache_types[] = {
        "write through", "none", "write back",
        "write back, no read (daft)"
@@ -370,6 +373,31 @@ static void scsi_disk_put(struct scsi_disk *sdkp)
        mutex_unlock(&sd_ref_mutex);
 }
 
+static void sd_prot_op(struct scsi_cmnd *scmd, unsigned int dif)
+{
+       unsigned int prot_op = SCSI_PROT_NORMAL;
+       unsigned int dix = scsi_prot_sg_count(scmd);
+
+       if (scmd->sc_data_direction == DMA_FROM_DEVICE) {
+               if (dif && dix)
+                       prot_op = SCSI_PROT_READ_PASS;
+               else if (dif && !dix)
+                       prot_op = SCSI_PROT_READ_STRIP;
+               else if (!dif && dix)
+                       prot_op = SCSI_PROT_READ_INSERT;
+       } else {
+               if (dif && dix)
+                       prot_op = SCSI_PROT_WRITE_PASS;
+               else if (dif && !dix)
+                       prot_op = SCSI_PROT_WRITE_INSERT;
+               else if (!dif && dix)
+                       prot_op = SCSI_PROT_WRITE_STRIP;
+       }
+
+       scsi_set_prot_op(scmd, prot_op);
+       scsi_set_prot_type(scmd, dif);
+}
+
 /**
  *     sd_init_command - build a scsi (read or write) command from
  *     information in the request structure.
@@ -388,6 +416,7 @@ static int sd_prep_fn(struct request_queue *q, struct request *rq)
        sector_t threshold;
        unsigned int this_count = blk_rq_sectors(rq);
        int ret, host_dif;
+       unsigned char protect;
 
        if (rq->cmd_type == REQ_TYPE_BLOCK_PC) {
                ret = scsi_setup_blk_pc_cmnd(sdp, rq);
@@ -520,13 +549,49 @@ static int sd_prep_fn(struct request_queue *q, struct request *rq)
        /* Set RDPROTECT/WRPROTECT if disk is formatted with DIF */
        host_dif = scsi_host_dif_capable(sdp->host, sdkp->protection_type);
        if (host_dif)
-               SCpnt->cmnd[1] = 1 << 5;
+               protect = 1 << 5;
        else
-               SCpnt->cmnd[1] = 0;
+               protect = 0;
 
-       if (block > 0xffffffff) {
+       if (host_dif == SD_DIF_TYPE2_PROTECTION) {
+               SCpnt->cmnd = mempool_alloc(sd_cdb_pool, GFP_ATOMIC);
+
+               if (unlikely(SCpnt->cmnd == NULL)) {
+                       ret = BLKPREP_DEFER;
+                       goto out;
+               }
+
+               SCpnt->cmd_len = SD_EXT_CDB_SIZE;
+               memset(SCpnt->cmnd, 0, SCpnt->cmd_len);
+               SCpnt->cmnd[0] = VARIABLE_LENGTH_CMD;
+               SCpnt->cmnd[7] = 0x18;
+               SCpnt->cmnd[9] = (rq_data_dir(rq) == READ) ? READ_32 : WRITE_32;
+               SCpnt->cmnd[10] = protect | (blk_fua_rq(rq) ? 0x8 : 0);
+
+               /* LBA */
+               SCpnt->cmnd[12] = sizeof(block) > 4 ? (unsigned char) (block >> 56) & 0xff : 0;
+               SCpnt->cmnd[13] = sizeof(block) > 4 ? (unsigned char) (block >> 48) & 0xff : 0;
+               SCpnt->cmnd[14] = sizeof(block) > 4 ? (unsigned char) (block >> 40) & 0xff : 0;
+               SCpnt->cmnd[15] = sizeof(block) > 4 ? (unsigned char) (block >> 32) & 0xff : 0;
+               SCpnt->cmnd[16] = (unsigned char) (block >> 24) & 0xff;
+               SCpnt->cmnd[17] = (unsigned char) (block >> 16) & 0xff;
+               SCpnt->cmnd[18] = (unsigned char) (block >> 8) & 0xff;
+               SCpnt->cmnd[19] = (unsigned char) block & 0xff;
+
+               /* Expected Indirect LBA */
+               SCpnt->cmnd[20] = (unsigned char) (block >> 24) & 0xff;
+               SCpnt->cmnd[21] = (unsigned char) (block >> 16) & 0xff;
+               SCpnt->cmnd[22] = (unsigned char) (block >> 8) & 0xff;
+               SCpnt->cmnd[23] = (unsigned char) block & 0xff;
+
+               /* Transfer length */
+               SCpnt->cmnd[28] = (unsigned char) (this_count >> 24) & 0xff;
+               SCpnt->cmnd[29] = (unsigned char) (this_count >> 16) & 0xff;
+               SCpnt->cmnd[30] = (unsigned char) (this_count >> 8) & 0xff;
+               SCpnt->cmnd[31] = (unsigned char) this_count & 0xff;
+       } else if (block > 0xffffffff) {
                SCpnt->cmnd[0] += READ_16 - READ_6;
-               SCpnt->cmnd[1] |= blk_fua_rq(rq) ? 0x8 : 0;
+               SCpnt->cmnd[1] = protect | (blk_fua_rq(rq) ? 0x8 : 0);
                SCpnt->cmnd[2] = sizeof(block) > 4 ? (unsigned char) (block >> 56) & 0xff : 0;
                SCpnt->cmnd[3] = sizeof(block) > 4 ? (unsigned char) (block >> 48) & 0xff : 0;
                SCpnt->cmnd[4] = sizeof(block) > 4 ? (unsigned char) (block >> 40) & 0xff : 0;
@@ -547,7 +612,7 @@ static int sd_prep_fn(struct request_queue *q, struct request *rq)
                        this_count = 0xffff;
 
                SCpnt->cmnd[0] += READ_10 - READ_6;
-               SCpnt->cmnd[1] |= blk_fua_rq(rq) ? 0x8 : 0;
+               SCpnt->cmnd[1] = protect | (blk_fua_rq(rq) ? 0x8 : 0);
                SCpnt->cmnd[2] = (unsigned char) (block >> 24) & 0xff;
                SCpnt->cmnd[3] = (unsigned char) (block >> 16) & 0xff;
                SCpnt->cmnd[4] = (unsigned char) (block >> 8) & 0xff;
@@ -578,8 +643,7 @@ static int sd_prep_fn(struct request_queue *q, struct request *rq)
 
        /* If DIF or DIX is enabled, tell HBA how to handle request */
        if (host_dif || scsi_prot_sg_count(SCpnt))
-               sd_dif_op(SCpnt, host_dif, scsi_prot_sg_count(SCpnt),
-                         sdkp->protection_type);
+               sd_prot_op(SCpnt, host_dif);
 
        /*
         * We shouldn't disconnect in the middle of a sector, so with a dumb
@@ -1023,6 +1087,7 @@ static int sd_done(struct scsi_cmnd *SCpnt)
        int result = SCpnt->result;
        unsigned int good_bytes = result ? 0 : scsi_bufflen(SCpnt);
        struct scsi_sense_hdr sshdr;
+       struct scsi_disk *sdkp = scsi_disk(SCpnt->request->rq_disk);
        int sense_valid = 0;
        int sense_deferred = 0;
 
@@ -1084,6 +1149,10 @@ static int sd_done(struct scsi_cmnd *SCpnt)
        if (rq_data_dir(SCpnt->request) == READ && scsi_prot_sg_count(SCpnt))
                sd_dif_complete(SCpnt, good_bytes);
 
+       if (scsi_host_dif_capable(sdkp->device->host, sdkp->protection_type)
+           == SD_DIF_TYPE2_PROTECTION && SCpnt->cmnd != SCpnt->request->cmd)
+               mempool_free(SCpnt->cmnd, sd_cdb_pool);
+
        return good_bytes;
 }
 
@@ -1238,34 +1307,28 @@ void sd_read_protection_type(struct scsi_disk *sdkp, unsigned char *buffer)
        u8 type;
 
        if (scsi_device_protection(sdp) == 0 || (buffer[12] & 1) == 0)
-               type = 0;
-       else
-               type = ((buffer[12] >> 1) & 7) + 1; /* P_TYPE 0 = Type 1 */
+               return;
 
-       sdkp->protection_type = type;
+       type = ((buffer[12] >> 1) & 7) + 1; /* P_TYPE 0 = Type 1 */
 
-       switch (type) {
-       case SD_DIF_TYPE0_PROTECTION:
-       case SD_DIF_TYPE1_PROTECTION:
-       case SD_DIF_TYPE3_PROTECTION:
-               break;
+       if (type == sdkp->protection_type || !sdkp->first_scan)
+               return;
 
-       case SD_DIF_TYPE2_PROTECTION:
-               sd_printk(KERN_ERR, sdkp, "formatted with DIF Type 2 "  \
-                         "protection which is currently unsupported. " \
-                         "Disabling disk!\n");
-               goto disable;
+       sdkp->protection_type = type;
 
-       default:
-               sd_printk(KERN_ERR, sdkp, "formatted with unknown "     \
-                         "protection type %d. Disabling disk!\n", type);
-               goto disable;
+       if (type > SD_DIF_TYPE3_PROTECTION) {
+               sd_printk(KERN_ERR, sdkp, "formatted with unsupported " \
+                         "protection type %u. Disabling disk!\n", type);
+               sdkp->capacity = 0;
+               return;
        }
 
-       return;
-
-disable:
-       sdkp->capacity = 0;
+       if (scsi_host_dif_capable(sdp->host, type))
+               sd_printk(KERN_NOTICE, sdkp,
+                         "Enabling DIF Type %u protection\n", type);
+       else
+               sd_printk(KERN_NOTICE, sdkp,
+                         "Disabling DIF Type %u protection\n", type);
 }
 
 static void read_capacity_error(struct scsi_disk *sdkp, struct scsi_device *sdp,
@@ -2300,8 +2363,24 @@ static int __init init_sd(void)
        if (err)
                goto err_out_class;
 
+       sd_cdb_cache = kmem_cache_create("sd_ext_cdb", SD_EXT_CDB_SIZE,
+                                        0, 0, NULL);
+       if (!sd_cdb_cache) {
+               printk(KERN_ERR "sd: can't init extended cdb cache\n");
+               goto err_out_class;
+       }
+
+       sd_cdb_pool = mempool_create_slab_pool(SD_MEMPOOL_SIZE, sd_cdb_cache);
+       if (!sd_cdb_pool) {
+               printk(KERN_ERR "sd: can't init extended cdb pool\n");
+               goto err_out_cache;
+       }
+
        return 0;
 
+err_out_cache:
+       kmem_cache_destroy(sd_cdb_cache);
+
 err_out_class:
        class_unregister(&sd_disk_class);
 err_out:
@@ -2321,6 +2400,9 @@ static void __exit exit_sd(void)
 
        SCSI_LOG_HLQUEUE(3, printk("exit_sd: exiting sd driver\n"));
 
+       mempool_destroy(sd_cdb_pool);
+       kmem_cache_destroy(sd_cdb_cache);
+
        scsi_unregister_driver(&sd_template.gendrv);
        class_unregister(&sd_disk_class);
 
index 8474b5b..e374804 100644 (file)
  */
 #define SD_LAST_BUGGY_SECTORS  8
 
+enum {
+       SD_EXT_CDB_SIZE = 32,   /* Extended CDB size */
+       SD_MEMPOOL_SIZE = 2,    /* CDB pool size */
+};
+
 struct scsi_disk {
        struct scsi_driver *driver;     /* always &sd_template */
        struct scsi_device *device;
@@ -101,16 +106,12 @@ struct sd_dif_tuple {
 
 #ifdef CONFIG_BLK_DEV_INTEGRITY
 
-extern void sd_dif_op(struct scsi_cmnd *, unsigned int, unsigned int, unsigned int);
 extern void sd_dif_config_host(struct scsi_disk *);
 extern int sd_dif_prepare(struct request *rq, sector_t, unsigned int);
 extern void sd_dif_complete(struct scsi_cmnd *, unsigned int);
 
 #else /* CONFIG_BLK_DEV_INTEGRITY */
 
-static inline void sd_dif_op(struct scsi_cmnd *cmd, unsigned int a, unsigned int b, unsigned int c)
-{
-}
 static inline void sd_dif_config_host(struct scsi_disk *disk)
 {
 }
index 82f14a9..88da977 100644 (file)
@@ -320,15 +320,6 @@ void sd_dif_config_host(struct scsi_disk *sdkp)
                dif = 0; dix = 1;
        }
 
-       if (type) {
-               if (dif)
-                       sd_printk(KERN_NOTICE, sdkp,
-                                 "Enabling DIF Type %d protection\n", type);
-               else
-                       sd_printk(KERN_NOTICE, sdkp,
-                                 "Disabling DIF Type %d protection\n", type);
-       }
-
        if (!dix)
                return;
 
@@ -360,62 +351,6 @@ void sd_dif_config_host(struct scsi_disk *sdkp)
 }
 
 /*
- * DIF DMA operation magic decoder ring.
- */
-void sd_dif_op(struct scsi_cmnd *scmd, unsigned int dif, unsigned int dix, unsigned int type)
-{
-       int csum_convert, prot_op;
-
-       prot_op = 0;
-
-       /* Convert checksum? */
-       if (scsi_host_get_guard(scmd->device->host) != SHOST_DIX_GUARD_CRC)
-               csum_convert = 1;
-       else
-               csum_convert = 0;
-
-       BUG_ON(dif && (scmd->cmnd[0] == READ_6 || scmd->cmnd[0] == WRITE_6));
-
-       switch (scmd->cmnd[0]) {
-       case READ_6:
-       case READ_10:
-       case READ_12:
-       case READ_16:
-               if (dif && dix)
-                       if (csum_convert)
-                               prot_op = SCSI_PROT_READ_CONVERT;
-                       else
-                               prot_op = SCSI_PROT_READ_PASS;
-               else if (dif && !dix)
-                       prot_op = SCSI_PROT_READ_STRIP;
-               else if (!dif && dix)
-                       prot_op = SCSI_PROT_READ_INSERT;
-
-               break;
-
-       case WRITE_6:
-       case WRITE_10:
-       case WRITE_12:
-       case WRITE_16:
-               if (dif && dix)
-                       if (csum_convert)
-                               prot_op = SCSI_PROT_WRITE_CONVERT;
-                       else
-                               prot_op = SCSI_PROT_WRITE_PASS;
-               else if (dif && !dix)
-                       prot_op = SCSI_PROT_WRITE_INSERT;
-               else if (!dif && dix)
-                       prot_op = SCSI_PROT_WRITE_STRIP;
-
-               break;
-       }
-
-       scsi_set_prot_op(scmd, prot_op);
-       if (dif)
-               scsi_set_prot_type(scmd, type);
-}
-
-/*
  * The virtual start sector is the one that was originally submitted
  * by the block layer. Due to partitioning, MD/DM cloning, etc. the
  * actual physical start sector is likely to be different.  Remap
index 747a5e5..040f751 100644 (file)
@@ -1708,11 +1708,6 @@ static int sg_finish_rem_req(Sg_request * srp)
        Sg_scatter_hold *req_schp = &srp->data;
 
        SCSI_LOG_TIMEOUT(4, printk("sg_finish_rem_req: res_used=%d\n", (int) srp->res_used));
-       if (srp->res_used)
-               sg_unlink_reserve(sfp, srp);
-       else
-               sg_remove_scat(req_schp);
-
        if (srp->rq) {
                if (srp->bio)
                        ret = blk_rq_unmap_user(srp->bio);
@@ -1720,6 +1715,11 @@ static int sg_finish_rem_req(Sg_request * srp)
                blk_put_request(srp->rq);
        }
 
+       if (srp->res_used)
+               sg_unlink_reserve(sfp, srp);
+       else
+               sg_remove_scat(req_schp);
+
        sg_remove_request(sfp, srp);
 
        return ret;
index eb61f7a..d6f340f 100644 (file)
@@ -684,14 +684,20 @@ static void get_sectorsize(struct scsi_cd *cd)
                cd->capacity = 0x1fffff;
                sector_size = 2048;     /* A guess, just in case */
        } else {
-#if 0
-               if (cdrom_get_last_written(&cd->cdi,
-                                          &cd->capacity))
-#endif
-                       cd->capacity = 1 + ((buffer[0] << 24) |
-                                                   (buffer[1] << 16) |
-                                                   (buffer[2] << 8) |
-                                                   buffer[3]);
+               long last_written;
+
+               cd->capacity = 1 + ((buffer[0] << 24) | (buffer[1] << 16) |
+                                   (buffer[2] << 8) | buffer[3]);
+               /*
+                * READ_CAPACITY doesn't return the correct size on
+                * certain UDF media.  If last_written is larger, use
+                * it instead.
+                *
+                * http://bugzilla.kernel.org/show_bug.cgi?id=9668
+                */
+               if (!cdrom_get_last_written(&cd->cdi, &last_written))
+                       cd->capacity = max_t(long, cd->capacity, last_written);
+
                sector_size = (buffer[4] << 24) |
                    (buffer[5] << 16) | (buffer[6] << 8) | buffer[7];
                switch (sector_size) {
index b33d042..12d58a7 100644 (file)
@@ -2859,11 +2859,8 @@ static int st_int_ioctl(struct scsi_tape *STp, unsigned int cmd_in, unsigned lon
                        ioctl_result = st_int_ioctl(STp, MTBSF, 1);
 
                if (cmd_in == MTSETBLK || cmd_in == SET_DENS_AND_BLK) {
-                       int old_block_size = STp->block_size;
                        STp->block_size = arg & MT_ST_BLKSIZE_MASK;
                        if (STp->block_size != 0) {
-                               if (old_block_size == 0)
-                                       normalize_buffer(STp->buffer);
                                (STp->buffer)->buffer_blocks =
                                    (STp->buffer)->buffer_size / STp->block_size;
                        }
index e7108e7..42e8550 100644 (file)
@@ -1561,11 +1561,16 @@ enum pci_board_num_t {
        pbn_exar_XR17C152,
        pbn_exar_XR17C154,
        pbn_exar_XR17C158,
+       pbn_exar_ibm_saturn,
        pbn_pasemi_1682M,
        pbn_ni8430_2,
        pbn_ni8430_4,
        pbn_ni8430_8,
        pbn_ni8430_16,
+       pbn_ADDIDATA_PCIe_1_3906250,
+       pbn_ADDIDATA_PCIe_2_3906250,
+       pbn_ADDIDATA_PCIe_4_3906250,
+       pbn_ADDIDATA_PCIe_8_3906250,
 };
 
 /*
@@ -2146,6 +2151,13 @@ static struct pciserial_board pci_boards[] __devinitdata = {
                .base_baud      = 921600,
                .uart_offset    = 0x200,
        },
+       [pbn_exar_ibm_saturn] = {
+               .flags          = FL_BASE0,
+               .num_ports      = 1,
+               .base_baud      = 921600,
+               .uart_offset    = 0x200,
+       },
+
        /*
         * PA Semi PWRficient PA6T-1682M on-chip UART
         */
@@ -2185,6 +2197,37 @@ static struct pciserial_board pci_boards[] __devinitdata = {
                .uart_offset    = 0x10,
                .first_offset   = 0x800,
        },
+       /*
+        * ADDI-DATA GmbH PCI-Express communication cards <info@addi-data.com>
+        */
+       [pbn_ADDIDATA_PCIe_1_3906250] = {
+               .flags          = FL_BASE0,
+               .num_ports      = 1,
+               .base_baud      = 3906250,
+               .uart_offset    = 0x200,
+               .first_offset   = 0x1000,
+       },
+       [pbn_ADDIDATA_PCIe_2_3906250] = {
+               .flags          = FL_BASE0,
+               .num_ports      = 2,
+               .base_baud      = 3906250,
+               .uart_offset    = 0x200,
+               .first_offset   = 0x1000,
+       },
+       [pbn_ADDIDATA_PCIe_4_3906250] = {
+               .flags          = FL_BASE0,
+               .num_ports      = 4,
+               .base_baud      = 3906250,
+               .uart_offset    = 0x200,
+               .first_offset   = 0x1000,
+       },
+       [pbn_ADDIDATA_PCIe_8_3906250] = {
+               .flags          = FL_BASE0,
+               .num_ports      = 8,
+               .base_baud      = 3906250,
+               .uart_offset    = 0x200,
+               .first_offset   = 0x1000,
+       },
 };
 
 static const struct pci_device_id softmodem_blacklist[] = {
@@ -2649,6 +2692,9 @@ static struct pci_device_id serial_pci_tbl[] = {
                PCI_SUBVENDOR_ID_CONNECT_TECH,
                PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_8_485, 0, 0,
                pbn_b0_8_1843200_200 },
+       {       PCI_VENDOR_ID_EXAR, PCI_DEVICE_ID_EXAR_XR17C152,
+               PCI_VENDOR_ID_IBM, PCI_SUBDEVICE_ID_IBM_SATURN_SERIAL_ONE_PORT,
+               0, 0, pbn_exar_ibm_saturn },
 
        {       PCI_VENDOR_ID_SEALEVEL, PCI_DEVICE_ID_SEALEVEL_U530,
                PCI_ANY_ID, PCI_ANY_ID, 0, 0,
@@ -3556,6 +3602,38 @@ static struct pci_device_id serial_pci_tbl[] = {
                0,
                pbn_b0_8_115200 },
 
+       {       PCI_VENDOR_ID_ADDIDATA,
+               PCI_DEVICE_ID_ADDIDATA_APCIe7500,
+               PCI_ANY_ID,
+               PCI_ANY_ID,
+               0,
+               0,
+               pbn_ADDIDATA_PCIe_4_3906250 },
+
+       {       PCI_VENDOR_ID_ADDIDATA,
+               PCI_DEVICE_ID_ADDIDATA_APCIe7420,
+               PCI_ANY_ID,
+               PCI_ANY_ID,
+               0,
+               0,
+               pbn_ADDIDATA_PCIe_2_3906250 },
+
+       {       PCI_VENDOR_ID_ADDIDATA,
+               PCI_DEVICE_ID_ADDIDATA_APCIe7300,
+               PCI_ANY_ID,
+               PCI_ANY_ID,
+               0,
+               0,
+               pbn_ADDIDATA_PCIe_1_3906250 },
+
+       {       PCI_VENDOR_ID_ADDIDATA,
+               PCI_DEVICE_ID_ADDIDATA_APCIe7800,
+               PCI_ANY_ID,
+               PCI_ANY_ID,
+               0,
+               0,
+               pbn_ADDIDATA_PCIe_8_3906250 },
+
        {       PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9835,
                PCI_VENDOR_ID_IBM, 0x0299,
                0, 0, pbn_b0_bt_2_115200 },
index 3551c5c..9d948bc 100644 (file)
@@ -1531,7 +1531,7 @@ static int __devinit atmel_serial_probe(struct platform_device *pdev)
        void *data;
        int ret;
 
-       BUILD_BUG_ON(!is_power_of_2(ATMEL_SERIAL_RINGSIZE));
+       BUILD_BUG_ON(ATMEL_SERIAL_RINGSIZE & (ATMEL_SERIAL_RINGSIZE - 1));
 
        port = &atmel_ports[pdev->id];
        port->backup_imr = 0;
index d7bcd07..7ce9e9f 100644 (file)
@@ -705,7 +705,7 @@ mpc52xx_uart_verify_port(struct uart_port *port, struct serial_struct *ser)
                return -EINVAL;
 
        if ((ser->irq != port->irq) ||
-           (ser->io_type != SERIAL_IO_MEM) ||
+           (ser->io_type != UPIO_MEM) ||
            (ser->baud_base != port->uartclk)  ||
            (ser->iomem_base != (void *)port->mapbase) ||
            (ser->hub6 != 0))
index 1689bda..dcc7244 100644 (file)
@@ -1270,6 +1270,9 @@ static void uart_close(struct tty_struct *tty, struct file *filp)
 
        BUG_ON(!kernel_locked());
 
+       if (!state)
+               return;
+
        uport = state->uart_port;
        port = &state->port;
 
@@ -1316,9 +1319,9 @@ static void uart_close(struct tty_struct *tty, struct file *filp)
         */
        if (port->flags & ASYNC_INITIALIZED) {
                unsigned long flags;
-               spin_lock_irqsave(&port->lock, flags);
+               spin_lock_irqsave(&uport->lock, flags);
                uport->ops->stop_rx(uport);
-               spin_unlock_irqrestore(&port->lock, flags);
+               spin_unlock_irqrestore(&uport->lock, flags);
                /*
                 * Before we drop DTR, make sure the UART transmitter
                 * has completely drained; this is especially
index a3bb490..7c7914f 100644 (file)
@@ -873,20 +873,20 @@ static struct pcmcia_device_id serial_ids[] = {
        PCMCIA_PFC_DEVICE_CIS_PROD_ID12(1, "Psion Dacom", "Gold Card V34 Ethernet", 0xf5f025c2, 0x338e8155, "cis/PCMLM28.cis"),
        PCMCIA_PFC_DEVICE_CIS_PROD_ID12(1, "Psion Dacom", "Gold Card V34 Ethernet GSM", 0xf5f025c2, 0x4ae85d35, "cis/PCMLM28.cis"),
        PCMCIA_PFC_DEVICE_CIS_PROD_ID12(1, "LINKSYS", "PCMLM28", 0xf7cb0b07, 0x66881874, "cis/PCMLM28.cis"),
-       PCMCIA_MFC_DEVICE_CIS_PROD_ID12(1, "DAYNA COMMUNICATIONS", "LAN AND MODEM MULTIFUNCTION", 0x8fdf8f89, 0xdd5ed9e8, "DP83903.cis"),
-       PCMCIA_MFC_DEVICE_CIS_PROD_ID4(1, "NSC MF LAN/Modem", 0x58fc6056, "DP83903.cis"),
+       PCMCIA_MFC_DEVICE_CIS_PROD_ID12(1, "DAYNA COMMUNICATIONS", "LAN AND MODEM MULTIFUNCTION", 0x8fdf8f89, 0xdd5ed9e8, "cis/DP83903.cis"),
+       PCMCIA_MFC_DEVICE_CIS_PROD_ID4(1, "NSC MF LAN/Modem", 0x58fc6056, "cis/DP83903.cis"),
        PCMCIA_MFC_DEVICE_CIS_MANF_CARD(1, 0x0101, 0x0556, "cis/3CCFEM556.cis"),
-       PCMCIA_MFC_DEVICE_CIS_MANF_CARD(1, 0x0175, 0x0000, "DP83903.cis"),
+       PCMCIA_MFC_DEVICE_CIS_MANF_CARD(1, 0x0175, 0x0000, "cis/DP83903.cis"),
        PCMCIA_MFC_DEVICE_CIS_MANF_CARD(1, 0x0101, 0x0035, "cis/3CXEM556.cis"),
        PCMCIA_MFC_DEVICE_CIS_MANF_CARD(1, 0x0101, 0x003d, "cis/3CXEM556.cis"),
-       PCMCIA_DEVICE_CIS_PROD_ID12("Sierra Wireless", "AC850", 0xd85f6206, 0x42a2c018, "SW_8xx_SER.cis"),  /* Sierra Wireless AC850 3G Network Adapter R1 */
-       PCMCIA_DEVICE_CIS_MANF_CARD(0x0192, 0x0710, "SW_7xx_SER.cis"),  /* Sierra Wireless AC710/AC750 GPRS Network Adapter R1 */
-       PCMCIA_DEVICE_CIS_MANF_CARD(0x0192, 0xa555, "SW_555_SER.cis"),  /* Sierra Aircard 555 CDMA 1xrtt Modem -- pre update */
-       PCMCIA_DEVICE_CIS_MANF_CARD(0x013f, 0xa555, "SW_555_SER.cis"),  /* Sierra Aircard 555 CDMA 1xrtt Modem -- post update */
+       PCMCIA_DEVICE_CIS_PROD_ID12("Sierra Wireless", "AC850", 0xd85f6206, 0x42a2c018, "cis/SW_8xx_SER.cis"), /* Sierra Wireless AC850 3G Network Adapter R1 */
+       PCMCIA_DEVICE_CIS_PROD_ID12("Sierra Wireless", "AC710/AC750", 0xd85f6206, 0x761b11e0, "cis/SW_7xx_SER.cis"),  /* Sierra Wireless AC710/AC750 GPRS Network Adapter R1 */
+       PCMCIA_DEVICE_CIS_MANF_CARD(0x0192, 0xa555, "cis/SW_555_SER.cis"),  /* Sierra Aircard 555 CDMA 1xrtt Modem -- pre update */
+       PCMCIA_DEVICE_CIS_MANF_CARD(0x013f, 0xa555, "cis/SW_555_SER.cis"),  /* Sierra Aircard 555 CDMA 1xrtt Modem -- post update */
        PCMCIA_DEVICE_CIS_PROD_ID12("MultiTech", "PCMCIA 56K DataFax", 0x842047ee, 0xc2efcf03, "cis/MT5634ZLX.cis"),
-       PCMCIA_DEVICE_CIS_PROD_ID12("ADVANTECH", "COMpad-32/85B-2", 0x96913a85, 0x27ab5437, "COMpad2.cis"),
-       PCMCIA_DEVICE_CIS_PROD_ID12("ADVANTECH", "COMpad-32/85B-4", 0x96913a85, 0xcec8f102, "COMpad4.cis"),
-       PCMCIA_DEVICE_CIS_PROD_ID123("ADVANTECH", "COMpad-32/85", "1.0", 0x96913a85, 0x8fbe92ae, 0x0877b627, "COMpad2.cis"),
+       PCMCIA_DEVICE_CIS_PROD_ID12("ADVANTECH", "COMpad-32/85B-2", 0x96913a85, 0x27ab5437, "cis/COMpad2.cis"),
+       PCMCIA_DEVICE_CIS_PROD_ID12("ADVANTECH", "COMpad-32/85B-4", 0x96913a85, 0xcec8f102, "cis/COMpad4.cis"),
+       PCMCIA_DEVICE_CIS_PROD_ID123("ADVANTECH", "COMpad-32/85", "1.0", 0x96913a85, 0x8fbe92ae, 0x0877b627, "cis/COMpad2.cis"),
        PCMCIA_DEVICE_CIS_PROD_ID2("RS-COM 2P", 0xad20b156, "cis/RS-COM-2P.cis"),
        PCMCIA_DEVICE_CIS_MANF_CARD(0x0013, 0x0000, "GLOBETROTTER.cis"),
        PCMCIA_DEVICE_PROD_ID12("ELAN DIGITAL SYSTEMS LTD, c1997.","SERIAL CARD: SL100  1.00.",0x19ca78af,0xf964f42b),
index 958a3ff..ff5bbb9 100644 (file)
@@ -1826,7 +1826,7 @@ static struct amba_id pl022_ids[] = {
                 * ST Micro derivative, this has 32bit wide
                 * and 32 locations deep TX/RX FIFO
                 */
-               .id     = 0x00108022,
+               .id     = 0x01080022,
                .mask   = 0xffffffff,
                .data   = &vendor_st,
        },
index 9a4dd59..d21b346 100644 (file)
@@ -59,8 +59,6 @@ source "drivers/staging/echo/Kconfig"
 
 source "drivers/staging/poch/Kconfig"
 
-source "drivers/staging/agnx/Kconfig"
-
 source "drivers/staging/otus/Kconfig"
 
 source "drivers/staging/rt2860/Kconfig"
@@ -95,8 +93,6 @@ source "drivers/staging/dst/Kconfig"
 
 source "drivers/staging/pohmelfs/Kconfig"
 
-source "drivers/staging/stlc45xx/Kconfig"
-
 source "drivers/staging/b3dfg/Kconfig"
 
 source "drivers/staging/phison/Kconfig"
@@ -129,7 +125,5 @@ source "drivers/staging/sep/Kconfig"
 
 source "drivers/staging/iio/Kconfig"
 
-source "drivers/staging/cowloop/Kconfig"
-
 endif # !STAGING_EXCLUDE_BUILD
 endif # STAGING
index 104f2f8..8cbf1ae 100644 (file)
@@ -12,7 +12,6 @@ obj-$(CONFIG_W35UND)          += winbond/
 obj-$(CONFIG_PRISM2_USB)       += wlan-ng/
 obj-$(CONFIG_ECHO)             += echo/
 obj-$(CONFIG_POCH)             += poch/
-obj-$(CONFIG_AGNX)             += agnx/
 obj-$(CONFIG_OTUS)             += otus/
 obj-$(CONFIG_RT2860)           += rt2860/
 obj-$(CONFIG_RT2870)           += rt2870/
@@ -30,7 +29,6 @@ obj-$(CONFIG_ANDROID)         += android/
 obj-$(CONFIG_ANDROID)          += dream/
 obj-$(CONFIG_DST)              += dst/
 obj-$(CONFIG_POHMELFS)         += pohmelfs/
-obj-$(CONFIG_STLC45XX)         += stlc45xx/
 obj-$(CONFIG_B3DFG)            += b3dfg/
 obj-$(CONFIG_IDE_PHISON)       += phison/
 obj-$(CONFIG_PLAN9AUTH)                += p9auth/
@@ -46,4 +44,3 @@ obj-$(CONFIG_VME_BUS)         += vme/
 obj-$(CONFIG_RAR_REGISTER)     += rar/
 obj-$(CONFIG_DX_SEP)           += sep/
 obj-$(CONFIG_IIO)              += iio/
-obj-$(CONFIG_COWLOOP)          += cowloop/
diff --git a/drivers/staging/agnx/Kconfig b/drivers/staging/agnx/Kconfig
deleted file mode 100644 (file)
index 7f43549..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-config AGNX
-       tristate "Wireless Airgo AGNX support"
-       depends on WLAN_80211 && MAC80211
-       ---help---
-         This is an experimental driver for Airgo AGNX00 wireless chip.
diff --git a/drivers/staging/agnx/Makefile b/drivers/staging/agnx/Makefile
deleted file mode 100644 (file)
index 1216564..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-obj-$(CONFIG_AGNX)     += agnx.o
-
-agnx-objs :=   rf.o    \
-               pci.o   \
-               xmit.o  \
-               table.o \
-               sta.o   \
-               phy.o
diff --git a/drivers/staging/agnx/TODO b/drivers/staging/agnx/TODO
deleted file mode 100644 (file)
index 89bec74..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-2008 7/18
-
-The RX has can't receive OFDM packet correctly,
-Guess it need be do RX calibrate.
-
-
-before 2008 3/1
-
-1: The RX get too much "CRC failed" pakets, it make the card work very unstable,
-2: After running a while, the card will get infinity "RX Frame" and "Error"
-interrupt, not know the root reason so far, try to fix it
-3: Using two tx queue txd and txm but not only txm.
-4: Set the hdr correctly.
-5: Try to do recalibrate correvtly
-6: To support G mode in future
-7: Fix the mac address can't be readed and set correctly in BE machine.
-8: Fix include and exclude FCS in promisous mode and manage mode
-9: Using sta_notify to notice sta change
-10: Turn on frame reception at the end of start
-11: Guess the card support HW_MULTICAST_FILTER
-12: The tx process should be implment atomic?
-13: Using mac80211 function to control the TX&RX LED.
diff --git a/drivers/staging/agnx/agnx.h b/drivers/staging/agnx/agnx.h
deleted file mode 100644 (file)
index 3963d25..0000000
+++ /dev/null
@@ -1,156 +0,0 @@
-#ifndef AGNX_H_
-#define AGNX_H_
-
-#include <linux/io.h>
-
-#include "xmit.h"
-
-#define PFX                            KBUILD_MODNAME ": "
-
-static inline u32 agnx_read32(void __iomem *mem_region, u32 offset)
-{
-       return ioread32(mem_region + offset);
-}
-
-static inline void agnx_write32(void __iomem *mem_region, u32 offset, u32 val)
-{
-       iowrite32(val, mem_region + offset);
-}
-
-/* static const struct ieee80211_rate agnx_rates_80211b[] = { */
-/*     { .rate = 10, */
-/*       .val = 0xa, */
-/*       .flags = IEEE80211_RATE_CCK }, */
-/*     { .rate = 20, */
-/*       .val = 0x14, */
-/*       .hw_value = -0x14, */
-/*       .flags = IEEE80211_RATE_CCK_2 }, */
-/*     { .rate = 55, */
-/*       .val = 0x37, */
-/*       .val2 = -0x37, */
-/*       .flags = IEEE80211_RATE_CCK_2 }, */
-/*     { .rate = 110, */
-/*       .val = 0x6e, */
-/*       .val2 = -0x6e, */
-/*       .flags = IEEE80211_RATE_CCK_2 } */
-/* }; */
-
-
-static const struct ieee80211_rate agnx_rates_80211g[] = {
-/*     { .bitrate = 10, .hw_value = 1, .flags = IEEE80211_RATE_SHORT_PREAMBLE }, */
-/*     { .bitrate = 20, .hw_value = 2, .flags = IEEE80211_RATE_SHORT_PREAMBLE }, */
-/*     { .bitrate = 55, .hw_value = 3, .flags = IEEE80211_RATE_SHORT_PREAMBLE }, */
-/*     { .bitrate = 110, .hw_value = 4, .flags = IEEE80211_RATE_SHORT_PREAMBLE }, */
-       { .bitrate = 10, .hw_value = 1, },
-       { .bitrate = 20, .hw_value = 2, },
-       { .bitrate = 55, .hw_value = 3, },
-       { .bitrate = 110, .hw_value = 4,},
-
-       { .bitrate = 60, .hw_value = 0xB, },
-       { .bitrate = 90, .hw_value = 0xF, },
-       { .bitrate = 120, .hw_value = 0xA },
-       { .bitrate = 180, .hw_value = 0xE, },
-/*     { .bitrate = 240, .hw_value = 0xd, }, */
-       { .bitrate = 360, .hw_value = 0xD, },
-       { .bitrate = 480, .hw_value = 0x8, },
-       { .bitrate = 540, .hw_value = 0xC, },
-};
-
-static const struct ieee80211_channel agnx_channels[] = {
-       { .center_freq = 2412, .hw_value = 1, },
-       { .center_freq = 2417, .hw_value = 2, },
-       { .center_freq = 2422, .hw_value = 3, },
-       { .center_freq = 2427, .hw_value = 4, },
-       { .center_freq = 2432, .hw_value = 5, },
-       { .center_freq = 2437, .hw_value = 6, },
-       { .center_freq = 2442, .hw_value = 7, },
-       { .center_freq = 2447, .hw_value = 8, },
-       { .center_freq = 2452, .hw_value = 9, },
-       { .center_freq = 2457, .hw_value = 10, },
-       { .center_freq = 2462, .hw_value = 11, },
-       { .center_freq = 2467, .hw_value = 12, },
-       { .center_freq = 2472, .hw_value = 13, },
-       { .center_freq = 2484, .hw_value = 14, },
-};
-
-#define NUM_DRIVE_MODES        2
-/* Agnx operate mode */
-enum {
-       AGNX_MODE_80211A,
-       AGNX_MODE_80211A_OOB,
-       AGNX_MODE_80211A_MIMO,
-       AGNX_MODE_80211B_SHORT,
-       AGNX_MODE_80211B_LONG,
-       AGNX_MODE_80211G,
-       AGNX_MODE_80211G_OOB,
-       AGNX_MODE_80211G_MIMO,
-};
-
-enum {
-       AGNX_UNINIT,
-       AGNX_START,
-       AGNX_STOP,
-};
-
-struct agnx_priv {
-       struct pci_dev *pdev;
-       struct ieee80211_hw *hw;
-
-       spinlock_t lock;
-       struct mutex mutex;
-       unsigned int init_status;
-
-       void __iomem *ctl;      /* pointer to base ram address */
-       void __iomem *data;     /* pointer to mem region #2 */
-
-       struct agnx_ring rx;
-       struct agnx_ring txm;
-       struct agnx_ring txd;
-
-       /* Need volatile? */
-       u32 irq_status;
-
-       struct delayed_work periodic_work; /* Periodic tasks like recalibrate */
-       struct ieee80211_low_level_stats stats;
-
-       /* unsigned int phymode; */
-       int mode;
-       int channel;
-       u8 bssid[ETH_ALEN];
-
-       u8 mac_addr[ETH_ALEN];
-       u8 revid;
-
-       struct ieee80211_supported_band band;
-};
-
-
-#define AGNX_CHAINS_MAX        6
-#define AGNX_PERIODIC_DELAY 60000 /* unit: ms */
-#define LOCAL_STAID    0       /* the station entry for the card itself */
-#define BSSID_STAID    1       /* the station entry for the bsssid AP */
-#define        spi_delay()     udelay(40)
-#define eeprom_delay() udelay(40)
-#define        routing_table_delay()   udelay(50)
-
-/* PDU pool MEM region #2 */
-#define AGNX_PDUPOOL           0x40000 /* PDU pool */
-#define AGNX_PDUPOOL_SIZE      0x8000  /* PDU pool size*/
-#define AGNX_PDU_TX_WQ         0x41000 /* PDU list TX workqueue */
-#define AGNX_PDU_FREE          0x41800 /* Free Pool */
-#define PDU_SIZE               0x80    /* Free Pool node size */
-#define PDU_FREE_CNT           0xd0 /* Free pool node count */
-
-
-/* RF stuffs */
-extern void rf_chips_init(struct agnx_priv *priv);
-extern void spi_rc_write(void __iomem *mem_region, u32 chip_ids, u32 sw);
-extern void calibrate_oscillator(struct agnx_priv *priv);
-extern void do_calibration(struct agnx_priv *priv);
-extern void antenna_calibrate(struct agnx_priv *priv);
-extern void __antenna_calibrate(struct agnx_priv *priv);
-extern void print_offsets(struct agnx_priv *priv);
-extern int agnx_set_channel(struct agnx_priv *priv, unsigned int channel);
-
-
-#endif /* AGNX_H_ */
diff --git a/drivers/staging/agnx/debug.h b/drivers/staging/agnx/debug.h
deleted file mode 100644 (file)
index 7947f32..0000000
+++ /dev/null
@@ -1,416 +0,0 @@
-#ifndef AGNX_DEBUG_H_
-#define AGNX_DEBUG_H_
-
-#include "agnx.h"
-#include "phy.h"
-#include "sta.h"
-#include "xmit.h"
-
-#define AGNX_TRACE              printk(KERN_ERR PFX "function:%s line:%d\n", __func__, __LINE__)
-
-#define PRINTK_LE16(prefix, var)       printk(KERN_DEBUG PFX #prefix ": " #var " 0x%.4x\n", le16_to_cpu(var))
-#define PRINTK_LE32(prefix, var)       printk(KERN_DEBUG PFX #prefix ": " #var " 0x%.8x\n", le32_to_cpu(var))
-#define PRINTK_U8(prefix, var)                 printk(KERN_DEBUG PFX #prefix ": " #var " 0x%.2x\n", var)
-#define PRINTK_BE16(prefix, var)       printk(KERN_DEBUG PFX #prefix ": " #var " 0x%.4x\n", be16_to_cpu(var))
-#define PRINTK_BE32(prefix, var)       printk(KERN_DEBUG PFX #prefix ": " #var " 0x%.8x\n", be32_to_cpu(var))
-#define PRINTK_BITS(prefix, field)     printk(KERN_DEBUG PFX #prefix ": " #field ": 0x%x\n", (reg & field) >> field##_SHIFT)
-
-static inline void agnx_bug(char *reason)
-{
-       printk(KERN_ERR PFX "%s\n", reason);
-       BUG();
-}
-
-static inline void agnx_print_desc(struct agnx_desc *desc)
-{
-       u32 reg = be32_to_cpu(desc->frag);
-
-       PRINTK_BITS(DESC, PACKET_LEN);
-
-       if (reg & FIRST_FRAG) {
-               PRINTK_BITS(DESC, FIRST_PACKET_MASK);
-               PRINTK_BITS(DESC, FIRST_RESERV2);
-               PRINTK_BITS(DESC, FIRST_TKIP_ERROR);
-               PRINTK_BITS(DESC, FIRST_TKIP_PACKET);
-               PRINTK_BITS(DESC, FIRST_RESERV1);
-               PRINTK_BITS(DESC, FIRST_FRAG_LEN);
-       } else {
-               PRINTK_BITS(DESC, SUB_RESERV2);
-               PRINTK_BITS(DESC, SUB_TKIP_ERROR);
-               PRINTK_BITS(DESC, SUB_TKIP_PACKET);
-               PRINTK_BITS(DESC, SUB_RESERV1);
-               PRINTK_BITS(DESC, SUB_FRAG_LEN);
-       }
-
-       PRINTK_BITS(DESC, FIRST_FRAG);
-       PRINTK_BITS(DESC, LAST_FRAG);
-       PRINTK_BITS(DESC, OWNER);
-}
-
-
-static inline void dump_ieee80211b_phy_hdr(__be32 _11b0, __be32 _11b1)
-{
-
-}
-
-static inline void agnx_print_hdr(struct agnx_hdr *hdr)
-{
-       u32 reg;
-       int i;
-
-       reg = be32_to_cpu(hdr->reg0);
-       PRINTK_BITS(HDR, RTS);
-       PRINTK_BITS(HDR, MULTICAST);
-       PRINTK_BITS(HDR, ACK);
-       PRINTK_BITS(HDR, TM);
-       PRINTK_BITS(HDR, RELAY);
-       PRINTK_BITS(HDR, REVISED_FCS);
-       PRINTK_BITS(HDR, NEXT_BUFFER_ADDR);
-
-       reg = be32_to_cpu(hdr->reg1);
-       PRINTK_BITS(HDR, MAC_HDR_LEN);
-       PRINTK_BITS(HDR, DURATION_OVERIDE);
-       PRINTK_BITS(HDR, PHY_HDR_OVERIDE);
-       PRINTK_BITS(HDR, CRC_FAIL);
-       PRINTK_BITS(HDR, SEQUENCE_NUMBER);
-       PRINTK_BITS(HDR, BUFF_HEAD_ADDR);
-
-       reg = be32_to_cpu(hdr->reg2);
-       PRINTK_BITS(HDR, PDU_COUNT);
-       PRINTK_BITS(HDR, WEP_KEY);
-       PRINTK_BITS(HDR, USES_WEP_KEY);
-       PRINTK_BITS(HDR, KEEP_ALIVE);
-       PRINTK_BITS(HDR, BUFF_TAIL_ADDR);
-
-       reg = be32_to_cpu(hdr->reg3);
-       PRINTK_BITS(HDR, CTS_11G);
-       PRINTK_BITS(HDR, RTS_11G);
-       PRINTK_BITS(HDR, FRAG_SIZE);
-       PRINTK_BITS(HDR, PAYLOAD_LEN);
-       PRINTK_BITS(HDR, FRAG_NUM);
-
-       reg = be32_to_cpu(hdr->reg4);
-       PRINTK_BITS(HDR, RELAY_STAID);
-       PRINTK_BITS(HDR, STATION_ID);
-       PRINTK_BITS(HDR, WORKQUEUE_ID);
-
-       reg = be32_to_cpu(hdr->reg5);
-       /* printf the route flag */
-       PRINTK_BITS(HDR, ROUTE_HOST);
-       PRINTK_BITS(HDR, ROUTE_CARD_CPU);
-       PRINTK_BITS(HDR, ROUTE_ENCRYPTION);
-       PRINTK_BITS(HDR, ROUTE_TX);
-       PRINTK_BITS(HDR, ROUTE_RX1);
-       PRINTK_BITS(HDR, ROUTE_RX2);
-       PRINTK_BITS(HDR, ROUTE_COMPRESSION);
-
-       PRINTK_BE32(HDR, hdr->_11g0);
-       PRINTK_BE32(HDR, hdr->_11g1);
-       PRINTK_BE32(HDR, hdr->_11b0);
-       PRINTK_BE32(HDR, hdr->_11b1);
-
-       dump_ieee80211b_phy_hdr(hdr->_11b0, hdr->_11b1);
-
-       /* Fixme */
-       for (i = 0; i < ARRAY_SIZE(hdr->mac_hdr); i++) {
-               if (i == 0)
-                       printk(KERN_DEBUG PFX "IEEE80211 HDR: ");
-               printk("%.2x ", hdr->mac_hdr[i]);
-               if (i + 1 == ARRAY_SIZE(hdr->mac_hdr))
-                       printk("\n");
-       }
-
-       PRINTK_BE16(HDR, hdr->rts_duration);
-       PRINTK_BE16(HDR, hdr->last_duration);
-       PRINTK_BE16(HDR, hdr->sec_last_duration);
-       PRINTK_BE16(HDR, hdr->other_duration);
-       PRINTK_BE16(HDR, hdr->tx_other_duration);
-       PRINTK_BE16(HDR, hdr->last_11g_len);
-       PRINTK_BE16(HDR, hdr->other_11g_len);
-       PRINTK_BE16(HDR, hdr->last_11b_len);
-       PRINTK_BE16(HDR, hdr->other_11b_len);
-
-       /* FIXME */
-       reg = be16_to_cpu(hdr->reg6);
-       PRINTK_BITS(HDR, MBF);
-       PRINTK_BITS(HDR, RSVD4);
-
-       PRINTK_BE16(HDR, hdr->rx_frag_stat);
-
-       PRINTK_BE32(HDR, hdr->time_stamp);
-       PRINTK_BE32(HDR, hdr->phy_stats_hi);
-       PRINTK_BE32(HDR, hdr->phy_stats_lo);
-       PRINTK_BE32(HDR, hdr->mic_key0);
-       PRINTK_BE32(HDR, hdr->mic_key1);
-} /* agnx_print_hdr */
-
-
-static inline void agnx_print_rx_hdr(struct agnx_hdr *hdr)
-{
-       agnx_print_hdr(hdr);
-
-       PRINTK_BE16(HDR, hdr->rx.rx_packet_duration);
-       PRINTK_BE16(HDR, hdr->rx.replay_cnt);
-
-       PRINTK_U8(HDR, hdr->rx_channel);
-}
-
-static inline void agnx_print_tx_hdr(struct agnx_hdr *hdr)
-{
-       agnx_print_hdr(hdr);
-
-       PRINTK_U8(HDR, hdr->tx.long_retry_limit);
-       PRINTK_U8(HDR, hdr->tx.short_retry_limit);
-       PRINTK_U8(HDR, hdr->tx.long_retry_cnt);
-       PRINTK_U8(HDR, hdr->tx.short_retry_cnt);
-
-       PRINTK_U8(HDR, hdr->rx_channel);
-}
-
-static inline void
-agnx_print_sta_power(struct agnx_priv *priv, unsigned int sta_idx)
-{
-       struct agnx_sta_power power;
-       u32 reg;
-
-       get_sta_power(priv, &power, sta_idx);
-
-       reg = le32_to_cpu(power.reg);
-       PRINTK_BITS(STA_POWER, SIGNAL);
-       PRINTK_BITS(STA_POWER, RATE);
-       PRINTK_BITS(STA_POWER, TIFS);
-       PRINTK_BITS(STA_POWER, EDCF);
-       PRINTK_BITS(STA_POWER, CHANNEL_BOND);
-       PRINTK_BITS(STA_POWER, PHY_MODE);
-       PRINTK_BITS(STA_POWER, POWER_LEVEL);
-       PRINTK_BITS(STA_POWER, NUM_TRANSMITTERS);
-}
-
-static inline void
-agnx_print_sta_tx_wq(struct agnx_priv *priv, unsigned int sta_idx, unsigned int wq_idx)
-{
-       struct agnx_sta_tx_wq tx_wq;
-       u32 reg;
-
-       get_sta_tx_wq(priv, &tx_wq, sta_idx, wq_idx);
-
-       reg = le32_to_cpu(tx_wq.reg0);
-       PRINTK_BITS(STA_TX_WQ, TAIL_POINTER);
-       PRINTK_BITS(STA_TX_WQ, HEAD_POINTER_LOW);
-
-       reg = le32_to_cpu(tx_wq.reg3);
-       PRINTK_BITS(STA_TX_WQ, HEAD_POINTER_HIGH);
-       PRINTK_BITS(STA_TX_WQ, ACK_POINTER_LOW);
-
-       reg = le32_to_cpu(tx_wq.reg1);
-       PRINTK_BITS(STA_TX_WQ, ACK_POINTER_HIGH);
-       PRINTK_BITS(STA_TX_WQ, HEAD_TIMOUT_TAIL_PACK_CNT);
-       PRINTK_BITS(STA_TX_WQ, ACK_TIMOUT_TAIL_PACK_CNT);
-
-       reg = le32_to_cpu(tx_wq.reg2);
-       PRINTK_BITS(STA_TX_WQ, HEAD_TIMOUT_WIN_LIM_BYTE_CNT);
-       PRINTK_BITS(STA_TX_WQ, HEAD_TIMOUT_WIN_LIM_FRAG_CNT);
-       PRINTK_BITS(STA_TX_WQ, WORK_QUEUE_ACK_TYPE);
-       PRINTK_BITS(STA_TX_WQ, WORK_QUEUE_VALID);
-}
-
-static inline void agnx_print_sta_traffic(struct agnx_sta_traffic *traffic)
-{
-       u32 reg;
-
-       reg = le32_to_cpu(traffic->reg0);
-       PRINTK_BITS(STA_TRAFFIC, ACK_TIMOUT_CNT);
-       PRINTK_BITS(STA_TRAFFIC, TRAFFIC_ACK_TYPE);
-       PRINTK_BITS(STA_TRAFFIC, NEW_PACKET);
-       PRINTK_BITS(STA_TRAFFIC, TRAFFIC_VALID);
-       PRINTK_BITS(STA_TRAFFIC, RX_HDR_DESC_POINTER);
-
-       reg = le32_to_cpu(traffic->reg1);
-       PRINTK_BITS(STA_TRAFFIC, RX_PACKET_TIMESTAMP);
-       PRINTK_BITS(STA_TRAFFIC, TRAFFIC_RESERVED);
-       PRINTK_BITS(STA_TRAFFIC, SV);
-       PRINTK_BITS(STA_TRAFFIC, RX_SEQUENCE_NUM);
-
-       PRINTK_LE32(STA_TRAFFIC, traffic->tx_replay_cnt_low);
-
-       PRINTK_LE16(STA_TRAFFIC, traffic->tx_replay_cnt_high);
-       PRINTK_LE16(STA_TRAFFIC, traffic->rx_replay_cnt_high);
-
-       PRINTK_LE32(STA_TRAFFIC, traffic->rx_replay_cnt_low);
-}
-
-static inline void agnx_print_sta(struct agnx_priv *priv, unsigned int sta_idx)
-{
-       struct agnx_sta station;
-       struct agnx_sta *sta = &station;
-       u32 reg;
-       unsigned int i;
-
-       get_sta(priv, sta, sta_idx);
-
-       for (i = 0; i < 4; i++)
-               PRINTK_LE32(STA, sta->tx_session_keys[i]);
-       for (i = 0; i < 4; i++)
-               PRINTK_LE32(STA, sta->rx_session_keys[i]);
-
-       reg = le32_to_cpu(sta->reg);
-       PRINTK_BITS(STA, ID_1);
-       PRINTK_BITS(STA, ID_0);
-       PRINTK_BITS(STA, ENABLE_CONCATENATION);
-       PRINTK_BITS(STA, ENABLE_DECOMPRESSION);
-       PRINTK_BITS(STA, STA_RESERVED);
-       PRINTK_BITS(STA, EAP);
-       PRINTK_BITS(STA, ED_NULL);
-       PRINTK_BITS(STA, ENCRYPTION_POLICY);
-       PRINTK_BITS(STA, DEFINED_KEY_ID);
-       PRINTK_BITS(STA, FIXED_KEY);
-       PRINTK_BITS(STA, KEY_VALID);
-       PRINTK_BITS(STA, STATION_VALID);
-
-       PRINTK_LE32(STA, sta->tx_aes_blks_unicast);
-       PRINTK_LE32(STA, sta->rx_aes_blks_unicast);
-
-       PRINTK_LE16(STA, sta->aes_format_err_unicast_cnt);
-       PRINTK_LE16(STA, sta->aes_replay_unicast);
-
-       PRINTK_LE16(STA, sta->aes_decrypt_err_unicast);
-       PRINTK_LE16(STA, sta->aes_decrypt_err_default);
-
-       PRINTK_LE16(STA, sta->single_retry_packets);
-       PRINTK_LE16(STA, sta->failed_tx_packets);
-
-       PRINTK_LE16(STA, sta->muti_retry_packets);
-       PRINTK_LE16(STA, sta->ack_timeouts);
-
-       PRINTK_LE16(STA, sta->frag_tx_cnt);
-       PRINTK_LE16(STA, sta->rts_brq_sent);
-
-       PRINTK_LE16(STA, sta->tx_packets);
-       PRINTK_LE16(STA, sta->cts_back_timeout);
-
-       PRINTK_LE32(STA, sta->phy_stats_high);
-       PRINTK_LE32(STA, sta->phy_stats_low);
-
-       /* for (i = 0; i < 8; i++) */
-       agnx_print_sta_traffic(sta->traffic + 0);
-
-       PRINTK_LE16(STA, sta->traffic_class0_frag_success);
-       PRINTK_LE16(STA, sta->traffic_class1_frag_success);
-       PRINTK_LE16(STA, sta->traffic_class2_frag_success);
-       PRINTK_LE16(STA, sta->traffic_class3_frag_success);
-       PRINTK_LE16(STA, sta->traffic_class4_frag_success);
-       PRINTK_LE16(STA, sta->traffic_class5_frag_success);
-       PRINTK_LE16(STA, sta->traffic_class6_frag_success);
-       PRINTK_LE16(STA, sta->traffic_class7_frag_success);
-
-       PRINTK_LE16(STA, sta->num_frag_non_prime_rates);
-       PRINTK_LE16(STA, sta->ack_timeout_non_prime_rates);
-}
-
-
-static inline void dump_ieee80211_hdr(struct ieee80211_hdr *hdr, char *tag)
-{
-       u16 fctl;
-       int hdrlen;
-
-       fctl = le16_to_cpu(hdr->frame_control);
-       switch (fctl & IEEE80211_FCTL_FTYPE) {
-       case IEEE80211_FTYPE_DATA:
-               printk(PFX "%s DATA ", tag);
-               break;
-       case IEEE80211_FTYPE_CTL:
-               printk(PFX "%s CTL ", tag);
-               break;
-       case IEEE80211_FTYPE_MGMT:
-               printk(PFX "%s MGMT ", tag);
-               switch (fctl & IEEE80211_FCTL_STYPE) {
-               case IEEE80211_STYPE_ASSOC_REQ:
-                       printk("SubType: ASSOC_REQ ");
-                       break;
-               case IEEE80211_STYPE_ASSOC_RESP:
-                       printk("SubType: ASSOC_RESP ");
-                       break;
-               case IEEE80211_STYPE_REASSOC_REQ:
-                       printk("SubType: REASSOC_REQ ");
-                       break;
-               case IEEE80211_STYPE_REASSOC_RESP:
-                       printk("SubType: REASSOC_RESP ");
-                       break;
-               case IEEE80211_STYPE_PROBE_REQ:
-                       printk("SubType: PROBE_REQ ");
-                       break;
-               case IEEE80211_STYPE_PROBE_RESP:
-                       printk("SubType: PROBE_RESP ");
-                       break;
-               case IEEE80211_STYPE_BEACON:
-                       printk("SubType: BEACON ");
-                       break;
-               case IEEE80211_STYPE_ATIM:
-                       printk("SubType: ATIM ");
-                       break;
-               case IEEE80211_STYPE_DISASSOC:
-                       printk("SubType: DISASSOC ");
-                       break;
-               case IEEE80211_STYPE_AUTH:
-                       printk("SubType: AUTH ");
-                       break;
-               case IEEE80211_STYPE_DEAUTH:
-                       printk("SubType: DEAUTH ");
-                       break;
-               case IEEE80211_STYPE_ACTION:
-                       printk("SubType: ACTION ");
-                       break;
-               default:
-                       printk("SubType: Unknow\n");
-               }
-               break;
-       default:
-               printk(PFX "%s Packet type: Unknow\n", tag);
-       }
-
-       hdrlen = ieee80211_hdrlen(fctl);
-
-       if (hdrlen >= 4)
-               printk("FC=0x%04x DUR=0x%04x",
-                      fctl, le16_to_cpu(hdr->duration_id));
-       if (hdrlen >= 10)
-               printk(" A1=%pM", hdr->addr1);
-       if (hdrlen >= 16)
-               printk(" A2=%pM", hdr->addr2);
-       if (hdrlen >= 24)
-               printk(" A3=%pM", hdr->addr3);
-       if (hdrlen >= 30)
-               printk(" A4=%pM", hdr->addr4);
-       printk("\n");
-}
-
-static inline void dump_txm_registers(struct agnx_priv *priv)
-{
-       void __iomem *ctl = priv->ctl;
-       int i;
-       for (i = 0; i <= 0x1e8; i += 4)
-               printk(KERN_DEBUG PFX "TXM: %x---> 0x%.8x\n", i, ioread32(ctl + i));
-}
-static inline void dump_rxm_registers(struct agnx_priv *priv)
-{
-       void __iomem *ctl = priv->ctl;
-       int i;
-       for (i = 0; i <= 0x108; i += 4)
-               printk(KERN_DEBUG PFX "RXM: %x---> 0x%.8x\n", i, ioread32(ctl + 0x2000 + i));
-}
-static inline void dump_bm_registers(struct agnx_priv *priv)
-{
-       void __iomem *ctl = priv->ctl;
-       int i;
-       for (i = 0; i <= 0x90; i += 4)
-               printk(KERN_DEBUG PFX "BM: %x---> 0x%.8x\n", i, ioread32(ctl + 0x2c00 + i));
-}
-static inline void dump_cir_registers(struct agnx_priv *priv)
-{
-       void __iomem *ctl = priv->ctl;
-       int i;
-       for (i = 0; i <= 0xb8; i += 4)
-               printk(KERN_DEBUG PFX "CIR: %x---> 0x%.8x\n", i, ioread32(ctl + 0x3000 + i));
-}
-
-#endif /* AGNX_DEBUG_H_ */
diff --git a/drivers/staging/agnx/pci.c b/drivers/staging/agnx/pci.c
deleted file mode 100644 (file)
index 32b5489..0000000
+++ /dev/null
@@ -1,635 +0,0 @@
-/**
- * Airgo MIMO wireless driver
- *
- * Copyright (c) 2007 Li YanBo <dreamfly281@gmail.com>
-
- * Thanks for Jeff Williams <angelbane@gmail.com> do reverse engineer
- * works and published the SPECS at http://airgo.wdwconsulting.net/mymoin
-
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include <linux/init.h>
-#include <linux/etherdevice.h>
-#include <linux/pci.h>
-#include <linux/delay.h>
-
-#include "agnx.h"
-#include "debug.h"
-#include "xmit.h"
-#include "phy.h"
-
-MODULE_AUTHOR("Li YanBo <dreamfly281@gmail.com>");
-MODULE_DESCRIPTION("Airgo MIMO PCI wireless driver");
-MODULE_LICENSE("GPL");
-
-static struct pci_device_id agnx_pci_id_tbl[] __devinitdata = {
-       { PCI_DEVICE(0x17cb, 0x0001) }, /* Beklin F5d8010, Netgear WGM511 etc */
-       { PCI_DEVICE(0x17cb, 0x0002) }, /* Netgear Wpnt511 */
-       { 0 }
-};
-
-MODULE_DEVICE_TABLE(pci, agnx_pci_id_tbl);
-
-
-static inline void agnx_interrupt_ack(struct agnx_priv *priv, u32 *reason)
-{
-       void __iomem *ctl = priv->ctl;
-       u32 reg;
-
-       if (*reason & AGNX_STAT_RX) {
-               /* Mark complete RX */
-               reg = ioread32(ctl + AGNX_CIR_RXCTL);
-               reg |= 0x4;
-               iowrite32(reg, ctl + AGNX_CIR_RXCTL);
-               /* disable Rx interrupt */
-       }
-       if (*reason & AGNX_STAT_TX) {
-               reg = ioread32(ctl + AGNX_CIR_TXDCTL);
-               if (reg & 0x4) {
-                       iowrite32(reg, ctl + AGNX_CIR_TXDCTL);
-                       *reason |= AGNX_STAT_TXD;
-               }
-               reg = ioread32(ctl + AGNX_CIR_TXMCTL);
-               if (reg & 0x4) {
-                       iowrite32(reg, ctl + AGNX_CIR_TXMCTL);
-                       *reason |= AGNX_STAT_TXM;
-               }
-       }
-#if 0
-       if (*reason & AGNX_STAT_X) {
-               reg = ioread32(ctl + AGNX_INT_STAT);
-               iowrite32(reg, ctl + AGNX_INT_STAT);
-               /* FIXME reinit interrupt mask */
-               reg = 0xc390bf9 & ~IRQ_TX_BEACON;
-               reg &= ~IRQ_TX_DISABLE;
-               iowrite32(reg, ctl + AGNX_INT_MASK);
-               iowrite32(0x800, ctl + AGNX_CIR_BLKCTL);
-       }
-#endif
-} /* agnx_interrupt_ack */
-
-static irqreturn_t agnx_interrupt_handler(int irq, void *dev_id)
-{
-       struct ieee80211_hw *dev = dev_id;
-       struct agnx_priv *priv = dev->priv;
-       void __iomem *ctl = priv->ctl;
-       irqreturn_t ret = IRQ_NONE;
-       u32 irq_reason;
-
-       spin_lock(&priv->lock);
-
-/*     printk(KERN_ERR PFX "Get a interrupt %s\n", __func__); */
-
-       if (priv->init_status != AGNX_START)
-               goto out;
-
-       /* FiXME  Here has no lock, Is this will lead to race? */
-       irq_reason = ioread32(ctl + AGNX_CIR_BLKCTL);
-       if (!(irq_reason & 0x7))
-               goto out;
-
-       ret = IRQ_HANDLED;
-       priv->irq_status = ioread32(ctl + AGNX_INT_STAT);
-
-/*     printk(PFX "Interrupt reason is 0x%x\n", irq_reason); */
-       /* Make sure the txm and txd flags don't conflict with other unknown
-          interrupt flag, maybe is not necessary */
-       irq_reason &= 0xF;
-
-       disable_rx_interrupt(priv);
-       /* TODO Make sure the card finished initialized */
-       agnx_interrupt_ack(priv, &irq_reason);
-
-       if (irq_reason & AGNX_STAT_RX)
-               handle_rx_irq(priv);
-       if (irq_reason & AGNX_STAT_TXD)
-               handle_txd_irq(priv);
-       if (irq_reason & AGNX_STAT_TXM)
-               handle_txm_irq(priv);
-       if (irq_reason & AGNX_STAT_X)
-               handle_other_irq(priv);
-
-       enable_rx_interrupt(priv);
-out:
-       spin_unlock(&priv->lock);
-       return ret;
-} /* agnx_interrupt_handler */
-
-
-/* FIXME */
-static int agnx_tx(struct ieee80211_hw *dev, struct sk_buff *skb)
-{
-       AGNX_TRACE;
-       return _agnx_tx(dev->priv, skb);
-} /* agnx_tx */
-
-
-static int agnx_get_mac_address(struct agnx_priv *priv)
-{
-       void __iomem *ctl = priv->ctl;
-       u32 reg;
-       AGNX_TRACE;
-
-       /* Attention! directly read the MAC or other date from EEPROM will
-        lead to cardbus(WGM511) lock up when write to PM PLL register */
-       reg = agnx_read32(ctl, 0x3544);
-       udelay(40);
-       reg = agnx_read32(ctl, 0x354c);
-       udelay(50);
-       /* Get the mac address */
-       reg = agnx_read32(ctl, 0x3544);
-       udelay(40);
-
-       /* HACK */
-       reg = cpu_to_le32(reg);
-       priv->mac_addr[0] = ((u8 *)&reg)[2];
-       priv->mac_addr[1] = ((u8 *)&reg)[3];
-       reg = agnx_read32(ctl, 0x3548);
-       udelay(50);
-       *((u32 *)(priv->mac_addr + 2)) = cpu_to_le32(reg);
-
-       if (!is_valid_ether_addr(priv->mac_addr)) {
-               printk(KERN_WARNING PFX "read mac %pM\n", priv->mac_addr);
-               printk(KERN_WARNING PFX "Invalid hwaddr! Using random hwaddr\n");
-               random_ether_addr(priv->mac_addr);
-       }
-
-       return 0;
-} /* agnx_get_mac_address */
-
-static int agnx_alloc_rings(struct agnx_priv *priv)
-{
-       unsigned int len;
-       AGNX_TRACE;
-
-       /* Allocate RX/TXM/TXD rings info */
-       priv->rx.size = AGNX_RX_RING_SIZE;
-       priv->txm.size = AGNX_TXM_RING_SIZE;
-       priv->txd.size = AGNX_TXD_RING_SIZE;
-
-       len = priv->rx.size + priv->txm.size + priv->txd.size;
-
-/*     priv->rx.info = kzalloc(sizeof(struct agnx_info) * len, GFP_KERNEL); */
-       priv->rx.info = kzalloc(sizeof(struct agnx_info) * len, GFP_ATOMIC);
-       if (!priv->rx.info)
-               return -ENOMEM;
-       priv->txm.info = priv->rx.info + priv->rx.size;
-       priv->txd.info = priv->txm.info + priv->txm.size;
-
-       /* Allocate RX/TXM/TXD descriptors */
-       priv->rx.desc = pci_alloc_consistent(priv->pdev, sizeof(struct agnx_desc) * len,
-                                            &priv->rx.dma);
-       if (!priv->rx.desc) {
-               kfree(priv->rx.info);
-               return -ENOMEM;
-       }
-
-       priv->txm.desc = priv->rx.desc + priv->rx.size;
-       priv->txm.dma = priv->rx.dma + sizeof(struct agnx_desc) * priv->rx.size;
-       priv->txd.desc = priv->txm.desc + priv->txm.size;
-       priv->txd.dma = priv->txm.dma + sizeof(struct agnx_desc) * priv->txm.size;
-
-       return 0;
-} /* agnx_alloc_rings */
-
-static void rings_free(struct agnx_priv *priv)
-{
-       unsigned int len = priv->rx.size + priv->txm.size + priv->txd.size;
-       unsigned long flags;
-       AGNX_TRACE;
-
-       spin_lock_irqsave(&priv->lock, flags);
-       kfree(priv->rx.info);
-       pci_free_consistent(priv->pdev, sizeof(struct agnx_desc) * len,
-                           priv->rx.desc, priv->rx.dma);
-       spin_unlock_irqrestore(&priv->lock, flags);
-}
-
-#if 0
-static void agnx_periodic_work_handler(struct work_struct *work)
-{
-       struct agnx_priv *priv = container_of(work, struct agnx_priv, periodic_work.work);
-/*     unsigned long flags; */
-       unsigned long delay;
-
-       /* fixme: using mutex?? */
-/*     spin_lock_irqsave(&priv->lock, flags); */
-
-       /* TODO Recalibrate*/
-/*     calibrate_oscillator(priv); */
-/*     antenna_calibrate(priv); */
-/*     agnx_send_packet(priv, 997); */
-       /* FIXME */
-/*     if (debug == 3) */
-/*                 delay = msecs_to_jiffies(AGNX_PERIODIC_DELAY); */
-/*     else */
-       delay = msecs_to_jiffies(AGNX_PERIODIC_DELAY);
-/*     delay = round_jiffies(HZ * 15); */
-
-       queue_delayed_work(priv->hw->workqueue, &priv->periodic_work, delay);
-
-/*     spin_unlock_irqrestore(&priv->lock, flags); */
-}
-#endif
-
-static int agnx_start(struct ieee80211_hw *dev)
-{
-       struct agnx_priv *priv = dev->priv;
-       /* unsigned long delay; */
-       int err = 0;
-       AGNX_TRACE;
-
-       err = agnx_alloc_rings(priv);
-       if (err) {
-               printk(KERN_ERR PFX "Can't alloc RX/TXM/TXD rings\n");
-               goto out;
-       }
-       err = request_irq(priv->pdev->irq, &agnx_interrupt_handler,
-                         IRQF_SHARED, "agnx_pci", dev);
-       if (err) {
-               printk(KERN_ERR PFX "Failed to register IRQ handler\n");
-               rings_free(priv);
-               goto out;
-       }
-
-/*     mdelay(500); */
-
-       might_sleep();
-       agnx_hw_init(priv);
-
-/*     mdelay(500); */
-       might_sleep();
-
-       priv->init_status = AGNX_START;
-/*         INIT_DELAYED_WORK(&priv->periodic_work, agnx_periodic_work_handler); */
-/*     delay = msecs_to_jiffies(AGNX_PERIODIC_DELAY); */
-/*         queue_delayed_work(priv->hw->workqueue, &priv->periodic_work, delay); */
-out:
-       return err;
-} /* agnx_start */
-
-static void agnx_stop(struct ieee80211_hw *dev)
-{
-       struct agnx_priv *priv = dev->priv;
-       AGNX_TRACE;
-
-       priv->init_status = AGNX_STOP;
-       /* make sure hardware will not generate irq */
-       agnx_hw_reset(priv);
-       free_irq(priv->pdev->irq, dev);
-/*     flush_workqueue(priv->hw->workqueue); */
-/*     cancel_delayed_work_sync(&priv->periodic_work); */
-       unfill_rings(priv);
-       rings_free(priv);
-}
-
-static int agnx_config(struct ieee80211_hw *dev, u32 changed)
-{
-       struct agnx_priv *priv = dev->priv;
-       struct ieee80211_conf *conf = &dev->conf;
-       int channel = ieee80211_frequency_to_channel(conf->channel->center_freq);
-       AGNX_TRACE;
-
-       spin_lock(&priv->lock);
-       /* FIXME need priv lock? */
-       if (channel != priv->channel) {
-               priv->channel = channel;
-               agnx_set_channel(priv, priv->channel);
-       }
-
-       spin_unlock(&priv->lock);
-       return 0;
-}
-
-static void agnx_bss_info_changed(struct ieee80211_hw *dev,
-                                 struct ieee80211_vif *vif,
-                                 struct ieee80211_bss_conf *conf,
-                                 u32 changed)
-{
-       struct agnx_priv *priv = dev->priv;
-       void __iomem *ctl = priv->ctl;
-       AGNX_TRACE;
-
-       if (!(changed & BSS_CHANGED_BSSID))
-               return;
-
-       spin_lock(&priv->lock);
-
-       if (memcmp(conf->bssid, priv->bssid, ETH_ALEN)) {
-               agnx_set_bssid(priv, conf->bssid);
-               memcpy(priv->bssid, conf->bssid, ETH_ALEN);
-               hash_write(priv, conf->bssid, BSSID_STAID);
-               sta_init(priv, BSSID_STAID);
-               /* FIXME needed? */
-               sta_power_init(priv, BSSID_STAID);
-               agnx_write32(ctl, AGNX_BM_MTSM, 0xff & ~0x1);
-       }
-       spin_unlock(&priv->lock);
-} /* agnx_bss_info_changed */
-
-
-static void agnx_configure_filter(struct ieee80211_hw *dev,
-                                 unsigned int changed_flags,
-                                 unsigned int *total_flags,
-                                 int mc_count, struct dev_mc_list *mclist)
-{
-       unsigned int new_flags = 0;
-
-       *total_flags = new_flags;
-       /* TODO */
-}
-
-static int agnx_add_interface(struct ieee80211_hw *dev,
-                             struct ieee80211_if_init_conf *conf)
-{
-       struct agnx_priv *priv = dev->priv;
-       AGNX_TRACE;
-
-       spin_lock(&priv->lock);
-       /* FIXME */
-       if (priv->mode != NL80211_IFTYPE_MONITOR)
-               return -EOPNOTSUPP;
-
-       switch (conf->type) {
-       case NL80211_IFTYPE_STATION:
-               priv->mode = conf->type;
-               break;
-       default:
-               return -EOPNOTSUPP;
-       }
-
-       spin_unlock(&priv->lock);
-
-       return 0;
-}
-
-static void agnx_remove_interface(struct ieee80211_hw *dev,
-                                 struct ieee80211_if_init_conf *conf)
-{
-       struct agnx_priv *priv = dev->priv;
-       AGNX_TRACE;
-
-       /* TODO */
-       priv->mode = NL80211_IFTYPE_MONITOR;
-}
-
-static int agnx_get_stats(struct ieee80211_hw *dev,
-                         struct ieee80211_low_level_stats *stats)
-{
-       struct agnx_priv *priv = dev->priv;
-       AGNX_TRACE;
-       spin_lock(&priv->lock);
-       /* TODO !! */
-       memcpy(stats, &priv->stats, sizeof(*stats));
-       spin_unlock(&priv->lock);
-
-       return 0;
-}
-
-static u64 agnx_get_tsft(struct ieee80211_hw *dev)
-{
-       void __iomem *ctl = ((struct agnx_priv *)dev->priv)->ctl;
-       u32 tsftl;
-       u64 tsft;
-       AGNX_TRACE;
-
-       /* FIXME */
-       tsftl = ioread32(ctl + AGNX_TXM_TIMESTAMPLO);
-       tsft = ioread32(ctl + AGNX_TXM_TIMESTAMPHI);
-       tsft <<= 32;
-       tsft |= tsftl;
-
-       return tsft;
-}
-
-static int agnx_get_tx_stats(struct ieee80211_hw *dev,
-                            struct ieee80211_tx_queue_stats *stats)
-{
-       struct agnx_priv *priv = dev->priv;
-       AGNX_TRACE;
-
-       /* FIXME now we just using txd queue, but should using txm queue too */
-       stats[0].len = (priv->txd.idx - priv->txd.idx_sent) / 2;
-       stats[0].limit = priv->txd.size - 2;
-       stats[0].count = priv->txd.idx / 2;
-
-       return 0;
-}
-
-static struct ieee80211_ops agnx_ops = {
-       .tx                     = agnx_tx,
-       .start                  = agnx_start,
-       .stop                   = agnx_stop,
-       .add_interface          = agnx_add_interface,
-       .remove_interface       = agnx_remove_interface,
-       .config                 = agnx_config,
-       .bss_info_changed       = agnx_bss_info_changed,
-       .configure_filter       = agnx_configure_filter,
-       .get_stats              = agnx_get_stats,
-       .get_tx_stats           = agnx_get_tx_stats,
-       .get_tsf                = agnx_get_tsft
-};
-
-static void __devexit agnx_pci_remove(struct pci_dev *pdev)
-{
-       struct ieee80211_hw *dev = pci_get_drvdata(pdev);
-       struct agnx_priv *priv;
-       AGNX_TRACE;
-
-       if (!dev)
-               return;
-       priv = dev->priv;
-       ieee80211_unregister_hw(dev);
-       pci_iounmap(pdev, priv->ctl);
-       pci_iounmap(pdev, priv->data);
-       pci_release_regions(pdev);
-       pci_disable_device(pdev);
-
-       ieee80211_free_hw(dev);
-}
-
-static int __devinit agnx_pci_probe(struct pci_dev *pdev,
-                                   const struct pci_device_id *id)
-{
-       struct ieee80211_hw *dev;
-       struct agnx_priv *priv;
-       int err;
-
-       err = pci_enable_device(pdev);
-       if (err) {
-               dev_err(&pdev->dev, "can't enable pci device\n");
-               return err;
-       }
-
-       err = pci_request_regions(pdev, "agnx-pci");
-       if (err) {
-               dev_err(&pdev->dev, "can't reserve PCI resources\n");
-               return err;
-       }
-
-       if (pci_set_dma_mask(pdev, DMA_BIT_MASK(32)) ||
-           pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32))) {
-               dev_err(&pdev->dev, "no suitable DMA available\n");
-               err = -EIO;
-               goto err_free_reg;
-       }
-
-       pci_set_master(pdev);
-
-       dev = ieee80211_alloc_hw(sizeof(*priv), &agnx_ops);
-       if (!dev) {
-               dev_err(&pdev->dev, "ieee80211 alloc failed\n");
-               err = -ENOMEM;
-               goto err_free_reg;
-       }
-       priv = dev->priv;
-       memset(priv, 0, sizeof(*priv));
-       priv->mode = NL80211_IFTYPE_MONITOR;
-       priv->pdev = pdev;
-       priv->hw = dev;
-       spin_lock_init(&priv->lock);
-       priv->init_status = AGNX_UNINIT;
-
-       priv->ctl = pci_iomap(pdev, 0, 0);
-/*     dev_dbg(&pdev->dev, "MEM1 mapped address is 0x%p\n", priv->ctl); */
-       if (!priv->ctl) {
-               dev_err(&pdev->dev, "can't map device memory\n");
-               err = -ENOMEM;
-               goto err_free_dev;
-       }
-       priv->data = pci_iomap(pdev, 1, 0);
-       if (!priv->data) {
-               dev_err(&pdev->dev, "can't map device memory\n");
-               err = -ENOMEM;
-               goto err_iounmap2;
-       }
-
-       pci_read_config_byte(pdev, PCI_REVISION_ID, &priv->revid);
-
-       priv->band.channels   = (struct ieee80211_channel *)agnx_channels;
-       priv->band.n_channels = ARRAY_SIZE(agnx_channels);
-       priv->band.bitrates   = (struct ieee80211_rate *)agnx_rates_80211g;
-       priv->band.n_bitrates = ARRAY_SIZE(agnx_rates_80211g);
-
-       /* Init ieee802.11 dev  */
-       SET_IEEE80211_DEV(dev, &pdev->dev);
-       pci_set_drvdata(pdev, dev);
-       dev->extra_tx_headroom = sizeof(struct agnx_hdr);
-
-       /* FIXME It only include FCS in promious mode but not manage mode */
-/*      dev->flags =  IEEE80211_HW_RX_INCLUDES_FCS; */
-       dev->channel_change_time = 5000;
-       dev->max_signal = 100;
-       /* FIXME */
-       dev->queues = 1;
-
-       agnx_get_mac_address(priv);
-
-       SET_IEEE80211_PERM_ADDR(dev, priv->mac_addr);
-
-/*     /\* FIXME *\/ */
-/*     for (i = 1; i < NUM_DRIVE_MODES; i++) { */
-/*             err = ieee80211_register_hwmode(dev, &priv->modes[i]); */
-/*             if (err) { */
-/*                     printk(KERN_ERR PFX "Can't register hwmode\n"); */
-/*                     goto  err_iounmap; */
-/*             } */
-/*     } */
-
-       priv->channel = 1;
-       dev->wiphy->bands[IEEE80211_BAND_2GHZ] = &priv->band;
-
-       err = ieee80211_register_hw(dev);
-       if (err) {
-               dev_err(&pdev->dev, "can't register hardware\n");
-               goto err_iounmap;
-       }
-
-       agnx_hw_reset(priv);
-
-       dev_info(&pdev->dev, "%s: hwaddr %pM, Rev 0x%02x\n",
-               wiphy_name(dev->wiphy),
-               dev->wiphy->perm_addr, priv->revid);
-       return 0;
-
- err_iounmap:
-       pci_iounmap(pdev, priv->data);
-
- err_iounmap2:
-       pci_iounmap(pdev, priv->ctl);
-
- err_free_dev:
-       pci_set_drvdata(pdev, NULL);
-       ieee80211_free_hw(dev);
-
- err_free_reg:
-       pci_release_regions(pdev);
-
-       pci_disable_device(pdev);
-       return err;
-} /* agnx_pci_probe*/
-
-#ifdef CONFIG_PM
-
-static int agnx_pci_suspend(struct pci_dev *pdev, pm_message_t state)
-{
-       struct ieee80211_hw *dev = pci_get_drvdata(pdev);
-       AGNX_TRACE;
-
-       ieee80211_stop_queues(dev);
-       agnx_stop(dev);
-
-       pci_save_state(pdev);
-       pci_set_power_state(pdev, pci_choose_state(pdev, state));
-       return 0;
-}
-
-static int agnx_pci_resume(struct pci_dev *pdev)
-{
-       struct ieee80211_hw *dev = pci_get_drvdata(pdev);
-       AGNX_TRACE;
-
-       pci_set_power_state(pdev, PCI_D0);
-       pci_restore_state(pdev);
-
-       agnx_start(dev);
-       ieee80211_wake_queues(dev);
-
-       return 0;
-}
-
-#else
-
-#define agnx_pci_suspend NULL
-#define agnx_pci_resume NULL
-
-#endif /* CONFIG_PM */
-
-
-static struct pci_driver agnx_pci_driver = {
-       .name           = "agnx-pci",
-       .id_table       = agnx_pci_id_tbl,
-       .probe          = agnx_pci_probe,
-       .remove         = __devexit_p(agnx_pci_remove),
-       .suspend        = agnx_pci_suspend,
-       .resume         = agnx_pci_resume,
-};
-
-static int __init agnx_pci_init(void)
-{
-       AGNX_TRACE;
-       return pci_register_driver(&agnx_pci_driver);
-}
-
-static void __exit agnx_pci_exit(void)
-{
-       AGNX_TRACE;
-       pci_unregister_driver(&agnx_pci_driver);
-}
-
-
-module_init(agnx_pci_init);
-module_exit(agnx_pci_exit);
diff --git a/drivers/staging/agnx/phy.c b/drivers/staging/agnx/phy.c
deleted file mode 100644 (file)
index ec1ca86..0000000
+++ /dev/null
@@ -1,960 +0,0 @@
-/**
- * Airgo MIMO wireless driver
- *
- * Copyright (c) 2007 Li YanBo <dreamfly281@gmail.com>
-
- * Thanks for Jeff Williams <angelbane@gmail.com> do reverse engineer
- * works and published the SPECS at http://airgo.wdwconsulting.net/mymoin
-
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include <linux/init.h>
-#include <linux/etherdevice.h>
-#include <linux/pci.h>
-#include <linux/delay.h>
-#include "agnx.h"
-#include "debug.h"
-#include "phy.h"
-#include "table.h"
-#include "sta.h"
-#include "xmit.h"
-
-u8 read_from_eeprom(struct agnx_priv *priv, u16 address)
-{
-       void __iomem *ctl = priv->ctl;
-       struct agnx_eeprom cmd;
-       u32 reg;
-
-       memset(&cmd, 0, sizeof(cmd));
-       cmd.cmd = EEPROM_CMD_READ << AGNX_EEPROM_COMMAND_SHIFT;
-       cmd.address = address;
-       /* Verify that the Status bit is clear */
-       /* Read Command and Address are written to the Serial Interface */
-       iowrite32(*(__le32 *)&cmd, ctl + AGNX_CIR_SERIALITF);
-       /* Wait for the Status bit to clear again */
-       eeprom_delay();
-       /* Read from Data */
-       reg = ioread32(ctl + AGNX_CIR_SERIALITF);
-
-       cmd = *(struct agnx_eeprom *)&reg;
-
-       return cmd.data;
-}
-
-static int card_full_reset(struct agnx_priv *priv)
-{
-       void __iomem *ctl = priv->ctl;
-       u32 reg;
-       AGNX_TRACE;
-
-       reg = agnx_read32(ctl, AGNX_CIR_BLKCTL);
-       agnx_write32(ctl, AGNX_CIR_BLKCTL, 0x80);
-       reg = agnx_read32(ctl, AGNX_CIR_BLKCTL);
-       return 0;
-}
-
-inline void enable_power_saving(struct agnx_priv *priv)
-{
-       void __iomem *ctl = priv->ctl;
-       u32 reg;
-
-       reg = agnx_read32(ctl, AGNX_PM_PMCTL);
-       reg &= ~0x8;
-       agnx_write32(ctl, AGNX_PM_PMCTL, reg);
-}
-
-inline void disable_power_saving(struct agnx_priv *priv)
-{
-       void __iomem *ctl = priv->ctl;
-       u32 reg;
-
-       reg = agnx_read32(ctl, AGNX_PM_PMCTL);
-       reg |= 0x8;
-       agnx_write32(ctl, AGNX_PM_PMCTL, reg);
-}
-
-
-void disable_receiver(struct agnx_priv *priv)
-{
-       void __iomem *ctl = priv->ctl;
-       AGNX_TRACE;
-
-       /* FIXME Disable the receiver */
-       agnx_write32(ctl, AGNX_GCR_DISCOVMOD, 0x0);
-       /* Set gain control reset */
-       agnx_write32(ctl, AGNX_GCR_RSTGCTL, 0x1);
-       /* Reset gain control reset */
-       agnx_write32(ctl, AGNX_GCR_RSTGCTL, 0x0);
-}
-
-
-/* Fixme this shoule be disable RX, above is enable RX */
-void enable_receiver(struct agnx_priv *priv)
-{
-       void __iomem *ctl = priv->ctl;
-       AGNX_TRACE;
-
-       /* Set adaptive gain control discovery mode */
-       agnx_write32(ctl, AGNX_GCR_DISCOVMOD, 0x3);
-       /* Set gain control reset */
-       agnx_write32(ctl, AGNX_GCR_RSTGCTL, 0x1);
-       /* Clear gain control reset */
-       agnx_write32(ctl, AGNX_GCR_RSTGCTL, 0x0);
-}
-
-static void mac_address_set(struct agnx_priv *priv)
-{
-       void __iomem *ctl = priv->ctl;
-       u8 *mac_addr = priv->mac_addr;
-       u32 reg;
-
-       /* FIXME */
-       reg = (mac_addr[0] << 24) | (mac_addr[1] << 16) | mac_addr[2] << 8 | mac_addr[3];
-       iowrite32(reg, ctl + AGNX_RXM_MACHI);
-       reg = (mac_addr[4] << 8) | mac_addr[5];
-       iowrite32(reg, ctl + AGNX_RXM_MACLO);
-}
-
-static void receiver_bssid_set(struct agnx_priv *priv, const u8 *bssid)
-{
-       void __iomem *ctl = priv->ctl;
-       u32 reg;
-
-       disable_receiver(priv);
-       /* FIXME */
-       reg = bssid[0] << 24 | (bssid[1] << 16) | (bssid[2] << 8) | bssid[3];
-       iowrite32(reg, ctl + AGNX_RXM_BSSIDHI);
-       reg = (bssid[4] << 8) | bssid[5];
-       iowrite32(reg, ctl + AGNX_RXM_BSSIDLO);
-
-       /* Enable the receiver */
-       enable_receiver(priv);
-
-       /* Clear the TSF */
-/*     agnx_write32(ctl, AGNX_TXM_TSFLO, 0x0); */
-/*     agnx_write32(ctl, AGNX_TXM_TSFHI, 0x0); */
-       /* Clear the TBTT */
-       agnx_write32(ctl, AGNX_TXM_TBTTLO, 0x0);
-       agnx_write32(ctl, AGNX_TXM_TBTTHI, 0x0);
-       disable_receiver(priv);
-} /* receiver_bssid_set */
-
-static void band_management_init(struct agnx_priv *priv)
-{
-       void __iomem *ctl = priv->ctl;
-       void __iomem *data = priv->data;
-       u32 reg;
-       int i;
-       AGNX_TRACE;
-
-       agnx_write32(ctl, AGNX_BM_TXWADDR, AGNX_PDU_TX_WQ);
-       agnx_write32(ctl, AGNX_CIR_ADDRWIN, 0x0);
-       memset_io(data + AGNX_PDUPOOL, 0x0, AGNX_PDUPOOL_SIZE);
-       agnx_write32(ctl, AGNX_BM_BMCTL, 0x200);
-
-       agnx_write32(ctl, AGNX_BM_CIPDUWCNT, 0x40);
-       agnx_write32(ctl, AGNX_BM_SPPDUWCNT, 0x2);
-       agnx_write32(ctl, AGNX_BM_RFPPDUWCNT, 0x0);
-       agnx_write32(ctl, AGNX_BM_RHPPDUWCNT, 0x22);
-
-       /* FIXME Initialize the Free Pool Linked List */
-       /*    1. Write the Address of the Next Node ((0x41800 + node*size)/size)
-             to the first word of each node.  */
-       for (i = 0; i < PDU_FREE_CNT; i++) {
-               iowrite32((AGNX_PDU_FREE + (i+1)*PDU_SIZE)/PDU_SIZE,
-                         data + AGNX_PDU_FREE + (PDU_SIZE * i));
-               /* The last node should be set to 0x0 */
-               if ((i + 1) == PDU_FREE_CNT)
-                       memset_io(data + AGNX_PDU_FREE + (PDU_SIZE * i),
-                                 0x0, PDU_SIZE);
-       }
-
-       /* Head is First Pool address (0x41800) / size (0x80) */
-       agnx_write32(ctl, AGNX_BM_FPLHP, AGNX_PDU_FREE/PDU_SIZE);
-       /* Tail is Last Pool Address (0x47f80) / size (0x80) */
-       agnx_write32(ctl, AGNX_BM_FPLTP, 0x47f80/PDU_SIZE);
-       /* Count is Number of Nodes in the Pool (0xd0) */
-       agnx_write32(ctl, AGNX_BM_FPCNT, PDU_FREE_CNT);
-
-       /* Start all workqueue */
-       agnx_write32(ctl, AGNX_BM_CIWQCTL, 0x80000);
-       agnx_write32(ctl, AGNX_BM_CPULWCTL, 0x80000);
-       agnx_write32(ctl, AGNX_BM_CPUHWCTL, 0x80000);
-       agnx_write32(ctl, AGNX_BM_CPUTXWCTL, 0x80000);
-       agnx_write32(ctl, AGNX_BM_CPURXWCTL, 0x80000);
-       agnx_write32(ctl, AGNX_BM_SPRXWCTL, 0x80000);
-       agnx_write32(ctl, AGNX_BM_SPTXWCTL, 0x80000);
-       agnx_write32(ctl, AGNX_BM_RFPWCTL, 0x80000);
-
-       /* Enable the Band Management */
-       reg = agnx_read32(ctl, AGNX_BM_BMCTL);
-       reg |= 0x1;
-       agnx_write32(ctl, AGNX_BM_BMCTL, reg);
-} /* band_managment_init */
-
-
-static void system_itf_init(struct agnx_priv *priv)
-{
-       void __iomem *ctl = priv->ctl;
-       u32 reg;
-       AGNX_TRACE;
-
-       agnx_write32(ctl, AGNX_SYSITF_GPIOUT, 0x0);
-       agnx_write32(ctl, AGNX_PM_TESTPHY, 0x11e143a);
-
-       if (priv->revid == 0) {
-               reg = agnx_read32(ctl, AGNX_SYSITF_SYSMODE);
-               reg |= 0x11;
-               agnx_write32(ctl, AGNX_SYSITF_SYSMODE, reg);
-       }
-       /* ??? What is that means? it should difference for differice type
-        of cards */
-       agnx_write32(ctl, AGNX_CIR_SERIALITF, 0xfff81006);
-
-       agnx_write32(ctl, AGNX_SYSITF_GPIOIN, 0x1f0000);
-       agnx_write32(ctl, AGNX_SYSITF_GPIOUT, 0x5);
-       reg = agnx_read32(ctl, AGNX_SYSITF_GPIOIN);
-}
-
-static void encryption_init(struct agnx_priv *priv)
-{
-       void __iomem *ctl = priv->ctl;
-       AGNX_TRACE;
-
-       agnx_write32(ctl, AGNX_ENCRY_WEPKEY0, 0x0);
-       agnx_write32(ctl, AGNX_ENCRY_WEPKEY1, 0x0);
-       agnx_write32(ctl, AGNX_ENCRY_WEPKEY2, 0x0);
-       agnx_write32(ctl, AGNX_ENCRY_WEPKEY3, 0x0);
-       agnx_write32(ctl, AGNX_ENCRY_CCMRECTL, 0x8);
-}
-
-static void tx_management_init(struct agnx_priv *priv)
-{
-       void __iomem *ctl = priv->ctl;
-       void __iomem *data = priv->data;
-       u32 reg;
-       AGNX_TRACE;
-
-       /* Fill out the ComputationalEngineLookupTable
-        * starting at memory #2 offset 0x800
-        */
-       tx_engine_lookup_tbl_init(priv);
-       memset_io(data + 0x1000, 0, 0xfe0);
-       /* Enable Transmission Management Functions */
-       agnx_write32(ctl, AGNX_TXM_ETMF, 0x3ff);
-       /* Write 0x3f to Transmission Template */
-       agnx_write32(ctl, AGNX_TXM_TXTEMP, 0x3f);
-
-       if (priv->revid >= 2)
-               agnx_write32(ctl, AGNX_TXM_SIFSPIFS, 0x1e140a0b);
-       else
-               agnx_write32(ctl, AGNX_TXM_SIFSPIFS, 0x1e190a0b);
-
-       reg = agnx_read32(ctl, AGNX_TXM_TIFSEIFS);
-       reg &= 0xff00;
-       reg |= 0xb;
-       agnx_write32(ctl, AGNX_TXM_TIFSEIFS, reg);
-       reg = agnx_read32(ctl, AGNX_TXM_TIFSEIFS);
-       reg &= 0xffff00ff;
-       reg |= 0xa00;
-       agnx_write32(ctl, AGNX_TXM_TIFSEIFS, reg);
-       /* Enable TIFS */
-       agnx_write32(ctl, AGNX_TXM_CTL, 0x40000);
-
-       reg = agnx_read32(ctl, AGNX_TXM_TIFSEIFS);
-       reg &= 0xff00ffff;
-       reg |= 0x510000;
-       agnx_write32(ctl, AGNX_TXM_TIFSEIFS, reg);
-       reg = agnx_read32(ctl, AGNX_TXM_PROBDELAY);
-       reg &= 0xff00ffff;
-       agnx_write32(ctl, AGNX_TXM_PROBDELAY, reg);
-       reg = agnx_read32(ctl, AGNX_TXM_TIFSEIFS);
-       reg &= 0x00ffffff;
-       reg |= 0x1c000000;
-       agnx_write32(ctl, AGNX_TXM_TIFSEIFS, reg);
-       reg = agnx_read32(ctl, AGNX_TXM_PROBDELAY);
-       reg &= 0x00ffffff;
-       reg |= 0x01000000;
-       agnx_write32(ctl, AGNX_TXM_PROBDELAY, reg);
-
-       /* # Set DIF 0-1,2-3,4-5,6-7 to defaults */
-       agnx_write32(ctl, AGNX_TXM_DIF01, 0x321d321d);
-       agnx_write32(ctl, AGNX_TXM_DIF23, 0x321d321d);
-       agnx_write32(ctl, AGNX_TXM_DIF45, 0x321d321d);
-       agnx_write32(ctl, AGNX_TXM_DIF67, 0x321d321d);
-
-       /* Max Ack timeout limit */
-       agnx_write32(ctl, AGNX_TXM_MAXACKTIM, 0x1e19);
-       /* Max RX Data Timeout count, */
-       reg = agnx_read32(ctl, AGNX_TXM_MAXRXTIME);
-       reg &= 0xffff0000;
-       reg |= 0xff;
-       agnx_write32(ctl, AGNX_TXM_MAXRXTIME, reg);
-
-       /* CF poll RX Timeout count */
-       reg = agnx_read32(ctl, AGNX_TXM_CFPOLLRXTIM);
-       reg &= 0xffff;
-       reg |= 0xff0000;
-       agnx_write32(ctl, AGNX_TXM_CFPOLLRXTIM, reg);
-
-       /* Max Timeout Exceeded count, */
-       reg = agnx_read32(ctl, AGNX_TXM_MAXTIMOUT);
-       reg &= 0xff00ffff;
-       reg |= 0x190000;
-       agnx_write32(ctl, AGNX_TXM_MAXTIMOUT, reg);
-
-       /* CF ack timeout limit for 11b */
-       reg = agnx_read32(ctl, AGNX_TXM_CFACKT11B);
-       reg &= 0xff00;
-       reg |= 0x1e;
-       agnx_write32(ctl, AGNX_TXM_CFACKT11B, reg);
-
-       /* Max CF Poll Timeout Count */
-       reg = agnx_read32(ctl, AGNX_TXM_CFPOLLRXTIM);
-       reg &= 0xffff0000;
-       reg |= 0x19;
-       agnx_write32(ctl, AGNX_TXM_CFPOLLRXTIM, reg);
-       /* CF Poll RX Timeout Count */
-       reg = agnx_read32(ctl, AGNX_TXM_CFPOLLRXTIM);
-       reg &= 0xffff0000;
-       reg |= 0x1e;
-       agnx_write32(ctl, AGNX_TXM_CFPOLLRXTIM, reg);
-
-       /* # write default to */
-       /*    1. Schedule Empty Count */
-       agnx_write32(ctl, AGNX_TXM_SCHEMPCNT, 0x5);
-       /*    2. CFP Period Count */
-       agnx_write32(ctl, AGNX_TXM_CFPERCNT, 0x1);
-       /*    3. CFP MDV  */
-       agnx_write32(ctl, AGNX_TXM_CFPMDV, 0x10000);
-
-       /* Probe Delay */
-       reg = agnx_read32(ctl, AGNX_TXM_PROBDELAY);
-       reg &= 0xffff0000;
-       reg |= 0x400;
-       agnx_write32(ctl, AGNX_TXM_PROBDELAY, reg);
-
-       /* Max CCA count Slot */
-       reg = agnx_read32(ctl, AGNX_TXM_MAXCCACNTSLOT);
-       reg &= 0xffff00ff;
-       reg |= 0x900;
-       agnx_write32(ctl, AGNX_TXM_MAXCCACNTSLOT, reg);
-
-       /* Slot limit/1 msec Limit */
-       reg = agnx_read32(ctl, AGNX_TXM_SLOTLIMIT);
-       reg &= 0xff00ffff;
-       reg |= 0x140077;
-       agnx_write32(ctl, AGNX_TXM_SLOTLIMIT, reg);
-
-       /* # Set CW #(0-7) to default */
-       agnx_write32(ctl, AGNX_TXM_CW0, 0xff0007);
-       agnx_write32(ctl, AGNX_TXM_CW1, 0xff0007);
-       agnx_write32(ctl, AGNX_TXM_CW2, 0xff0007);
-       agnx_write32(ctl, AGNX_TXM_CW3, 0xff0007);
-       agnx_write32(ctl, AGNX_TXM_CW4, 0xff0007);
-       agnx_write32(ctl, AGNX_TXM_CW5, 0xff0007);
-       agnx_write32(ctl, AGNX_TXM_CW6, 0xff0007);
-       agnx_write32(ctl, AGNX_TXM_CW7, 0xff0007);
-
-       /* # Set Short/Long limit #(0-7) to default */
-       agnx_write32(ctl, AGNX_TXM_SLBEALIM0,  0xa000a);
-       agnx_write32(ctl, AGNX_TXM_SLBEALIM1,  0xa000a);
-       agnx_write32(ctl, AGNX_TXM_SLBEALIM2,  0xa000a);
-       agnx_write32(ctl, AGNX_TXM_SLBEALIM3,  0xa000a);
-       agnx_write32(ctl, AGNX_TXM_SLBEALIM4,  0xa000a);
-       agnx_write32(ctl, AGNX_TXM_SLBEALIM5,  0xa000a);
-       agnx_write32(ctl, AGNX_TXM_SLBEALIM6,  0xa000a);
-       agnx_write32(ctl, AGNX_TXM_SLBEALIM7,  0xa000a);
-
-       reg = agnx_read32(ctl, AGNX_TXM_CTL);
-       reg |= 0x1400;
-       agnx_write32(ctl, AGNX_TXM_CTL, reg);
-       /* Wait for bit 0 in Control Reg to clear  */
-       udelay(80);
-       reg = agnx_read32(ctl, AGNX_TXM_CTL);
-       /* Or 0x18000 to Control reg */
-       reg = agnx_read32(ctl, AGNX_TXM_CTL);
-       reg |= 0x18000;
-       agnx_write32(ctl, AGNX_TXM_CTL, reg);
-       /* Wait for bit 0 in Control Reg to clear */
-       udelay(80);
-       reg = agnx_read32(ctl, AGNX_TXM_CTL);
-
-       /* Set Listen Interval Count to default */
-       agnx_write32(ctl, AGNX_TXM_LISINTERCNT, 0x1);
-       /* Set DTIM period count to default */
-       agnx_write32(ctl, AGNX_TXM_DTIMPERICNT, 0x2000);
-} /* tx_management_init */
-
-static void rx_management_init(struct agnx_priv *priv)
-{
-       void __iomem *ctl = priv->ctl;
-       AGNX_TRACE;
-
-       /* Initialize the Routing Table */
-       routing_table_init(priv);
-
-       if (priv->revid >= 3) {
-               agnx_write32(ctl, 0x2074, 0x1f171710);
-               agnx_write32(ctl, 0x2078, 0x10100d0d);
-               agnx_write32(ctl, 0x207c, 0x11111010);
-       } else {
-               agnx_write32(ctl, AGNX_RXM_DELAY11, 0x0);
-       }
-       agnx_write32(ctl, AGNX_RXM_REQRATE, 0x8195e00);
-}
-
-
-static void agnx_timer_init(struct agnx_priv *priv)
-{
-       void __iomem *ctl = priv->ctl;
-       AGNX_TRACE;
-
-/*     /\* Write 0x249f00 (tick duration?) to Timer 1 *\/ */
-/*     agnx_write32(ctl, AGNX_TIMCTL_TIMER1, 0x249f00); */
-/*     /\* Write 0xe2 to Timer 1 Control *\/ */
-/*     agnx_write32(ctl, AGNX_TIMCTL_TIM1CTL, 0xe2); */
-
-       /* Write 0x249f00 (tick duration?) to Timer 1 */
-       agnx_write32(ctl, AGNX_TIMCTL_TIMER1, 0x0);
-       /* Write 0xe2 to Timer 1 Control */
-       agnx_write32(ctl, AGNX_TIMCTL_TIM1CTL, 0x0);
-
-       iowrite32(0xFFFFFFFF, priv->ctl + AGNX_TXM_BEACON_CTL);
-}
-
-static void power_manage_init(struct agnx_priv *priv)
-{
-       void __iomem *ctl = priv->ctl;
-       u32 reg;
-       AGNX_TRACE;
-
-       agnx_write32(ctl, AGNX_PM_MACMSW, 0x1f);
-       agnx_write32(ctl, AGNX_PM_RFCTL, 0x1f);
-
-       reg = agnx_read32(ctl, AGNX_PM_PMCTL);
-       reg &= 0xf00f;
-       reg |= 0xa0;
-       agnx_write32(ctl, AGNX_PM_PMCTL, reg);
-
-       if (priv->revid >= 3) {
-               reg = agnx_read32(ctl, AGNX_PM_SOFTRST);
-               reg |= 0x18;
-               agnx_write32(ctl, AGNX_PM_SOFTRST, reg);
-       }
-} /* power_manage_init */
-
-
-static void gain_ctlcnt_init(struct agnx_priv *priv)
-{
-       void __iomem *ctl = priv->ctl;
-       u32 reg;
-       AGNX_TRACE;
-
-       agnx_write32(ctl, AGNX_GCR_TRACNT5, 0x119);
-       agnx_write32(ctl, AGNX_GCR_TRACNT6, 0x118);
-       agnx_write32(ctl, AGNX_GCR_TRACNT7, 0x117);
-
-       reg = agnx_read32(ctl, AGNX_PM_PMCTL);
-       reg |= 0x8;
-       agnx_write32(ctl, AGNX_PM_PMCTL, reg);
-
-       reg = agnx_read32(ctl, AGNX_PM_PMCTL);
-       reg &= ~0x8;
-       agnx_write32(ctl, AGNX_PM_PMCTL, reg);
-
-       agnx_write32(ctl, AGNX_CIR_ADDRWIN, 0x0);
-
-       /* FIXME Write the initial Station Descriptor for the card */
-       sta_init(priv, LOCAL_STAID);
-       sta_init(priv, BSSID_STAID);
-
-       /* Enable staion 0 and 1 can do TX */
-       /* It seemed if we set other bit to 1 the bit 0 will
-          be auto change to 0 */
-       agnx_write32(ctl, AGNX_BM_TXTOPEER, 0x2 | 0x1);
-/*     agnx_write32(ctl, AGNX_BM_TXTOPEER, 0x1); */
-} /* gain_ctlcnt_init */
-
-
-static void phy_init(struct agnx_priv *priv)
-{
-       void __iomem *ctl = priv->ctl;
-       void __iomem *data = priv->data;
-       u32 reg;
-       AGNX_TRACE;
-
-       /* Load InitialGainTable */
-       gain_table_init(priv);
-
-       agnx_write32(ctl, AGNX_CIR_ADDRWIN, 0x2000000);
-
-       /* Clear the following offsets in Memory Range #2: */
-       memset_io(data + 0x5040, 0, 0xa * 4);
-       memset_io(data + 0x5080, 0, 0xa * 4);
-       memset_io(data + 0x50c0, 0, 0xa * 4);
-       memset_io(data + 0x5400, 0, 0x80 * 4);
-       memset_io(data + 0x6000, 0, 0x280 * 4);
-       memset_io(data + 0x7000, 0, 0x280 * 4);
-       memset_io(data + 0x8000, 0, 0x280 * 4);
-
-       /* Initialize the Following Registers According to PCI Revision ID */
-       if (priv->revid == 0) {
-               /* fixme the part hasn't been update but below has been update
-                  based on WGM511 */
-               agnx_write32(ctl, AGNX_ACI_LEN, 0xf);
-               agnx_write32(ctl, AGNX_ACI_TIMER1, 0x1d);
-               agnx_write32(ctl, AGNX_ACI_TIMER2, 0x3);
-               agnx_write32(ctl, AGNX_ACI_AICCHA0OVE, 0x11);
-               agnx_write32(ctl, AGNX_ACI_AICCHA1OVE, 0x0);
-               agnx_write32(ctl, AGNX_GCR_THD0A, 0x64);
-               agnx_write32(ctl, AGNX_GCR_THD0AL, 0x4b);
-               agnx_write32(ctl, AGNX_GCR_THD0B, 0x4b);
-               agnx_write32(ctl, AGNX_GCR_DUNSAT, 0x14);
-               agnx_write32(ctl, AGNX_GCR_DSAT, 0x24);
-               agnx_write32(ctl, AGNX_GCR_DFIRCAL, 0x8);
-               agnx_write32(ctl, AGNX_GCR_DGCTL11A, 0x1a);
-               agnx_write32(ctl, AGNX_GCR_DGCTL11B, 0x3);
-               agnx_write32(ctl, AGNX_GCR_GAININIT, 0xd);
-               agnx_write32(ctl, AGNX_GCR_THNOSIG, 0x1);
-               agnx_write32(ctl, AGNX_GCR_COARSTEP, 0x7);
-               agnx_write32(ctl, AGNX_GCR_SIFST11A, 0x28);
-               agnx_write32(ctl, AGNX_GCR_SIFST11B, 0x28);
-               reg = agnx_read32(ctl, AGNX_GCR_CWDETEC);
-               reg |= 0x1;
-               agnx_write32(ctl, AGNX_GCR_CWDETEC, reg);
-               agnx_write32(ctl, AGNX_GCR_0X38, 0x1e);
-               agnx_write32(ctl, AGNX_GCR_BOACT, 0x26);
-               agnx_write32(ctl, AGNX_GCR_DISCOVMOD, 0x3);
-               agnx_write32(ctl, AGNX_GCR_NLISTANT, 0x3);
-               agnx_write32(ctl, AGNX_GCR_NACTIANT, 0x3);
-               agnx_write32(ctl, AGNX_GCR_NMEASANT, 0x3);
-               agnx_write32(ctl, AGNX_GCR_NCAPTANT, 0x3);
-               agnx_write32(ctl, AGNX_GCR_THCAP11A, 0x0);
-               agnx_write32(ctl, AGNX_GCR_THCAP11B, 0x0);
-               agnx_write32(ctl, AGNX_GCR_THCAPRX11A, 0x0);
-               agnx_write32(ctl, AGNX_GCR_THCAPRX11B, 0x0);
-               agnx_write32(ctl, AGNX_GCR_THLEVDRO, 0x10);
-               agnx_write32(ctl, AGNX_GCR_MAXRXTIME11A, 0x1);
-               agnx_write32(ctl, AGNX_GCR_MAXRXTIME11B, 0x1);
-               agnx_write32(ctl, AGNX_GCR_CORRTIME, 0x190);
-               agnx_write32(ctl, AGNX_GCR_SIGHTH, 0x78);
-               agnx_write32(ctl, AGNX_GCR_SIGLTH, 0x1c);
-               agnx_write32(ctl, AGNX_GCR_CORRDROP, 0x0);
-               agnx_write32(ctl, AGNX_GCR_THCD, 0x0);
-               agnx_write32(ctl, AGNX_GCR_MAXPOWDIFF, 0x1);
-               agnx_write32(ctl, AGNX_GCR_TESTBUS, 0x0);
-               agnx_write32(ctl, AGNX_GCR_ANTCFG, 0x1f);
-               agnx_write32(ctl, AGNX_GCR_THJUMP, 0x14);
-               agnx_write32(ctl, AGNX_GCR_THPOWER, 0x0);
-               agnx_write32(ctl, AGNX_GCR_THPOWCLIP, 0x30);
-               agnx_write32(ctl, AGNX_GCR_THD0BTFEST, 0x32);
-               agnx_write32(ctl, AGNX_GCR_THRX11BPOWMIN, 0x19);
-               agnx_write32(ctl, AGNX_GCR_0X14c, 0x0);
-               agnx_write32(ctl, AGNX_GCR_0X150, 0x0);
-               agnx_write32(ctl, 0x9400, 0x0);
-               agnx_write32(ctl, 0x940c, 0x6ff);
-               agnx_write32(ctl, 0x9428, 0xa0);
-               agnx_write32(ctl, 0x9434, 0x0);
-               agnx_write32(ctl, 0x9c04, 0x15);
-               agnx_write32(ctl, 0x9c0c, 0x7f);
-               agnx_write32(ctl, 0x9c34, 0x0);
-               agnx_write32(ctl, 0xc000, 0x38d);
-               agnx_write32(ctl, 0x14018, 0x0);
-               agnx_write32(ctl, 0x16000, 0x1);
-               agnx_write32(ctl, 0x11004, 0x0);
-               agnx_write32(ctl, 0xec54, 0xa);
-               agnx_write32(ctl, 0xec1c, 0x5);
-       } else if (priv->revid > 0) {
-               agnx_write32(ctl, AGNX_ACI_LEN, 0xf);
-               agnx_write32(ctl, AGNX_ACI_TIMER1, 0x21);
-               agnx_write32(ctl, AGNX_ACI_TIMER2, 0x27);
-               agnx_write32(ctl, AGNX_ACI_AICCHA0OVE, 0x11);
-               agnx_write32(ctl, AGNX_ACI_AICCHA1OVE, 0x0);
-               agnx_write32(ctl, AGNX_GCR_DUNSAT, 0x14);
-               agnx_write32(ctl, AGNX_GCR_DSAT, 0x24);
-               agnx_write32(ctl, AGNX_GCR_DFIRCAL, 0x8);
-               agnx_write32(ctl, AGNX_GCR_DGCTL11A, 0x1a);
-               agnx_write32(ctl, AGNX_GCR_DGCTL11B, 0x3);
-               agnx_write32(ctl, AGNX_GCR_GAININIT, 0xd);
-               agnx_write32(ctl, AGNX_GCR_THNOSIG, 0x1);
-               agnx_write32(ctl, AGNX_GCR_COARSTEP, 0x7);
-               agnx_write32(ctl, AGNX_GCR_SIFST11A, 0x28);
-               agnx_write32(ctl, AGNX_GCR_SIFST11B, 0x28);
-               agnx_write32(ctl, AGNX_GCR_CWDETEC, 0x0);
-               agnx_write32(ctl, AGNX_GCR_0X38, 0x1e);
-/*             agnx_write32(ctl, AGNX_GCR_BOACT, 0x26);*/
-               agnx_write32(ctl, AGNX_GCR_DISCOVMOD, 0x3);
-
-               agnx_write32(ctl, AGNX_GCR_THCAP11A, 0x32);
-               agnx_write32(ctl, AGNX_GCR_THCAP11B, 0x32);
-               agnx_write32(ctl, AGNX_GCR_THCAPRX11A, 0x32);
-               agnx_write32(ctl, AGNX_GCR_THCAPRX11B, 0x32);
-               agnx_write32(ctl, AGNX_GCR_THLEVDRO, 0x10);
-               agnx_write32(ctl, AGNX_GCR_MAXRXTIME11A, 0x1ad);
-               agnx_write32(ctl, AGNX_GCR_MAXRXTIME11B, 0xa10);
-               agnx_write32(ctl, AGNX_GCR_CORRTIME, 0x190);
-               agnx_write32(ctl, AGNX_GCR_CORRDROP, 0x0);
-               agnx_write32(ctl, AGNX_GCR_THCD, 0x0);
-               agnx_write32(ctl, AGNX_GCR_THCS, 0x0);
-               agnx_write32(ctl, AGNX_GCR_MAXPOWDIFF, 0x4);
-               agnx_write32(ctl, AGNX_GCR_TESTBUS, 0x0);
-               agnx_write32(ctl, AGNX_GCR_THJUMP, 0x1e);
-               agnx_write32(ctl, AGNX_GCR_THPOWER, 0x0);
-               agnx_write32(ctl, AGNX_GCR_THPOWCLIP, 0x2a);
-               agnx_write32(ctl, AGNX_GCR_THD0BTFEST, 0x3c);
-               agnx_write32(ctl, AGNX_GCR_THRX11BPOWMIN, 0x19);
-               agnx_write32(ctl, AGNX_GCR_0X14c, 0x0);
-               agnx_write32(ctl, AGNX_GCR_0X150, 0x0);
-               agnx_write32(ctl, AGNX_GCR_RXOVERIDE, 0x0);
-               agnx_write32(ctl, AGNX_GCR_WATCHDOG, 0x37);
-               agnx_write32(ctl, 0x9400, 0x0);
-               agnx_write32(ctl, 0x940c, 0x6ff);
-               agnx_write32(ctl, 0x9428, 0xa0);
-               agnx_write32(ctl, 0x9434, 0x0);
-               agnx_write32(ctl, 0x9c04, 0x15);
-               agnx_write32(ctl, 0x9c0c, 0x7f);
-               agnx_write32(ctl, 0x9c34, 0x0);
-               agnx_write32(ctl, 0xc000, 0x38d);
-               agnx_write32(ctl, 0x14014, 0x1000);
-               agnx_write32(ctl, 0x14018, 0x0);
-               agnx_write32(ctl, 0x16000, 0x1);
-               agnx_write32(ctl, 0x11004, 0x0);
-               agnx_write32(ctl, 0xec54, 0xa);
-               agnx_write32(ctl, 0xec1c, 0x50);
-       } else if (priv->revid > 1) {
-               reg = agnx_read32(ctl, 0xec18);
-               reg |= 0x8;
-               agnx_write32(ctl, 0xec18, reg);
-       }
-
-       /* Write the TX Fir Coefficient Table */
-       tx_fir_table_init(priv);
-
-       reg = agnx_read32(ctl, AGNX_PM_PMCTL);
-       reg &= ~0x8;
-       agnx_write32(ctl, AGNX_PM_PMCTL, reg);
-       reg = agnx_read32(ctl, AGNX_PM_PLLCTL);
-       reg |= 0x1;
-       agnx_write32(ctl, AGNX_PM_PLLCTL, reg);
-
-/*     reg = agnx_read32(ctl, 0x1a030); */
-/*     reg &= ~0x4; */
-/*     agnx_write32(ctl, 0x1a030, reg); */
-
-       agnx_write32(ctl, AGNX_GCR_TRACNT4, 0x113);
-} /* phy_init */
-
-static void chip_init(struct agnx_priv *priv)
-{
-       void __iomem *ctl = priv->ctl;
-       u32 reg;
-       AGNX_TRACE;
-
-       band_management_init(priv);
-
-       rf_chips_init(priv);
-
-       reg = agnx_read32(ctl, AGNX_PM_PMCTL);
-       reg |= 0x8;
-       agnx_write32(ctl, AGNX_PM_PMCTL, reg);
-
-       /* Initialize the PHY */
-       phy_init(priv);
-
-       encryption_init(priv);
-
-       tx_management_init(priv);
-
-       rx_management_init(priv);
-
-       power_manage_init(priv);
-
-       /* Initialize the Timers */
-       agnx_timer_init(priv);
-
-       /* Write 0xc390bf9 to Interrupt Mask (Disable TX) */
-       reg = 0xc390bf9 & ~IRQ_TX_BEACON;
-       reg &= ~IRQ_TX_DISABLE;
-       agnx_write32(ctl, AGNX_INT_MASK, reg);
-
-       reg = agnx_read32(ctl, AGNX_CIR_BLKCTL);
-       reg |= 0x800;
-       agnx_write32(ctl, AGNX_CIR_BLKCTL, reg);
-
-       /* set it when need get multicast enable? */
-       agnx_write32(ctl, AGNX_BM_MTSM, 0xff);
-} /* chip_init */
-
-
-static inline void set_promis_and_managed(struct agnx_priv *priv)
-{
-       void __iomem *ctl = priv->ctl;
-       agnx_write32(ctl, AGNX_SYSITF_SYSMODE, 0x10 | 0x2);
-       agnx_write32(ctl, AGNX_SYSITF_SYSMODE, 0x10 | 0x2);
-}
-static inline void set_learn_mode(struct agnx_priv *priv)
-{
-       void __iomem *ctl = priv->ctl;
-       agnx_write32(ctl, AGNX_SYSITF_SYSMODE, 0x8);
-}
-static inline void set_scan_mode(struct agnx_priv *priv)
-{
-       void __iomem *ctl = priv->ctl;
-       agnx_write32(ctl, AGNX_SYSITF_SYSMODE, 0x20);
-}
-static inline void set_promiscuous_mode(struct agnx_priv *priv)
-{
-       void __iomem *ctl = priv->ctl;
-       /* agnx_write32(ctl, AGNX_SYSITF_SYSMODE, 0x210);*/
-       agnx_write32(ctl, AGNX_SYSITF_SYSMODE, 0x10);
-}
-static inline void set_managed_mode(struct agnx_priv *priv)
-{
-       void __iomem *ctl = priv->ctl;
-       agnx_write32(ctl, AGNX_SYSITF_SYSMODE, 0x2);
-}
-static inline void set_adhoc_mode(struct agnx_priv *priv)
-{
-       void __iomem *ctl = priv->ctl;
-       agnx_write32(ctl, AGNX_SYSITF_SYSMODE, 0x0);
-}
-
-#if 0
-static void unknow_register_write(struct agnx_priv *priv)
-{
-       void __iomem *ctl = priv->ctl;
-
-       agnx_write32(ctl, AGNX_UNKNOWN_BASE + 0x0, 0x3e);
-       agnx_write32(ctl, AGNX_UNKNOWN_BASE + 0x4, 0xb2);
-       agnx_write32(ctl, AGNX_UNKNOWN_BASE + 0x8, 0x140);
-       agnx_write32(ctl, AGNX_UNKNOWN_BASE + 0xc, 0x1C0);
-       agnx_write32(ctl, AGNX_UNKNOWN_BASE + 0x10, 0x1FF);
-       agnx_write32(ctl, AGNX_UNKNOWN_BASE + 0x14, 0x1DD);
-       agnx_write32(ctl, AGNX_UNKNOWN_BASE + 0x18, 0x15F);
-       agnx_write32(ctl, AGNX_UNKNOWN_BASE + 0x1c, 0xA1);
-       agnx_write32(ctl, AGNX_UNKNOWN_BASE + 0x20, 0x3E7);
-       agnx_write32(ctl, AGNX_UNKNOWN_BASE + 0x24, 0x36B);
-       agnx_write32(ctl, AGNX_UNKNOWN_BASE + 0x28, 0x348);
-       agnx_write32(ctl, AGNX_UNKNOWN_BASE + 0x2c, 0x37D);
-       agnx_write32(ctl, AGNX_UNKNOWN_BASE + 0x30, 0x3DE);
-       agnx_write32(ctl, AGNX_UNKNOWN_BASE + 0x34, 0x36);
-       agnx_write32(ctl, AGNX_UNKNOWN_BASE + 0x38, 0x64);
-       agnx_write32(ctl, AGNX_UNKNOWN_BASE + 0x3c, 0x57);
-       agnx_write32(ctl, AGNX_UNKNOWN_BASE + 0x40, 0x23);
-       agnx_write32(ctl, AGNX_UNKNOWN_BASE + 0x44, 0x3ED);
-       agnx_write32(ctl, AGNX_UNKNOWN_BASE + 0x48, 0x3C9);
-       agnx_write32(ctl, AGNX_UNKNOWN_BASE + 0x4c, 0x3CA);
-       agnx_write32(ctl, AGNX_UNKNOWN_BASE + 0x50, 0x3E7);
-       agnx_write32(ctl, AGNX_UNKNOWN_BASE + 0x54, 0x8);
-       agnx_write32(ctl, AGNX_UNKNOWN_BASE + 0x58, 0x1F);
-       agnx_write32(ctl, AGNX_UNKNOWN_BASE + 0x5c, 0x1a);
-}
-#endif
-
-static void card_interface_init(struct agnx_priv *priv)
-{
-       void __iomem *ctl = priv->ctl;
-       u8 bssid[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
-       u32 reg;
-       unsigned int i;
-       AGNX_TRACE;
-
-       might_sleep();
-       /* Clear RX Control and Enable RX queues */
-       agnx_write32(ctl, AGNX_CIR_RXCTL, 0x8);
-
-       might_sleep();
-       /* Do a full reset of the card */
-       card_full_reset(priv);
-       might_sleep();
-
-       /* Check and set Card Endianness */
-       reg = ioread32(priv->ctl + AGNX_CIR_ENDIAN);
-       /* TODO If not 0xB3B2B1B0 set to 0xB3B2B1B0 */
-       printk(KERN_INFO PFX "CIR_ENDIAN is %x\n", reg);
-
-
-       /* Config the eeprom */
-       agnx_write32(ctl, AGNX_CIR_SERIALITF, 0x7000086);
-       udelay(10);
-       reg = agnx_read32(ctl, AGNX_CIR_SERIALITF);
-
-
-       agnx_write32(ctl, AGNX_PM_SOFTRST, 0x80000033);
-       reg = agnx_read32(ctl, 0xec50);
-       reg |= 0xf;
-       agnx_write32(ctl, 0xec50, reg);
-       agnx_write32(ctl, AGNX_PM_SOFTRST, 0x0);
-
-
-       reg = agnx_read32(ctl, AGNX_SYSITF_GPIOIN);
-       udelay(10);
-       reg = agnx_read32(ctl, AGNX_CIR_SERIALITF);
-
-       /* Dump the eeprom */
-       do {
-               char eeprom[0x100000/0x100];
-
-               for (i = 0; i < 0x100000; i += 0x100) {
-                       agnx_write32(ctl, AGNX_CIR_SERIALITF, 0x3000000 + i);
-                       udelay(13);
-                       reg = agnx_read32(ctl, AGNX_CIR_SERIALITF);
-                       udelay(70);
-                       reg = agnx_read32(ctl, AGNX_CIR_SERIALITF);
-                       eeprom[i/0x100] = reg & 0xFF;
-                       udelay(10);
-               }
-               print_hex_dump_bytes(PFX "EEPROM: ", DUMP_PREFIX_NONE, eeprom,
-                                    ARRAY_SIZE(eeprom));
-       } while (0);
-
-       spi_rc_write(ctl, RF_CHIP0, 0x26);
-       reg = agnx_read32(ctl, AGNX_SPI_RLSW);
-
-       /* Initialize the system interface */
-       system_itf_init(priv);
-
-       might_sleep();
-       /* Chip Initialization (Polaris) */
-       chip_init(priv);
-       might_sleep();
-
-       /* Calibrate the antennae */
-       antenna_calibrate(priv);
-
-       reg = agnx_read32(ctl, 0xec50);
-       reg &= ~0x40;
-       agnx_write32(ctl, 0xec50, reg);
-       agnx_write32(ctl, AGNX_PM_SOFTRST, 0x0);
-       agnx_write32(ctl, AGNX_PM_PLLCTL, 0x1);
-
-       reg = agnx_read32(ctl, AGNX_BM_BMCTL);
-       reg |= 0x8000;
-       agnx_write32(ctl, AGNX_BM_BMCTL, reg);
-       enable_receiver(priv);
-       reg = agnx_read32(ctl, AGNX_SYSITF_SYSMODE);
-       reg |= 0x200;
-       agnx_write32(ctl, AGNX_SYSITF_SYSMODE, reg);
-       enable_receiver(priv);
-
-       might_sleep();
-       /* Initialize Gain Control Counts */
-       gain_ctlcnt_init(priv);
-
-       /* Write Initial Station Power Template for this station(#0) */
-       sta_power_init(priv, LOCAL_STAID);
-
-       might_sleep();
-       /* Initialize the rx,td,tm rings, for each node in the ring */
-       fill_rings(priv);
-
-       might_sleep();
-
-
-       agnx_write32(ctl, AGNX_PM_SOFTRST, 0x80000033);
-       agnx_write32(ctl, 0xec50, 0xc);
-       agnx_write32(ctl, AGNX_PM_SOFTRST, 0x0);
-
-       /* FIXME Initialize the transmit control register */
-       agnx_write32(ctl, AGNX_TXM_CTL, 0x194c1);
-
-       enable_receiver(priv);
-
-       might_sleep();
-       /* FIXME Set the Receive Control Mac Address to card address */
-       mac_address_set(priv);
-       enable_receiver(priv);
-       might_sleep();
-
-       /* Set the recieve request rate */
-       /* FIXME Enable the request */
-       /* Check packet length */
-       /* Set maximum packet length */
-/*     agnx_write32(ctl, AGNX_RXM_REQRATE, 0x88195e00); */
-/*     enable_receiver(priv); */
-
-       /* Set the Receiver BSSID */
-       receiver_bssid_set(priv, bssid);
-
-       /* FIXME Set to managed mode */
-       set_managed_mode(priv);
-/*     set_promiscuous_mode(priv); */
-/*     set_scan_mode(priv); */
-/*     set_learn_mode(priv); */
-/*     set_promis_and_managed(priv); */
-/*     set_adhoc_mode(priv); */
-
-       /* Set the recieve request rate */
-       /* Check packet length */
-       agnx_write32(ctl, AGNX_RXM_REQRATE, 0x08000000);
-       reg = agnx_read32(ctl, AGNX_RXM_REQRATE);
-       /* Set maximum packet length */
-       reg |= 0x00195e00;
-       agnx_write32(ctl, AGNX_RXM_REQRATE, reg);
-
-       /* Configure the RX and TX interrupt */
-       reg = ENABLE_RX_INTERRUPT | RX_CACHE_LINE | FRAG_LEN_2048 | FRAG_BE;
-       agnx_write32(ctl, AGNX_CIR_RXCFG, reg);
-       /* FIXME */
-       reg = ENABLE_TX_INTERRUPT | TX_CACHE_LINE | FRAG_LEN_2048 | FRAG_BE;
-       agnx_write32(ctl, AGNX_CIR_TXCFG, reg);
-
-       /* Enable RX TX Interrupts */
-       agnx_write32(ctl, AGNX_CIR_RXCTL, 0x80);
-       agnx_write32(ctl, AGNX_CIR_TXMCTL, 0x80);
-       agnx_write32(ctl, AGNX_CIR_TXDCTL, 0x80);
-
-       /* FIXME Set the master control interrupt in block control */
-       agnx_write32(ctl, AGNX_CIR_BLKCTL, 0x800);
-
-       /* Enable RX and TX queues */
-       reg = agnx_read32(ctl, AGNX_CIR_RXCTL);
-       reg |= 0x8;
-       agnx_write32(ctl, AGNX_CIR_RXCTL, reg);
-       reg = agnx_read32(ctl, AGNX_CIR_TXMCTL);
-       reg |= 0x8;
-       agnx_write32(ctl, AGNX_CIR_TXMCTL, reg);
-       reg = agnx_read32(ctl, AGNX_CIR_TXDCTL);
-       reg |= 0x8;
-       agnx_write32(ctl, AGNX_CIR_TXDCTL, reg);
-
-       agnx_write32(ctl, AGNX_SYSITF_GPIOUT, 0x5);
-       /* FIXME */
-       /*  unknow_register_write(priv); */
-       /* Update local card hash entry */
-       hash_write(priv, priv->mac_addr, LOCAL_STAID);
-
-       might_sleep();
-
-       /* FIXME */
-       agnx_set_channel(priv, 1);
-       might_sleep();
-} /* agnx_card_interface_init */
-
-
-void agnx_hw_init(struct agnx_priv *priv)
-{
-       AGNX_TRACE;
-       might_sleep();
-       card_interface_init(priv);
-}
-
-int agnx_hw_reset(struct agnx_priv *priv)
-{
-       return card_full_reset(priv);
-}
-
-int agnx_set_ssid(struct agnx_priv *priv, u8 *ssid, size_t ssid_len)
-{
-       AGNX_TRACE;
-       return 0;
-}
-
-void agnx_set_bssid(struct agnx_priv *priv, const u8 *bssid)
-{
-       receiver_bssid_set(priv, bssid);
-}
diff --git a/drivers/staging/agnx/phy.h b/drivers/staging/agnx/phy.h
deleted file mode 100644 (file)
index a955f05..0000000
+++ /dev/null
@@ -1,409 +0,0 @@
-#ifndef AGNX_PHY_H_
-#define AGNX_PHY_H_
-
-#include "agnx.h"
-
-/* Transmission Managment Registers */
-#define AGNX_TXM_BASE          0x0000
-#define AGNX_TXM_CTL           0x0000  /* control register */
-#define AGNX_TXM_ETMF          0x0004 /* enable transmission management functions */
-#define AGNX_TXM_TXTEMP                0x0008 /* transmission template */
-#define AGNX_TXM_RETRYSTAID    0x000c /* Retry Station ID */
-#define AGNX_TXM_TIMESTAMPLO           0x0010  /* Timestamp Lo */
-#define AGNX_TXM_TIMESTAMPHI           0x0014  /* Timestamp Hi */
-#define AGNX_TXM_TXDELAY       0x0018  /* tx delay */
-#define AGNX_TXM_TBTTLO                0x0020  /* tbtt Lo */
-#define AGNX_TXM_TBTTHI                0x0024  /* tbtt Hi */
-#define AGNX_TXM_BEAINTER      0x0028 /* Beacon Interval */
-#define AGNX_TXM_NAV           0x0030 /* NAV */
-#define AGNX_TXM_CFPMDV                0x0034 /* CFP MDV */
-#define AGNX_TXM_CFPERCNT      0x0038 /* CFP period count */
-#define AGNX_TXM_PROBDELAY     0x003c /* probe delay */
-#define AGNX_TXM_LISINTERCNT   0x0040 /* listen interval count */
-#define AGNX_TXM_DTIMPERICNT   0x004c /* DTIM period count */
-
-#define AGNX_TXM_BEACON_CTL    0x005c /* beacon control */
-
-#define AGNX_TXM_SCHEMPCNT     0x007c /* schedule empty count */
-#define AGNX_TXM_MAXTIMOUT     0x0084 /* max timeout exceed count */
-#define AGNX_TXM_MAXCFPTIM     0x0088 /* max CF poll timeout count */
-#define AGNX_TXM_MAXRXTIME     0x008c /* max RX timeout count */
-#define AGNX_TXM_MAXACKTIM     0x0090  /* max ACK timeout count */
-#define AGNX_TXM_DIF01         0x00a0 /* DIF 0-1 */
-#define AGNX_TXM_DIF23         0x00a4 /* DIF 2-3 */
-#define AGNX_TXM_DIF45         0x00a8 /* DIF 4-5 */
-#define AGNX_TXM_DIF67         0x00ac /* DIF 6-7 */
-#define AGNX_TXM_SIFSPIFS      0x00b0 /* SIFS/PIFS */
-#define AGNX_TXM_TIFSEIFS      0x00b4 /* TIFS/EIFS */
-#define AGNX_TXM_MAXCCACNTSLOT 0x00b8 /* max CCA count slot */
-#define AGNX_TXM_SLOTLIMIT     0x00bc /* slot limit/1 msec limit */
-#define AGNX_TXM_CFPOLLRXTIM   0x00f0 /* CF poll RX timeout count */
-#define AGNX_TXM_CFACKT11B     0x00f4 /* CF ack timeout limit for 11b */
-#define AGNX_TXM_CW0           0x0100 /* CW 0 */
-#define AGNX_TXM_SLBEALIM0     0x0108 /* short/long beacon limit 0 */
-#define AGNX_TXM_CW1           0x0120 /* CW 1 */
-#define AGNX_TXM_SLBEALIM1     0x0128 /* short/long beacon limit 1 */
-#define AGNX_TXM_CW2           0x0140 /* CW 2 */
-#define AGNX_TXM_SLBEALIM2     0x0148 /* short/long beacon limit 2 */
-#define AGNX_TXM_CW3           0x0160 /* CW 3 */
-#define AGNX_TXM_SLBEALIM3     0x0168 /* short/long beacon limit 3 */
-#define AGNX_TXM_CW4           0x0180 /* CW 4 */
-#define AGNX_TXM_SLBEALIM4     0x0188 /* short/long beacon limit 4 */
-#define AGNX_TXM_CW5           0x01a0 /* CW 5 */
-#define AGNX_TXM_SLBEALIM5     0x01a8 /* short/long beacon limit 5 */
-#define AGNX_TXM_CW6           0x01c0 /* CW 6 */
-#define AGNX_TXM_SLBEALIM6     0x01c8 /* short/long beacon limit 6 */
-#define AGNX_TXM_CW7           0x01e0 /* CW 7 */
-#define AGNX_TXM_SLBEALIM7     0x01e8 /* short/long beacon limit 7 */
-#define AGNX_TXM_BEACONTEMP     0x1000 /* beacon template */
-#define AGNX_TXM_STAPOWTEMP    0x1a00 /*  Station Power Template */
-
-/* Receive Management Control Registers */
-#define AGNX_RXM_BASE          0x2000
-#define AGNX_RXM_REQRATE       0x2000  /* requested rate */
-#define AGNX_RXM_MACHI         0x2004  /* first 4 bytes of mac address */
-#define AGNX_RXM_MACLO         0x2008  /* last 2 bytes of mac address */
-#define AGNX_RXM_BSSIDHI       0x200c  /* bssid hi */
-#define AGNX_RXM_BSSIDLO       0x2010  /* bssid lo */
-#define AGNX_RXM_HASH_CMD_FLAG 0x2014  /* Flags for the RX Hash Command Default:0 */
-#define AGNX_RXM_HASH_CMD_HIGH 0x2018  /* The High half of the Hash Command */
-#define AGNX_RXM_HASH_CMD_LOW  0x201c  /* The Low half of the Hash Command */
-#define AGNX_RXM_ROUTAB                0x2020  /* routing table */
-#define                ROUTAB_SUBTYPE_SHIFT    24
-#define                ROUTAB_TYPE_SHIFT       28
-#define                ROUTAB_STATUS_SHIFT     30
-#define                ROUTAB_RW_SHIFT         31
-#define                ROUTAB_ROUTE_DROP       0xf00000 /* Drop */
-#define                ROUTAB_ROUTE_CPU        0x400000 /* CPU */
-#define                ROUTAB_ROUTE_ENCRY      0x500800 /* Encryption */
-#define                ROUTAB_ROUTE_RFP        0x800000 /* RFP */
-
-#define                ROUTAB_TYPE_MANAG       0x0 /* Management */
-#define                ROUTAB_TYPE_CTL         0x1 /* Control */
-#define                ROUTAB_TYPE_DATA        0x2 /* Data */
-
-#define                ROUTAB_SUBTYPE_DATA             0x0
-#define                ROUTAB_SUBTYPE_DATAACK          0x1
-#define                ROUTAB_SUBTYPE_DATAPOLL         0x2
-#define                ROUTAB_SUBTYPE_DATAPOLLACK      0x3
-#define                ROUTAB_SUBTYPE_NULL             0x4 /* NULL */
-#define                ROUTAB_SUBTYPE_NULLACK          0x5
-#define                ROUTAB_SUBTYPE_NULLPOLL         0x6
-#define                ROUTAB_SUBTYPE_NULLPOLLACK      0x7
-#define                ROUTAB_SUBTYPE_QOSDATA          0x8 /* QOS DATA */
-#define                ROUTAB_SUBTYPE_QOSDATAACK       0x9
-#define                ROUTAB_SUBTYPE_QOSDATAPOLL      0xa
-#define                ROUTAB_SUBTYPE_QOSDATAACKPOLL   0xb
-#define                ROUTAB_SUBTYPE_QOSNULL          0xc
-#define                ROUTAB_SUBTYPE_QOSNULLACK       0xd
-#define                ROUTAB_SUBTYPE_QOSNULLPOLL      0xe
-#define                ROUTAB_SUBTYPE_QOSNULLPOLLACK   0xf
-#define AGNX_RXM_DELAY11          0x2024       /* delay 11(AB) */
-#define AGNX_RXM_SOF_CNT          0x2028       /* SOF Count */
-#define AGNX_RXM_FRAG_CNT         0x202c       /* Fragment Count*/
-#define AGNX_RXM_FCS_CNT          0x2030       /* FCS Count */
-#define AGNX_RXM_BSSID_MISS_CNT           0x2034       /* BSSID Miss Count */
-#define AGNX_RXM_PDU_ERR_CNT      0x2038       /* PDU Error Count */
-#define AGNX_RXM_DEST_MISS_CNT    0x203C       /* Destination Miss Count */
-#define AGNX_RXM_DROP_CNT         0x2040       /* Drop Count */
-#define AGNX_RXM_ABORT_CNT        0x2044       /* Abort Count */
-#define AGNX_RXM_RELAY_CNT        0x2048       /* Relay Count */
-#define AGNX_RXM_HASH_MISS_CNT    0x204c       /* Hash Miss Count */
-#define AGNX_RXM_SA_HI            0x2050       /* Address of received packet Hi */
-#define AGNX_RXM_SA_LO            0x2054       /* Address of received packet Lo */
-#define AGNX_RXM_HASH_DUMP_LST    0x2100       /* Contains Hash Data */
-#define AGNX_RXM_HASH_DUMP_MST    0x2104       /* Contains Hash Data */
-#define AGNX_RXM_HASH_DUMP_DATA    0x2108      /* The Station ID to dump */
-
-
-/* Encryption Managment */
-#define AGNX_ENCRY_BASE                0x2400
-#define AGNX_ENCRY_WEPKEY0     0x2440 /* wep key #0 */
-#define AGNX_ENCRY_WEPKEY1     0x2444 /* wep key #1 */
-#define AGNX_ENCRY_WEPKEY2     0x2448 /* wep key #2 */
-#define AGNX_ENCRY_WEPKEY3     0x244c /* wep key #3 */
-#define AGNX_ENCRY_CCMRECTL    0x2460 /* ccm replay control */
-
-
-/* Band Management Registers */
-#define AGNX_BM_BASE           0x2c00
-#define AGNX_BM_BMCTL          0x2c00  /* band management control */
-#define AGNX_BM_TXWADDR                0x2c18  /* tx workqueue address start */
-#define AGNX_BM_TXTOPEER       0x2c24  /* transmit to peers */
-#define AGNX_BM_FPLHP          0x2c2c  /* free pool list head pointer */
-#define AGNX_BM_FPLTP          0x2c30  /* free pool list tail pointer */
-#define AGNX_BM_FPCNT          0x2c34  /* free pool count */
-#define AGNX_BM_CIPDUWCNT      0x2c38  /* card interface pdu workqueue count */
-#define AGNX_BM_SPPDUWCNT      0x2c3c  /* sp pdu workqueue count */
-#define AGNX_BM_RFPPDUWCNT     0x2c40  /* rfp pdu workqueue count */
-#define AGNX_BM_RHPPDUWCNT     0x2c44  /* rhp pdu workqueue count */
-#define AGNX_BM_CIWQCTL                0x2c48 /* Card Interface WorkQueue Control */
-#define AGNX_BM_CPUTXWCTL      0x2c50  /* cpu tx workqueue control */
-#define AGNX_BM_CPURXWCTL      0x2c58  /* cpu rx workqueue control */
-#define AGNX_BM_CPULWCTL       0x2c60 /* cpu low workqueue control */
-#define AGNX_BM_CPUHWCTL       0x2c68 /* cpu high workqueue control */
-#define AGNX_BM_SPTXWCTL       0x2c70 /* sp tx workqueue control */
-#define AGNX_BM_SPRXWCTL       0x2c78 /* sp rx workqueue control */
-#define AGNX_BM_RFPWCTL                0x2c80 /* RFP workqueue control */
-#define AGNX_BM_MTSM           0x2c90 /* Multicast Transmit Station Mask */
-
-/* Card Interface Registers (32bits) */
-#define AGNX_CIR_BASE          0x3000
-#define AGNX_CIR_BLKCTL                0x3000  /* block control*/
-#define                AGNX_STAT_TX    0x1
-#define                AGNX_STAT_RX    0x2
-#define                AGNX_STAT_X     0x4
-/* Below two interrupt flags will be set by our but not CPU or the card */
-#define                AGNX_STAT_TXD   0x10
-#define                AGNX_STAT_TXM   0x20
-
-#define AGNX_CIR_ADDRWIN       0x3004  /* Addressable Windows*/
-#define AGNX_CIR_ENDIAN                0x3008  /* card endianness */
-#define AGNX_CIR_SERIALITF     0x3020  /* serial interface */
-#define AGNX_CIR_RXCFG         0x3040  /* receive config */
-#define                ENABLE_RX_INTERRUPT 0x20
-#define                RX_CACHE_LINE       0x8
-/* the RX fragment length */
-#define                FRAG_LEN_256    0x0 /* 256B */
-#define                FRAG_LEN_512    0x1
-#define                FRAG_LEN_1024   0x2
-#define                FRAG_LEN_2048   0x3
-#define                FRAG_BE         0x10
-#define AGNX_CIR_RXCTL         0x3050  /* receive control */
-/* memory address, chipside */
-#define AGNX_CIR_RXCMSTART     0x3054  /* receive client memory start */
-#define AGNX_CIR_RXCMEND       0x3058  /* receive client memory end */
-/* memory address, pci */
-#define AGNX_CIR_RXHOSTADDR    0x3060  /* receive hostside address */
-/* memory address, chipside */
-#define AGNX_CIR_RXCLIADDR     0x3064  /* receive clientside address */
-#define AGNX_CIR_RXDMACTL      0x3068  /* receive dma control */
-#define AGNX_CIR_TXCFG         0x3080  /* transmit config */
-#define AGNX_CIR_TXMCTL                0x3090 /* Transmit Management Control */
-#define                ENABLE_TX_INTERRUPT 0x20
-#define                TX_CACHE_LINE       0x8
-#define AGNX_CIR_TXMSTART      0x3094 /* Transmit Management Start */
-#define AGNX_CIR_TXMEND                0x3098 /* Transmit Management End */
-#define AGNX_CIR_TXDCTL                0x30a0  /* transmit data control */
-/* memeory address, chipset */
-#define AGNX_CIR_TXDSTART      0x30a4  /* transmit data start */
-#define AGNX_CIR_TXDEND                0x30a8  /* transmit data end */
-#define AGNX_CIR_TXMHADDR      0x30b0 /* Transmit Management Hostside Address */
-#define AGNX_CIR_TXMCADDR      0x30b4 /* Transmit Management Clientside Address */
-#define AGNX_CIR_TXDMACTL      0x30b8  /* transmit dma control */
-
-
-/* Power Managment Unit */
-#define AGNX_PM_BASE           0x3c00
-#define AGNX_PM_PMCTL          0x3c00  /* PM Control*/
-#define AGNX_PM_MACMSW         0x3c08 /* MAC Manual Slow Work Enable */
-#define AGNX_PM_RFCTL          0x3c0c /* RF Control */
-#define AGNX_PM_PHYMW          0x3c14  /* Phy Mannal Work */
-#define AGNX_PM_SOFTRST                0x3c18  /* PMU Soft Reset */
-#define AGNX_PM_PLLCTL         0x3c1c  /* PMU PLL control*/
-#define AGNX_PM_TESTPHY                0x3c24 /* PMU Test Phy */
-
-
-/* Interrupt Control interface */
-#define AGNX_INT_BASE          0x4000
-#define AGNX_INT_STAT          0x4000  /* interrupt status */
-#define AGNX_INT_MASK          0x400c  /* interrupt mask */
-/* FIXME */
-#define                IRQ_TX_BEACON   0x1     /* TX Beacon */
-#define                IRQ_TX_RETRY    0x8     /* TX Retry Interrupt */
-#define                IRQ_TX_ACTIVITY 0x10    /* TX Activity */
-#define                IRQ_RX_ACTIVITY 0x20    /* RX Activity */
-/* FIXME I guess that instead RX a none exist staion's packet or
-   the station hasn't been init */
-#define                IRQ_RX_X        0x40
-#define                IRQ_RX_Y        0x80    /* RX ? */
-#define                IRQ_RX_HASHHIT  0x100   /* RX Hash Hit */
-#define                IRQ_RX_FRAME    0x200   /* RX Frame */
-#define                IRQ_ERR_INT     0x400   /* Error Interrupt */
-#define                IRQ_TX_QUE_FULL 0x800   /* TX Workqueue Full */
-#define                IRQ_BANDMAN_ERR 0x10000 /* Bandwidth Management Error */
-#define                IRQ_TX_DISABLE  0x20000 /* TX Disable */
-#define                IRQ_RX_IVASESKEY 0x80000 /* RX Invalid Session Key */
-#define                IRQ_RX_KEYIDMIS 0x100000 /* RX key ID Mismatch */
-#define                IRQ_REP_THHIT   0x200000 /* Replay Threshold Hit */
-#define                IRQ_TIMER1      0x4000000 /* Timer1 */
-#define                IRQ_TIMER_CNT   0x10000000 /* Timer Count */
-#define                IRQ_PHY_FASTINT 0x20000000 /* Phy Fast Interrupt */
-#define                IRQ_PHY_SLOWINT 0x40000000 /* Phy Slow Interrupt */
-#define                IRQ_OTHER       0x80000000 /* Unknow interrupt */
-#define                AGNX_IRQ_ALL    0xffffffff
-
-/* System Interface */
-#define AGNX_SYSITF_BASE       0x4400
-#define AGNX_SYSITF_SYSMODE    0x4400  /* system mode */
-#define AGNX_SYSITF_GPIOIN     0x4410 /* GPIO In */
-/* PIN lines for leds? */
-#define AGNX_SYSITF_GPIOUT     0x4414  /* GPIO Out */
-
-/* Timer Control */
-#define AGNX_TIMCTL_TIMER1     0x4800 /* Timer 1 */
-#define AGNX_TIMCTL_TIM1CTL    0x4808 /* Timer 1 Control */
-
-
-/* Antenna Calibration Interface */
-#define AGNX_ACI_BASE          0x5000
-#define AGNX_ACI_MODE          0x5000 /* Mode */
-#define AGNX_ACI_MEASURE       0x5004 /* Measure */
-#define AGNX_ACI_SELCHAIN      0x5008 /* Select Chain */
-#define AGNX_ACI_LEN           0x500c /* Length */
-#define AGNX_ACI_TIMER1                0x5018 /* Timer 1 */
-#define AGNX_ACI_TIMER2                0x501c /* Timer 2 */
-#define AGNX_ACI_OFFSET                0x5020 /* Offset */
-#define AGNX_ACI_STATUS                0x5030 /* Status */
-#define                CALI_IDLE       0x0
-#define                CALI_DONE       0x1
-#define                CALI_BUSY       0x2
-#define                CALI_ERR        0x3
-#define AGNX_ACI_AICCHA0OVE    0x5034 /* AIC Channel 0 Override */
-#define AGNX_ACI_AICCHA1OVE    0x5038 /* AIC Channel 1 Override */
-
-/* Gain Control Registers */
-#define AGNX_GCR_BASE          0x9000
-/* threshold of primary antenna */
-#define AGNX_GCR_THD0A         0x9000  /* threshold? D0 A */
-/* low threshold of primary antenna */
-#define AGNX_GCR_THD0AL                0x9004  /* threshold? D0 A low */
-/* threshold of secondary antenna */
-#define AGNX_GCR_THD0B         0x9008  /* threshold? D0_B */
-#define AGNX_GCR_DUNSAT                0x900c /* d unsaturated */
-#define AGNX_GCR_DSAT          0x9010 /* d saturated */
-#define AGNX_GCR_DFIRCAL       0x9014 /* D Fir/Cal */
-#define AGNX_GCR_DGCTL11A      0x9018 /* d gain control 11a */
-#define AGNX_GCR_DGCTL11B      0x901c /* d gain control 11b */
-/* strength of gain */
-#define AGNX_GCR_GAININIT      0x9020  /* gain initialization */
-#define AGNX_GCR_THNOSIG       0x9024 /* threhold no signal */
-#define AGNX_GCR_COARSTEP      0x9028 /* coarse stepping */
-#define AGNX_GCR_SIFST11A      0x902c /* sifx time 11a */
-#define AGNX_GCR_SIFST11B      0x9030 /* sifx time 11b */
-#define AGNX_GCR_CWDETEC       0x9034 /* cw detection */
-#define AGNX_GCR_0X38          0x9038 /* ???? */
-#define AGNX_GCR_BOACT         0x903c  /* BO Active */
-#define AGNX_GCR_BOINACT       0x9040  /* BO Inactive */
-#define AGNX_GCR_BODYNA                0x9044  /* BO dynamic */
-/* 802.11 mode(a,b,g) */
-#define AGNX_GCR_DISCOVMOD     0x9048  /* discovery mode */
-#define AGNX_GCR_NLISTANT      0x904c  /* number of listening antenna */
-#define AGNX_GCR_NACTIANT      0x9050  /* number of active antenna */
-#define AGNX_GCR_NMEASANT      0x9054  /* number of measuring antenna */
-#define AGNX_GCR_NCAPTANT      0x9058  /* number of capture antenna */
-#define AGNX_GCR_THCAP11A      0x905c /* threshold capture 11a */
-#define AGNX_GCR_THCAP11B      0x9060 /* threshold capture 11b */
-#define AGNX_GCR_THCAPRX11A    0x9064 /* threshold capture rx 11a */
-#define AGNX_GCR_THCAPRX11B    0x9068 /* threshold capture rx 11b */
-#define AGNX_GCR_THLEVDRO      0x906c /* threshold level drop */
-#define AGNX_GCR_GAINSET0      0x9070 /* Gainset 0 */
-#define AGNX_GCR_GAINSET1      0x9074 /* Gainset 1 */
-#define AGNX_GCR_GAINSET2      0x9078 /* Gainset 2 */
-#define AGNX_GCR_MAXRXTIME11A  0x907c /* maximum rx time 11a */
-#define AGNX_GCR_MAXRXTIME11B  0x9080 /* maximum rx time 11b */
-#define AGNX_GCR_CORRTIME      0x9084 /* correction time */
-/* reset the subsystem, 0 = disable, 1 = enable */
-#define AGNX_GCR_RSTGCTL       0x9088  /* reset gain control */
-/* channel receiving */
-#define AGNX_GCR_RXCHANEL      0x908c  /* receive channel */
-#define AGNX_GCR_NOISE0                0x9090 /* Noise 0 */
-#define AGNX_GCR_NOISE1                0x9094 /* Noise 1 */
-#define AGNX_GCR_NOISE2                0x9098 /* Noise 2 */
-#define AGNX_GCR_SIGHTH                0x909c  /* Signal High Threshold */
-#define AGNX_GCR_SIGLTH                0x90a0  /* Signal Low Threshold */
-#define AGNX_GCR_CORRDROP      0x90a4 /* correction drop */
-/* threshold of tertiay antenna */
-#define AGNX_GCR_THCD          0x90a8  /* threshold? CD */
-#define AGNX_GCR_THCS          0x90ac  /* threshold? CS */
-#define AGNX_GCR_MAXPOWDIFF    0x90b8 /* maximum power difference */
-#define AGNX_GCR_TRACNT4       0x90ec /* Transition Count 4 */
-#define AGNX_GCR_TRACNT5       0x90f0  /* transition count 5 */
-#define AGNX_GCR_TRACNT6               0x90f4  /* transition count 6 */
-#define AGNX_GCR_TRACNT7               0x90f8  /* transition coutn 7 */
-#define AGNX_GCR_TESTBUS       0x911c /* test bus */
-#define AGNX_GCR_CHAINNUM      0x9120 /* Number of Chains */
-#define AGNX_GCR_ANTCFG                0x9124  /* Antenna Config */
-#define AGNX_GCR_THJUMP                0x912c /* threhold jump */
-#define AGNX_GCR_THPOWER       0x9130 /* threshold power */
-#define AGNX_GCR_THPOWCLIP     0x9134 /* threshold power clip*/
-#define AGNX_GCR_FORCECTLCLK   0x9138 /* Force Gain Control Clock */
-#define AGNX_GCR_GAINSETWRITE  0x913c /* Gainset Write */
-#define AGNX_GCR_THD0BTFEST    0x9140  /* threshold d0 b tf estimate */
-#define AGNX_GCR_THRX11BPOWMIN 0x9144  /* threshold rx 11b power minimum */
-#define AGNX_GCR_0X14c         0x914c /* ?? */
-#define AGNX_GCR_0X150         0x9150 /* ?? */
-#define AGNX_GCR_RXOVERIDE     0x9194  /* recieve override */
-#define AGNX_GCR_WATCHDOG      0x91b0  /* watchdog timeout */
-
-
-/* Spi Interface */
-#define AGNX_SPI_BASE          0xdc00
-#define AGNX_SPI_CFG           0xdc00 /* spi configuration */
-/* Only accept 16 bits */
-#define AGNX_SPI_WMSW          0xdc04  /* write most significant word */
-/* Only accept 16 bits */
-#define AGNX_SPI_WLSW          0xdc08  /* write least significant word */
-#define AGNX_SPI_CTL           0xdc0c  /* spi control */
-#define AGNX_SPI_RMSW          0xdc10 /* read most significant word */
-#define AGNX_SPI_RLSW          0xdc14 /* read least significant word */
-/* SPI Control Mask */
-#define                SPI_READ_CTL            0x4000 /* read control */
-#define                SPI_BUSY_CTL            0x8000 /* busy control */
-/* RF and synth chips in spi */
-#define                RF_CHIP0        0x400
-#define                RF_CHIP1        0x800
-#define                RF_CHIP2        0x1000
-#define                SYNTH_CHIP      0x2000
-
-/* Unknown register */
-#define AGNX_UNKNOWN_BASE      0x7800
-
-/* FIXME MonitorGain */
-#define AGNX_MONGCR_BASE       0x12000
-
-/* Gain Table */
-#define AGNX_GAIN_TABLE                0x12400
-
-/* The initial FIR coefficient table */
-#define AGNX_FIR_BASE          0x19804
-
-#define AGNX_ENGINE_LOOKUP_TBL 0x800
-
-/* eeprom commands */
-#define EEPROM_CMD_NULL                0x0 /* NULL */
-#define EEPROM_CMD_WRITE       0x2 /* write */
-#define EEPROM_CMD_READ                0x3 /* read */
-#define EEPROM_CMD_STATUSREAD  0x5 /* status register read */
-#define EEPROM_CMD_WRITEENABLE 0x6 /* write enable */
-#define EEPROM_CMD_CONFIGURE   0x7 /* configure */
-
-#define EEPROM_DATAFORCOFIGURE 0x6 /* ??? */
-
-/* eeprom address */
-#define EEPROM_ADDR_SUBVID     0x0 /* Sub Vendor ID */
-#define EEPROM_ADDR_SUBSID     0x2 /* Sub System ID */
-#define EEPROM_ADDR_MACADDR    0x146 /* MAC Address */
-#define EEPROM_ADDR_LOTYPE     0x14f /* LO type */
-
-struct agnx_eeprom {
-       u8 data;        /* date */
-       u16 address;    /* address in EEPROM */
-       u8 cmd;         /* command, unknown, status */
-}  __attribute__((__packed__));
-
-#define AGNX_EEPROM_COMMAND_SHIFT      5
-#define AGNX_EEPROM_COMMAND_STAT       0x01
-
-void disable_receiver(struct agnx_priv *priv);
-void enable_receiver(struct agnx_priv *priv);
-u8 read_from_eeprom(struct agnx_priv *priv, u16 address);
-void agnx_hw_init(struct agnx_priv *priv);
-int agnx_hw_reset(struct agnx_priv *priv);
-int agnx_set_ssid(struct agnx_priv *priv, u8 *ssid, size_t ssid_len);
-void agnx_set_bssid(struct agnx_priv *priv, const u8 *bssid);
-void enable_power_saving(struct agnx_priv *priv);
-void disable_power_saving(struct agnx_priv *priv);
-void calibrate_antenna_period(unsigned long data);
-
-#endif /* AGNX_PHY_H_ */
diff --git a/drivers/staging/agnx/rf.c b/drivers/staging/agnx/rf.c
deleted file mode 100644 (file)
index 42e457a..0000000
+++ /dev/null
@@ -1,893 +0,0 @@
-/**
- * Airgo MIMO wireless driver
- *
- * Copyright (c) 2007 Li YanBo <dreamfly281@gmail.com>
-
- * Thanks for Jeff Williams <angelbane@gmail.com> do reverse engineer
- * works and published the SPECS at http://airgo.wdwconsulting.net/mymoin
-
- * 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/pci.h>
-#include <linux/delay.h>
-#include "agnx.h"
-#include "debug.h"
-#include "phy.h"
-#include "table.h"
-
-/* FIXME! */
-static inline void spi_write(void __iomem *region, u32 chip_ids, u32 sw,
-                     u16 size, u32 control)
-{
-       u32 reg;
-       u32 lsw = sw & 0xffff;          /* lower 16 bits of sw*/
-       u32 msw = sw >> 16;             /* high 16 bits of sw */
-
-       /* FIXME Write Most Significant Word of the 32bit data to MSW */
-       /* FIXME And Least Significant Word to LSW */
-       iowrite32((lsw), region + AGNX_SPI_WLSW);
-       iowrite32((msw), region + AGNX_SPI_WMSW);
-       reg = chip_ids | size | control;
-       /* Write chip id(s), write size and busy control to Control Register */
-       iowrite32((reg), region + AGNX_SPI_CTL);
-       /* Wait for Busy control to clear */
-       spi_delay();
-}
-
-/*
- * Write to SPI Synth register
- */
-static inline void spi_sy_write(void __iomem *region, u32 chip_ids, u32 sw)
-{
-       /* FIXME the size 0x15 is a magic value*/
-       spi_write(region, chip_ids, sw, 0x15, SPI_BUSY_CTL);
-}
-
-/*
- * Write to SPI RF register
- */
-static inline void spi_rf_write(void __iomem *region, u32 chip_ids, u32 sw)
-{
-       /* FIXME the size 0xd is a magic value*/
-       spi_write(region, chip_ids, sw, 0xd, SPI_BUSY_CTL);
-} /* spi_rf_write */
-
-/*
- * Write to SPI with Read Control bit set
- */
-inline void spi_rc_write(void __iomem *region, u32 chip_ids, u32 sw)
-{
-       /* FIXME the size 0xe5 is a magic value */
-       spi_write(region, chip_ids, sw, 0xe5, SPI_BUSY_CTL|SPI_READ_CTL);
-}
-
-/* Get the active chains's count */
-static int get_active_chains(struct agnx_priv *priv)
-{
-       void __iomem *ctl = priv->ctl;
-       int num = 0;
-       u32 reg;
-       AGNX_TRACE;
-
-       spi_rc_write(ctl, RF_CHIP0, 0x21);
-       reg = agnx_read32(ctl, AGNX_SPI_RLSW);
-       if (reg == 1)
-               num++;
-
-       spi_rc_write(ctl, RF_CHIP1, 0x21);
-       reg = agnx_read32(ctl, AGNX_SPI_RLSW);
-       if (reg == 1)
-               num++;
-
-       spi_rc_write(ctl, RF_CHIP2, 0x21);
-       reg = agnx_read32(ctl, AGNX_SPI_RLSW);
-       if (reg == 1)
-               num++;
-
-       spi_rc_write(ctl, RF_CHIP0, 0x26);
-       reg = agnx_read32(ctl, AGNX_SPI_RLSW);
-       if (0x33 != reg)
-               printk(KERN_WARNING PFX "Unmatched rf chips result\n");
-
-       return num;
-} /* get_active_chains */
-
-void rf_chips_init(struct agnx_priv *priv)
-{
-       void __iomem *ctl = priv->ctl;
-       u32 reg;
-       int num;
-       AGNX_TRACE;
-
-       if (priv->revid == 1) {
-               reg = agnx_read32(ctl, AGNX_SYSITF_GPIOUT);
-               reg |= 0x8;
-               agnx_write32(ctl, AGNX_SYSITF_GPIOUT, reg);
-       }
-
-       /* Set SPI clock speed to 200NS */
-       reg = agnx_read32(ctl, AGNX_SPI_CFG);
-       reg &= ~0xF;
-       reg |= 0x3;
-       agnx_write32(ctl, AGNX_SPI_CFG, reg);
-
-       /* Set SPI clock speed to 50NS */
-       reg = agnx_read32(ctl, AGNX_SPI_CFG);
-       reg &= ~0xF;
-       reg |= 0x1;
-       agnx_write32(ctl, AGNX_SPI_CFG, reg);
-
-       spi_rf_write(ctl, RF_CHIP0|RF_CHIP1|RF_CHIP2, 0x1101);
-
-       num = get_active_chains(priv);
-       printk(KERN_INFO PFX "Active chains are %d\n", num);
-
-       reg = agnx_read32(ctl, AGNX_SPI_CFG);
-       reg &= ~0xF;
-       agnx_write32(ctl, AGNX_SPI_CFG, reg);
-
-       spi_rf_write(ctl, RF_CHIP0|RF_CHIP1|RF_CHIP2, 0x1908);
-} /* rf_chips_init */
-
-
-static u32 channel_tbl[15][9] = {
-       {0,  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-       {1,  0x00, 0x00, 0x624, 0x00, 0x1a4, 0x28, 0x00, 0x1e},
-       {2,  0x00, 0x00, 0x615, 0x00, 0x1ae, 0x28, 0x00, 0x1e},
-       {3,  0x00, 0x00, 0x61a, 0x00, 0x1ae, 0x28, 0x00, 0x1e},
-       {4,  0x00, 0x00, 0x61f, 0x00, 0x1ae, 0x28, 0x00, 0x1e},
-       {5,  0x00, 0x00, 0x624, 0x00, 0x1ae, 0x28, 0x00, 0x1e},
-       {6,  0x00, 0x00, 0x61f, 0x00, 0x1b3, 0x28, 0x00, 0x1e},
-       {7,  0x00, 0x00, 0x624, 0x00, 0x1b3, 0x28, 0x00, 0x1e},
-       {8,  0x00, 0x00, 0x629, 0x00, 0x1b3, 0x28, 0x00, 0x1e},
-       {9,  0x00, 0x00, 0x624, 0x00, 0x1b8, 0x28, 0x00, 0x1e},
-       {10, 0x00, 0x00, 0x629, 0x00, 0x1b8, 0x28, 0x00, 0x1e},
-       {11, 0x00, 0x00, 0x62e, 0x00, 0x1b8, 0x28, 0x00, 0x1e},
-       {12, 0x00, 0x00, 0x633, 0x00, 0x1b8, 0x28, 0x00, 0x1e},
-       {13, 0x00, 0x00, 0x628, 0x00, 0x1b8, 0x28, 0x00, 0x1e},
-       {14, 0x00, 0x00, 0x644, 0x00, 0x1b8, 0x28, 0x00, 0x1e},
-};
-
-
-static inline void
-channel_tbl_write(struct agnx_priv *priv, unsigned int channel, unsigned int reg_num)
-{
-       void __iomem *ctl = priv->ctl;
-       u32 reg;
-
-       reg = channel_tbl[channel][reg_num];
-       reg <<= 4;
-       reg |= reg_num;
-       spi_sy_write(ctl, SYNTH_CHIP, reg);
-}
-
-static void synth_freq_set(struct agnx_priv *priv, unsigned int channel)
-{
-       void __iomem *ctl = priv->ctl;
-       u32 reg;
-       AGNX_TRACE;
-
-       spi_rf_write(ctl, RF_CHIP0|RF_CHIP1, 0x1201);
-
-       /* Set the Clock bits to 50NS */
-       reg = agnx_read32(ctl, AGNX_SPI_CFG);
-       reg &= ~0xF;
-       reg |= 0x1;
-       agnx_write32(ctl, AGNX_SPI_CFG, reg);
-
-       /* Write 0x00c0 to LSW and 0x3 to MSW of Synth Chip */
-       spi_sy_write(ctl, SYNTH_CHIP, 0x300c0);
-
-       spi_sy_write(ctl, SYNTH_CHIP, 0x32);
-
-       /* # Write to Register 1 on the Synth Chip */
-       channel_tbl_write(priv, channel, 1);
-       /* # Write to Register 3 on the Synth Chip */
-       channel_tbl_write(priv, channel, 3);
-       /* # Write to Register 6 on the Synth Chip */
-       channel_tbl_write(priv, channel, 6);
-       /* # Write to Register 5 on the Synth Chip */
-       channel_tbl_write(priv, channel, 5);
-       /* # Write to register 8 on the Synth Chip */
-       channel_tbl_write(priv, channel, 8);
-
-       /* FIXME Clear the clock bits */
-       reg = agnx_read32(ctl, AGNX_SPI_CFG);
-       reg &= ~0xf;
-       agnx_write32(ctl, AGNX_SPI_CFG, reg);
-} /* synth_chip_init */
-
-
-static void antenna_init(struct agnx_priv *priv, int num_antenna)
-{
-       void __iomem *ctl = priv->ctl;
-
-       switch (num_antenna) {
-       case 1:
-               agnx_write32(ctl, AGNX_GCR_NLISTANT, 1);
-               agnx_write32(ctl, AGNX_GCR_NMEASANT, 1);
-               agnx_write32(ctl, AGNX_GCR_NACTIANT, 1);
-               agnx_write32(ctl, AGNX_GCR_NCAPTANT, 1);
-
-               agnx_write32(ctl, AGNX_GCR_ANTCFG, 7);
-               agnx_write32(ctl, AGNX_GCR_BOACT, 34);
-               agnx_write32(ctl, AGNX_GCR_BOINACT, 34);
-               agnx_write32(ctl, AGNX_GCR_BODYNA, 30);
-
-               agnx_write32(ctl, AGNX_GCR_THD0A, 125);
-               agnx_write32(ctl, AGNX_GCR_THD0AL, 100);
-               agnx_write32(ctl, AGNX_GCR_THD0B, 90);
-
-               agnx_write32(ctl, AGNX_GCR_THD0BTFEST, 80);
-               agnx_write32(ctl, AGNX_GCR_SIGHTH, 100);
-               agnx_write32(ctl, AGNX_GCR_SIGLTH, 16);
-               break;
-       case 2:
-               agnx_write32(ctl, AGNX_GCR_NLISTANT, 2);
-               agnx_write32(ctl, AGNX_GCR_NMEASANT, 2);
-               agnx_write32(ctl, AGNX_GCR_NACTIANT, 2);
-               agnx_write32(ctl, AGNX_GCR_NCAPTANT, 2);
-               agnx_write32(ctl, AGNX_GCR_ANTCFG, 15);
-               agnx_write32(ctl, AGNX_GCR_BOACT, 36);
-               agnx_write32(ctl, AGNX_GCR_BOINACT, 36);
-               agnx_write32(ctl, AGNX_GCR_BODYNA, 32);
-               agnx_write32(ctl, AGNX_GCR_THD0A, 120);
-               agnx_write32(ctl, AGNX_GCR_THD0AL, 100);
-               agnx_write32(ctl, AGNX_GCR_THD0B, 80);
-               agnx_write32(ctl, AGNX_GCR_THD0BTFEST, 70);
-               agnx_write32(ctl, AGNX_GCR_SIGHTH, 100);
-               agnx_write32(ctl, AGNX_GCR_SIGLTH, 32);
-               break;
-       case 3:
-               agnx_write32(ctl, AGNX_GCR_NLISTANT, 3);
-               agnx_write32(ctl, AGNX_GCR_NMEASANT, 3);
-               agnx_write32(ctl, AGNX_GCR_NACTIANT, 3);
-               agnx_write32(ctl, AGNX_GCR_NCAPTANT, 3);
-               agnx_write32(ctl, AGNX_GCR_ANTCFG, 31);
-               agnx_write32(ctl, AGNX_GCR_BOACT, 36);
-               agnx_write32(ctl, AGNX_GCR_BOINACT, 36);
-               agnx_write32(ctl, AGNX_GCR_BODYNA, 32);
-               agnx_write32(ctl, AGNX_GCR_THD0A, 100);
-               agnx_write32(ctl, AGNX_GCR_THD0AL, 100);
-               agnx_write32(ctl, AGNX_GCR_THD0B, 70);
-               agnx_write32(ctl, AGNX_GCR_THD0BTFEST, 70);
-               agnx_write32(ctl, AGNX_GCR_SIGHTH, 100);
-               agnx_write32(ctl, AGNX_GCR_SIGLTH, 48);
-/*             agnx_write32(ctl, AGNX_GCR_SIGLTH, 16); */
-               break;
-       default:
-               printk(KERN_WARNING PFX "Unknow antenna number\n");
-       }
-} /* antenna_init */
-
-static void chain_update(struct agnx_priv *priv, u32 chain)
-{
-       void __iomem *ctl = priv->ctl;
-       u32 reg;
-       AGNX_TRACE;
-
-       spi_rc_write(ctl, RF_CHIP0, 0x20);
-       reg = agnx_read32(ctl, AGNX_SPI_RLSW);
-
-       if (reg == 0x4)
-               spi_rf_write(ctl, RF_CHIP0|RF_CHIP1, reg|0x1000);
-       else if (reg != 0x0)
-               spi_rf_write(ctl, RF_CHIP0|RF_CHIP1|RF_CHIP2, reg|0x1000);
-       else {
-               if (chain == 3 || chain == 6) {
-                       spi_rf_write(ctl, RF_CHIP0|RF_CHIP1|RF_CHIP2, reg|0x1000);
-                       agnx_write32(ctl, AGNX_GCR_RXOVERIDE, 0x0);
-               } else if (chain == 2 || chain == 4) {
-                       spi_rf_write(ctl, RF_CHIP0|RF_CHIP1, reg|0x1000);
-                       spi_rf_write(ctl, RF_CHIP2, 0x1005);
-                       agnx_write32(ctl, AGNX_GCR_RXOVERIDE, 0x824);
-               } else if (chain == 1) {
-                       spi_rf_write(ctl, RF_CHIP0, reg|0x1000);
-                       spi_rf_write(ctl, RF_CHIP1|RF_CHIP2, 0x1004);
-                       agnx_write32(ctl, AGNX_GCR_RXOVERIDE, 0xc36);
-               }
-       }
-
-       spi_rc_write(ctl, RF_CHIP0, 0x22);
-       reg = agnx_read32(ctl, AGNX_SPI_RLSW);
-
-       switch (reg) {
-       case 0:
-               spi_rf_write(ctl, RF_CHIP0|RF_CHIP1|RF_CHIP2, 0x1005);
-               break;
-       case 1:
-               spi_rf_write(ctl, RF_CHIP0|RF_CHIP1, 0x1201);
-               break;
-       case 2:
-               if (chain == 6 || chain == 4) {
-                       spi_rf_write(ctl, RF_CHIP0|RF_CHIP1, 0x1202);
-                       spi_rf_write(ctl, RF_CHIP2, 0x1005);
-               } else if (chain < 3) {
-                       spi_rf_write(ctl, RF_CHIP0, 0x1202);
-                       spi_rf_write(ctl, RF_CHIP1|RF_CHIP2, 0x1005);
-               }
-               break;
-       default:
-               if (chain == 3) {
-                       spi_rf_write(ctl, RF_CHIP0|RF_CHIP1, 0x1203);
-                       spi_rf_write(ctl, RF_CHIP2, 0x1201);
-               } else if (chain == 2) {
-                       spi_rf_write(ctl, RF_CHIP0, 0x1203);
-                       spi_rf_write(ctl, RF_CHIP2, 0x1200);
-                       spi_rf_write(ctl, RF_CHIP1, 0x1201);
-               } else if (chain == 1) {
-                       spi_rf_write(ctl, RF_CHIP0, 0x1203);
-                       spi_rf_write(ctl, RF_CHIP1|RF_CHIP2, 0x1200);
-               } else if (chain == 4) {
-                       spi_rf_write(ctl, RF_CHIP0|RF_CHIP1, 0x1203);
-                       spi_rf_write(ctl, RF_CHIP2, 0x1201);
-               } else {
-                       spi_rf_write(ctl, RF_CHIP0, 0x1203);
-                       spi_rf_write(ctl, RF_CHIP1|RF_CHIP2, 0x1201);
-               }
-       }
-} /* chain_update */
-
-static void antenna_config(struct agnx_priv *priv)
-{
-       void __iomem *ctl = priv->ctl;
-       u32 reg;
-       AGNX_TRACE;
-
-       /* Write 0x0 to the TX Management Control Register Enable bit */
-       reg = agnx_read32(ctl, AGNX_TXM_CTL);
-       reg &= ~0x1;
-       agnx_write32(ctl, AGNX_TXM_CTL, reg);
-
-       /* FIXME */
-       /* Set initial value based on number of Antennae */
-       antenna_init(priv, 3);
-
-       /* FIXME Update Power Templates for current valid Stations */
-       /* sta_power_init(priv, 0);*/
-
-       /* FIXME the number of chains should get from eeprom*/
-       chain_update(priv, AGNX_CHAINS_MAX);
-} /* antenna_config */
-
-void calibrate_oscillator(struct agnx_priv *priv)
-{
-       void __iomem *ctl = priv->ctl;
-       u32 reg;
-       AGNX_TRACE;
-
-       spi_rc_write(ctl, RF_CHIP0|RF_CHIP1, 0x1201);
-       reg = agnx_read32(ctl, AGNX_GCR_GAINSET1);
-       reg |= 0x10;
-       agnx_write32(ctl, AGNX_GCR_GAINSET1, reg);
-
-       agnx_write32(ctl, AGNX_GCR_GAINSETWRITE, 1);
-       agnx_write32(ctl, AGNX_GCR_RSTGCTL, 1);
-
-       agnx_write32(ctl, AGNX_ACI_LEN, 0x3ff);
-
-       agnx_write32(ctl, AGNX_ACI_TIMER1, 0x27);
-       agnx_write32(ctl, AGNX_ACI_TIMER2, 0x27);
-       /* (Residual DC Calibration) to Calibration Mode */
-       agnx_write32(ctl, AGNX_ACI_MODE, 0x2);
-
-       spi_rc_write(ctl, RF_CHIP0|RF_CHIP1, 0x1004);
-       agnx_write32(ctl, AGNX_ACI_LEN, 0x3ff);
-       /* (TX LO Calibration) to Calibration Mode */
-       agnx_write32(ctl, AGNX_ACI_MODE, 0x4);
-
-       do {
-               u32  reg1, reg2, reg3;
-               /* Enable Power Saving Control */
-               enable_power_saving(priv);
-               /* Save the following registers to restore */
-               reg1 = ioread32(ctl + 0x11000);
-               reg2 = ioread32(ctl + 0xec50);
-               reg3 = ioread32(ctl + 0xec54);
-               wmb();
-
-               agnx_write32(ctl, 0x11000, 0xcfdf);
-               agnx_write32(ctl, 0xec50, 0x70);
-               /* Restore the registers */
-               agnx_write32(ctl, 0x11000, reg1);
-               agnx_write32(ctl, 0xec50, reg2);
-               agnx_write32(ctl, 0xec54, reg3);
-               /* Disable Power Saving Control */
-               disable_power_saving(priv);
-       } while (0);
-
-       agnx_write32(ctl, AGNX_GCR_RSTGCTL, 0);
-} /* calibrate_oscillator */
-
-
-static void radio_channel_set(struct agnx_priv *priv, unsigned int channel)
-{
-       void __iomem *ctl = priv->ctl;
-       unsigned int freq = priv->band.channels[channel - 1].center_freq;
-       u32 reg;
-       AGNX_TRACE;
-
-       spi_rf_write(ctl, RF_CHIP0|RF_CHIP1, 0x1201);
-       /* Set SPI Clock to 50 Ns */
-       reg = agnx_read32(ctl, AGNX_SPI_CFG);
-       reg &= ~0xF;
-       reg |= 0x1;
-       agnx_write32(ctl, AGNX_SPI_CFG, reg);
-
-       /* Clear the Disable Tx interrupt bit in Interrupt Mask */
-/*     reg = agnx_read32(ctl, AGNX_INT_MASK); */
-/*     reg &= ~IRQ_TX_DISABLE; */
-/*     agnx_write32(ctl, AGNX_INT_MASK, reg); */
-
-       /* Band Selection */
-       reg = agnx_read32(ctl, AGNX_SYSITF_GPIOUT);
-       reg |= 0x8;
-       agnx_write32(ctl, AGNX_SYSITF_GPIOUT, reg);
-
-       /* FIXME Set the SiLabs Chip Frequency */
-       synth_freq_set(priv, channel);
-
-       reg = agnx_read32(ctl, AGNX_PM_SOFTRST);
-       reg |= 0x80100030;
-       agnx_write32(ctl, AGNX_PM_SOFTRST, reg);
-       reg = agnx_read32(ctl, AGNX_PM_PLLCTL);
-       reg |= 0x20009;
-       agnx_write32(ctl, AGNX_PM_PLLCTL, reg);
-
-       agnx_write32(ctl, AGNX_SYSITF_GPIOUT, 0x5);
-
-       spi_rf_write(ctl, RF_CHIP0|RF_CHIP1|RF_CHIP2, 0x1100);
-
-       /* Load the MonitorGain Table */
-       monitor_gain_table_init(priv);
-
-       /* Load the TX Fir table */
-       tx_fir_table_init(priv);
-
-       reg = agnx_read32(ctl, AGNX_PM_PMCTL);
-       reg |= 0x8;
-       agnx_write32(ctl, AGNX_PM_PMCTL, reg);
-
-       spi_rc_write(ctl, RF_CHIP0|RF_CHIP1, 0x22);
-       udelay(80);
-       reg = agnx_read32(ctl, AGNX_SPI_RLSW);
-
-
-       agnx_write32(ctl, AGNX_GCR_RXOVERIDE, 0xff);
-       agnx_write32(ctl, AGNX_GCR_DISCOVMOD, 0x3);
-
-       reg = agnx_read32(ctl, 0xec50);
-       reg |= 0x4f;
-       agnx_write32(ctl, 0xec50, reg);
-
-       spi_rf_write(ctl, RF_CHIP0|RF_CHIP1, 0x1201);
-       agnx_write32(ctl, 0x11008, 0x1);
-       agnx_write32(ctl, 0x1100c, 0x0);
-       agnx_write32(ctl, 0x11008, 0x0);
-       agnx_write32(ctl, 0xec50, 0xc);
-
-       agnx_write32(ctl, AGNX_GCR_DISCOVMOD, 0x3);
-       agnx_write32(ctl, AGNX_GCR_RXOVERIDE, 0x0);
-       agnx_write32(ctl, 0x11010, 0x6e);
-       agnx_write32(ctl, 0x11014, 0x6c);
-
-       spi_rf_write(ctl, RF_CHIP0|RF_CHIP1, 0x1201);
-
-       /* Calibrate the Antenna */
-       /* antenna_calibrate(priv); */
-       /* Calibrate the TxLocalOscillator */
-       calibrate_oscillator(priv);
-
-       reg = agnx_read32(ctl, AGNX_PM_PMCTL);
-       reg &= ~0x8;
-       agnx_write32(ctl, AGNX_PM_PMCTL, reg);
-       agnx_write32(ctl, AGNX_GCR_GAININIT, 0xa);
-       agnx_write32(ctl, AGNX_GCR_THCD, 0x0);
-
-       agnx_write32(ctl, 0x11018, 0xb);
-       agnx_write32(ctl, AGNX_GCR_DISCOVMOD, 0x0);
-
-       /* Write Frequency to Gain Control Channel */
-       agnx_write32(ctl, AGNX_GCR_RXCHANEL, freq);
-       /* Write 0x140000/Freq to 0x9c08 */
-       reg = 0x140000/freq;
-       agnx_write32(ctl, 0x9c08, reg);
-
-       reg = agnx_read32(ctl, AGNX_PM_SOFTRST);
-       reg &= ~0x80100030;
-       agnx_write32(ctl, AGNX_PM_SOFTRST, reg);
-
-       reg = agnx_read32(ctl, AGNX_PM_PLLCTL);
-       reg &= ~0x20009;
-       reg |= 0x1;
-       agnx_write32(ctl, AGNX_PM_PLLCTL, reg);
-
-       agnx_write32(ctl, AGNX_ACI_MODE, 0x0);
-
-/* FIXME According to Number of Chains: */
-
-/*                        1. 1: */
-/*          1. Write 0x1203 to RF Chip 0 */
-/*          2. Write 0x1200 to RF Chips 1 +2  */
-/*                        2. 2: */
-/*          1. Write 0x1203 to RF Chip 0 */
-/*          2. Write 0x1200 to RF Chip 2 */
-/*          3. Write 0x1201 to RF Chip 1  */
-/*                        3. 3: */
-/*          1. Write 0x1203 to RF Chip 0 */
-/*          2. Write 0x1201 to RF Chip 1 + 2  */
-/*                        4. 4: */
-/*          1. Write 0x1203 to RF Chip 0 + 1 */
-/*          2. Write 0x1200 to RF Chip 2  */
-
-/*                        5. 6: */
-       spi_rf_write(ctl, RF_CHIP0|RF_CHIP1, 0x1203);
-       spi_rf_write(ctl, RF_CHIP2, 0x1201);
-
-       spi_rf_write(ctl, RF_CHIP0|RF_CHIP1|RF_CHIP2, 0x1000);
-       agnx_write32(ctl, AGNX_GCR_RXOVERIDE, 0x0);
-
-       /* FIXME Set the Disable Tx interrupt bit in Interrupt Mask
-          (Or 0x20000 to Interrupt Mask) */
-/*     reg = agnx_read32(ctl, AGNX_INT_MASK); */
-/*     reg |= IRQ_TX_DISABLE; */
-/*     agnx_write32(ctl, AGNX_INT_MASK, reg); */
-
-       agnx_write32(ctl, AGNX_GCR_RSTGCTL, 0x1);
-       agnx_write32(ctl, AGNX_GCR_RSTGCTL, 0x0);
-
-       /* Configure the Antenna */
-       antenna_config(priv);
-
-       /* Write 0x0 to Discovery Mode Enable detect G, B, A packet? */
-       agnx_write32(ctl, AGNX_GCR_DISCOVMOD, 0);
-
-       reg = agnx_read32(ctl, AGNX_RXM_REQRATE);
-       reg |= 0x80000000;
-       agnx_write32(ctl, AGNX_RXM_REQRATE, reg);
-       agnx_write32(ctl, AGNX_GCR_RSTGCTL, 0x1);
-       agnx_write32(ctl, AGNX_GCR_RSTGCTL, 0x0);
-
-       /* enable radio on and the power LED */
-       reg = agnx_read32(ctl, AGNX_SYSITF_GPIOUT);
-       reg &= ~0x1;
-       reg |= 0x2;
-       agnx_write32(ctl, AGNX_SYSITF_GPIOUT, reg);
-
-       reg = agnx_read32(ctl, AGNX_TXM_CTL);
-       reg |= 0x1;
-       agnx_write32(ctl, AGNX_TXM_CTL, reg);
-} /* radio_channel_set */
-
-static void base_band_filter_calibrate(struct agnx_priv *priv)
-{
-       void __iomem *ctl = priv->ctl;
-
-       spi_rf_write(ctl, RF_CHIP0|RF_CHIP1|RF_CHIP2, 0x1700);
-       spi_rf_write(ctl, RF_CHIP0|RF_CHIP1|RF_CHIP2, 0x1001);
-       agnx_write32(ctl, AGNX_GCR_FORCECTLCLK, 0x0);
-       spi_rc_write(ctl, RF_CHIP0, 0x27);
-       spi_rc_write(ctl, RF_CHIP1, 0x27);
-       spi_rc_write(ctl, RF_CHIP2, 0x27);
-       agnx_write32(ctl, AGNX_GCR_FORCECTLCLK, 0x1);
-}
-
-static void print_offset(struct agnx_priv *priv, u32 chain)
-{
-       void __iomem *ctl = priv->ctl;
-       u32 offset;
-
-       iowrite32((chain), ctl + AGNX_ACI_SELCHAIN);
-       udelay(10);
-       offset = (ioread32(ctl + AGNX_ACI_OFFSET));
-       printk(PFX "Chain is 0x%x, Offset is 0x%x\n", chain, offset);
-}
-
-void print_offsets(struct agnx_priv *priv)
-{
-       print_offset(priv, 0);
-       print_offset(priv, 4);
-       print_offset(priv, 1);
-       print_offset(priv, 5);
-       print_offset(priv, 2);
-       print_offset(priv, 6);
-}
-
-
-struct chains {
-       u32 cali;               /* calibrate  value*/
-
-#define  NEED_CALIBRATE                0
-#define  SUCCESS_CALIBRATE     1
-       int status;
-};
-
-static void chain_calibrate(struct agnx_priv *priv, struct chains *chains,
-                           unsigned int num)
-{
-       void __iomem *ctl = priv->ctl;
-       u32 calibra = chains[num].cali;
-
-       if (num < 3)
-               calibra |= 0x1400;
-       else
-               calibra |= 0x1500;
-
-       switch (num) {
-       case 0:
-       case 4:
-               spi_rf_write(ctl, RF_CHIP0, calibra);
-               break;
-       case 1:
-       case 5:
-               spi_rf_write(ctl, RF_CHIP1, calibra);
-               break;
-       case 2:
-       case 6:
-               spi_rf_write(ctl, RF_CHIP2, calibra);
-               break;
-       default:
-               BUG();
-       }
-} /* chain_calibrate */
-
-static inline void get_calibrete_value(struct agnx_priv *priv, struct chains *chains,
-                                      unsigned int num)
-{
-       void __iomem *ctl = priv->ctl;
-       u32 offset;
-
-       iowrite32((num), ctl + AGNX_ACI_SELCHAIN);
-       /* FIXME */
-       udelay(10);
-       offset = (ioread32(ctl + AGNX_ACI_OFFSET));
-
-       if (offset < 0xf) {
-               chains[num].status = SUCCESS_CALIBRATE;
-               return;
-       }
-
-       if (num == 0 || num == 1 || num == 2) {
-               if (0 == chains[num].cali)
-                       chains[num].cali = 0xff;
-               else
-                       chains[num].cali--;
-       } else
-               chains[num].cali++;
-
-       chains[num].status = NEED_CALIBRATE;
-}
-
-static inline void calibra_delay(struct agnx_priv *priv)
-{
-       void __iomem *ctl = priv->ctl;
-       u32 reg;
-       unsigned int i = 100;
-
-       wmb();
-       while (--i) {
-               reg = (ioread32(ctl + AGNX_ACI_STATUS));
-               if (reg == 0x4000)
-                       break;
-               udelay(10);
-       }
-       if (!i)
-               printk(PFX "calibration failed\n");
-}
-
-void do_calibration(struct agnx_priv *priv)
-{
-       void __iomem *ctl = priv->ctl;
-       struct chains chains[7];
-       unsigned int i, j;
-       AGNX_TRACE;
-
-       for (i = 0; i < 7; i++) {
-               if (i == 3)
-                       continue;
-
-               chains[i].cali = 0x7f;
-               chains[i].status = NEED_CALIBRATE;
-       }
-
-       /* FIXME 0x300 is a magic number */
-       for (j = 0; j < 0x300; j++) {
-               if (chains[0].status == SUCCESS_CALIBRATE &&
-                   chains[1].status == SUCCESS_CALIBRATE &&
-                   chains[2].status == SUCCESS_CALIBRATE &&
-                   chains[4].status == SUCCESS_CALIBRATE &&
-                   chains[5].status == SUCCESS_CALIBRATE &&
-                   chains[6].status == SUCCESS_CALIBRATE)
-                       break;
-
-               /* Attention, there is no chain 3 */
-               for (i = 0; i < 7; i++) {
-                       if (i == 3)
-                               continue;
-                       if (chains[i].status == NEED_CALIBRATE)
-                               chain_calibrate(priv, chains, i);
-               }
-               /* Write 0x1 to Calibration Measure */
-               iowrite32((0x1), ctl + AGNX_ACI_MEASURE);
-               calibra_delay(priv);
-
-               for (i = 0; i < 7; i++) {
-                       if (i == 3)
-                               continue;
-
-                       get_calibrete_value(priv, chains, i);
-               }
-       }
-       printk(PFX "Clibrate times is %d\n", j);
-       print_offsets(priv);
-} /* do_calibration */
-
-void antenna_calibrate(struct agnx_priv *priv)
-{
-       void __iomem *ctl = priv->ctl;
-       u32 reg;
-       AGNX_TRACE;
-
-       agnx_write32(ctl, AGNX_GCR_NLISTANT, 0x3);
-       agnx_write32(ctl, AGNX_GCR_NMEASANT, 0x3);
-       agnx_write32(ctl, AGNX_GCR_NACTIANT, 0x3);
-       agnx_write32(ctl, AGNX_GCR_NCAPTANT, 0x3);
-
-       agnx_write32(ctl, AGNX_GCR_ANTCFG, 0x1f);
-       agnx_write32(ctl, AGNX_GCR_BOACT, 0x24);
-       agnx_write32(ctl, AGNX_GCR_BOINACT, 0x24);
-       agnx_write32(ctl, AGNX_GCR_BODYNA, 0x20);
-       agnx_write32(ctl, AGNX_GCR_THD0A, 0x64);
-       agnx_write32(ctl, AGNX_GCR_THD0AL, 0x64);
-       agnx_write32(ctl, AGNX_GCR_THD0B, 0x46);
-       agnx_write32(ctl, AGNX_GCR_THD0BTFEST, 0x3c);
-       agnx_write32(ctl, AGNX_GCR_SIGHTH, 0x64);
-       agnx_write32(ctl, AGNX_GCR_SIGLTH, 0x30);
-
-       spi_rc_write(ctl, RF_CHIP0, 0x20);
-       /* Fixme */
-       udelay(80);
-       /*    1. Should read 0x0  */
-       reg = agnx_read32(ctl, AGNX_SPI_RLSW);
-       if (0x0 != reg)
-               printk(KERN_WARNING PFX "Unmatched rf chips result\n");
-       spi_rf_write(ctl, RF_CHIP0|RF_CHIP1|RF_CHIP2, 0x1000);
-
-       agnx_write32(ctl, AGNX_GCR_RXOVERIDE, 0x0);
-
-       spi_rc_write(ctl, RF_CHIP0, 0x22);
-       udelay(80);
-       reg = agnx_read32(ctl, AGNX_SPI_RLSW);
-       if (0x0 != reg)
-               printk(KERN_WARNING PFX "Unmatched rf chips result\n");
-       spi_rf_write(ctl, RF_CHIP0|RF_CHIP1|RF_CHIP2, 0x1005);
-
-       agnx_write32(ctl, AGNX_GCR_RSTGCTL, 0x1);
-       agnx_write32(ctl, AGNX_GCR_RSTGCTL, 0x0);
-
-       reg = agnx_read32(ctl, AGNX_PM_SOFTRST);
-       reg |= 0x1c000032;
-       agnx_write32(ctl, AGNX_PM_SOFTRST, reg);
-       reg = agnx_read32(ctl, AGNX_PM_PLLCTL);
-       reg |= 0x0003f07;
-       agnx_write32(ctl, AGNX_PM_PLLCTL, reg);
-
-       reg = agnx_read32(ctl, 0xec50);
-       reg |= 0x40;
-       agnx_write32(ctl, 0xec50, reg);
-
-       agnx_write32(ctl, AGNX_GCR_RXOVERIDE, 0xff8);
-       agnx_write32(ctl, AGNX_GCR_DISCOVMOD, 0x3);
-
-       agnx_write32(ctl, AGNX_GCR_CHAINNUM, 0x6);
-       agnx_write32(ctl, 0x19874, 0x0);
-       spi_rf_write(ctl, RF_CHIP0|RF_CHIP1|RF_CHIP2, 0x1700);
-
-       /* Calibrate the BaseBandFilter */
-       base_band_filter_calibrate(priv);
-
-       spi_rf_write(ctl, RF_CHIP0|RF_CHIP1|RF_CHIP2, 0x1002);
-
-       agnx_write32(ctl, AGNX_GCR_GAINSET0, 0x1d);
-       agnx_write32(ctl, AGNX_GCR_GAINSET1, 0x1d);
-       agnx_write32(ctl, AGNX_GCR_GAINSET2, 0x1d);
-       agnx_write32(ctl, AGNX_GCR_GAINSETWRITE, 0x1);
-
-       agnx_write32(ctl, AGNX_ACI_MODE, 0x1);
-       agnx_write32(ctl, AGNX_ACI_LEN, 0x3ff);
-
-       agnx_write32(ctl, AGNX_ACI_TIMER1, 0x27);
-       agnx_write32(ctl, AGNX_ACI_TIMER2, 0x27);
-
-       spi_rf_write(ctl, RF_CHIP0|RF_CHIP1|RF_CHIP2, 0x1400);
-       spi_rf_write(ctl, RF_CHIP0|RF_CHIP1|RF_CHIP2, 0x1500);
-
-       /* Measure Calibration */
-       agnx_write32(ctl, AGNX_ACI_MEASURE, 0x1);
-       calibra_delay(priv);
-
-       /* do calibration */
-       do_calibration(priv);
-
-       agnx_write32(ctl, AGNX_GCR_RXOVERIDE, 0x0);
-       agnx_write32(ctl, AGNX_ACI_TIMER1, 0x21);
-       agnx_write32(ctl, AGNX_ACI_TIMER2, 0x27);
-       agnx_write32(ctl, AGNX_ACI_LEN, 0xf);
-
-       reg = agnx_read32(ctl, AGNX_GCR_GAINSET0);
-       reg &= 0xf;
-       agnx_write32(ctl, AGNX_GCR_GAINSET0, reg);
-       reg = agnx_read32(ctl, AGNX_GCR_GAINSET1);
-       reg &= 0xf;
-       agnx_write32(ctl, AGNX_GCR_GAINSET1, reg);
-       reg = agnx_read32(ctl, AGNX_GCR_GAINSET2);
-       reg &= 0xf;
-       agnx_write32(ctl, AGNX_GCR_GAINSET2, reg);
-
-       agnx_write32(ctl, AGNX_GCR_GAINSETWRITE, 0x0);
-       disable_receiver(priv);
-} /* antenna_calibrate */
-
-void __antenna_calibrate(struct agnx_priv *priv)
-{
-       void __iomem *ctl = priv->ctl;
-       u32 reg;
-
-       /* Calibrate the BaseBandFilter */
-       /* base_band_filter_calibrate(priv); */
-       spi_rf_write(ctl, RF_CHIP0|RF_CHIP1|RF_CHIP2, 0x1002);
-
-
-       agnx_write32(ctl, AGNX_GCR_GAINSET0, 0x1d);
-       agnx_write32(ctl, AGNX_GCR_GAINSET1, 0x1d);
-       agnx_write32(ctl, AGNX_GCR_GAINSET2, 0x1d);
-
-       agnx_write32(ctl, AGNX_GCR_GAINSETWRITE, 0x1);
-
-       agnx_write32(ctl, AGNX_ACI_MODE, 0x1);
-       agnx_write32(ctl, AGNX_ACI_LEN, 0x3ff);
-
-
-       agnx_write32(ctl, AGNX_ACI_TIMER1, 0x27);
-       agnx_write32(ctl, AGNX_ACI_TIMER2, 0x27);
-       spi_rf_write(ctl, RF_CHIP0|RF_CHIP1|RF_CHIP2, 0x1400);
-       spi_rf_write(ctl, RF_CHIP0|RF_CHIP1|RF_CHIP2, 0x1500);
-       /* Measure Calibration */
-       agnx_write32(ctl, AGNX_ACI_MEASURE, 0x1);
-       calibra_delay(priv);
-       do_calibration(priv);
-       agnx_write32(ctl, AGNX_GCR_RXOVERIDE, 0x0);
-
-       agnx_write32(ctl, AGNX_ACI_TIMER1, 0x21);
-       agnx_write32(ctl, AGNX_ACI_TIMER2, 0x27);
-
-       agnx_write32(ctl, AGNX_ACI_LEN, 0xf);
-
-       reg = agnx_read32(ctl, AGNX_GCR_GAINSET0);
-       reg &= 0xf;
-       agnx_write32(ctl, AGNX_GCR_GAINSET0, reg);
-       reg = agnx_read32(ctl, AGNX_GCR_GAINSET1);
-       reg &= 0xf;
-       agnx_write32(ctl, AGNX_GCR_GAINSET1, reg);
-       reg = agnx_read32(ctl, AGNX_GCR_GAINSET2);
-       reg &= 0xf;
-       agnx_write32(ctl, AGNX_GCR_GAINSET2, reg);
-
-
-       agnx_write32(ctl, AGNX_GCR_GAINSETWRITE, 0x0);
-
-       /* Write 0x3 Gain Control Discovery Mode */
-       enable_receiver(priv);
-}
-
-int agnx_set_channel(struct agnx_priv *priv, unsigned int channel)
-{
-       AGNX_TRACE;
-
-       printk(KERN_ERR PFX "Channel is %d %s\n", channel, __func__);
-       radio_channel_set(priv, channel);
-       return 0;
-}
diff --git a/drivers/staging/agnx/sta.c b/drivers/staging/agnx/sta.c
deleted file mode 100644 (file)
index 3e7db5e..0000000
+++ /dev/null
@@ -1,218 +0,0 @@
-#include <linux/delay.h>
-#include <linux/etherdevice.h>
-#include "phy.h"
-#include "sta.h"
-#include "debug.h"
-
-void hash_read(struct agnx_priv *priv, u32 reghi, u32 reglo, u8 sta_id)
-{
-       void __iomem *ctl = priv->ctl;
-
-       reglo &= 0xFFFF;
-       reglo |= 0x30000000;
-       reglo |= 0x40000000;    /* Set status busy */
-       reglo |= sta_id << 16;
-
-       iowrite32(0, ctl + AGNX_RXM_HASH_CMD_FLAG);
-       iowrite32(reghi, ctl + AGNX_RXM_HASH_CMD_HIGH);
-       iowrite32(reglo, ctl + AGNX_RXM_HASH_CMD_LOW);
-
-       reghi = ioread32(ctl + AGNX_RXM_HASH_CMD_HIGH);
-       reglo = ioread32(ctl + AGNX_RXM_HASH_CMD_LOW);
-       printk(PFX "RX hash cmd are : %.8x%.8x\n", reghi, reglo);
-}
-
-void hash_write(struct agnx_priv *priv, const u8 *mac_addr, u8 sta_id)
-{
-       void __iomem *ctl = priv->ctl;
-       u32 reghi, reglo;
-
-       if (!is_valid_ether_addr(mac_addr))
-               printk(KERN_WARNING PFX "Update hash table: Invalid hwaddr!\n");
-
-       reghi = mac_addr[0] << 24 | mac_addr[1] << 16 | mac_addr[2] << 8 | mac_addr[3];
-       reglo = mac_addr[4] << 8 | mac_addr[5];
-       reglo |= 0x10000000;    /* Set hash commmand */
-       reglo |= 0x40000000;    /* Set status busy */
-       reglo |= sta_id << 16;
-
-       iowrite32(0, ctl + AGNX_RXM_HASH_CMD_FLAG);
-       iowrite32(reghi, ctl + AGNX_RXM_HASH_CMD_HIGH);
-       iowrite32(reglo, ctl + AGNX_RXM_HASH_CMD_LOW);
-
-       reglo = ioread32(ctl + AGNX_RXM_HASH_CMD_LOW);
-       if (!(reglo & 0x80000000))
-               printk(KERN_WARNING PFX "Update hash table failed\n");
-}
-
-void hash_delete(struct agnx_priv *priv, u32 reghi, u32 reglo, u8 sta_id)
-{
-       void __iomem *ctl = priv->ctl;
-
-       reglo &= 0xFFFF;
-       reglo |= 0x20000000;
-       reglo |= 0x40000000;    /* Set status busy */
-       reglo |= sta_id << 16;
-
-       iowrite32(0, ctl + AGNX_RXM_HASH_CMD_FLAG);
-       iowrite32(reghi, ctl + AGNX_RXM_HASH_CMD_HIGH);
-       iowrite32(reglo, ctl + AGNX_RXM_HASH_CMD_LOW);
-       reghi = ioread32(ctl + AGNX_RXM_HASH_CMD_HIGH);
-
-       reglo = ioread32(ctl + AGNX_RXM_HASH_CMD_LOW);
-       printk(PFX "RX hash cmd are : %.8x%.8x\n", reghi, reglo);
-
-}
-
-void hash_dump(struct agnx_priv *priv, u8 sta_id)
-{
-       void __iomem *ctl = priv->ctl;
-       u32 reghi, reglo;
-
-       reglo = 0x40000000;     /* status bit */
-       iowrite32(reglo, ctl + AGNX_RXM_HASH_CMD_LOW);
-       iowrite32(sta_id << 16, ctl + AGNX_RXM_HASH_DUMP_DATA);
-
-       udelay(80);
-
-       reghi = ioread32(ctl + AGNX_RXM_HASH_CMD_HIGH);
-       reglo = ioread32(ctl + AGNX_RXM_HASH_CMD_LOW);
-       printk(PFX "hash cmd are : %.8x%.8x\n", reghi, reglo);
-       reghi = ioread32(ctl + AGNX_RXM_HASH_CMD_FLAG);
-       printk(PFX "hash flag is : %.8x\n", reghi);
-       reghi = ioread32(ctl + AGNX_RXM_HASH_DUMP_MST);
-       reglo = ioread32(ctl + AGNX_RXM_HASH_DUMP_LST);
-       printk(PFX "hash dump mst lst: %.8x%.8x\n", reghi, reglo);
-       reghi = ioread32(ctl + AGNX_RXM_HASH_DUMP_DATA);
-       printk(PFX "hash dump data: %.8x\n", reghi);
-}
-
-void get_sta_power(struct agnx_priv *priv, struct agnx_sta_power *power, unsigned int sta_idx)
-{
-       void __iomem *ctl = priv->ctl;
-       memcpy_fromio(power, ctl + AGNX_TXM_STAPOWTEMP + sizeof(*power) * sta_idx,
-                     sizeof(*power));
-}
-
-inline void
-set_sta_power(struct agnx_priv *priv, struct agnx_sta_power *power, unsigned int sta_idx)
-{
-       void __iomem *ctl = priv->ctl;
-       /* FIXME   2. Write Template to offset + station number  */
-       memcpy_toio(ctl + AGNX_TXM_STAPOWTEMP + sizeof(*power) * sta_idx,
-                   power, sizeof(*power));
-}
-
-
-void get_sta_tx_wq(struct agnx_priv *priv, struct agnx_sta_tx_wq *tx_wq,
-                  unsigned int sta_idx, unsigned int wq_idx)
-{
-       void __iomem *data = priv->data;
-       memcpy_fromio(tx_wq, data + AGNX_PDU_TX_WQ + sizeof(*tx_wq) * STA_TX_WQ_NUM * sta_idx +
-                     sizeof(*tx_wq) * wq_idx,  sizeof(*tx_wq));
-
-}
-
-inline void set_sta_tx_wq(struct agnx_priv *priv, struct agnx_sta_tx_wq *tx_wq,
-                  unsigned int sta_idx, unsigned int wq_idx)
-{
-       void __iomem *data = priv->data;
-       memcpy_toio(data + AGNX_PDU_TX_WQ + sizeof(*tx_wq) * STA_TX_WQ_NUM * sta_idx +
-                   sizeof(*tx_wq) * wq_idx, tx_wq, sizeof(*tx_wq));
-}
-
-
-void get_sta(struct agnx_priv *priv, struct agnx_sta *sta, unsigned int sta_idx)
-{
-       void __iomem *data = priv->data;
-
-       memcpy_fromio(sta, data + AGNX_PDUPOOL + sizeof(*sta) * sta_idx,
-                     sizeof(*sta));
-}
-
-inline void set_sta(struct agnx_priv *priv, struct agnx_sta *sta, unsigned int sta_idx)
-{
-       void __iomem *data = priv->data;
-
-       memcpy_toio(data + AGNX_PDUPOOL + sizeof(*sta) * sta_idx,
-                   sta, sizeof(*sta));
-}
-
-/* FIXME */
-void sta_power_init(struct agnx_priv *priv, unsigned int sta_idx)
-{
-       struct agnx_sta_power power;
-       u32 reg;
-       AGNX_TRACE;
-
-       memset(&power, 0, sizeof(power));
-       reg = agnx_set_bits(EDCF, EDCF_SHIFT, 0x1);
-       power.reg = cpu_to_le32(reg);
-       set_sta_power(priv, &power, sta_idx);
-       udelay(40);
-} /* add_power_template */
-
-
-/* @num: The #number of station that is visible to the card */
-static void sta_tx_workqueue_init(struct agnx_priv *priv, unsigned int sta_idx)
-{
-       struct agnx_sta_tx_wq tx_wq;
-       u32 reg;
-       unsigned int i;
-
-       memset(&tx_wq, 0, sizeof(tx_wq));
-
-       reg = agnx_set_bits(WORK_QUEUE_VALID, WORK_QUEUE_VALID_SHIFT, 1);
-       reg |= agnx_set_bits(WORK_QUEUE_ACK_TYPE, WORK_QUEUE_ACK_TYPE_SHIFT, 1);
-/*     reg |= agnx_set_bits(WORK_QUEUE_ACK_TYPE, WORK_QUEUE_ACK_TYPE_SHIFT, 0); */
-       tx_wq.reg2 |= cpu_to_le32(reg);
-
-       /* Suppose all 8 traffic class are used */
-       for (i = 0; i < STA_TX_WQ_NUM; i++)
-               set_sta_tx_wq(priv, &tx_wq, sta_idx, i);
-} /* sta_tx_workqueue_init */
-
-
-static void sta_traffic_init(struct agnx_sta_traffic *traffic)
-{
-       u32 reg;
-       memset(traffic, 0, sizeof(*traffic));
-
-       reg = agnx_set_bits(NEW_PACKET, NEW_PACKET_SHIFT, 1);
-       reg |= agnx_set_bits(TRAFFIC_VALID, TRAFFIC_VALID_SHIFT, 1);
-/*     reg |= agnx_set_bits(TRAFFIC_ACK_TYPE, TRAFFIC_ACK_TYPE_SHIFT, 1); */
-       traffic->reg0 = cpu_to_le32(reg);
-
-       /*      3. setting RX Sequence Number to 4095 */
-       reg = agnx_set_bits(RX_SEQUENCE_NUM, RX_SEQUENCE_NUM_SHIFT, 4095);
-       traffic->reg1 = cpu_to_le32(reg);
-}
-
-
-/* @num: The #number of station that is visible to the card */
-void sta_init(struct agnx_priv *priv, unsigned int sta_idx)
-{
-       /* FIXME the length of sta is 256 bytes Is that
-        * dangerous to stack overflow? */
-       struct agnx_sta sta;
-       u32 reg;
-       int i;
-
-       memset(&sta, 0, sizeof(sta));
-       /* Set valid to 1 */
-       reg = agnx_set_bits(STATION_VALID, STATION_VALID_SHIFT, 1);
-       /* Set Enable Concatenation to 0 (?) */
-       reg |= agnx_set_bits(ENABLE_CONCATENATION, ENABLE_CONCATENATION_SHIFT, 0);
-       /* Set Enable Decompression to 0 (?) */
-       reg |= agnx_set_bits(ENABLE_DECOMPRESSION, ENABLE_DECOMPRESSION_SHIFT, 0);
-       sta.reg = cpu_to_le32(reg);
-
-       /* Initialize each of the Traffic Class Structures by: */
-       for (i = 0; i < 8; i++)
-               sta_traffic_init(sta.traffic + i);
-
-       set_sta(priv, &sta, sta_idx);
-       sta_tx_workqueue_init(priv, sta_idx);
-} /* sta_descriptor_init */
-
-
diff --git a/drivers/staging/agnx/sta.h b/drivers/staging/agnx/sta.h
deleted file mode 100644 (file)
index fd504e3..0000000
+++ /dev/null
@@ -1,222 +0,0 @@
-#ifndef AGNX_STA_H_
-#define AGNX_STA_H_
-
-#define STA_TX_WQ_NUM  8       /* The number of TX workqueue one STA has */
-
-struct agnx_hash_cmd {
-       __be32 cmdhi;
-#define MACLO          0xFFFF0000
-#define MACLO_SHIFT    16
-#define STA_ID         0x0000FFF0
-#define STA_ID_SHIFT   4
-#define CMD            0x0000000C
-#define CMD_SHIFT      2
-#define STATUS         0x00000002
-#define STATUS_SHIFT   1
-#define PASS           0x00000001
-#define PASS_SHIFT     1
-       __be32 cmdlo;
-} __attribute__((__packed__));
-
-
-/*
- * Station Power Template
- * FIXME Just for agn100 yet
- */
-struct agnx_sta_power {
-       __le32 reg;
-#define SIGNAL                 0x000000FF /* signal */
-#define SIGNAL_SHIFT           0
-#define RATE                   0x00000F00
-#define RATE_SHIFT             8
-#define TIFS                   0x00001000
-#define TIFS_SHIFT             12
-#define EDCF                   0x00002000
-#define EDCF_SHIFT             13
-#define CHANNEL_BOND           0x00004000
-#define CHANNEL_BOND_SHIFT     14
-#define PHY_MODE               0x00038000
-#define PHY_MODE_SHIFT         15
-#define POWER_LEVEL            0x007C0000
-#define POWER_LEVEL_SHIFT      18
-#define NUM_TRANSMITTERS       0x00800000
-#define NUM_TRANSMITTERS_SHIFT 23
-} __attribute__((__packed__));
-
-/*
- * TX Workqueue Descriptor
- */
-struct agnx_sta_tx_wq {
-       __le32 reg0;
-#define HEAD_POINTER_LOW       0xFF000000 /* Head pointer low */
-#define HEAD_POINTER_LOW_SHIFT 24
-#define TAIL_POINTER           0x00FFFFFF /* Tail pointer */
-#define TAIL_POINTER_SHIFT     0
-
-       __le32 reg3;
-#define ACK_POINTER_LOW                0xFFFF0000      /* ACK pointer low */
-#define ACK_POINTER_LOW_SHIFT  16
-#define HEAD_POINTER_HIGH      0x0000FFFF      /* Head pointer high */
-#define HEAD_POINTER_HIGH_SHIFT        0
-
-       __le32 reg1;
-/* ACK timeout tail packet count */
-#define ACK_TIMOUT_TAIL_PACK_CNT       0xFFF00000
-#define ACK_TIMOUT_TAIL_PACK_CNT_SHIFT 20
-/* Head timeout tail packet count */
-#define HEAD_TIMOUT_TAIL_PACK_CNT      0x000FFF00
-#define HEAD_TIMOUT_TAIL_PACK_CNT_SHIFT        8
-#define ACK_POINTER_HIGH               0x000000FF /* ACK pointer high */
-#define ACK_POINTER_HIGH_SHIFT         0
-
-       __le32 reg2;
-#define WORK_QUEUE_VALID               0x80000000 /* valid */
-#define WORK_QUEUE_VALID_SHIFT         31
-#define WORK_QUEUE_ACK_TYPE            0x40000000 /* ACK type */
-#define WORK_QUEUE_ACK_TYPE_SHIFT      30
-/* Head timeout window limit fragmentation count */
-#define HEAD_TIMOUT_WIN_LIM_FRAG_CNT   0x3FFF0000
-#define HEAD_TIMOUT_WIN_LIM_FRAG_CNT_SHIFT     16
-/* Head timeout window limit byte count */
-#define HEAD_TIMOUT_WIN_LIM_BYTE_CNT   0x0000FFFF
-#define HEAD_TIMOUT_WIN_LIM_BYTE_CNT_SHIFT      0
-} __attribute__((__packed__));
-
-
-/*
- * Traffic Class Structure
- */
-struct agnx_sta_traffic {
-       __le32 reg0;
-#define ACK_TIMOUT_CNT         0xFF800000 /* ACK Timeout Counts */
-#define ACK_TIMOUT_CNT_SHIFT   23
-#define TRAFFIC_ACK_TYPE       0x00600000 /* ACK Type */
-#define TRAFFIC_ACK_TYPE_SHIFT 21
-#define NEW_PACKET             0x00100000 /* New Packet  */
-#define NEW_PACKET_SHIFT       20
-#define TRAFFIC_VALID          0x00080000 /* Valid */
-#define TRAFFIC_VALID_SHIFT    19
-#define RX_HDR_DESC_POINTER    0x0007FFFF /* RX Header Descripter pointer */
-#define RX_HDR_DESC_POINTER_SHIFT       0
-
-       __le32 reg1;
-#define RX_PACKET_TIMESTAMP    0xFFFF0000 /* RX Packet Timestamp */
-#define RX_PACKET_TIMESTAMP_SHIFT      16
-#define TRAFFIC_RESERVED       0x0000E000 /* Reserved */
-#define TRAFFIC_RESERVED_SHIFT  13
-#define SV                     0x00001000 /* sv */
-#define SV_SHIFT               12
-#define RX_SEQUENCE_NUM                0x00000FFF /* RX Sequence Number */
-#define RX_SEQUENCE_NUM_SHIFT  0
-
-       __le32 tx_replay_cnt_low; /* TX Replay Counter Low */
-
-       __le16 tx_replay_cnt_high; /* TX Replay Counter High */
-       __le16 rx_replay_cnt_high; /* RX Replay Counter High */
-
-       __be32 rx_replay_cnt_low; /* RX Replay Counter Low */
-} __attribute__((__packed__));
-
-/*
- * Station Descriptors
- */
-struct agnx_sta {
-       __le32 tx_session_keys[4]; /* Transmit Session Key (0-3) */
-       __le32 rx_session_keys[4]; /* Receive Session Key (0-3) */
-
-       __le32 reg;
-#define ID_1                   0xC0000000 /* id 1 */
-#define ID_1_SHIFT             30
-#define ID_0                   0x30000000 /* id 0 */
-#define ID_0_SHIFT             28
-#define ENABLE_CONCATENATION   0x0FF00000 /* Enable concatenation */
-#define ENABLE_CONCATENATION_SHIFT     20
-#define ENABLE_DECOMPRESSION   0x000FF000 /* Enable decompression */
-#define ENABLE_DECOMPRESSION_SHIFT     12
-#define STA_RESERVED           0x00000C00 /* Reserved */
-#define STA_RESERVED_SHIFT     10
-#define EAP                    0x00000200 /* EAP */
-#define EAP_SHIFT              9
-#define ED_NULL                        0x00000100 /* ED NULL */
-#define ED_NULL_SHIFT          8
-#define ENCRYPTION_POLICY      0x000000E0 /* Encryption Policy */
-#define ENCRYPTION_POLICY_SHIFT 5
-#define DEFINED_KEY_ID         0x00000018 /* Defined Key ID */
-#define DEFINED_KEY_ID_SHIFT   3
-#define FIXED_KEY              0x00000004 /* Fixed Key */
-#define FIXED_KEY_SHIFT                2
-#define KEY_VALID              0x00000002 /* Key Valid */
-#define KEY_VALID_SHIFT                1
-#define STATION_VALID          0x00000001 /* Station Valid */
-#define STATION_VALID_SHIFT    0
-
-       __le32 tx_aes_blks_unicast; /* TX AES Blks Unicast */
-       __le32 rx_aes_blks_unicast; /* RX AES Blks Unicast */
-
-       __le16 aes_format_err_unicast_cnt; /* AES Format Error Unicast Counts */
-       __le16 aes_replay_unicast; /* AES Replay Unicast */
-
-       __le16 aes_decrypt_err_unicast; /* AES Decrypt Error Unicast */
-       __le16 aes_decrypt_err_default; /* AES Decrypt Error default */
-
-       __le16 single_retry_packets; /* Single Retry Packets */
-       __le16 failed_tx_packets; /* Failed Tx Packets */
-
-       __le16 muti_retry_packets; /* Multiple Retry Packets */
-       __le16 ack_timeouts;    /* ACK Timeouts */
-
-       __le16 frag_tx_cnt;     /* Fragment TX Counts */
-       __le16 rts_brq_sent;    /* RTS Brq Sent */
-
-       __le16 tx_packets;      /* TX Packets */
-       __le16 cts_back_timeout; /* CTS Back Timeout */
-
-       __le32 phy_stats_high;  /* PHY Stats High */
-       __le32 phy_stats_low;   /* PHY Stats Low */
-
-       struct agnx_sta_traffic traffic[8];     /* Traffic Class Structure (8) */
-
-       __le16 traffic_class0_frag_success; /* Traffic Class 0 Fragment Success */
-       __le16 traffic_class1_frag_success; /* Traffic Class 1 Fragment Success */
-       __le16 traffic_class2_frag_success; /* Traffic Class 2 Fragment Success */
-       __le16 traffic_class3_frag_success; /* Traffic Class 3 Fragment Success */
-       __le16 traffic_class4_frag_success; /* Traffic Class 4 Fragment Success */
-       __le16 traffic_class5_frag_success; /* Traffic Class 5 Fragment Success */
-       __le16 traffic_class6_frag_success; /* Traffic Class 6 Fragment Success */
-       __le16 traffic_class7_frag_success; /* Traffic Class 7 Fragment Success */
-
-       __le16 num_frag_non_prime_rates; /* number of Fragments for non-prime rates */
-       __le16 ack_timeout_non_prime_rates; /* ACK Timeout for non-prime rates */
-
-} __attribute__((__packed__));
-
-
-struct agnx_beacon_hdr {
-       struct agnx_sta_power power; /* Tx Station Power Template  */
-       u8 phy_hdr[6];          /* PHY Hdr */
-       u8 frame_len_lo;        /* Frame Length Lo */
-       u8 frame_len_hi;        /* Frame Length Hi */
-       u8 mac_hdr[24];         /* MAC Header */
-       /* FIXME */
-       /* 802.11(abg) beacon */
-} __attribute__((__packed__));
-
-void hash_write(struct agnx_priv *priv, const u8 *mac_addr, u8 sta_id);
-void hash_dump(struct agnx_priv *priv, u8 sta_id);
-void hash_read(struct agnx_priv *priv, u32 reghi, u32 reglo, u8 sta_id);
-void hash_delete(struct agnx_priv *priv, u32 reghi, u32 reglo, u8 sta_id);
-
-void get_sta_power(struct agnx_priv *priv, struct agnx_sta_power *power, unsigned int sta_idx);
-void set_sta_power(struct agnx_priv *priv, struct agnx_sta_power *power,
-                  unsigned int sta_idx);
-void get_sta_tx_wq(struct agnx_priv *priv, struct agnx_sta_tx_wq *tx_wq,
-                  unsigned int sta_idx, unsigned int wq_idx);
-void set_sta_tx_wq(struct agnx_priv *priv, struct agnx_sta_tx_wq *tx_wq,
-                  unsigned int sta_idx, unsigned int wq_idx);
-void get_sta(struct agnx_priv *priv, struct agnx_sta *sta, unsigned int sta_idx);
-void set_sta(struct agnx_priv *priv, struct agnx_sta *sta, unsigned int sta_idx);
-
-void sta_power_init(struct agnx_priv *priv, unsigned int num);
-void sta_init(struct agnx_priv *priv, unsigned int num);
-
-#endif /* AGNX_STA_H_ */
diff --git a/drivers/staging/agnx/table.c b/drivers/staging/agnx/table.c
deleted file mode 100644 (file)
index b52fef9..0000000
+++ /dev/null
@@ -1,168 +0,0 @@
-#include <linux/pci.h>
-#include <linux/delay.h>
-#include "agnx.h"
-#include "debug.h"
-#include "phy.h"
-
-static const u32
-tx_fir_table[] = { 0x19, 0x5d, 0xce, 0x151, 0x1c3, 0x1ff, 0x1ea, 0x17c, 0xcf,
-                  0x19, 0x38e, 0x350, 0x362, 0x3ad, 0x5, 0x44, 0x59, 0x49,
-                  0x21, 0x3f7, 0x3e0, 0x3e3, 0x3f3, 0x0 };
-
-void tx_fir_table_init(struct agnx_priv *priv)
-{
-       void __iomem *ctl = priv->ctl;
-       int i;
-
-       for (i = 0; i < ARRAY_SIZE(tx_fir_table); i++)
-               iowrite32(tx_fir_table[i], ctl + AGNX_FIR_BASE + i*4);
-} /* fir_table_setup */
-
-
-static const u32
-gain_table[] = { 0x8, 0x8, 0xf, 0x13, 0x17, 0x1b, 0x1f, 0x23, 0x27, 0x2b,
-                0x2f, 0x33, 0x37, 0x3b, 0x3f, 0x43, 0x47, 0x4b, 0x4f,
-                0x53, 0x57, 0x5b, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f,
-                0x5f, 0x5f, 0x5f, 0x5f };
-
-void gain_table_init(struct agnx_priv *priv)
-{
-       void __iomem *ctl = priv->ctl;
-       int i;
-
-       for (i = 0; i < ARRAY_SIZE(gain_table); i++) {
-               iowrite32(gain_table[i], ctl + AGNX_GAIN_TABLE + i*4);
-               iowrite32(gain_table[i], ctl + AGNX_GAIN_TABLE + i*4 + 0x80);
-       }
-} /* gain_table_init */
-
-void monitor_gain_table_init(struct agnx_priv *priv)
-{
-       void __iomem *ctl = priv->ctl;
-       unsigned int i;
-
-       for (i = 0; i < 0x44; i += 4) {
-               iowrite32(0x61, ctl + AGNX_MONGCR_BASE + i);
-               iowrite32(0x61, ctl + AGNX_MONGCR_BASE + 0x200 + i);
-       }
-       for (i = 0x44; i < 0x64; i += 4) {
-               iowrite32(0x6e, ctl + AGNX_MONGCR_BASE + i);
-               iowrite32(0x6e, ctl + AGNX_MONGCR_BASE + 0x200 + i);
-       }
-       for (i = 0x64; i < 0x94; i += 4) {
-               iowrite32(0x7a, ctl + AGNX_MONGCR_BASE + i);
-               iowrite32(0x7a, ctl + AGNX_MONGCR_BASE + 0x200 + i);
-       }
-       for (i = 0x94; i < 0xdc; i += 4) {
-               iowrite32(0x87, ctl + AGNX_MONGCR_BASE + i);
-               iowrite32(0x87, ctl + AGNX_MONGCR_BASE + 0x200 + i);
-       }
-       for (i = 0xdc; i < 0x148; i += 4) {
-               iowrite32(0x95, ctl + AGNX_MONGCR_BASE + i);
-               iowrite32(0x95, ctl + AGNX_MONGCR_BASE + 0x200 + i);
-       }
-       for (i = 0x148; i < 0x1e8; i += 4) {
-               iowrite32(0xa2, ctl + AGNX_MONGCR_BASE + i);
-               iowrite32(0xa2, ctl + AGNX_MONGCR_BASE + 0x200 + i);
-       }
-       for (i = 0x1e8; i <= 0x1fc; i += 4) {
-               iowrite32(0xb0, ctl + AGNX_MONGCR_BASE + i);
-               iowrite32(0xb0, ctl + AGNX_MONGCR_BASE + 0x200 + i);
-       }
-} /* monitor_gain_table_init */
-
-
-void routing_table_init(struct agnx_priv *priv)
-{
-       void __iomem *ctl = priv->ctl;
-       unsigned int type, subtype;
-       u32 reg;
-
-       disable_receiver(priv);
-
-       for (type = 0; type < 0x3; type++) {
-               for (subtype = 0; subtype < 0x10; subtype++) {
-                       /* 1. Set Routing table to R/W and to Return status on Read */
-                       reg = (type << ROUTAB_TYPE_SHIFT) |
-                               (subtype << ROUTAB_SUBTYPE_SHIFT);
-                       reg |= (1 << ROUTAB_RW_SHIFT) | (1 << ROUTAB_STATUS_SHIFT);
-                       if (type == ROUTAB_TYPE_DATA) {
-                               /* NULL goes to RFP */
-                               if (subtype == ROUTAB_SUBTYPE_NULL)
-/*                                     reg |= ROUTAB_ROUTE_RFP; */
-                                       reg |= ROUTAB_ROUTE_CPU;
-                               /* QOS NULL goes to CPU */
-                               else if (subtype == ROUTAB_SUBTYPE_QOSNULL)
-                                       reg |= ROUTAB_ROUTE_CPU;
-                               /* All Data and QOS data subtypes go to Encryption */
-                               else if ((subtype == ROUTAB_SUBTYPE_DATA) ||
-                                        (subtype == ROUTAB_SUBTYPE_DATAACK) ||
-                                        (subtype == ROUTAB_SUBTYPE_DATAPOLL) ||
-                                        (subtype == ROUTAB_SUBTYPE_DATAPOLLACK) ||
-                                        (subtype == ROUTAB_SUBTYPE_QOSDATA) ||
-                                        (subtype == ROUTAB_SUBTYPE_QOSDATAACK) ||
-                                        (subtype == ROUTAB_SUBTYPE_QOSDATAPOLL) ||
-                                        (subtype == ROUTAB_SUBTYPE_QOSDATAACKPOLL))
-                                       reg |= ROUTAB_ROUTE_ENCRY;
-/*                                     reg |= ROUTAB_ROUTE_CPU; */
-                               /*Drop NULL and QOS NULL ack, poll and poll ack*/
-                               else if ((subtype == ROUTAB_SUBTYPE_NULLACK) ||
-                                        (subtype == ROUTAB_SUBTYPE_QOSNULLACK) ||
-                                        (subtype == ROUTAB_SUBTYPE_NULLPOLL) ||
-                                        (subtype == ROUTAB_SUBTYPE_QOSNULLPOLL) ||
-                                        (subtype == ROUTAB_SUBTYPE_NULLPOLLACK) ||
-                                        (subtype == ROUTAB_SUBTYPE_QOSNULLPOLLACK))
-/*                                     reg |= ROUTAB_ROUTE_DROP; */
-                                       reg |= ROUTAB_ROUTE_CPU;
-                       } else {
-                               reg |= (ROUTAB_ROUTE_CPU);
-                       }
-                       iowrite32(reg, ctl + AGNX_RXM_ROUTAB);
-                       /* Check to verify that the status bit cleared */
-                       routing_table_delay();
-               }
-       }
-       enable_receiver(priv);
-} /* routing_table_init */
-
-void tx_engine_lookup_tbl_init(struct agnx_priv *priv)
-{
-       void __iomem *data = priv->data;
-       unsigned int i;
-
-       for (i = 0; i <= 28; i += 4)
-               iowrite32(0xb00c, data + AGNX_ENGINE_LOOKUP_TBL + i);
-       for (i = 32; i <= 120; i += 8) {
-               iowrite32(0x1e58, data + AGNX_ENGINE_LOOKUP_TBL + i);
-               iowrite32(0xb00c, data + AGNX_ENGINE_LOOKUP_TBL + i + 4);
-       }
-
-       for (i = 128; i <= 156; i += 4)
-               iowrite32(0x980c, data + AGNX_ENGINE_LOOKUP_TBL + i);
-       for (i = 160; i <= 248; i += 8) {
-               iowrite32(0x1858, data + AGNX_ENGINE_LOOKUP_TBL + i);
-               iowrite32(0x980c, data + AGNX_ENGINE_LOOKUP_TBL + i + 4);
-       }
-
-       for (i = 256; i <= 284; i += 4)
-               iowrite32(0x980c, data + AGNX_ENGINE_LOOKUP_TBL + i);
-       for (i = 288; i <= 376; i += 8) {
-               iowrite32(0x1a58, data + AGNX_ENGINE_LOOKUP_TBL + i);
-               iowrite32(0x1858, data + AGNX_ENGINE_LOOKUP_TBL + i + 4);
-       }
-
-       for (i = 512; i <= 540; i += 4)
-               iowrite32(0xc00c, data + AGNX_ENGINE_LOOKUP_TBL + i);
-       for (i = 544; i <= 632; i += 8) {
-               iowrite32(0x2058, data + AGNX_ENGINE_LOOKUP_TBL + i);
-               iowrite32(0xc00c, data + AGNX_ENGINE_LOOKUP_TBL + i + 4);
-       }
-
-       for (i = 640; i <= 668; i += 4)
-               iowrite32(0xc80c, data + AGNX_ENGINE_LOOKUP_TBL + i);
-       for (i = 672; i <= 764; i += 8) {
-               iowrite32(0x2258, data + AGNX_ENGINE_LOOKUP_TBL + i);
-               iowrite32(0xc80c, data + AGNX_ENGINE_LOOKUP_TBL + i + 4);
-       }
-}
-
diff --git a/drivers/staging/agnx/table.h b/drivers/staging/agnx/table.h
deleted file mode 100644 (file)
index f0626b5..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-#ifndef AGNX_TABLE_H_
-#define AGNX_TABLE_H_
-
-void tx_fir_table_init(struct agnx_priv *priv);
-void gain_table_init(struct agnx_priv *priv);
-void monitor_gain_table_init(struct agnx_priv *priv);
-void routing_table_init(struct agnx_priv *priv);
-void tx_engine_lookup_tbl_init(struct agnx_priv *priv);
-
-#endif /* AGNX_TABLE_H_ */
diff --git a/drivers/staging/agnx/xmit.c b/drivers/staging/agnx/xmit.c
deleted file mode 100644 (file)
index 42db410..0000000
+++ /dev/null
@@ -1,836 +0,0 @@
-/**
- * Airgo MIMO wireless driver
- *
- * Copyright (c) 2007 Li YanBo <dreamfly281@gmail.com>
-
- * Thanks for Jeff Williams <angelbane@gmail.com> do reverse engineer
- * works and published the SPECS at http://airgo.wdwconsulting.net/mymoin
-
- * 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/pci.h>
-#include <linux/delay.h>
-#include "agnx.h"
-#include "debug.h"
-#include "phy.h"
-
-unsigned int rx_frame_cnt;
-/* unsigned int local_tx_sent_cnt = 0; */
-
-static inline void disable_rx_engine(struct agnx_priv *priv)
-{
-       void __iomem *ctl = priv->ctl;
-       iowrite32(0x100, ctl + AGNX_CIR_RXCTL);
-       /* Wait for RX Control to have the Disable Rx Interrupt (0x100) set */
-       ioread32(ctl + AGNX_CIR_RXCTL);
-}
-
-static inline void enable_rx_engine(struct agnx_priv *priv)
-{
-       void __iomem *ctl = priv->ctl;
-       iowrite32(0x80, ctl + AGNX_CIR_RXCTL);
-       ioread32(ctl + AGNX_CIR_RXCTL);
-}
-
-inline void disable_rx_interrupt(struct agnx_priv *priv)
-{
-       void __iomem *ctl = priv->ctl;
-       u32 reg;
-
-       disable_rx_engine(priv);
-       reg = ioread32(ctl + AGNX_CIR_RXCFG);
-       reg &= ~0x20;
-       iowrite32(reg, ctl + AGNX_CIR_RXCFG);
-       ioread32(ctl + AGNX_CIR_RXCFG);
-}
-
-inline void enable_rx_interrupt(struct agnx_priv *priv)
-{
-       void __iomem *ctl = priv->ctl;
-       u32 reg;
-
-       reg = ioread32(ctl + AGNX_CIR_RXCFG);
-       reg |= 0x20;
-       iowrite32(reg, ctl + AGNX_CIR_RXCFG);
-       ioread32(ctl + AGNX_CIR_RXCFG);
-       enable_rx_engine(priv);
-}
-
-static inline void rx_desc_init(struct agnx_priv *priv, unsigned int idx)
-{
-       struct agnx_desc *desc = priv->rx.desc + idx;
-       struct agnx_info *info = priv->rx.info + idx;
-
-       memset(info, 0, sizeof(*info));
-
-       info->dma_len = IEEE80211_MAX_RTS_THRESHOLD + sizeof(struct agnx_hdr);
-       info->skb = dev_alloc_skb(info->dma_len);
-       if (info->skb == NULL)
-               agnx_bug("refill err");
-
-       info->mapping = pci_map_single(priv->pdev, skb_tail_pointer(info->skb),
-                                      info->dma_len, PCI_DMA_FROMDEVICE);
-       memset(desc, 0, sizeof(*desc));
-       desc->dma_addr = cpu_to_be32(info->mapping);
-       /* Set the owner to the card */
-       desc->frag = cpu_to_be32(be32_to_cpu(desc->frag) | OWNER);
-}
-
-static inline void rx_desc_reinit(struct agnx_priv *priv, unsigned int idx)
-{
-       struct agnx_info *info = priv->rx.info + idx;
-
-       /* Cause ieee80211 will free the skb buffer, so we needn't to free it again?! */
-       pci_unmap_single(priv->pdev, info->mapping, info->dma_len, PCI_DMA_FROMDEVICE);
-       rx_desc_init(priv, idx);
-}
-
-static inline void rx_desc_reusing(struct agnx_priv *priv, unsigned int idx)
-{
-       struct agnx_desc *desc = priv->rx.desc + idx;
-       struct agnx_info *info = priv->rx.info + idx;
-
-       memset(desc, 0, sizeof(*desc));
-       desc->dma_addr = cpu_to_be32(info->mapping);
-       /* Set the owner to the card */
-       desc->frag = cpu_to_be32(be32_to_cpu(desc->frag) | OWNER);
-}
-
-static void rx_desc_free(struct agnx_priv *priv, unsigned int idx)
-{
-       struct agnx_desc *desc = priv->rx.desc + idx;
-       struct agnx_info *info = priv->rx.info + idx;
-
-       BUG_ON(!desc || !info);
-       if (info->mapping)
-               pci_unmap_single(priv->pdev, info->mapping, info->dma_len, PCI_DMA_FROMDEVICE);
-       if (info->skb)
-               dev_kfree_skb(info->skb);
-       memset(info, 0, sizeof(*info));
-       memset(desc, 0, sizeof(*desc));
-}
-
-static inline void __tx_desc_free(struct agnx_priv *priv,
-                                 struct agnx_desc *desc, struct agnx_info *info)
-{
-       BUG_ON(!desc || !info);
-       /* TODO make sure mapping, skb and len are consistency */
-       if (info->mapping)
-               pci_unmap_single(priv->pdev, info->mapping,
-                                info->dma_len, PCI_DMA_TODEVICE);
-       if (info->type == PACKET)
-               dev_kfree_skb(info->skb);
-
-       memset(info, 0, sizeof(*info));
-       memset(desc, 0, sizeof(*desc));
-}
-
-static void txm_desc_free(struct agnx_priv *priv, unsigned int idx)
-{
-       struct agnx_desc *desc = priv->txm.desc + idx;
-       struct agnx_info *info = priv->txm.info + idx;
-
-       __tx_desc_free(priv, desc, info);
-}
-
-static void txd_desc_free(struct agnx_priv *priv, unsigned int idx)
-{
-       struct agnx_desc *desc = priv->txd.desc + idx;
-       struct agnx_info *info = priv->txd.info + idx;
-
-       __tx_desc_free(priv, desc, info);
-}
-
-int fill_rings(struct agnx_priv *priv)
-{
-       void __iomem *ctl = priv->ctl;
-       unsigned int i;
-       u32 reg;
-       AGNX_TRACE;
-
-       priv->txd.idx_sent = priv->txm.idx_sent = 0;
-       priv->rx.idx = priv->txm.idx = priv->txd.idx = 0;
-
-       for (i = 0; i < priv->rx.size; i++)
-               rx_desc_init(priv, i);
-       for (i = 0; i < priv->txm.size; i++) {
-               memset(priv->txm.desc + i, 0, sizeof(struct agnx_desc));
-               memset(priv->txm.info + i, 0, sizeof(struct agnx_info));
-       }
-       for (i = 0; i < priv->txd.size; i++) {
-               memset(priv->txd.desc + i, 0, sizeof(struct agnx_desc));
-               memset(priv->txd.info + i, 0, sizeof(struct agnx_info));
-       }
-
-       /* FIXME Set the card RX TXM and TXD address */
-       agnx_write32(ctl, AGNX_CIR_RXCMSTART, priv->rx.dma);
-       agnx_write32(ctl, AGNX_CIR_RXCMEND, priv->txm.dma);
-
-       agnx_write32(ctl, AGNX_CIR_TXMSTART, priv->txm.dma);
-       agnx_write32(ctl, AGNX_CIR_TXMEND, priv->txd.dma);
-
-       agnx_write32(ctl, AGNX_CIR_TXDSTART, priv->txd.dma);
-       agnx_write32(ctl, AGNX_CIR_TXDEND, priv->txd.dma +
-                    sizeof(struct agnx_desc) * priv->txd.size);
-
-       /* FIXME Relinquish control of rings to card */
-       reg = agnx_read32(ctl, AGNX_CIR_BLKCTL);
-       reg &= ~0x800;
-       agnx_write32(ctl, AGNX_CIR_BLKCTL, reg);
-       return 0;
-} /* fill_rings */
-
-void unfill_rings(struct agnx_priv *priv)
-{
-       unsigned long flags;
-       unsigned int i;
-       AGNX_TRACE;
-
-       spin_lock_irqsave(&priv->lock, flags);
-
-       for (i = 0; i < priv->rx.size; i++)
-               rx_desc_free(priv, i);
-       for (i = 0; i < priv->txm.size; i++)
-               txm_desc_free(priv, i);
-       for (i = 0; i < priv->txd.size; i++)
-               txd_desc_free(priv, i);
-
-       spin_unlock_irqrestore(&priv->lock, flags);
-}
-
-/* Extract the bitrate out of a CCK PLCP header.
-   copy from bcm43xx driver */
-static inline u8 agnx_plcp_get_bitrate_cck(__be32 *phyhdr_11b)
-{
-       /* FIXME */
-       switch (*(u8 *)phyhdr_11b) {
-       case 0x0A:
-               return 0;
-       case 0x14:
-               return 1;
-       case 0x37:
-               return 2;
-       case 0x6E:
-               return 3;
-       }
-       agnx_bug("Wrong plcp rate");
-       return 0;
-}
-
-/* FIXME */
-static inline u8 agnx_plcp_get_bitrate_ofdm(__be32 *phyhdr_11g)
-{
-       u8 rate = *(u8 *)phyhdr_11g & 0xF;
-
-       printk(PFX "G mode rate is 0x%x\n", rate);
-       return rate;
-}
-
-/* FIXME */
-static void get_rx_stats(struct agnx_priv *priv, struct agnx_hdr *hdr,
-                        struct ieee80211_rx_status *stat)
-{
-       void __iomem *ctl = priv->ctl;
-       u8 *rssi;
-       u32 noise;
-       /* FIXME just for test */
-       int snr = 40;           /* signal-to-noise ratio */
-
-       memset(stat, 0, sizeof(*stat));
-       /* RSSI */
-       rssi = (u8 *)&hdr->phy_stats_lo;
-/*     stat->ssi = (rssi[0] + rssi[1] + rssi[2]) / 3; */
-       /* Noise */
-       noise = ioread32(ctl + AGNX_GCR_NOISE0);
-       noise += ioread32(ctl + AGNX_GCR_NOISE1);
-       noise += ioread32(ctl + AGNX_GCR_NOISE2);
-       stat->noise = noise / 3;
-       /* Signal quality */
-/*     snr = stat->ssi - stat->noise; */
-       if (snr >= 0 && snr < 40)
-               stat->signal = 5 * snr / 2;
-       else if (snr >= 40)
-               stat->signal = 100;
-       else
-               stat->signal = 0;
-
-
-       if (hdr->_11b0 && !hdr->_11g0) {
-               stat->rate_idx = agnx_plcp_get_bitrate_cck(&hdr->_11b0);
-       } else if (!hdr->_11b0 && hdr->_11g0) {
-               printk(PFX "RX: Found G mode packet\n");
-               stat->rate_idx = agnx_plcp_get_bitrate_ofdm(&hdr->_11g0);
-       } else
-               agnx_bug("Unknown packets type");
-
-
-       stat->band = IEEE80211_BAND_2GHZ;
-       stat->freq = agnx_channels[priv->channel - 1].center_freq;
-/*     stat->antenna = 3;
-       stat->mactime = be32_to_cpu(hdr->time_stamp);
-       stat->channel = priv->channel; */
-}
-
-static inline void combine_hdr_frag(struct ieee80211_hdr *ieeehdr,
-                                   struct sk_buff *skb)
-{
-       u16 fctl;
-       unsigned int hdrlen;
-
-       fctl = le16_to_cpu(ieeehdr->frame_control);
-       hdrlen = ieee80211_hdrlen(fctl);
-       /* FIXME */
-       if (hdrlen < (2+2+6)/*minimum hdr*/ ||
-           hdrlen > sizeof(struct ieee80211_mgmt)) {
-               printk(KERN_ERR PFX "hdr len is %d\n", hdrlen);
-               agnx_bug("Wrong ieee80211 hdr detected");
-       }
-       skb_push(skb, hdrlen);
-       memcpy(skb->data, ieeehdr, hdrlen);
-} /* combine_hdr_frag */
-
-static inline int agnx_packet_check(struct agnx_priv *priv, struct agnx_hdr *agnxhdr,
-                                   unsigned packet_len)
-{
-       if (agnx_get_bits(CRC_FAIL, CRC_FAIL_SHIFT, be32_to_cpu(agnxhdr->reg1)) == 1) {
-               printk(PFX "RX: CRC check fail\n");
-               goto drop;
-       }
-       if (packet_len > 2048) {
-               printk(PFX "RX: Too long packet detected\n");
-               goto drop;
-       }
-
-       /* FIXME Just usable for Promious Mode, for Manage mode exclude FCS */
-/*     if (packet_len - sizeof(*agnxhdr) < FCS_LEN) { */
-/*             printk(PFX "RX: Too short packet detected\n"); */
-/*             goto drop; */
-/*     } */
-       return 0;
-drop:
-       priv->stats.dot11FCSErrorCount++;
-       return -1;
-}
-
-void handle_rx_irq(struct agnx_priv *priv)
-{
-       struct ieee80211_rx_status status;
-       unsigned int len;
-/*     AGNX_TRACE; */
-
-       do {
-               struct agnx_desc *desc;
-               u32 frag;
-               struct agnx_info *info;
-               struct agnx_hdr *hdr;
-               struct sk_buff *skb;
-               unsigned int i = priv->rx.idx % priv->rx.size;
-
-               desc = priv->rx.desc + i;
-               frag = be32_to_cpu(desc->frag);
-               if (frag & OWNER)
-                       break;
-
-               info = priv->rx.info + i;
-               skb = info->skb;
-               hdr = (struct agnx_hdr *)(skb->data);
-
-               len = (frag & PACKET_LEN) >> PACKET_LEN_SHIFT;
-               if (agnx_packet_check(priv, hdr, len) == -1) {
-                       rx_desc_reusing(priv, i);
-                       continue;
-               }
-               skb_put(skb, len);
-
-               do {
-                               u16 fctl;
-                       fctl = le16_to_cpu(((struct ieee80211_hdr *)hdr->mac_hdr)->frame_control);
-                       if ((fctl & IEEE80211_FCTL_STYPE) != IEEE80211_STYPE_BEACON)/* && !(fctl & IEEE80211_STYPE_BEACON)) */
-                               dump_ieee80211_hdr((struct ieee80211_hdr *)hdr->mac_hdr, "RX");
-               } while (0);
-
-               if (hdr->_11b0 && !hdr->_11g0) {
-/*                     int j;
-                       u16 fctl = le16_to_cpu(((struct ieee80211_hdr *)hdr->mac_hdr)
-                                              ->frame_control);
-                       if ( (fctl & IEEE80211_FCTL_FTYPE) ==  IEEE80211_FTYPE_DATA) {
-                               agnx_print_rx_hdr(hdr);
-                               agnx_print_sta(priv, BSSID_STAID);
-                               for (j = 0; j < 8; j++)
-                                       agnx_print_sta_tx_wq(priv, BSSID_STAID, j);
-                       } */
-
-                       get_rx_stats(priv, hdr, &status);
-                       skb_pull(skb, sizeof(*hdr));
-                       combine_hdr_frag((struct ieee80211_hdr *)hdr->mac_hdr, skb);
-               } else if (!hdr->_11b0 && hdr->_11g0) {
-/*                     int j; */
-                       agnx_print_rx_hdr(hdr);
-                       agnx_print_sta(priv, BSSID_STAID);
-/*                     for (j = 0; j < 8; j++) */
-                       agnx_print_sta_tx_wq(priv, BSSID_STAID, 0);
-
-                       print_hex_dump_bytes("agnx: RX_PACKET: ", DUMP_PREFIX_NONE,
-                                            skb->data, skb->len + 8);
-
-/*                     if (agnx_plcp_get_bitrate_ofdm(&hdr->_11g0) == 0) */
-                       get_rx_stats(priv, hdr, &status);
-                       skb_pull(skb, sizeof(*hdr));
-                       combine_hdr_frag((struct ieee80211_hdr *)
-                                        ((void *)&hdr->mac_hdr), skb);
-/*                     dump_ieee80211_hdr((struct ieee80211_hdr *)skb->data, "RX G"); */
-               } else
-                       agnx_bug("Unknown packets type");
-               memcpy(IEEE80211_SKB_RXCB(skb), &status, sizeof(status));
-               ieee80211_rx_irqsafe(priv->hw, skb);
-               rx_desc_reinit(priv, i);
-
-       } while (priv->rx.idx++);
-} /* handle_rx_irq */
-
-static inline void handle_tx_irq(struct agnx_priv *priv, struct agnx_ring *ring)
-{
-       struct agnx_desc *desc;
-       struct agnx_info *info;
-       unsigned int idx;
-
-       for (idx = ring->idx_sent; idx < ring->idx; idx++) {
-               unsigned int i = idx % ring->size;
-               u32  frag;
-
-               desc = ring->desc + i;
-               info = ring->info + i;
-
-               frag = be32_to_cpu(desc->frag);
-               if (frag & OWNER) {
-                       if (info->type == HEADER)
-                               break;
-                       else
-                               agnx_bug("TX error");
-               }
-
-               pci_unmap_single(priv->pdev, info->mapping, info->dma_len, PCI_DMA_TODEVICE);
-
-               do {
-/*                     int j; */
-                       size_t len;
-                       len = info->skb->len - sizeof(struct agnx_hdr) + info->hdr_len;
-/*                     if (len == 614) { */
-/*                             agnx_print_desc(desc); */
-                               if (info->type == PACKET) {
-/*                                     agnx_print_tx_hdr((struct agnx_hdr *)info->skb->data); */
-/*                                     agnx_print_sta_power(priv, LOCAL_STAID); */
-/*                                     agnx_print_sta(priv, LOCAL_STAID); */
-/*                                     for (j = 0; j < 8; j++) */
-/*                                     agnx_print_sta_tx_wq(priv, LOCAL_STAID, 0); */
-/*                                     agnx_print_sta_power(priv, BSSID_STAID); */
-/*                                     agnx_print_sta(priv, BSSID_STAID); */
-/*                                     for (j = 0; j < 8; j++) */
-/*                                     agnx_print_sta_tx_wq(priv, BSSID_STAID, 0); */
-                               }
-/*                     } */
-               } while (0);
-
-               if (info->type == PACKET) {
-/*                     dump_txm_registers(priv);
-                       dump_rxm_registers(priv);
-                       dump_bm_registers(priv);
-                       dump_cir_registers(priv); */
-               }
-
-               if (info->type == PACKET) {
-/*                     struct ieee80211_hdr *hdr; */
-                       struct ieee80211_tx_info *txi = IEEE80211_SKB_CB(info->skb);
-
-                       skb_pull(info->skb, sizeof(struct agnx_hdr));
-                       memcpy(skb_push(info->skb, info->hdr_len), &info->hdr, info->hdr_len);
-
-/*                     dump_ieee80211_hdr((struct ieee80211_hdr *)info->skb->data, "TX_HANDLE"); */
-/*                     print_hex_dump_bytes("agnx: TX_HANDLE: ", DUMP_PREFIX_NONE, */
-/*                                          info->skb->data, info->skb->len); */
-
-                       if (!(txi->flags & IEEE80211_TX_CTL_NO_ACK))
-                               txi->flags |= IEEE80211_TX_STAT_ACK;
-
-                       ieee80211_tx_status_irqsafe(priv->hw, info->skb);
-
-
-/*                             info->tx_status.queue_number = (ring->size - i) / 2; */
-/*                             ieee80211_tx_status_irqsafe(priv->hw, info->skb, &(info->tx_status)); */
-/*                     } else */
-/*                             dev_kfree_skb_irq(info->skb); */
-               }
-               memset(desc, 0, sizeof(*desc));
-               memset(info, 0, sizeof(*info));
-       }
-
-       ring->idx_sent = idx;
-       /* TODO fill the priv->low_level_stats */
-
-       /* ieee80211_wake_queue(priv->hw, 0); */
-}
-
-void handle_txm_irq(struct agnx_priv *priv)
-{
-       handle_tx_irq(priv, &priv->txm);
-}
-
-void handle_txd_irq(struct agnx_priv *priv)
-{
-       handle_tx_irq(priv, &priv->txd);
-}
-
-void handle_other_irq(struct agnx_priv *priv)
-{
-/*     void __iomem *ctl = priv->ctl; */
-       u32 status = priv->irq_status;
-       void __iomem *ctl = priv->ctl;
-       u32 reg;
-
-       if (status & IRQ_TX_BEACON) {
-               iowrite32(IRQ_TX_BEACON, ctl + AGNX_INT_STAT);
-               printk(PFX "IRQ: TX Beacon control is 0X%.8X\n", ioread32(ctl + AGNX_TXM_BEACON_CTL));
-               printk(PFX "IRQ: TX Beacon rx frame num: %d\n", rx_frame_cnt);
-       }
-       if (status & IRQ_TX_RETRY) {
-               reg = ioread32(ctl + AGNX_TXM_RETRYSTAID);
-               printk(PFX "IRQ: TX Retry, RETRY STA ID is %x\n", reg);
-       }
-       if (status & IRQ_TX_ACTIVITY)
-               printk(PFX "IRQ: TX Activity\n");
-       if (status & IRQ_RX_ACTIVITY)
-               printk(PFX "IRQ: RX Activity\n");
-       if (status & IRQ_RX_X)
-               printk(PFX "IRQ: RX X\n");
-       if (status & IRQ_RX_Y) {
-               reg = ioread32(ctl + AGNX_INT_MASK);
-               reg &= ~IRQ_RX_Y;
-               iowrite32(reg, ctl + AGNX_INT_MASK);
-               iowrite32(IRQ_RX_Y, ctl + AGNX_INT_STAT);
-               printk(PFX "IRQ: RX Y\n");
-       }
-       if (status & IRQ_RX_HASHHIT)  {
-               reg = ioread32(ctl + AGNX_INT_MASK);
-               reg &= ~IRQ_RX_HASHHIT;
-               iowrite32(reg, ctl + AGNX_INT_MASK);
-               iowrite32(IRQ_RX_HASHHIT, ctl + AGNX_INT_STAT);
-               printk(PFX "IRQ: RX Hash Hit\n");
-
-       }
-       if (status & IRQ_RX_FRAME) {
-               reg = ioread32(ctl + AGNX_INT_MASK);
-               reg &= ~IRQ_RX_FRAME;
-               iowrite32(reg, ctl + AGNX_INT_MASK);
-               iowrite32(IRQ_RX_FRAME, ctl + AGNX_INT_STAT);
-               printk(PFX "IRQ: RX Frame\n");
-               rx_frame_cnt++;
-       }
-       if (status & IRQ_ERR_INT) {
-               iowrite32(IRQ_ERR_INT, ctl + AGNX_INT_STAT);
-/*             agnx_hw_reset(priv); */
-               printk(PFX "IRQ: Error Interrupt\n");
-       }
-       if (status & IRQ_TX_QUE_FULL)
-               printk(PFX "IRQ: TX Workqueue Full\n");
-       if (status & IRQ_BANDMAN_ERR)
-               printk(PFX "IRQ: Bandwidth Management Error\n");
-       if (status & IRQ_TX_DISABLE)
-               printk(PFX "IRQ: TX Disable\n");
-       if (status & IRQ_RX_IVASESKEY)
-               printk(PFX "IRQ: RX Invalid Session Key\n");
-       if (status & IRQ_REP_THHIT)
-               printk(PFX "IRQ: Replay Threshold Hit\n");
-       if (status & IRQ_TIMER1)
-               printk(PFX "IRQ: Timer1\n");
-       if (status & IRQ_TIMER_CNT)
-               printk(PFX "IRQ: Timer Count\n");
-       if (status & IRQ_PHY_FASTINT)
-               printk(PFX "IRQ: Phy Fast Interrupt\n");
-       if (status & IRQ_PHY_SLOWINT)
-               printk(PFX "IRQ: Phy Slow Interrupt\n");
-       if (status & IRQ_OTHER)
-               printk(PFX "IRQ: 0x80000000\n");
-} /* handle_other_irq */
-
-
-static inline void route_flag_set(struct agnx_hdr *txhdr)
-{
-/*     u32 reg = 0; */
-
-       /* FIXME */
-/*     reg = (0x7 << ROUTE_COMPRESSION_SHIFT) & ROUTE_COMPRESSION; */
-/*     txhdr->reg5 = cpu_to_be32(reg); */
-       txhdr->reg5 = (0xa << 0x0) | (0x7 << 0x18);
-/*     txhdr->reg5 = cpu_to_be32((0xa << 0x0) | (0x7 << 0x18)); */
-/*     txhdr->reg5 = cpu_to_be32(0x7 << 0x0); */
-}
-
-/* Return 0 if no match */
-static inline unsigned int get_power_level(unsigned int rate, unsigned int antennas_num)
-{
-       unsigned int power_level;
-
-       switch (rate) {
-       case 10:
-       case 20:
-       case 55:
-       case 60:
-       case 90:
-       case 120:
-               power_level = 22;
-               break;
-
-       case 180:
-               power_level = 19;
-               break;
-
-       case 240:
-               power_level = 18;
-               break;
-
-       case 360:
-               power_level = 16;
-               break;
-
-       case 480:
-               power_level = 15;
-               break;
-
-       case 540:
-               power_level = 14;
-               break;
-       default:
-               agnx_bug("Error rate setting\n");
-       }
-
-       if (power_level && (antennas_num == 2))
-               power_level -= 3;
-
-       return power_level;
-}
-
-static inline void fill_agnx_hdr(struct agnx_priv *priv, struct agnx_info *tx_info)
-{
-       struct agnx_hdr *txhdr = (struct agnx_hdr *)tx_info->skb->data;
-       size_t len;
-       u16 fc = le16_to_cpu(*(__le16 *)&tx_info->hdr);
-       u32 reg;
-
-       memset(txhdr, 0, sizeof(*txhdr));
-
-/*     reg = agnx_set_bits(STATION_ID, STATION_ID_SHIFT, LOCAL_STAID); */
-       reg = agnx_set_bits(STATION_ID, STATION_ID_SHIFT, BSSID_STAID);
-       reg |= agnx_set_bits(WORKQUEUE_ID, WORKQUEUE_ID_SHIFT, 0);
-       txhdr->reg4 = cpu_to_be32(reg);
-
-       /* Set the Hardware Sequence Number to 1? */
-       reg = agnx_set_bits(SEQUENCE_NUMBER, SEQUENCE_NUMBER_SHIFT, 0);
-/*     reg = agnx_set_bits(SEQUENCE_NUMBER, SEQUENCE_NUMBER_SHIFT, 1); */
-       reg |= agnx_set_bits(MAC_HDR_LEN, MAC_HDR_LEN_SHIFT, tx_info->hdr_len);
-       txhdr->reg1 = cpu_to_be32(reg);
-       /* Set the agnx_hdr's MAC header */
-       memcpy(txhdr->mac_hdr, &tx_info->hdr, tx_info->hdr_len);
-
-       reg = agnx_set_bits(ACK, ACK_SHIFT, 1);
-/*     reg = agnx_set_bits(ACK, ACK_SHIFT, 0); */
-       reg |= agnx_set_bits(MULTICAST, MULTICAST_SHIFT, 0);
-/*     reg |= agnx_set_bits(MULTICAST, MULTICAST_SHIFT, 1); */
-       reg |= agnx_set_bits(RELAY, RELAY_SHIFT, 0);
-       reg |= agnx_set_bits(TM, TM_SHIFT, 0);
-       txhdr->reg0 = cpu_to_be32(reg);
-
-       /* Set the long and short retry limits */
-       txhdr->tx.short_retry_limit = tx_info->txi->control.rates[0].count;
-       txhdr->tx.long_retry_limit = tx_info->txi->control.rates[0].count;
-
-       /* FIXME */
-       len = tx_info->skb->len - sizeof(*txhdr) + tx_info->hdr_len + FCS_LEN;
-       if (fc & IEEE80211_FCTL_PROTECTED)
-               len += 8;
-       len = 2398;
-       reg = agnx_set_bits(FRAG_SIZE, FRAG_SIZE_SHIFT, len);
-       len = tx_info->skb->len - sizeof(*txhdr);
-       reg |= agnx_set_bits(PAYLOAD_LEN, PAYLOAD_LEN_SHIFT, len);
-       txhdr->reg3 = cpu_to_be32(reg);
-
-       route_flag_set(txhdr);
-} /* fill_hdr */
-
-static void txm_power_set(struct agnx_priv *priv,
-                         struct ieee80211_tx_info *txi)
-{
-       struct agnx_sta_power power;
-       u32 reg;
-
-       /* FIXME */
-       if (txi->control.rates[0].idx < 0) {
-               /* For B mode Short Preamble */
-               reg = agnx_set_bits(PHY_MODE, PHY_MODE_SHIFT, AGNX_MODE_80211B_SHORT);
-/*             control->tx_rate = -control->tx_rate; */
-       } else
-               reg = agnx_set_bits(PHY_MODE, PHY_MODE_SHIFT, AGNX_MODE_80211G);
-/*             reg = agnx_set_bits(PHY_MODE, PHY_MODE_SHIFT, AGNX_MODE_80211B_LONG); */
-       reg |= agnx_set_bits(SIGNAL, SIGNAL_SHIFT, 0xB);
-       reg |= agnx_set_bits(RATE, RATE_SHIFT, 0xB);
-/*     reg |= agnx_set_bits(POWER_LEVEL, POWER_LEVEL_SHIFT, 15); */
-       reg |= agnx_set_bits(POWER_LEVEL, POWER_LEVEL_SHIFT, 20);
-       /* if rate < 11M set it to 0 */
-       reg |= agnx_set_bits(NUM_TRANSMITTERS, NUM_TRANSMITTERS_SHIFT, 1);
-/*     reg |= agnx_set_bits(EDCF, EDCF_SHIFT, 1); */
-/*     reg |= agnx_set_bits(TIFS, TIFS_SHIFT, 1); */
-
-       power.reg = reg;
-/*     power.reg = cpu_to_le32(reg); */
-
-/*     set_sta_power(priv, &power, LOCAL_STAID); */
-       set_sta_power(priv, &power, BSSID_STAID);
-}
-
-static inline int tx_packet_check(struct sk_buff *skb)
-{
-       unsigned int ieee_len = ieee80211_get_hdrlen_from_skb(skb);
-       if (skb->len > 2048) {
-               printk(KERN_ERR PFX "length is %d\n", skb->len);
-               agnx_bug("Too long TX skb");
-               return -1;
-       }
-       /* FIXME */
-       if (skb->len == ieee_len) {
-               printk(PFX "A strange TX packet\n");
-               return -1;
-               /* tx_faile_irqsafe(); */
-       }
-       return 0;
-}
-
-static int __agnx_tx(struct agnx_priv *priv, struct sk_buff *skb,
-                    struct agnx_ring *ring)
-{
-       struct agnx_desc *hdr_desc, *frag_desc;
-       struct agnx_info *hdr_info, *frag_info;
-       struct ieee80211_tx_info *txi = IEEE80211_SKB_CB(skb);
-       unsigned long flags;
-       unsigned int i;
-
-       spin_lock_irqsave(&priv->lock, flags);
-
-       /* The RX interrupt need be Disable until this TX packet
-          is handled in the next tx interrupt */
-       disable_rx_interrupt(priv);
-
-       i = ring->idx;
-       ring->idx += 2;
-/*     if (priv->txm_idx - priv->txm_idx_sent == AGNX_TXM_RING_SIZE - 2) */
-/*             ieee80211_stop_queue(priv->hw, 0); */
-
-       /* Set agnx header's info and desc */
-       i %= ring->size;
-       hdr_desc = ring->desc + i;
-       hdr_info = ring->info + i;
-       hdr_info->hdr_len = ieee80211_get_hdrlen_from_skb(skb);
-       memcpy(&hdr_info->hdr, skb->data, hdr_info->hdr_len);
-
-       /* Add the agnx header to the front of the SKB */
-       skb_push(skb, sizeof(struct agnx_hdr) - hdr_info->hdr_len);
-
-       hdr_info->txi = txi;
-       hdr_info->dma_len = sizeof(struct agnx_hdr);
-       hdr_info->skb = skb;
-       hdr_info->type = HEADER;
-       fill_agnx_hdr(priv, hdr_info);
-       hdr_info->mapping = pci_map_single(priv->pdev, skb->data,
-                                          hdr_info->dma_len, PCI_DMA_TODEVICE);
-       do {
-               u32 frag = 0;
-               frag |= agnx_set_bits(FIRST_FRAG, FIRST_FRAG_SHIFT, 1);
-               frag |= agnx_set_bits(LAST_FRAG, LAST_FRAG_SHIFT, 0);
-               frag |= agnx_set_bits(PACKET_LEN, PACKET_LEN_SHIFT, skb->len);
-               frag |= agnx_set_bits(FIRST_FRAG_LEN, FIRST_FRAG_LEN_SHIFT, 1);
-               frag |= agnx_set_bits(OWNER, OWNER_SHIFT, 1);
-               hdr_desc->frag = cpu_to_be32(frag);
-       } while (0);
-       hdr_desc->dma_addr = cpu_to_be32(hdr_info->mapping);
-
-
-       /* Set Frag's info and desc */
-       i = (i + 1) % ring->size;
-       frag_desc = ring->desc + i;
-       frag_info = ring->info + i;
-       memcpy(frag_info, hdr_info, sizeof(struct agnx_info));
-       frag_info->type = PACKET;
-       frag_info->dma_len = skb->len - hdr_info->dma_len;
-       frag_info->mapping = pci_map_single(priv->pdev, skb->data + hdr_info->dma_len,
-                                           frag_info->dma_len, PCI_DMA_TODEVICE);
-       do {
-               u32 frag = 0;
-               frag |= agnx_set_bits(FIRST_FRAG, FIRST_FRAG_SHIFT, 0);
-               frag |= agnx_set_bits(LAST_FRAG, LAST_FRAG_SHIFT, 1);
-               frag |= agnx_set_bits(PACKET_LEN, PACKET_LEN_SHIFT, skb->len);
-               frag |= agnx_set_bits(SUB_FRAG_LEN, SUB_FRAG_LEN_SHIFT, frag_info->dma_len);
-               frag_desc->frag = cpu_to_be32(frag);
-       } while (0);
-       frag_desc->dma_addr = cpu_to_be32(frag_info->mapping);
-
-       txm_power_set(priv, txi);
-
-/*     do { */
-/*             int j; */
-/*             size_t len; */
-/*             len = skb->len - hdr_info->dma_len + hdr_info->hdr_len;  */
-/*             if (len == 614) { */
-/*                     agnx_print_desc(hdr_desc); */
-/*                     agnx_print_desc(frag_desc); */
-/*                     agnx_print_tx_hdr((struct agnx_hdr *)skb->data); */
-/*                     agnx_print_sta_power(priv, LOCAL_STAID); */
-/*                     agnx_print_sta(priv, LOCAL_STAID); */
-/*                     for (j = 0; j < 8; j++) */
-/*                             agnx_print_sta_tx_wq(priv, LOCAL_STAID, j); */
-/*                     agnx_print_sta_power(priv, BSSID_STAID); */
-/*                     agnx_print_sta(priv, BSSID_STAID); */
-/*                     for (j = 0; j < 8; j++) */
-/*                             agnx_print_sta_tx_wq(priv, BSSID_STAID, j); */
-/*                     } */
-/*     } while (0); */
-
-       spin_unlock_irqrestore(&priv->lock, flags);
-
-       /* FIXME ugly code */
-       /* Trigger TXM */
-       do {
-               u32 reg;
-               reg = (ioread32(priv->ctl + AGNX_CIR_TXMCTL));
-               reg |= 0x8;
-               iowrite32((reg), priv->ctl + AGNX_CIR_TXMCTL);
-       } while (0);
-
-       /* Trigger TXD */
-       do {
-               u32 reg;
-               reg = (ioread32(priv->ctl + AGNX_CIR_TXDCTL));
-               reg |= 0x8;
-               iowrite32((reg), priv->ctl + AGNX_CIR_TXDCTL);
-       } while (0);
-
-       return 0;
-}
-
-int _agnx_tx(struct agnx_priv *priv, struct sk_buff *skb)
-{
-       u16 fctl;
-
-       if (tx_packet_check(skb))
-               return 0;
-
-/*     print_hex_dump_bytes("agnx: TX_PACKET: ", DUMP_PREFIX_NONE, */
-/*                          skb->data, skb->len); */
-
-       fctl = le16_to_cpu(*((__le16 *)skb->data));
-
-       if ((fctl & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA)
-               return __agnx_tx(priv, skb, &priv->txd);
-       else
-               return __agnx_tx(priv, skb, &priv->txm);
-}
diff --git a/drivers/staging/agnx/xmit.h b/drivers/staging/agnx/xmit.h
deleted file mode 100644 (file)
index 93ac415..0000000
+++ /dev/null
@@ -1,250 +0,0 @@
-#ifndef AGNX_XMIT_H_
-#define AGNX_XMIT_H_
-
-#include <net/mac80211.h>
-
-struct agnx_priv;
-
-static inline u32 agnx_set_bits(u32 mask, u8 shift, u32 value)
-{
-       return (value << shift) & mask;
-}
-
-static inline u32 agnx_get_bits(u32 mask, u8 shift, u32 value)
-{
-       return (value & mask) >> shift;
-}
-
-
-struct agnx_rx {
-       __be16 rx_packet_duration; /*  RX Packet Duration */
-       __be16 replay_cnt;      /* Replay Count */
-} __attribute__((__packed__));
-
-
-struct agnx_tx {
-       u8 long_retry_limit; /* Long Retry Limit */
-       u8 short_retry_limit; /* Short Retry Limit */
-       u8 long_retry_cnt;      /* Long Retry Count */
-       u8 short_retry_cnt; /* Short Retry Count */
-} __attribute__((__packed__));
-
-
-/* Copy from bcm43xx */
-#define P4D_BYT3S(magic, nr_bytes)      u8 __p4dding##magic[nr_bytes]
-#define P4D_BYTES(line, nr_bytes)       P4D_BYT3S(line, nr_bytes)
-#define PAD_BYTES(nr_bytes)             P4D_BYTES(__LINE__, nr_bytes)
-
-#define P4D_BIT3S(magic, nr_bits)       __be32 __padding##magic:nr_bits
-#define P4D_BITS(line, nr_bits)         P4D_BIT3S(line, nr_bits)
-#define PAD_BITS(nr_bits)              P4D_BITS(__LINE__, nr_bits)
-
-
-struct agnx_hdr {
-       __be32 reg0;
-#define RTS                    0x80000000 /* RTS */
-#define RTS_SHIFT              31
-#define MULTICAST              0x40000000 /* multicast */
-#define MULTICAST_SHIFT                30
-#define ACK                    0x30000000 /* ACK */
-#define ACK_SHIFT              28
-#define TM                     0x08000000 /* TM */
-#define TM_SHIFT               27
-#define RELAY                  0x04000000 /* Relay */
-#define RELAY_SHIFT            26
-/*     PAD_BITS(4); */
-#define REVISED_FCS            0x00380000 /* revised FCS */
-#define REVISED_FCS_SHIFT      19
-#define NEXT_BUFFER_ADDR       0x0007FFFF /* Next Buffer Address */
-#define NEXT_BUFFER_ADDR_SHIFT 0
-
-       __be32 reg1;
-#define MAC_HDR_LEN            0xFC000000 /* MAC Header Length  */
-#define MAC_HDR_LEN_SHIFT      26
-#define DURATION_OVERIDE       0x02000000 /* Duration Override */
-#define DURATION_OVERIDE_SHIFT 25
-#define PHY_HDR_OVERIDE                0x01000000 /* PHY Header Override */
-#define PHY_HDR_OVERIDE_SHIFT  24
-#define CRC_FAIL               0x00800000 /* CRC fail */
-#define CRC_FAIL_SHIFT         23
-/*     PAD_BITS(1); */
-#define SEQUENCE_NUMBER                0x00200000 /* Sequence Number */
-#define SEQUENCE_NUMBER_SHIFT  21
-/*     PAD_BITS(2); */
-#define BUFF_HEAD_ADDR         0x0007FFFF /* Buffer Head Address */
-#define BUFF_HEAD_ADDR_SHIFT   0
-
-       __be32 reg2;
-#define PDU_COUNT              0xFC000000 /* PDU Count */
-#define PDU_COUNT_SHIFT                26
-/*     PAD_BITS(3); */
-#define WEP_KEY                        0x00600000 /* WEP Key # */
-#define WEP_KEY_SHIFT          21
-#define USES_WEP_KEY           0x00100000 /* Uses WEP Key */
-#define USES_WEP_KEY_SHIFT     20
-#define KEEP_ALIVE             0x00080000 /* Keep alive */
-#define KEEP_ALIVE_SHIFT       19
-#define BUFF_TAIL_ADDR         0x0007FFFF /* Buffer Tail Address */
-#define BUFF_TAIL_ADDR_SHIFT   0
-
-       __be32 reg3;
-#define CTS_11G                        0x80000000      /* CTS in 11g */
-#define CTS_11G_SHIFT          31
-#define RTS_11G                        0x40000000      /* RTS in 11g */
-#define RTS_11G_SHIFT          30
-/* PAD_BITS(2); */
-#define FRAG_SIZE              0x0FFF0000      /* fragment size */
-#define FRAG_SIZE_SHIFT                16
-#define PAYLOAD_LEN            0x0000FFF0      /* payload length */
-#define PAYLOAD_LEN_SHIFT      4
-#define FRAG_NUM               0x0000000F      /* number of frags */
-#define FRAG_NUM_SHIFT         0
-
-       __be32 reg4;
-/*     PAD_BITS(4); */
-#define RELAY_STAID            0x0FFF0000 /* relayStald */
-#define RELAY_STAID_SHIFT      16
-#define STATION_ID             0x0000FFF0 /* Station ID */
-#define STATION_ID_SHIFT       4
-#define WORKQUEUE_ID           0x0000000F /* Workqueue ID */
-#define WORKQUEUE_ID_SHIFT     0
-
-       /* FIXME this register maybe is LE? */
-       __be32 reg5;
-/*     PAD_BITS(4); */
-#define ROUTE_HOST             0x0F000000
-#define ROUTE_HOST_SHIFT       24
-#define ROUTE_CARD_CPU         0x00F00000
-#define ROUTE_CARD_CPU_SHIFT   20
-#define ROUTE_ENCRYPTION       0x000F0000
-#define ROUTE_ENCRYPTION_SHIFT 16
-#define ROUTE_TX               0x0000F000
-#define ROUTE_TX_SHIFT         12
-#define ROUTE_RX1              0x00000F00
-#define ROUTE_RX1_SHIFT                8
-#define ROUTE_RX2              0x000000F0
-#define ROUTE_RX2_SHIFT                4
-#define ROUTE_COMPRESSION      0x0000000F
-#define ROUTE_COMPRESSION_SHIFT 0
-
-       __be32 _11g0;                   /* 11g */
-       __be32 _11g1;                   /* 11g */
-       __be32 _11b0;                   /* 11b */
-       __be32 _11b1;                   /* 11b */
-       u8 mac_hdr[32];                 /* MAC header */
-
-       __be16 rts_duration;            /* RTS duration */
-       __be16 last_duration;           /* Last duration */
-       __be16 sec_last_duration;       /* Second to Last duration */
-       __be16 other_duration;          /* Other duration */
-       __be16 tx_last_duration;        /* TX Last duration */
-       __be16 tx_other_duration;       /* TX Other Duration */
-       __be16 last_11g_len;            /* Length of last 11g */
-       __be16 other_11g_len;           /* Lenght of other 11g */
-
-       __be16 last_11b_len;            /* Length of last 11b */
-       __be16 other_11b_len;           /* Lenght of other 11b */
-
-
-       __be16 reg6;
-#define MBF                    0xF000 /* mbf */
-#define MBF_SHIFT              12
-#define RSVD4                  0x0FFF /* rsvd4 */
-#define RSVD4_SHIFT            0
-
-       __be16 rx_frag_stat;    /* RX fragmentation status */
-
-       __be32 time_stamp;      /* TimeStamp */
-       __be32 phy_stats_hi;    /* PHY stats hi */
-       __be32 phy_stats_lo;    /* PHY stats lo */
-       __be32 mic_key0;        /* MIC key 0 */
-       __be32 mic_key1;        /* MIC key 1 */
-
-       union {                 /* RX/TX Union */
-               struct agnx_rx rx;
-               struct agnx_tx tx;
-       };
-
-       u8 rx_channel;          /* Recieve Channel */
-       PAD_BYTES(3);
-
-       u8 reserved[4];
-} __attribute__((__packed__));
-
-
-struct agnx_desc {
-#define PACKET_LEN             0xFFF00000
-#define PACKET_LEN_SHIFT       20
-/* ------------------------------------------------ */
-#define FIRST_PACKET_MASK      0x00080000
-#define FIRST_PACKET_MASK_SHIFT        19
-#define FIRST_RESERV2          0x00040000
-#define FIRST_RESERV2_SHIFT    18
-#define FIRST_TKIP_ERROR       0x00020000
-#define FIRST_TKIP_ERROR_SHIFT 17
-#define FIRST_TKIP_PACKET      0x00010000
-#define FIRST_TKIP_PACKET_SHIFT        16
-#define FIRST_RESERV1          0x0000F000
-#define FIRST_RESERV1_SHIFT    12
-#define FIRST_FRAG_LEN         0x00000FF8
-#define FIRST_FRAG_LEN_SHIFT   3
-/* ------------------------------------------------ */
-#define SUB_RESERV2            0x000c0000
-#define SUB_RESERV2_SHIFT      18
-#define SUB_TKIP_ERROR         0x00020000
-#define SUB_TKIP_ERROR_SHIFT   17
-#define SUB_TKIP_PACKET                0x00010000
-#define SUB_TKIP_PACKET_SHIFT  16
-#define SUB_RESERV1            0x00008000
-#define SUB_RESERV1_SHIFT      15
-#define SUB_FRAG_LEN           0x00007FF8
-#define SUB_FRAG_LEN_SHIFT     3
-/* ------------------------------------------------ */
-#define FIRST_FRAG             0x00000004
-#define FIRST_FRAG_SHIFT       2
-#define LAST_FRAG              0x00000002
-#define LAST_FRAG_SHIFT                1
-#define OWNER                  0x00000001
-#define OWNER_SHIFT            0
-       __be32 frag;
-       __be32 dma_addr;
-} __attribute__((__packed__));
-
-enum {HEADER, PACKET};
-
-struct agnx_info {
-        struct sk_buff *skb;
-        dma_addr_t mapping;
-       u32 dma_len;            /* dma buffer len  */
-       /* Below fields only usful for tx */
-       u32 hdr_len;            /* ieee80211 header length */
-       unsigned int type;
-        struct ieee80211_tx_info *txi;
-        struct ieee80211_hdr hdr;
-};
-
-
-struct agnx_ring {
-       struct agnx_desc *desc;
-       dma_addr_t dma;
-       struct agnx_info *info;
-       /* Will lead to overflow when sent packet number enough? */
-       unsigned int idx;
-       unsigned int idx_sent;          /* only usful for txd and txm */
-       unsigned int size;
-};
-
-#define AGNX_RX_RING_SIZE      128
-#define AGNX_TXD_RING_SIZE     256
-#define AGNX_TXM_RING_SIZE     128
-
-void disable_rx_interrupt(struct agnx_priv *priv);
-void enable_rx_interrupt(struct agnx_priv *priv);
-int fill_rings(struct agnx_priv *priv);
-void unfill_rings(struct agnx_priv *priv);
-void handle_rx_irq(struct agnx_priv *priv);
-void handle_txd_irq(struct agnx_priv *priv);
-void handle_txm_irq(struct agnx_priv *priv);
-void handle_other_irq(struct agnx_priv *priv);
-int _agnx_tx(struct agnx_priv *priv, struct sk_buff *skb);
-#endif /* AGNX_XMIT_H_ */
index 2471949..eb67563 100644 (file)
@@ -2,6 +2,7 @@ menu "Android"
 
 config ANDROID
        bool "Android Drivers"
+       depends on BROKEN
        default N
        ---help---
          Enable support for various drivers needed on the Android platform
index 94c5d27..cda26bb 100644 (file)
@@ -36,6 +36,7 @@
 #include <linux/wait.h>
 #include <linux/mm.h>
 #include <linux/uaccess.h>
+#include <linux/sched.h>
 
 static unsigned int b3dfg_nbuf = 2;
 
index af723cb..d63c889 100644 (file)
@@ -1,7 +1,7 @@
 config COMEDI
        tristate "Data acquisition support (comedi)"
        default N
-       depends on m
+       depends on m && (PCI || PCMCIA || PCCARD || USB)
        ---help---
          Enable support a wide range of data acquisition devices
          for Linux.
index f54bb9b..aaad76e 100644 (file)
@@ -2337,7 +2337,7 @@ static int resize_async_buffer(struct comedi_device *dev,
        }
 
        DPRINTK("comedi%i subd %d buffer resized to %i bytes\n",
-               dev->minor, s - dev->subdevices, async->prealloc_bufsz);
+               dev->minor, (int)(s - dev->subdevices), async->prealloc_bufsz);
        return 0;
 }
 
index 12d12b4..80c0df8 100644 (file)
@@ -744,7 +744,7 @@ static int das16cs_pcmcia_attach(struct pcmcia_device *link)
 
        /* Initialize the pcmcia_device structure */
        /* Interrupt setup */
-       link->irq.Attributes = IRQ_TYPE_EXCLUSIVE;
+       link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING;
        link->irq.IRQInfo1 = IRQ_LEVEL_ID;
        link->irq.Handler = NULL;
 
index 4d10bc3..09e6e3b 100644 (file)
@@ -53,7 +53,8 @@ Passing a zero for an option is the same as leaving it unspecified.
  * Some drivers use arrays such as this, other do not.
  */
 struct pcidio_board {
-       const char *name;       /*  anme of the board */
+       const char *name;       /*  name of the board */
+       int dev_id;
        int n_8255;             /*  number of 8255 chips on board */
 
        /*  indices of base address regions */
@@ -64,18 +65,21 @@ struct pcidio_board {
 static const struct pcidio_board pcidio_boards[] = {
        {
         .name = "pci-dio24",
+        .dev_id = 0x0028,
         .n_8255 = 1,
         .pcicontroler_badrindex = 1,
         .dioregs_badrindex = 2,
         },
        {
         .name = "pci-dio24h",
+        .dev_id = 0x0014,
         .n_8255 = 1,
         .pcicontroler_badrindex = 1,
         .dioregs_badrindex = 2,
         },
        {
         .name = "pci-dio48h",
+        .dev_id = 0x000b,
         .n_8255 = 2,
         .pcicontroler_badrindex = 0,
         .dioregs_badrindex = 1,
@@ -206,7 +210,7 @@ static int pcidio_attach(struct comedi_device *dev, struct comedi_devconfig *it)
                        continue;
                /*  loop through cards supported by this driver */
                for (index = 0; index < ARRAY_SIZE(pcidio_boards); index++) {
-                       if (pcidio_pci_table[index].device != pcidev->device)
+                       if (pcidio_boards[index].dev_id != pcidev->device)
                                continue;
 
                        /*  was a particular bus/slot requested? */
index 14bf29b..0d2c2eb 100644 (file)
@@ -515,6 +515,7 @@ static struct poll_delay_t jr3_pci_poll_subdevice(struct comedi_subdevice *s)
 {
        struct poll_delay_t result = poll_delay_min_max(1000, 2000);
        struct jr3_pci_subdev_private *p = s->private;
+       int i;
 
        if (p) {
                volatile struct jr3_channel *channel = p->channel;
@@ -570,18 +571,11 @@ static struct poll_delay_t jr3_pci_poll_subdevice(struct comedi_subdevice *s)
                                               p->serial_no);
 
                                        /*  Transformation all zeros */
-                                       transf.link[0].link_type =
-                                           (enum link_types)0;
-                                       transf.link[0].link_amount = 0;
-                                       transf.link[1].link_type =
-                                           (enum link_types)0;
-                                       transf.link[1].link_amount = 0;
-                                       transf.link[2].link_type =
-                                           (enum link_types)0;
-                                       transf.link[2].link_amount = 0;
-                                       transf.link[3].link_type =
-                                           (enum link_types)0;
-                                       transf.link[3].link_amount = 0;
+                                       for (i = 0; i < ARRAY_SIZE(transf.link); i++) {
+                                               transf.link[i].link_type =
+                                                       (enum link_types)0;
+                                               transf.link[i].link_amount = 0;
+                                       }
 
                                        set_transforms(channel, transf, 0);
                                        use_transform(channel, 0);
index 2cda7ad..80e192d 100644 (file)
@@ -51,6 +51,7 @@ from http://www.comedi.org
 */
 
 #include <linux/interrupt.h>
+#include <linux/sched.h>
 #include "../comedidev.h"
 
 #include "comedi_pci.h"
index 6b118c1..bbf75eb 100644 (file)
@@ -418,15 +418,15 @@ static int ni_65xx_dio_insn_bits(struct comedi_device *dev,
                return -EINVAL;
        base_bitfield_channel = CR_CHAN(insn->chanspec);
        for (j = 0; j < max_ports_per_bitfield; ++j) {
+               const unsigned port_offset = ni_65xx_port_by_channel(base_bitfield_channel) + j;
                const unsigned port =
-                   sprivate(s)->base_port +
-                   ni_65xx_port_by_channel(base_bitfield_channel) + j;
+                   sprivate(s)->base_port + port_offset;
                unsigned base_port_channel;
                unsigned port_mask, port_data, port_read_bits;
                int bitshift;
                if (port >= ni_65xx_total_num_ports(board(dev)))
                        break;
-               base_port_channel = port * ni_65xx_channels_per_port;
+               base_port_channel = port_offset * ni_65xx_channels_per_port;
                port_mask = data[0];
                port_data = data[1];
                bitshift = base_port_channel - base_bitfield_channel;
@@ -457,6 +457,12 @@ static int ni_65xx_dio_insn_bits(struct comedi_device *dev,
                port_read_bits =
                    readb(private(dev)->mite->daq_io_addr + Port_Data(port));
 /* printk("read 0x%x from port %i\n", port_read_bits, port); */
+               if (s->type == COMEDI_SUBD_DO && board(dev)->invert_outputs) {
+                       /* Outputs inverted, so invert value read back from
+                        * DO subdevice.  (Does not apply to boards with DIO
+                        * subdevice.) */
+                       port_read_bits ^= 0xFF;
+               }
                if (bitshift > 0) {
                        port_read_bits <<= bitshift;
                } else {
index 6a77976..ec31a39 100644 (file)
@@ -520,7 +520,7 @@ static int dio700_cs_attach(struct pcmcia_device *link)
        link->priv = local;
 
        /* Interrupt setup */
-       link->irq.Attributes = IRQ_TYPE_EXCLUSIVE;
+       link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING;
        link->irq.IRQInfo1 = IRQ_LEVEL_ID;
        link->irq.Handler = NULL;
 
index b06e81c..0700a8b 100644 (file)
@@ -271,7 +271,7 @@ static int dio24_cs_attach(struct pcmcia_device *link)
        link->priv = local;
 
        /* Interrupt setup */
-       link->irq.Attributes = IRQ_TYPE_EXCLUSIVE;
+       link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING;
        link->irq.IRQInfo1 = IRQ_LEVEL_ID;
        link->irq.Handler = NULL;
 
index 57aecfa..a3053b8 100644 (file)
@@ -246,7 +246,7 @@ static int labpc_cs_attach(struct pcmcia_device *link)
        link->priv = local;
 
        /* Interrupt setup */
-       link->irq.Attributes = IRQ_TYPE_EXCLUSIVE | IRQ_FORCED_PULSE;
+       link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING | IRQ_FORCED_PULSE;
        link->irq.IRQInfo1 = IRQ_INFO2_VALID | IRQ_PULSE_ID;
        link->irq.Handler = NULL;
 
index e3ffb06..753ee05 100644 (file)
@@ -62,6 +62,7 @@
 /* #define DEBUG_STATUS_B */
 
 #include <linux/interrupt.h>
+#include <linux/sched.h>
 #include "8255.h"
 #include "mite.h"
 #include "comedi_fc.h"
index b732296..9aef87f 100644 (file)
@@ -273,7 +273,7 @@ static int cs_attach(struct pcmcia_device *link)
 {
        link->io.Attributes1 = IO_DATA_PATH_WIDTH_16;
        link->io.NumPorts1 = 16;
-       link->irq.Attributes = IRQ_TYPE_EXCLUSIVE;
+       link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING;
        link->irq.IRQInfo1 = IRQ_LEVEL_ID;
        link->conf.Attributes = CONF_ENABLE_IRQ;
        link->conf.IntType = INT_MEMORY_AND_IO;
index 52b2eca..d544698 100644 (file)
@@ -70,6 +70,7 @@ comedi_nonfree_firmware tarball available from http://www.comedi.org
 /* #define DEBUG_FLAGS */
 
 #include <linux/interrupt.h>
+#include <linux/sched.h>
 #include "../comedidev.h"
 
 #include "mite.h"
index 19d8755..24c8b8e 100644 (file)
@@ -29,7 +29,7 @@ Devices: [National Instruments] PCI-MIO-16XE-50 (ni_pcimio),
   PCI-MIO-16XE-10, PXI-6030E, PCI-MIO-16E-1, PCI-MIO-16E-4, PCI-6014, PCI-6040E,
   PXI-6040E, PCI-6030E, PCI-6031E, PCI-6032E, PCI-6033E, PCI-6071E, PCI-6023E,
   PCI-6024E, PCI-6025E, PXI-6025E, PCI-6034E, PCI-6035E, PCI-6052E,
-  PCI-6110, PCI-6111, PCI-6220, PCI-6221, PCI-6224, PXI-6224, PCI-6225,
+  PCI-6110, PCI-6111, PCI-6220, PCI-6221, PCI-6224, PXI-6224, PCI-6225, PXI-6225,
   PCI-6229, PCI-6250, PCI-6251, PCIe-6251, PCI-6254, PCI-6259, PCIe-6259,
   PCI-6280, PCI-6281, PXI-6281, PCI-6284, PCI-6289,
   PCI-6711, PXI-6711, PCI-6713, PXI-6713,
@@ -179,6 +179,7 @@ static DEFINE_PCI_DEVICE_TABLE(ni_pci_table) = {
        PCI_VENDOR_ID_NATINST, 0x70f2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {
        PCI_VENDOR_ID_NATINST, 0x710d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {
        PCI_VENDOR_ID_NATINST, 0x716c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {
+       PCI_VENDOR_ID_NATINST, 0x716d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {
        PCI_VENDOR_ID_NATINST, 0x717f, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {
        PCI_VENDOR_ID_NATINST, 0x71bc, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {
        PCI_VENDOR_ID_NATINST, 0x717d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {
@@ -953,6 +954,25 @@ static const struct ni_board_struct ni_boards[] = {
         .has_8255 = 0,
         },
        {
+        .device_id = 0x716d,
+        .name = "pxi-6225",
+        .n_adchan = 80,
+        .adbits = 16,
+        .ai_fifo_depth = 4095,
+        .gainlkup = ai_gain_622x,
+        .ai_speed = 4000,
+        .n_aochan = 2,
+        .aobits = 16,
+        .ao_fifo_depth = 8191,
+        .ao_range_table = &range_ni_M_622x_ao,
+        .reg_type = ni_reg_622x,
+        .ao_unipolar = 0,
+        .ao_speed = 1200,
+        .num_p0_dio_channels = 32,
+        .caldac = {caldac_none},
+        .has_8255 = 0,
+       },
+       {
         .device_id = 0x70aa,
         .name = "pci-6229",
         .n_adchan = 32,
index f63bdc3..344b823 100644 (file)
@@ -1079,7 +1079,7 @@ static int daqp_cs_attach(struct pcmcia_device *link)
        link->priv = local;
 
        /* Interrupt setup */
-       link->irq.Attributes = IRQ_TYPE_EXCLUSIVE | IRQ_HANDLE_PRESENT;
+       link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING | IRQ_HANDLE_PRESENT;
        link->irq.IRQInfo1 = IRQ_LEVEL_ID;
        link->irq.Handler = daqp_interrupt;
        link->irq.Instance = local;
index b89e1ec..07c21e6 100644 (file)
@@ -43,6 +43,7 @@ comedi_config /dev/comedi0 s526 0x2C0,0x3
 
 #include "../comedidev.h"
 #include <linux/ioport.h>
+#include <asm/byteorder.h>
 
 #define S526_SIZE 64
 
@@ -113,6 +114,7 @@ static const int s526_ports[] = {
 };
 
 struct counter_mode_register_t {
+#if defined (__LITTLE_ENDIAN_BITFIELD)
        unsigned short coutSource:1;
        unsigned short coutPolarity:1;
        unsigned short autoLoadResetRcap:3;
@@ -124,12 +126,27 @@ struct counter_mode_register_t {
        unsigned short outputRegLatchCtrl:1;
        unsigned short preloadRegSel:1;
        unsigned short reserved:1;
+ #elif defined(__BIG_ENDIAN_BITFIELD)
+       unsigned short reserved:1;
+       unsigned short preloadRegSel:1;
+       unsigned short outputRegLatchCtrl:1;
+       unsigned short countDirCtrl:1;
+       unsigned short countDir:1;
+       unsigned short clockSource:2;
+       unsigned short ctEnableCtrl:2;
+       unsigned short hwCtEnableSource:2;
+       unsigned short autoLoadResetRcap:3;
+       unsigned short coutPolarity:1;
+       unsigned short coutSource:1;
+#else
+#error Unknown bit field order
+#endif
 };
 
-union {
+union cmReg {
        struct counter_mode_register_t reg;
        unsigned short value;
-} cmReg;
+};
 
 #define MAX_GPCT_CONFIG_DATA 6
 
@@ -285,6 +302,7 @@ static int s526_attach(struct comedi_device *dev, struct comedi_devconfig *it)
        int i, n;
 /* short value; */
 /* int subdev_channel = 0; */
+       union cmReg cmReg;
 
        printk("comedi%d: s526: ", dev->minor);
 
@@ -375,7 +393,7 @@ static int s526_attach(struct comedi_device *dev, struct comedi_devconfig *it)
        if (thisboard->have_dio) {
                s->type = COMEDI_SUBD_DIO;
                s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
-               s->n_chan = 2;
+               s->n_chan = 8;
                s->maxdata = 1;
                s->range_table = &range_digital;
                s->insn_bits = s526_dio_insn_bits;
@@ -435,11 +453,11 @@ static int s526_attach(struct comedi_device *dev, struct comedi_devconfig *it)
        udelay(1000);
        printk("Read back mode reg=0x%04x\n", inw(ADDR_CHAN_REG(REG_C0M, n)));
 
-       /*  Load the pre-laod register high word */
+       /*  Load the pre-load register high word */
 /* value = (short) (0x55); */
 /* outw(value, ADDR_CHAN_REG(REG_C0H, n)); */
 
-       /*  Load the pre-laod register low word */
+       /*  Load the pre-load register low word */
 /* value = (short)(0xaa55); */
 /* outw(value, ADDR_CHAN_REG(REG_C0L, n)); */
 
@@ -516,6 +534,7 @@ static int s526_gpct_insn_config(struct comedi_device *dev,
        int subdev_channel = CR_CHAN(insn->chanspec);   /*  Unpack chanspec */
        int i;
        short value;
+       union cmReg cmReg;
 
 /* printk("s526: GPCT_INSN_CONFIG: Configuring Channel %d\n", subdev_channel); */
 
@@ -568,19 +587,8 @@ static int s526_gpct_insn_config(struct comedi_device *dev,
 
 #if 1
                /*  Set Counter Mode Register */
-               cmReg.reg.coutSource = 0;       /*  out RCAP */
-               cmReg.reg.coutPolarity = 0;     /*  Polarity inverted */
-               cmReg.reg.autoLoadResetRcap = 0;        /*  Auto load disabled */
-               cmReg.reg.hwCtEnableSource = 2; /*  NOT RCAP */
-               cmReg.reg.ctEnableCtrl = 1;     /*  1: Software,  >1 : Hardware */
-               cmReg.reg.clockSource = 3;      /*  x4 */
-               cmReg.reg.countDir = 0; /*  up */
-               cmReg.reg.countDirCtrl = 0;     /*  quadrature */
-               cmReg.reg.outputRegLatchCtrl = 0;       /*  latch on read */
-               cmReg.reg.preloadRegSel = 0;    /*  PR0 */
-               cmReg.reg.reserved = 0;
+               cmReg.value = insn->data[1] & 0xFFFF;
 
-               /*  Set Counter Mode Register */
 /* printk("s526: Counter Mode register=%x\n", cmReg.value); */
                outw(cmReg.value, ADDR_CHAN_REG(REG_C0M, subdev_channel));
 
@@ -615,11 +623,11 @@ static int s526_gpct_insn_config(struct comedi_device *dev,
                cmReg.value = (short)(insn->data[1] & 0xFFFF);
                outw(cmReg.value, ADDR_CHAN_REG(REG_C0M, subdev_channel));
 
-               /*  Load the pre-laod register high word */
+               /*  Load the pre-load register high word */
                value = (short)((insn->data[2] >> 16) & 0xFFFF);
                outw(value, ADDR_CHAN_REG(REG_C0H, subdev_channel));
 
-               /*  Load the pre-laod register low word */
+               /*  Load the pre-load register low word */
                value = (short)(insn->data[2] & 0xFFFF);
                outw(value, ADDR_CHAN_REG(REG_C0L, subdev_channel));
 
@@ -653,11 +661,11 @@ static int s526_gpct_insn_config(struct comedi_device *dev,
                cmReg.reg.preloadRegSel = 0;    /*  PR0 */
                outw(cmReg.value, ADDR_CHAN_REG(REG_C0M, subdev_channel));
 
-               /*  Load the pre-laod register 0 high word */
+               /*  Load the pre-load register 0 high word */
                value = (short)((insn->data[2] >> 16) & 0xFFFF);
                outw(value, ADDR_CHAN_REG(REG_C0H, subdev_channel));
 
-               /*  Load the pre-laod register 0 low word */
+               /*  Load the pre-load register 0 low word */
                value = (short)(insn->data[2] & 0xFFFF);
                outw(value, ADDR_CHAN_REG(REG_C0L, subdev_channel));
 
@@ -666,17 +674,17 @@ static int s526_gpct_insn_config(struct comedi_device *dev,
                cmReg.reg.preloadRegSel = 1;    /*  PR1 */
                outw(cmReg.value, ADDR_CHAN_REG(REG_C0M, subdev_channel));
 
-               /*  Load the pre-laod register 1 high word */
+               /*  Load the pre-load register 1 high word */
                value = (short)((insn->data[3] >> 16) & 0xFFFF);
                outw(value, ADDR_CHAN_REG(REG_C0H, subdev_channel));
 
-               /*  Load the pre-laod register 1 low word */
+               /*  Load the pre-load register 1 low word */
                value = (short)(insn->data[3] & 0xFFFF);
                outw(value, ADDR_CHAN_REG(REG_C0L, subdev_channel));
 
                /*  Write the Counter Control Register */
-               if (insn->data[3] != 0) {
-                       value = (short)(insn->data[3] & 0xFFFF);
+               if (insn->data[4] != 0) {
+                       value = (short)(insn->data[4] & 0xFFFF);
                        outw(value, ADDR_CHAN_REG(REG_C0C, subdev_channel));
                }
                break;
@@ -698,11 +706,11 @@ static int s526_gpct_insn_config(struct comedi_device *dev,
                cmReg.reg.preloadRegSel = 0;    /*  PR0 */
                outw(cmReg.value, ADDR_CHAN_REG(REG_C0M, subdev_channel));
 
-               /*  Load the pre-laod register 0 high word */
+               /*  Load the pre-load register 0 high word */
                value = (short)((insn->data[2] >> 16) & 0xFFFF);
                outw(value, ADDR_CHAN_REG(REG_C0H, subdev_channel));
 
-               /*  Load the pre-laod register 0 low word */
+               /*  Load the pre-load register 0 low word */
                value = (short)(insn->data[2] & 0xFFFF);
                outw(value, ADDR_CHAN_REG(REG_C0L, subdev_channel));
 
@@ -711,17 +719,17 @@ static int s526_gpct_insn_config(struct comedi_device *dev,
                cmReg.reg.preloadRegSel = 1;    /*  PR1 */
                outw(cmReg.value, ADDR_CHAN_REG(REG_C0M, subdev_channel));
 
-               /*  Load the pre-laod register 1 high word */
+               /*  Load the pre-load register 1 high word */
                value = (short)((insn->data[3] >> 16) & 0xFFFF);
                outw(value, ADDR_CHAN_REG(REG_C0H, subdev_channel));
 
-               /*  Load the pre-laod register 1 low word */
+               /*  Load the pre-load register 1 low word */
                value = (short)(insn->data[3] & 0xFFFF);
                outw(value, ADDR_CHAN_REG(REG_C0L, subdev_channel));
 
                /*  Write the Counter Control Register */
-               if (insn->data[3] != 0) {
-                       value = (short)(insn->data[3] & 0xFFFF);
+               if (insn->data[4] != 0) {
+                       value = (short)(insn->data[4] & 0xFFFF);
                        outw(value, ADDR_CHAN_REG(REG_C0C, subdev_channel));
                }
                break;
@@ -741,6 +749,7 @@ static int s526_gpct_winsn(struct comedi_device *dev,
 {
        int subdev_channel = CR_CHAN(insn->chanspec);   /*  Unpack chanspec */
        short value;
+       union cmReg cmReg;
 
        printk("s526: GPCT_INSN_WRITE on channel %d\n", subdev_channel);
        cmReg.value = inw(ADDR_CHAN_REG(REG_C0M, subdev_channel));
@@ -775,9 +784,8 @@ static int s526_gpct_winsn(struct comedi_device *dev,
                        (devpriv->s526_gpct_config[subdev_channel]).data[1] =
                            insn->data[1];
                } else {
-                       printk("%d \t %d\n", insn->data[1], insn->data[2]);
-                       printk
-                           ("s526: INSN_WRITE: PTG: Problem with Pulse params\n");
+                       printk("s526: INSN_WRITE: PTG: Problem with Pulse params -> %d %d\n",
+                               insn->data[0], insn->data[1]);
                        return -EINVAL;
                }
 
@@ -949,7 +957,7 @@ static int s526_dio_insn_bits(struct comedi_device *dev,
        data[1] = inw(ADDR_REG(REG_DIO)) & 0xFF;        /*  low 8 bits are the data */
        /* or we could just return the software copy of the output values if
         * it was a purely digital output subdevice */
-       /* data[1]=s->state; */
+       /* data[1]=s->state & 0xFF; */
 
        return 2;
 }
@@ -959,28 +967,33 @@ static int s526_dio_insn_config(struct comedi_device *dev,
                                struct comedi_insn *insn, unsigned int *data)
 {
        int chan = CR_CHAN(insn->chanspec);
-       short value;
+       int group, mask;
 
        printk("S526 DIO insn_config\n");
 
-       if (insn->n != 1)
-               return -EINVAL;
-
-       value = inw(ADDR_REG(REG_DIO));
-
        /* The input or output configuration of each digital line is
         * configured by a special insn_config instruction.  chanspec
         * contains the channel to be changed, and data[0] contains the
         * value COMEDI_INPUT or COMEDI_OUTPUT. */
 
-       if (data[0] == COMEDI_OUTPUT) {
-               value |= 1 << (chan + 10);      /*  bit 10/11 set the group 1/2's mode */
-               s->io_bits |= (0xF << chan);
-       } else {
-               value &= ~(1 << (chan + 10));   /*  1 is output, 0 is input. */
-               s->io_bits &= ~(0xF << chan);
+       group = chan >> 2;
+       mask = 0xF << (group << 2);
+       switch (data[0]) {
+       case INSN_CONFIG_DIO_OUTPUT:
+               s->state |= 1 << (group + 10);  // bit 10/11 set the group 1/2's mode
+               s->io_bits |= mask;
+               break;
+       case INSN_CONFIG_DIO_INPUT:
+               s->state &= ~(1 << (group + 10));// 1 is output, 0 is input.
+               s->io_bits &= ~mask;
+               break;
+       case INSN_CONFIG_DIO_QUERY:
+               data[1] = (s->io_bits & mask) ? COMEDI_OUTPUT : COMEDI_INPUT;
+               return insn->n;
+       default:
+               return -EINVAL;
        }
-       outw(value, ADDR_REG(REG_DIO));
+       outw(s->state, ADDR_REG(REG_DIO));
 
        return 1;
 }
index a219679..82aa86e 100644 (file)
@@ -35,6 +35,7 @@ Status: in development
 
 #include <linux/delay.h>
 #include <linux/ioport.h>
+#include <linux/sched.h>
 
 #include <asm/termios.h>
 #include <asm/ioctls.h>
diff --git a/drivers/staging/cowloop/Kconfig b/drivers/staging/cowloop/Kconfig
deleted file mode 100644 (file)
index 58d2a23..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-config COWLOOP
-       tristate "copy-on-write pseudo Block Driver"
-       depends on BLOCK
-       default n
-       ---help---
-         Cowloop is a "copy-on-write" pseudo block driver. It can be
-         stacked on top of a "real" block driver, and catches all write
-         operations on their way from the file systems layer above to
-         the real driver below, effectively shielding the lower driver
-         from those write accesses. The requests are then diverted to
-         an ordinary file, located somewhere else (configurable). Later
-         read requests are checked to see whether they can be serviced
-         by the "real" block driver below, or must be pulled in from
-         the diverted location. More information and userspace tools to
-         use the driver are on the project's website
-         http://www.ATComputing.nl/cowloop/
diff --git a/drivers/staging/cowloop/Makefile b/drivers/staging/cowloop/Makefile
deleted file mode 100644 (file)
index 2b6b81a..0000000
+++ /dev/null
@@ -1 +0,0 @@
-obj-$(CONFIG_COWLOOP)  += cowloop.o
diff --git a/drivers/staging/cowloop/TODO b/drivers/staging/cowloop/TODO
deleted file mode 100644 (file)
index 9399d1c..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-TODO:
-       - checkpatch.pl cleanups
-       - run sparse to ensure clean
-       - fix up 32/64bit ioctl issues
-       - move proc file usage to debugfs
-       - audit ioctls
-       - add documentation
-       - get linux-fsdevel to review it
-
-Please send patches to "H.J. Thomassen" <hjt@ATComputing.nl> and
-Greg Kroah-Hartman <gregkh@suse.de>
diff --git a/drivers/staging/cowloop/cowloop.c b/drivers/staging/cowloop/cowloop.c
deleted file mode 100644 (file)
index a71c743..0000000
+++ /dev/null
@@ -1,2842 +0,0 @@
-/*
-**       COWLOOP block device driver (2.6 kernel compliant)
-** =======================================================================
-** Read-write loop-driver with copy-on-write functionality.
-**
-** Synopsis:
-**
-**     modprobe cowloop [maxcows=..] [rdofile=..... cowfile=.... [option=r]]
-**
-** Definition of number of configured cowdevices:
-**   maxcows=  number of configured cowdevices (default: 16)
-** (do not confuse this with MAXCOWS: absolute maximum as compiled)
-**
-** One pair of filenames can be supplied during insmod/modprobe to open
-** the first cowdevice:
-**   rdofile=  read-only file (or filesystem)
-**   cowfile=  storage-space for modified blocks of read-only file(system)
-**   option=r  repair cowfile automatically if it appears to be dirty
-**
-** Other cowdevices can be activated via the command "cowdev"
-** whenever the cowloop-driver is loaded.
-**
-** The read-only file may be of type 'regular' or 'block-device'.
-**
-** The cowfile must be of type 'regular'.
-** If an existing regular file is used as cowfile, its contents will be
-** used again for the current read-only file. When the cowfile has not been
-** closed properly during a previous session (i.e. rmmod cowloop), the
-** cowloop-driver refuses to open it unless the parameter "option=r" is
-** specified.
-**
-** Layout of cowfile:
-**
-**     +-----------------------------+
-**     |       cow head block        |   MAPUNIT bytes
-**     |-----------------------------|
-**     |                             |   MAPUNIT bytes
-**     |---                       ---|
-**     |                             |   MAPUNIT bytes
-**     |---                       ---|
-**     |      used-block bitmap      |   MAPUNIT bytes
-**     |-----------------------------|
-**     |  gap to align start-offset  |
-**     |        to 4K multiple       |
-**     |-----------------------------|  <---- start-offset cow blocks
-**     |                             |
-**      |    written cow blocks       |   MAPUNIT bytes
-**      |          .....              |
-**
-**     cowhead block:
-**       - contains general info about the rdofile which is related
-**         to this cowfile
-**
-**     used-block bitmap:
-**       - contains one bit per block with a size of MAPUNIT bytes
-**       - bit-value '1' = block has been written on cow
-**                   '0' = block unused on cow
-**       - total bitmap rounded to multiples of MAPUNIT
-**
-** ============================================================================
-** Author:             Gerlof Langeveld - AT Computing (March 2003)
-** Current maintainer: Hendrik-Jan Thomassen - AT Computing (Summer 2006)
-** Email:              hjt@ATComputing.nl
-** ----------------------------------------------------------------------------
-** Copyright (C) 2003-2009 AT Consultancy
-**
-** This program is free software; you can redistribute it and/or modify it
-** under the terms of the GNU General Public License as published by the
-** Free Software Foundation; either version 2, or (at your option) any
-** later version.
-**
-** This program is distributed in the hope that it will be useful, but
-** WITHOUT ANY WARRANTY; without even the implied warranty of
-** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-** See the GNU General Public License for more details.
-**
-** You should have received a copy of the GNU General Public License
-** along with this program; if not, write to the Free Software
-** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-** ----------------------------------------------------------------------------
-**
-** Major modifications:
-**
-**     200405  Ported to kernel-version 2.6            Hendrik-Jan Thomassen
-**     200405  Added cowhead to cowfile to garantee
-**             consistency with read-only file         Gerlof Langeveld
-**     200405  Postponed flushing of bitmaps to improve
-**             performance.                            Gerlof Langeveld
-**     200405  Inline recovery for dirty cowfiles.     Gerlof Langeveld
-**     200502  Redesign to support more cowdevices.    Gerlof Langeveld
-**     200502  Support devices/file > 2 Gbytes.        Gerlof Langeveld
-**     200507  Check for free space to expand cowfile. Gerlof Langeveld
-**     200902  Upgrade for kernel 2.6.28               Hendrik-Jan Thomassen
-**
-** Inspired by
-**    loop.c  by Theodore Ts'o and
-**    cloop.c by Paul `Rusty' Russell & Klaus Knopper.
-**
-** Design-considerations:
-**
-**   For the first experiments with the cowloop-driver, the request-queue
-**   made use of the do_generic_file_read() which worked fine except
-**   in combination with the cloop-driver; that combination
-**   resulted in a non-interruptible hangup of the system during
-**   heavy load. Other experiments using the `make_request' interface also
-**   resulted in unpredictable system hangups (with proper use of spinlocks).
-**
-**   To overcome these problems, the cowloop-driver starts a kernel-thread
-**   for every active cowdevice.
-**   All read- and write-request on the read-only file and copy-on-write file
-**   are handled in the context of that thread.
-**   A scheme has been designed to wakeup the kernel-thread as
-**   soon as I/O-requests are available in the request-queue; this thread
-**   handles the requests one-by-one by calling the proper read- or
-**   write-function related to the open read-only file or copy-on-write file.
-**   When all pending requests have been handled, the kernel-thread goes
-**   back to sleep-state.
-**   This approach requires some additional context-switches; however the
-**   performance loss during heavy I/O is less than 3%.
-**
-** -------------------------------------------------------------------------*/
-/* The following is the cowloop package version number. It must be
-   identical to the content of the include-file "version.h" that is
-   used in all supporting utilities:                                  */
-char revision[] = "$Revision: 3.1 $"; /* cowlo_init_module() has
-                            assumptions about this string's format   */
-
-/* Note that the following numbers are *not* the cowloop package version
-   numbers, but separate revision history numbers to track the
-   modifications of this particular source file:                      */
-/* $Log: cowloop.c,v $
-**
-** Revision 1.30  2009/02/08 hjt
-** Integrated earlier fixes
-** Upgraded to kernel 2.6.28 (thanks Jerome Poulin)
-**
-** Revision 1.29  2006/12/03 22:12:00  hjt
-** changed 'cowdevlock' from spinlock to semaphore, to avoid
-** "scheduling while atomic". Contributed by Juergen Christ.
-** Added version.h again
-**
-** Revision 1.28  2006/08/16 16:00:00  hjt
-** malloc each individual cowloopdevice struct separately
-**
-** Revision 1.27  2006/03/14 14:57:03  root
-** Removed include version.h
-**
-** Revision 1.26  2005/08/08 11:22:48  root
-** Implement possibility to close a cow file or reopen a cowfile read-only.
-**
-** Revision 1.25  2005/08/03 14:00:39  root
-** Added modinfo info to driver.
-**
-** Revision 1.24  2005/07/21 06:14:53  root
-** Cosmetic changes source code.
-**
-** Revision 1.23  2005/07/20 13:07:32  root
-** Supply ioctl to write watchdog program to react on lack of cowfile space.
-**
-** Revision 1.22  2005/07/20 07:53:34  root
-** Regular verification of free space in filesystem holding the cowfile
-** (give warnings whenever space is almost exhausted).
-** Terminology change: checksum renamed to fingerprint.
-**
-** Revision 1.21  2005/07/19 09:21:52  root
-** Removing maximum limit of 16 Gb per cowdevice.
-**
-** Revision 1.20  2005/07/19 07:50:33  root
-** Minor bugfixes and cosmetic changes.
-**
-** Revision 1.19  2005/06/10 12:29:55  root
-** Removed lock/unlock operation from cowlo_open().
-**
-** Revision 1.18  2005/05/09 12:56:26  root
-** Allow a cowdevice to be open more than once
-** (needed for support of ReiserFS and XFS).
-**
-** Revision 1.17  2005/03/17 14:36:16  root
-** Fixed some license issues.
-**
-** Revision 1.16  2005/03/07 14:42:05  root
-** Only allow one parallel open per cowdevice.
-**
-** Revision 1.15  2005/02/18 11:52:04  gerlof
-** Redesign to support more than one cowdevice > 2 Gb space.
-**
-** Revision 1.14  2004/08/17 14:19:16  gerlof
-** Modified output of /proc/cowloop.
-**
-** Revision 1.13  2004/08/16 07:21:10  gerlof
-** Separate statistical counter for read on rdofile and cowfile.
-**
-** Revision 1.12  2004/08/11 06:52:11  gerlof
-** Modified messages.
-**
-** Revision 1.11  2004/08/11 06:44:11  gerlof
-** Modified log messages.
-**
-** Revision 1.10  2004/08/10 12:27:27  gerlof
-** Cosmetic changes.
-**
-** Revision 1.9  2004/08/09 11:43:37  gerlof
-** Removed double definition of major number (COWMAJOR).
-**
-** Revision 1.8  2004/08/09 08:03:39  gerlof
-** Cleanup of messages.
-**
-** Revision 1.7  2004/05/27 06:37:33  gerlof
-** Modified /proc message.
-**
-** Revision 1.6  2004/05/26 21:23:28  gerlof
-** Modified /proc output.
-**
-** Revision 1.5  2004/05/26 13:23:34  gerlof
-** Support cowsync to force flushing the bitmaps and cowhead.
-**
-** Revision 1.4  2004/05/26 11:11:10  gerlof
-** Updated the comment to the actual situation.
-**
-** Revision 1.3  2004/05/26 10:50:00  gerlof
-** Implemented recovery-option.
-**
-** Revision 1.2  2004/05/25 15:14:41  gerlof
-** Modified bitmap flushing strategy.
-**
-*/
-
-#define COWMAJOR       241
-
-// #define COWDEBUG
-
-#ifdef         COWDEBUG
-#define DEBUGP         printk
-#define DCOW           KERN_ALERT
-#else
-#define DEBUGP(format, x...)
-#endif
-
-#include <linux/types.h>
-#include <linux/autoconf.h>
-#ifndef AUTOCONF_INCLUDED
-#include <linux/config.h>
-#endif
-#include <linux/module.h>
-#include <linux/version.h>
-#include <linux/moduleparam.h>
-#include <linux/init.h>
-#include <linux/errno.h>
-#include <linux/kernel.h>
-#include <linux/major.h>
-#include <linux/sched.h>
-#include <linux/fs.h>
-#include <linux/file.h>
-#include <linux/stat.h>
-#include <linux/vmalloc.h>
-#include <linux/slab.h>
-#include <linux/semaphore.h>
-#include <asm/uaccess.h>
-#include <linux/proc_fs.h>
-#include <linux/blkdev.h>
-#include <linux/buffer_head.h>
-#include <linux/hdreg.h>
-#include <linux/genhd.h>
-#include <linux/statfs.h>
-
-#include "cowloop.h"
-
-MODULE_LICENSE("GPL");
-/* MODULE_AUTHOR("Gerlof Langeveld <gerlof@ATComputing.nl>");     obsolete address */
-MODULE_AUTHOR("Hendrik-Jan Thomassen <hjt@ATComputing.nl>"); /* current maintainer */
-MODULE_DESCRIPTION("Copy-on-write loop driver");
-MODULE_PARM_DESC(maxcows, " Number of configured cowdevices (default 16)");
-MODULE_PARM_DESC(rdofile, " Read-only file for /dev/cow/0");
-MODULE_PARM_DESC(cowfile, " Cowfile for /dev/cow/0");
-MODULE_PARM_DESC(option, "  Repair cowfile if inconsistent: option=r");
-
-#define DEVICE_NAME    "cow"
-
-#define        DFLCOWS         16              /* default cowloop devices      */
-
-static int maxcows = DFLCOWS;
-module_param(maxcows, int, 0);
-static char *rdofile = "";
-module_param(rdofile, charp, 0);
-static char *cowfile = "";
-module_param(cowfile, charp, 0);
-static char *option = "";
-module_param(option, charp, 0);
-
-/*
-** per cowdevice several bitmap chunks are allowed of MAPCHUNKSZ each
-**
-** each bitmap chunk can describe MAPCHUNKSZ * 8 * MAPUNIT bytes of data
-** suppose:
-**     MAPCHUNKSZ 4096 and MAPUNIT 1024 --> 4096 * 8 * 1024 = 32 Mb per chunk
-*/
-#define        MAPCHUNKSZ      4096    /* #bytes per bitmap chunk  (do not change)  */
-
-#define SPCMINBLK      100     /* space threshold to give warning messages  */
-#define SPCDFLINTVL    16      /* once every SPCDFLINTVL writes to cowfile, */
-                               /* available space in filesystem is checked  */
-
-#define        CALCMAP(x)      ((x)/(MAPCHUNKSZ*8))
-#define        CALCBYTE(x)     (((x)%(MAPCHUNKSZ*8))>>3)
-#define        CALCBIT(x)      ((x)&7)
-
-#define ALLCOW         1
-#define ALLRDO         2
-#define MIXEDUP                3
-
-static char    allzeroes[MAPUNIT];
-
-/*
-** administration per cowdevice (pair of cowfile/rdofile)
-*/
-
-/* bit-values for state */
-#define        COWDEVOPEN      0x01    /* cowdevice opened                          */
-#define        COWRWCOWOPEN    0x02    /* cowfile opened read-write                 */
-#define        COWRDCOWOPEN    0x04    /* cowfile opened read-only                  */
-#define        COWWATCHDOG     0x08    /* ioctl for watchdog cowfile space active   */
-
-#define        COWCOWOPEN      (COWRWCOWOPEN|COWRDCOWOPEN)
-
-struct cowloop_device
-{
-       /*
-       ** current status
-       */
-       int             state;                  /* bit-values (see above)    */
-       int             opencnt;                /* # opens for cowdevice     */
-
-        /*
-       ** open file pointers
-       */
-        struct file    *rdofp,   *cowfp;       /* open file pointers        */
-       char            *rdoname, *cowname;     /* file names                */
-
-       /*
-       ** request queue administration
-       */
-       struct request_queue    *rqueue;
-       spinlock_t              rqlock;
-       struct gendisk          *gd;
-
-       /*
-       ** administration about read-only file
-       */
-       unsigned int         numblocks; /* # blocks input file in MAPUNIT    */
-       unsigned int         blocksz;   /* minimum unit to access this dev   */
-       unsigned long        fingerprint; /* fingerprint of current rdofile  */
-       struct block_device  *belowdev; /* block device below us             */
-       struct gendisk       *belowgd;  /* gendisk for blk dev below us      */
-       struct request_queue *belowq;   /* req. queue of blk dev below us    */
-
-       /*
-       ** bitmap administration to register which blocks are modified
-       */
-       long int        mapsize;        /* total size of bitmap (bytes)      */
-       long int        mapremain;      /* remaining bytes in last bitmap    */
-       int             mapcount;       /* number of bitmaps in use          */
-       char            **mapcache;     /* area with pointers to bitmaps     */
-
-       char            *iobuf;         /* databuffer of MAPUNIT bytes       */
-       struct cowhead  *cowhead;       /* buffer containing cowhead         */
-
-       /*
-       ** administration for interface with the kernel-thread
-       */
-       int             pid;            /* pid==0: no thread available       */
-       struct request  *req;           /* request to be handled now         */
-       wait_queue_head_t waitq;        /* wait-Q: thread waits for work     */
-       char            closedown;      /* boolean: thread exit required     */
-       char            qfilled;        /* boolean: I/O request pending      */
-       char            iobusy;         /* boolean: req under treatment      */
-
-       /*
-       ** administration to keep track of free space in cowfile filesystem
-       */
-       unsigned long   blksize;        /* block size of fs (bytes)          */
-       unsigned long   blktotal;       /* recent total space in fs (blocks) */
-       unsigned long   blkavail;       /* recent free  space in fs (blocks) */
-
-       wait_queue_head_t watchq;       /* wait-Q: watcher awaits threshold  */
-       unsigned long   watchthresh;    /* threshold of watcher (blocks)     */
-
-       /*
-       ** statistical counters
-       */
-       unsigned long   rdoreads;       /* number of  read-actions rdo       */
-       unsigned long   cowreads;       /* number of  read-actions cow       */
-       unsigned long   cowwrites;      /* number of write-actions           */
-       unsigned long   nrcowblocks;    /* number of blocks in use on cow    */
-};
-
-static struct cowloop_device   **cowdevall;    /* ptr to ptrs to all cowdevices */
-static struct semaphore        cowdevlock;     /* generic lock for cowdevs      */
-
-static struct gendisk          *cowctlgd;      /* gendisk control channel       */
-static spinlock_t              cowctlrqlock;   /* for req.q. of ctrl. channel   */
-
-/*
-** private directory /proc/cow
-*/
-struct proc_dir_entry  *cowlo_procdir;
-
-/*
-** function prototypes
-*/
-static long int cowlo_do_request (struct request *req);
-static void    cowlo_sync       (void);
-static int     cowlo_checkio    (struct cowloop_device *,         int, loff_t);
-static int     cowlo_readmix    (struct cowloop_device *, void *, int, loff_t);
-static int     cowlo_writemix   (struct cowloop_device *, void *, int, loff_t);
-static long int cowlo_readrdo    (struct cowloop_device *, void *, int, loff_t);
-static long int cowlo_readcow    (struct cowloop_device *, void *, int, loff_t);
-static long int cowlo_readcowraw (struct cowloop_device *, void *, int, loff_t);
-static long int cowlo_writecow   (struct cowloop_device *, void *, int, loff_t);
-static long int cowlo_writecowraw(struct cowloop_device *, void *, int, loff_t);
-static int      cowlo_ioctl      (struct block_device *, fmode_t,
-                                               unsigned int, unsigned long);
-static int     cowlo_makepair    (struct cowpair __user *);
-static int     cowlo_removepair  (unsigned long  __user *);
-static int     cowlo_watch       (struct cowpair __user *);
-static int     cowlo_cowctl      (unsigned long  __user *, int);
-static int     cowlo_openpair    (char *, char *, int, int);
-static int     cowlo_closepair   (struct cowloop_device *);
-static int     cowlo_openrdo     (struct cowloop_device *, char *);
-static int     cowlo_opencow     (struct cowloop_device *, char *, int);
-static void    cowlo_undo_openrdo(struct cowloop_device *);
-static void    cowlo_undo_opencow(struct cowloop_device *);
-
-/*****************************************************************************/
-/* System call handling                                                      */
-/*****************************************************************************/
-
-/*
-** handle system call open()/mount()
-**
-** returns:
-**     0   - okay
-**    < 0   - error value
-*/
-static int cowlo_open(struct block_device *bdev, fmode_t mode)
-{
-       struct inode *inode = bdev->bd_inode;
-
-       if (!inode)
-               return -EINVAL;
-
-       if (imajor(inode) != COWMAJOR) {
-               printk(KERN_WARNING
-                      "cowloop - unexpected major %d\n", imajor(inode));
-               return -ENODEV;
-       }
-
-       switch (iminor(inode)) {
-          case COWCTL:
-               DEBUGP(DCOW"cowloop - open %d control\n", COWCTL);
-               break;
-
-          default:
-               DEBUGP(DCOW"cowloop - open minor %d\n", iminor(inode));
-
-               if ( iminor(inode) >= maxcows )
-                       return -ENODEV;
-
-               if ( !((cowdevall[iminor(inode)])->state & COWDEVOPEN) )
-                       return -ENODEV;
-
-               (cowdevall[iminor(inode)])->opencnt++;
-       }
-
-       return 0;
-}
-
-/*
-** handle system call close()/umount()
-**
-** returns:
-**     0   - okay
-*/
-static int cowlo_release(struct gendisk *gd, fmode_t mode)
-{
-       struct block_device *bdev;
-       struct inode *inode;
-
-       bdev = bdget_disk(gd, 0);
-       inode = bdev->bd_inode;
-       if (!inode)
-               return 0;
-
-       DEBUGP(DCOW"cowloop - release (close) minor %d\n", iminor(inode));
-
-       if ( iminor(inode) != COWCTL)
-               (cowdevall[iminor(inode)])->opencnt--;
-
-       return 0;
-}
-
-/*
-** handle system call ioctl()
-**
-** returns:
-**     0   - okay
-**    < 0   - error value
-*/
-static int cowlo_ioctl(struct block_device *bdev, fmode_t mode,
-                      unsigned int cmd, unsigned long arg)
-{
-       struct hd_geometry      geo;
-       struct inode *inode = bdev->bd_inode;
-
-       DEBUGP(DCOW "cowloop - ioctl cmd %x\n", cmd);
-
-       switch ( iminor(inode) ) {
-
-          /*
-          ** allowed via control device only
-          */
-          case COWCTL:
-               switch (cmd) {
-                  /*
-                  ** write all bitmap chunks and cowheaders to cowfiles
-                  */
-                  case COWSYNC:
-                       down(&cowdevlock);
-                       cowlo_sync();
-                       up(&cowdevlock);
-                       return 0;
-
-                  /*
-                  ** open a new cowdevice (pair of rdofile/cowfile)
-                  */
-                  case COWMKPAIR:
-                       return cowlo_makepair((void __user *)arg);
-
-                  /*
-                  ** close a cowdevice (pair of rdofile/cowfile)
-                  */
-                  case COWRMPAIR:
-                       return cowlo_removepair((void __user *)arg);
-
-                  /*
-                  ** watch free space of filesystem containing cowfile
-                  */
-                  case COWWATCH:
-                       return cowlo_watch((void __user *)arg);
-
-                  /*
-                  ** close cowfile for active device
-                  */
-                  case COWCLOSE:
-                       return cowlo_cowctl((void __user *)arg, COWCLOSE);
-
-                  /*
-                  ** reopen cowfile read-only for active device
-                  */
-                  case COWRDOPEN:
-                       return cowlo_cowctl((void __user *)arg, COWRDOPEN);
-
-                  default:
-                       return -EINVAL;
-               } /* end of switch on command */
-
-          /*
-          ** allowed for any other cowdevice
-          */
-          default:
-               switch (cmd) {
-                  /*
-                  ** HDIO_GETGEO must be supported for fdisk, etc
-                  */
-                  case HDIO_GETGEO:
-                       geo.cylinders = 0;
-                       geo.heads     = 0;
-                       geo.sectors   = 0;
-
-                       if (copy_to_user((void __user *)arg, &geo, sizeof geo))
-                               return -EFAULT;
-                       return 0;
-
-                  default:
-                       return -EINVAL;
-               } /* end of switch on ioctl-cmd code parameter */
-       } /* end of switch on minor number */
-}
-
-static struct block_device_operations cowlo_fops =
-{
-       .owner   =     THIS_MODULE,
-        .open    =     cowlo_open,     /* called upon open  */
-        .release =     cowlo_release,  /* called upon close */
-        .ioctl   =     cowlo_ioctl,     /* called upon ioctl */
-};
-
-/*
-** handle ioctl-command COWMKPAIR:
-**     open a new cowdevice (pair of rdofile/cowfile) on-the-fly
-**
-** returns:
-**     0   - okay
-**    < 0   - error value
-*/
-static int
-cowlo_makepair(struct cowpair __user *arg)
-{
-       int             i, rv=0;
-       struct cowpair  cowpair;
-       unsigned char   *cowpath;
-       unsigned char   *rdopath;
-
-       /*
-       ** retrieve info about pathnames
-       */
-       if ( copy_from_user(&cowpair, arg, sizeof cowpair) )
-               return -EFAULT;
-
-       if ( (MAJOR(cowpair.device) != COWMAJOR) && (cowpair.device != ANYDEV) )
-               return -EINVAL;
-
-       if ( (MINOR(cowpair.device) >= maxcows)  && (cowpair.device != ANYDEV) )
-               return -EINVAL;
-
-       /*
-       ** retrieve pathname strings
-       */
-       if ( (cowpair.cowflen > PATH_MAX) || (cowpair.rdoflen > PATH_MAX) )
-               return -ENAMETOOLONG;
-
-       if ( !(cowpath = kmalloc(cowpair.cowflen+1, GFP_KERNEL)) )
-               return -ENOMEM;
-
-       if ( copy_from_user(cowpath, (void __user *)cowpair.cowfile,
-                                                   cowpair.cowflen) ) {
-               kfree(cowpath);
-               return -EFAULT;
-       }
-       *(cowpath+cowpair.cowflen) = 0;
-
-       if ( !(rdopath = kmalloc(cowpair.rdoflen+1, GFP_KERNEL)) ) {
-               kfree(cowpath);
-               return -ENOMEM;
-       }
-
-       if ( copy_from_user(rdopath, (void __user *)cowpair.rdofile,
-                                                   cowpair.rdoflen) ) {
-               kfree(rdopath);
-               kfree(cowpath);
-               return -EFAULT;
-       }
-       *(rdopath+cowpair.rdoflen) = 0;
-
-       /*
-       ** open new cowdevice
-       */
-       if ( cowpair.device == ANYDEV) {
-               /*
-               ** search first unused minor
-               */
-               for (i=0, rv=-EBUSY; i < maxcows; i++) {
-                       if ( !((cowdevall[i])->state & COWDEVOPEN) ) {
-                               rv = cowlo_openpair(rdopath, cowpath, 0, i);
-                               break;
-                       }
-               }
-
-               if (rv) {               /* open failed? */
-                       kfree(rdopath);
-                       kfree(cowpath);
-                       return rv;
-               }
-
-               /*
-               ** return newly allocated cowdevice to user space
-               */
-               cowpair.device = MKDEV(COWMAJOR, i);
-
-               if ( copy_to_user(arg, &cowpair, sizeof cowpair)) {
-                       kfree(rdopath);
-                       kfree(cowpath);
-                       return -EFAULT;
-               }
-       } else {                /* specific minor requested */
-               if ( (rv = cowlo_openpair(rdopath, cowpath, 0,
-                                               MINOR(cowpair.device)))) {
-                       kfree(rdopath);
-                       kfree(cowpath);
-                       return rv;
-               }
-       }
-
-       return 0;
-}
-
-/*
-** handle ioctl-command COWRMPAIR:
-**     deactivate an existing cowdevice (pair of rdofile/cowfile) on-the-fly
-**
-** returns:
-**     0   - okay
-**    < 0   - error value
-*/
-static int
-cowlo_removepair(unsigned long __user *arg)
-{
-       unsigned long           cowdevice;
-       struct cowloop_device   *cowdev;
-
-       /*
-       ** retrieve info about device to be removed
-       */
-       if ( copy_from_user(&cowdevice, arg, sizeof cowdevice))
-               return -EFAULT;
-
-       /*
-       ** verify major-minor number
-       */
-       if ( MAJOR(cowdevice) != COWMAJOR)
-               return -EINVAL;
-
-       if ( MINOR(cowdevice) >= maxcows)
-               return -EINVAL;
-
-       cowdev = cowdevall[MINOR(cowdevice)];
-
-       if ( !(cowdev->state & COWDEVOPEN) )
-               return -ENODEV;
-
-       /*
-       ** synchronize bitmaps and close cowdevice
-       */
-       if (cowdev->state & COWRWCOWOPEN) {
-               down(&cowdevlock);
-               cowlo_sync();
-               up(&cowdevlock);
-       }
-
-       return cowlo_closepair(cowdev);
-}
-
-/*
-** handle ioctl-command COWWATCH:
-**     watch the free space of the filesystem containing a cowfile
-**      of an open cowdevice
-**
-** returns:
-**     0   - okay
-**    < 0   - error value
-*/
-static int
-cowlo_watch(struct cowpair __user *arg)
-{
-       struct cowloop_device   *cowdev;
-       struct cowwatch         cowwatch;
-
-       /*
-       ** retrieve structure holding info
-       */
-       if ( copy_from_user(&cowwatch, arg, sizeof cowwatch))
-               return -EFAULT;
-
-       /*
-       ** verify if cowdevice exists and is currently open
-       */
-       if ( MINOR(cowwatch.device) >= maxcows)
-               return -EINVAL;
-
-       cowdev = cowdevall[MINOR(cowwatch.device)];
-
-       if ( !(cowdev->state & COWDEVOPEN) )
-               return -ENODEV;
-
-       /*
-       ** if the WATCHWAIT-option is set, wait until the indicated
-       ** threshold is reached (only one waiter allowed)
-       */
-       if (cowwatch.flags & WATCHWAIT) {
-               /*
-               ** check if already another waiter active
-               ** for this cowdevice
-               */
-               if (cowdev->state & COWWATCHDOG)
-                       return -EAGAIN;
-
-               cowdev->state |= COWWATCHDOG;
-
-               cowdev->watchthresh = (unsigned long long)
-                                     cowwatch.threshold /
-                                     (cowdev->blksize / 1024);
-
-               if (wait_event_interruptible(cowdev->watchq,
-                                   cowdev->watchthresh >= cowdev->blkavail)) {
-                       cowdev->state &= ~COWWATCHDOG;
-                       return EINTR;
-               }
-
-               cowdev->state &= ~COWWATCHDOG;
-       }
-
-       cowwatch.totalkb = (unsigned long long)cowdev->blktotal *
-                                              cowdev->blksize / 1024;
-       cowwatch.availkb = (unsigned long long)cowdev->blkavail *
-                                              cowdev->blksize / 1024;
-
-       if ( copy_to_user(arg, &cowwatch, sizeof cowwatch))
-               return -EFAULT;
-
-       return 0;
-}
-
-/*
-** handle ioctl-commands COWCLOSE and COWRDOPEN:
-**     COWCLOSE  - close the cowfile while the cowdevice remains open;
-**                  this allows an unmount of the filesystem on which
-**                  the cowfile resides
-**     COWRDOPEN - close the cowfile and reopen it for read-only;
-**                  this allows a remount read-ony of the filesystem
-**                  on which the cowfile resides
-**
-** returns:
-**     0   - okay
-**    < 0   - error value
-*/
-static int
-cowlo_cowctl(unsigned long __user *arg, int cmd)
-{
-       struct cowloop_device   *cowdev;
-       unsigned long           cowdevice;
-
-       /*
-       ** retrieve info about device to be removed
-       */
-       if ( copy_from_user(&cowdevice, arg, sizeof cowdevice))
-               return -EFAULT;
-
-       /*
-       ** verify major-minor number
-       */
-       if ( MAJOR(cowdevice) != COWMAJOR)
-               return -EINVAL;
-
-       if ( MINOR(cowdevice) >= maxcows)
-               return -EINVAL;
-
-       cowdev = cowdevall[MINOR(cowdevice)];
-
-       if ( !(cowdev->state & COWDEVOPEN) )
-               return -ENODEV;
-
-       /*
-       ** synchronize bitmaps and close cowfile
-       */
-       if (cowdev->state & COWRWCOWOPEN) {
-               down(&cowdevlock);
-               cowlo_sync();
-               up(&cowdevlock);
-       }
-
-       /*
-       ** handle specific ioctl-command
-       */
-       switch (cmd) {
-          case COWRDOPEN:
-               /*
-               ** if the cowfile is still opened read-write
-               */
-               if (cowdev->state & COWRWCOWOPEN) {
-                       /*
-                       ** close the cowfile
-                       */
-                       if (cowdev->cowfp)
-                               filp_close(cowdev->cowfp, 0);
-
-                       cowdev->state &= ~COWRWCOWOPEN;
-
-                       /*
-                       ** open again for read-only
-                       */
-                       cowdev->cowfp = filp_open(cowdev->cowname,
-                                         O_RDONLY|O_LARGEFILE, 0600);
-
-                       if ( (cowdev->cowfp == NULL) || IS_ERR(cowdev->cowfp) ) {
-                               printk(KERN_ERR
-                                    "cowloop - failed to reopen cowfile %s\n",
-                                    cowdev->cowname);
-                               return -EINVAL;
-                       }
-
-                       /*
-                       ** mark cowfile open for read-only
-                       */
-                       cowdev->state |= COWRDCOWOPEN;
-               } else {
-                       return -EINVAL;
-               }
-               break;
-
-          case COWCLOSE:
-               /*
-               ** if the cowfile is still open
-               */
-               if (cowdev->state & COWCOWOPEN) {
-                       /*
-                       ** close the cowfile
-                       */
-                       if (cowdev->cowfp)
-                               filp_close(cowdev->cowfp, 0);
-
-                       cowdev->state &= ~COWCOWOPEN;
-               }
-       }
-
-       return 0;
-}
-
-
-/*****************************************************************************/
-/* Handling of I/O-requests for a cowdevice                                  */
-/*****************************************************************************/
-
-/*
-** function to be called by core-kernel to handle the I/O-requests
-** in the queue
-*/
-static void cowlo_request(struct request_queue *q)
-{
-       struct request          *req;
-       struct cowloop_device   *cowdev;
-
-       DEBUGP(DCOW "cowloop - request function called....\n");
-
-       while((req = blk_peek_request(q)) != NULL) {
-               DEBUGP(DCOW "cowloop - got next request\n");
-
-               if (! blk_fs_request(req)) {
-                                /* this is not a normal file system request */
-                       __blk_end_request_cur(req, -EIO);
-                       continue;
-               }
-               cowdev = req->rq_disk->private_data;
-
-               if (cowdev->iobusy)
-                       return;
-               else
-                       cowdev->iobusy = 1;
-
-               /*
-               ** when no kernel-thread is available, the request will
-               ** produce an I/O-error
-               */
-               if (!cowdev->pid) {
-                       printk(KERN_ERR"cowloop - no thread available\n");
-                       __blk_end_request_cur(req, -EIO);       /* request failed */
-                       cowdev->iobusy  = 0;
-                       continue;
-               }
-
-               /*
-               ** handle I/O-request in the context of the kernel-thread
-               */
-               cowdev->req     = req;
-               cowdev->qfilled = 1;
-
-               wake_up_interruptible_sync(&cowdev->waitq);
-
-               /*
-               ** get out of this function now while the I/O-request is
-               ** under treatment of the kernel-thread; this function
-               ** will be called again after the current I/O-request has
-               ** been finished by the thread
-               */
-               return;
-       }
-}
-
-/*
-** daemon-process (kernel-thread) executes this function
-*/
-static int
-cowlo_daemon(struct cowloop_device *cowdev)
-{
-       int     rv;
-       int     minor;
-       char    myname[16];
-
-       for (minor = 0; minor < maxcows; minor++) {
-               if (cowdev == cowdevall[minor]) break;
-       }
-       sprintf(myname, "cowloopd%d", minor);
-
-        daemonize(myname);
-
-       while (!cowdev->closedown) {
-               /*
-               ** sleep while waiting for an I/O request;
-               ** note that no non-interruptible wait has been used
-               ** because the non-interruptible version of
-               ** a *synchronous* wake_up does not exist (any more)
-               */
-               if (wait_event_interruptible(cowdev->waitq, cowdev->qfilled)){
-                       flush_signals(current); /* ignore signal-based wakeup */
-                       continue;
-               }
-
-               if (cowdev->closedown)          /* module will be unloaded ? */{
-                       cowdev->pid = 0;
-                       return 0;
-               }
-
-               /*
-               ** woken up by the I/O-request handler: treat requested I/O
-               */
-               cowdev->qfilled = 0;
-
-               rv = cowlo_do_request(cowdev->req);
-
-               /*
-               ** reacquire the queue-spinlock for manipulating
-               ** the request-queue and dequeue the request
-               */
-               spin_lock_irq(&cowdev->rqlock);
-
-               __blk_end_request_cur(cowdev->req, rv);
-               cowdev->iobusy = 0;
-
-               /*
-               ** initiate the next request from the queue
-               */
-               cowlo_request(cowdev->rqueue);
-
-               spin_unlock_irq(&cowdev->rqlock);
-       }
-       return 0;
-}
-
-/*
-** function to be called in the context of the kernel thread
-** to handle the queued I/O-requests
-**
-** returns:
-**     0   - fail
-**      1   - success
-*/
-static long int
-cowlo_do_request(struct request *req)
-{
-       unsigned long           len;
-       long int                rv;
-       loff_t                  offset;
-       struct cowloop_device   *cowdev = req->rq_disk->private_data;
-
-       /*
-       ** calculate some variables which are needed later on
-       */
-       len     =          blk_rq_cur_sectors(req) << 9;
-       offset  = (loff_t) blk_rq_pos(req)         << 9;
-
-       DEBUGP(DCOW"cowloop - req cmd=%d offset=%lld len=%lu addr=%p\n",
-                               *(req->cmd), offset, len, req->buffer);
-
-       /*
-       ** handle READ- or WRITE-request
-       */
-       switch (rq_data_dir(req)) {
-          /**********************************************************/
-          case READ:
-               switch ( cowlo_checkio(cowdev, len, offset) ) {
-                  case ALLCOW:
-                       rv = cowlo_readcow(cowdev, req->buffer, len, offset);
-                       break;
-
-                  case ALLRDO:
-                       rv = cowlo_readrdo(cowdev, req->buffer, len, offset);
-                       break;
-
-                  case MIXEDUP:
-                       rv = cowlo_readmix(cowdev, req->buffer, len, offset);
-                       break;
-
-                  default:
-                       rv = 0; /* never happens */
-               }
-               break;
-
-          /**********************************************************/
-          case WRITE:
-               switch ( cowlo_checkio(cowdev, len, offset) ) {
-                  case ALLCOW:
-                       /*
-                       ** straight-forward write will do...
-                       */
-                       DEBUGP(DCOW"cowloop - write straight ");
-
-                       rv = cowlo_writecow(cowdev, req->buffer, len, offset);
-                       break;  /* from switch */
-
-                  case ALLRDO:
-                       if ( (len & MUMASK) == 0) {
-                               DEBUGP(DCOW"cowloop - write straight ");
-
-                               rv = cowlo_writecow(cowdev, req->buffer,
-                                                               len, offset);
-                               break;
-                       }
-
-                  case MIXEDUP:
-                       rv = cowlo_writemix(cowdev, req->buffer, len, offset);
-                       break;
-
-                  default:
-                       rv = 0; /* never happens */
-               }
-               break;
-
-          default:
-               printk(KERN_ERR
-                      "cowloop - unrecognized command %d\n", *(req->cmd));
-               rv = 0;
-       }
-
-       return (rv <= 0 ? 0 : 1);
-}
-
-/*
-** check for a given I/O-request if all underlying blocks
-** (with size MAPUNIT) are either in the read-only file or in
-** the cowfile (or a combination of the two)
-**
-** returns:
-**     ALLRDO  - all underlying blocks in rdofile
-**      ALLCOW  - all underlying blocks in cowfile
-**      MIXEDUP - underlying blocks partly in rdofile and partly in cowfile
-*/
-static int
-cowlo_checkio(struct cowloop_device *cowdev, int len, loff_t offset)
-{
-       unsigned long   mapnum, bytenum, bitnum, blocknr, partlen;
-       long int        totcnt, cowcnt;
-       char            *mc;
-
-       /*
-       ** notice that the requested block might cross
-       ** a blocksize boundary while one of the concerned
-       ** blocks resides in the read-only file and another
-       ** one in the copy-on-write file; in that case the
-        ** request will be broken up into pieces
-       */
-       if ( (len <= MAPUNIT) &&
-            (MAPUNIT - (offset & MUMASK) <= len) ) {
-               /*
-               ** easy situation:
-               ** requested data-block entirely fits within
-               ** the mapunit used for the bitmap
-               ** check if that block is located in rdofile or
-               ** cowfile
-               */
-               blocknr = offset >> MUSHIFT;
-
-               mapnum  = CALCMAP (blocknr);
-               bytenum = CALCBYTE(blocknr);
-               bitnum  = CALCBIT (blocknr);
-
-               if (*(*(cowdev->mapcache+mapnum)+bytenum)&(1<<bitnum))
-                       return ALLCOW;
-               else
-                       return ALLRDO;
-       }
-
-       /*
-       ** less easy situation:
-       ** the requested data-block does not fit within the mapunit
-       ** used for the bitmap
-       ** check if *all* underlying blocks involved reside on the rdofile
-               ** or the cowfile (so still no breakup required)
-       */
-       for (cowcnt=totcnt=0; len > 0; len-=partlen, offset+=partlen, totcnt++){
-               /*
-               ** calculate blocknr of involved block
-               */
-               blocknr = offset >> MUSHIFT;
-
-               /*
-               ** calculate partial length for this transfer
-               */
-               partlen = MAPUNIT - (offset & MUMASK);
-               if (partlen > len)
-                       partlen = len;
-
-               /*
-               ** is this block located in the cowfile
-               */
-               mapnum  = CALCMAP (blocknr);
-               bytenum = CALCBYTE(blocknr);
-               bitnum  = CALCBIT (blocknr);
-
-               mc      = *(cowdev->mapcache+mapnum);
-
-               if (*(mc+bytenum)&(1<<bitnum))
-                       cowcnt++;;
-
-               DEBUGP(DCOW
-                      "cowloop - check %lu - map %lu, byte %lu, bit %lu, "
-                      "cowcnt %ld, totcnt %ld %02x %p\n",
-                       blocknr, mapnum, bytenum, bitnum, cowcnt, totcnt,
-                       *(mc+bytenum), mc);
-       }
-
-       if (cowcnt == 0)        /* all involved blocks on rdofile? */
-               return ALLRDO;
-
-       if (cowcnt == totcnt)   /* all involved blocks on cowfile? */
-               return ALLCOW;
-
-       /*
-       ** situation somewhat more complicated:
-       ** involved underlying blocks spread over both files
-       */
-       return MIXEDUP;
-}
-
-/*
-** read requested chunk partly from rdofile and partly from cowfile
-**
-** returns:
-**     0   - fail
-**      1   - success
-*/
-static int
-cowlo_readmix(struct cowloop_device *cowdev, void *buf, int len, loff_t offset)
-{
-       unsigned long   mapnum, bytenum, bitnum, blocknr, partlen;
-       long int        rv;
-       char            *mc;
-
-       /*
-       ** complicated approach: breakup required of read-request
-       */
-       for (rv=1; len > 0; len-=partlen, buf+=partlen, offset+=partlen) {
-               /*
-               ** calculate blocknr of entire block
-               */
-               blocknr = offset >> MUSHIFT;
-
-               /*
-               ** calculate partial length for this transfer
-               */
-               partlen = MAPUNIT - (offset & MUMASK);
-               if (partlen > len)
-                       partlen = len;
-
-               /*
-               ** is this block located in the cowfile
-               */
-               mapnum  = CALCMAP (blocknr);
-               bytenum = CALCBYTE(blocknr);
-               bitnum  = CALCBIT (blocknr);
-               mc      = *(cowdev->mapcache+mapnum);
-
-               if (*(mc+bytenum)&(1<<bitnum)) {
-                       /*
-                       ** read (partial) block from cowfile
-                       */
-                       DEBUGP(DCOW"cowloop - split read "
-                               "cow partlen=%ld off=%lld\n", partlen, offset);
-
-                       if (cowlo_readcow(cowdev, buf, partlen, offset) <= 0)
-                               rv = 0;
-               } else {
-                       /*
-                       ** read (partial) block from rdofile
-                       */
-                       DEBUGP(DCOW"cowloop - split read "
-                               "rdo partlen=%ld off=%lld\n", partlen, offset);
-
-                       if (cowlo_readrdo(cowdev, buf, partlen, offset) <= 0)
-                               rv = 0;
-               }
-       }
-
-       return rv;
-}
-
-/*
-** chunk to be written to the cowfile needs pieces to be
-** read from the rdofile
-**
-** returns:
-**     0   - fail
-**      1   - success
-*/
-static int
-cowlo_writemix(struct cowloop_device *cowdev, void *buf, int len, loff_t offset)
-{
-       unsigned long   mapnum, bytenum, bitnum, blocknr, partlen;
-       long int        rv;
-       char            *mc;
-
-       /*
-       ** somewhat more complicated stuff is required:
-       ** if the request is larger than one underlying
-       ** block or is spread over two underlying blocks,
-       ** split the request into pieces; if a block does not
-       ** start at a block boundary, take care that
-       ** surrounding data is read first (if needed),
-       ** fit the new data in and write it as a full block
-       */
-       for (rv=1; len > 0; len-=partlen, buf+=partlen, offset+=partlen) {
-               /*
-               ** calculate partial length for this transfer
-               */
-               partlen = MAPUNIT - (offset & MUMASK);
-               if (partlen > len)
-                       partlen = len;
-
-               /*
-               ** calculate blocknr of entire block
-               */
-               blocknr = offset >> MUSHIFT;
-
-               /*
-               ** has this block been written before?
-               */
-               mapnum  = CALCMAP (blocknr);
-               bytenum = CALCBYTE(blocknr);
-               bitnum  = CALCBIT (blocknr);
-               mc      = *(cowdev->mapcache+mapnum);
-
-               if (*(mc+bytenum)&(1<<bitnum)) {
-                       /*
-                       ** block has been written before;
-                       ** write transparantly to cowfile
-                       */
-                       DEBUGP(DCOW
-                              "cowloop - splitwr transp\n");
-
-                       if (cowlo_writecow(cowdev, buf, partlen, offset) <= 0)
-                               rv = 0;
-               } else {
-                       /*
-                       ** block has never been written before,
-                       ** so read entire block from
-                       ** read-only file first, unless
-                       ** a full block is requested to
-                       ** be written
-                       */
-                       if (partlen < MAPUNIT) {
-                               if (cowlo_readrdo(cowdev, cowdev->iobuf,
-                                     MAPUNIT, (loff_t)blocknr << MUSHIFT) <= 0)
-                                       rv = 0;
-                       }
-
-                       /*
-                       ** transfer modified part into
-                       ** the block just read
-                       */
-                       memcpy(cowdev->iobuf + (offset & MUMASK), buf, partlen);
-
-                       /*
-                       ** write entire block to cowfile
-                       */
-                       DEBUGP(DCOW"cowloop - split "
-                               "partlen=%ld off=%lld\n",
-                               partlen, (loff_t)blocknr << MUSHIFT);
-
-                       if (cowlo_writecow(cowdev, cowdev->iobuf, MAPUNIT,
-                                            (loff_t)blocknr << MUSHIFT) <= 0)
-                               rv = 0;
-               }
-       }
-
-       return rv;
-}
-
-/*****************************************************************************/
-/* I/O-support for read-only file and copy-on-write file                     */
-/*****************************************************************************/
-
-/*
-** read data from the read-only file
-**
-** return-value: similar to user-mode read
-*/
-static long int
-cowlo_readrdo(struct cowloop_device *cowdev, void *buf, int len, loff_t offset)
-{
-       long int        rv;
-       mm_segment_t    old_fs;
-       loff_t          saveoffset = offset;
-
-       DEBUGP(DCOW"cowloop - readrdo called\n");
-
-        old_fs = get_fs();
-       set_fs( get_ds() );
-       rv = cowdev->rdofp->f_op->read(cowdev->rdofp, buf, len, &offset);
-        set_fs(old_fs);
-
-       if (rv < len) {
-               printk(KERN_WARNING "cowloop - read-failure %ld on rdofile"
-                                   "- offset=%lld len=%d\n",
-                                       rv, saveoffset, len);
-       }
-
-       cowdev->rdoreads++;
-       return rv;
-}
-
-/*
-** read cowfile from a modified offset, i.e. skipping the bitmap and cowhead
-**
-** return-value: similar to user-mode read
-*/
-static long int
-cowlo_readcow(struct cowloop_device *cowdev, void *buf, int len, loff_t offset)
-{
-       DEBUGP(DCOW"cowloop - readcow called\n");
-
-       offset += cowdev->cowhead->doffset;
-
-       return cowlo_readcowraw(cowdev, buf, len, offset);
-}
-
-/*
-** read cowfile from an absolute offset
-**
-** return-value: similar to user-mode read
-*/
-static long int
-cowlo_readcowraw(struct cowloop_device *cowdev,
-                                       void *buf, int len, loff_t offset)
-{
-       long int        rv;
-       mm_segment_t    old_fs;
-       loff_t          saveoffset = offset;
-
-       DEBUGP(DCOW"cowloop - readcowraw called\n");
-
-       /*
-       ** be sure that cowfile is opened for read-write
-       */
-       if ( !(cowdev->state & COWCOWOPEN) ) {
-                printk(KERN_WARNING
-                       "cowloop - read request from cowfile refused\n");
-
-               return -EBADF;
-       }
-
-       /*
-       ** issue low level read
-       */
-        old_fs = get_fs();
-       set_fs( get_ds() );
-       rv = cowdev->cowfp->f_op->read(cowdev->cowfp, buf, len, &offset);
-        set_fs(old_fs);
-
-       if (rv < len) {
-               printk(KERN_WARNING
-                      "cowloop - read-failure %ld on cowfile"
-                      "- offset=%lld len=%d\n", rv, saveoffset, len);
-       }
-
-       cowdev->cowreads++;
-       return rv;
-}
-
-/*
-** write cowfile from a modified offset, i.e. skipping the bitmap and cowhead
-**
-** if a block is written for the first time while its contents consists
-** of binary zeroes only, the concerning bitmap is flushed to the cowfile
-**
-** return-value: similar to user-mode write
-*/
-static long int
-cowlo_writecow(struct cowloop_device *cowdev, void *buf, int len, loff_t offset)
-{
-       long int        rv;
-       unsigned long   mapnum=0, mapbyte=0, mapbit=0, cowblock=0, partlen;
-       char            *tmpptr,  *mapptr = NULL;
-       loff_t          tmpoffset, mapoffset = 0;
-
-       DEBUGP(DCOW"cowloop - writecow called\n");
-
-       /*
-       ** be sure that cowfile is opened for read-write
-       */
-       if ( !(cowdev->state & COWRWCOWOPEN) ) {
-                printk(KERN_WARNING
-                       "cowloop - Write request to cowfile refused\n");
-
-               return -EBADF;
-       }
-
-       /*
-       ** write the entire block to the cowfile
-       */
-       tmpoffset = offset + cowdev->cowhead->doffset;
-
-       rv = cowlo_writecowraw(cowdev, buf, len, tmpoffset);
-
-       /*
-       ** verify if enough space available on filesystem holding
-       ** the cowfile
-       **   - when the last write failed (might be caused by lack of space)
-       **   - when a watcher is active (to react adequatly)
-       **   - when the previous check indicated fs was almost full
-       **   - with regular intervals
-       */
-       if ( (rv <= 0)                                 ||
-            (cowdev->state        & COWWATCHDOG)      ||
-            (cowdev->blkavail / 2 < SPCDFLINTVL)      ||
-            (cowdev->cowwrites    % SPCDFLINTVL == 0) ) {
-               struct kstatfs          ks;
-
-               if (vfs_statfs(cowdev->cowfp->f_dentry, &ks)==0){
-                       if (ks.f_bavail <= SPCMINBLK) {
-                               switch (ks.f_bavail) {
-                                  case 0:
-                                  case 1:
-                                  case 2:
-                                  case 3:
-                                       printk(KERN_ALERT
-                                              "cowloop - "
-                                              "ALERT: cowfile full!\n");
-                                       break;
-
-                                  default:
-                                       printk(KERN_WARNING
-                                              "cowloop - cowfile almost "
-                                              "full (only %llu Kb free)\n",
-                                               (unsigned long long)
-                                                ks.f_bsize * ks.f_bavail /1024);
-                               }
-                       }
-
-                       cowdev->blktotal = ks.f_blocks;
-                       cowdev->blkavail = ks.f_bavail;
-
-                       /*
-                       ** wakeup watcher if threshold has been reached
-                       */
-                       if ( (cowdev->state & COWWATCHDOG) &&
-                           (cowdev->watchthresh >= cowdev->blkavail) ) {
-                               wake_up_interruptible(&cowdev->watchq);
-                       }
-               }
-       }
-
-       if (rv <= 0)
-               return rv;
-
-       DEBUGP(DCOW"cowloop - block written\n");
-
-       /*
-       ** check if block(s) is/are written to the cowfile
-       ** for the first time; if so, adapt the bitmap
-       */
-       for (; len > 0; len-=partlen, offset+=partlen, buf+=partlen) {
-               /*
-               ** calculate partial length for this transfer
-               */
-               partlen = MAPUNIT - (offset & MUMASK);
-               if (partlen > len)
-                       partlen = len;
-
-               /*
-               ** calculate bitnr of written chunk of cowblock
-               */
-               cowblock = offset >> MUSHIFT;
-
-               mapnum   = CALCMAP (cowblock);
-               mapbyte  = CALCBYTE(cowblock);
-               mapbit   = CALCBIT (cowblock);
-
-               if (*(*(cowdev->mapcache+mapnum)+mapbyte) & (1<<mapbit))
-                       continue;       /* already written before */
-
-               /*
-               ** if the block is written for the first time,
-               ** the corresponding bit should be set in the bitmap
-               */
-               *(*(cowdev->mapcache+mapnum)+mapbyte) |= (1<<mapbit);
-
-               cowdev->nrcowblocks++;
-
-               DEBUGP(DCOW"cowloop - bitupdate blk=%ld map=%ld "
-                       "byte=%ld bit=%ld\n",
-                       cowblock, mapnum, mapbyte, mapbit);
-
-               /*
-               ** check if the cowhead in the cowfile is currently
-               ** marked clean; if so, mark it dirty and flush it
-               */
-               if ( !(cowdev->cowhead->flags &= COWDIRTY)) {
-                       cowdev->cowhead->flags  |= COWDIRTY;
-
-                       cowlo_writecowraw(cowdev, cowdev->cowhead,
-                                                       MAPUNIT, (loff_t)0);
-               }
-
-               /*
-               ** if the written datablock contained binary zeroes,
-               ** the bitmap block should be marked to be flushed to disk
-               ** (blocks containing all zeroes cannot be recovered by
-               ** the cowrepair-program later on if cowloop is not properly
-               ** removed via rmmod)
-               */
-               if ( memcmp(buf, allzeroes, partlen) ) /* not all zeroes? */
-                       continue;                      /* no flush needed */
-
-               /*
-               ** calculate positions of bitmap block to be flushed
-               ** - pointer of bitmap block in memory
-               ** - offset  of bitmap block in cowfile
-               */
-               tmpptr    = *(cowdev->mapcache+mapnum) + (mapbyte & (~MUMASK));
-               tmpoffset = (loff_t) MAPUNIT + mapnum * MAPCHUNKSZ +
-                                                      (mapbyte & (~MUMASK));
-
-               /*
-               ** flush a bitmap block at the moment that all bits have
-               ** been set in that block, i.e. at the moment that we
-               ** switch to another bitmap block
-               */
-               if ( (mapoffset != 0) && (mapoffset != tmpoffset) ) {
-                       if (cowlo_writecowraw(cowdev, mapptr, MAPUNIT,
-                                                       mapoffset) < 0) {
-                               printk(KERN_WARNING
-                                      "cowloop - write-failure on bitmap - "
-                                      "blk=%ld map=%ld byte=%ld bit=%ld\n",
-                                       cowblock, mapnum, mapbyte, mapbit);
-                       }
-
-                       DEBUGP(DCOW"cowloop - bitmap blk written %lld\n",
-                                                               mapoffset);
-               }
-
-               /*
-               ** remember offset in cowfile and offset in memory
-               ** for bitmap to be flushed; flushing will be done
-               ** as soon as all updates in this bitmap block have
-               ** been done
-               */
-               mapoffset = tmpoffset;
-               mapptr    = tmpptr;
-       }
-
-       /*
-       ** any new block written containing binary zeroes?
-       */
-       if (mapoffset) {
-               if (cowlo_writecowraw(cowdev, mapptr, MAPUNIT, mapoffset) < 0) {
-                       printk(KERN_WARNING
-                              "cowloop - write-failure on bitmap - "
-                              "blk=%ld map=%ld byte=%ld bit=%ld\n",
-                              cowblock, mapnum, mapbyte, mapbit);
-               }
-
-               DEBUGP(DCOW"cowloop - bitmap block written %lld\n", mapoffset);
-       }
-
-       return rv;
-}
-
-/*
-** write cowfile from an absolute offset
-**
-** return-value: similar to user-mode write
-*/
-static long int
-cowlo_writecowraw(struct cowloop_device *cowdev,
-                                       void *buf, int len, loff_t offset)
-{
-       long int        rv;
-       mm_segment_t    old_fs;
-       loff_t          saveoffset = offset;
-
-       DEBUGP(DCOW"cowloop - writecowraw called\n");
-
-       /*
-       ** be sure that cowfile is opened for read-write
-       */
-       if ( !(cowdev->state & COWRWCOWOPEN) ) {
-                printk(KERN_WARNING
-                       "cowloop - write request to cowfile refused\n");
-
-               return -EBADF;
-       }
-
-       /*
-       ** issue low level write
-       */
-        old_fs = get_fs();
-       set_fs( get_ds() );
-       rv = cowdev->cowfp->f_op->write(cowdev->cowfp, buf, len, &offset);
-        set_fs(old_fs);
-
-       if (rv < len) {
-               printk(KERN_WARNING
-                      "cowloop - write-failure %ld on cowfile"
-                      "- offset=%lld len=%d\n", rv, saveoffset, len);
-       }
-
-       cowdev->cowwrites++;
-       return rv;
-}
-
-
-/*
-** readproc-function: called when the corresponding /proc-file is read
-*/
-static int
-cowlo_readproc(char *buf, char **start, off_t pos, int cnt, int *eof, void *p)
-{
-       struct cowloop_device *cowdev = p;
-
-       revision[sizeof revision - 3] = '\0';
-
-       return sprintf(buf,
-               "   cowloop version: %9s\n\n"
-               "      device state: %s%s%s%s\n"
-               "   number of opens: %9d\n"
-               "     pid of thread: %9d\n\n"
-               "    read-only file: %9s\n"
-               "          rdoreads: %9lu\n\n"
-               "copy-on-write file: %9s\n"
-               "     state cowfile: %9s\n"
-               "     bitmap-blocks: %9lu (of %d bytes)\n"
-               "  cowblocks in use: %9lu (of %d bytes)\n"
-               "          cowreads: %9lu\n"
-               "         cowwrites: %9lu\n",
-                       &revision[11],
-
-                       cowdev->state & COWDEVOPEN   ? "devopen "   : "",
-                       cowdev->state & COWRWCOWOPEN ? "cowopenrw " : "",
-                       cowdev->state & COWRDCOWOPEN ? "cowopenro " : "",
-                       cowdev->state & COWWATCHDOG  ? "watchdog "  : "",
-
-                       cowdev->opencnt,
-                       cowdev->pid,
-                       cowdev->rdoname,
-                       cowdev->rdoreads,
-                       cowdev->cowname,
-                       cowdev->cowhead->flags & COWDIRTY ? "dirty":"clean",
-                       cowdev->mapsize >> MUSHIFT, MAPUNIT,
-                       cowdev->nrcowblocks, MAPUNIT,
-                       cowdev->cowreads,
-                       cowdev->cowwrites);
-}
-
-/*****************************************************************************/
-/* Setup and destroy cowdevices                                              */
-/*****************************************************************************/
-
-/*
-** open and prepare a cowdevice (rdofile and cowfile) and allocate bitmaps
-**
-** returns:
-**     0   - okay
-**    < 0   - error value
-*/
-static int
-cowlo_openpair(char *rdof, char *cowf, int autorecover, int minor)
-{
-       long int                rv;
-       struct cowloop_device   *cowdev = cowdevall[minor];
-       struct kstatfs          ks;
-
-       down(&cowdevlock);
-
-       /*
-       ** requested device exists?
-       */
-       if (minor >= maxcows) {
-               up(&cowdevlock);
-               return -ENODEV;
-       }
-
-       /*
-       ** requested device already assigned to cowdevice?
-       */
-       if (cowdev->state & COWDEVOPEN) {
-               up(&cowdevlock);
-               return -EBUSY;
-       }
-
-       /*
-       ** initialize administration
-       */
-       memset(cowdev, 0, sizeof *cowdev);
-
-       spin_lock_init     (&cowdev->rqlock);
-       init_waitqueue_head(&cowdev->waitq);
-       init_waitqueue_head(&cowdev->watchq);
-
-       /*
-       ** open the read-only file
-       */
-       DEBUGP(DCOW"cowloop - call openrdo....\n");
-
-       if ( (rv = cowlo_openrdo(cowdev, rdof)) ) {
-               cowlo_undo_openrdo(cowdev);
-               up(&cowdevlock);
-               return rv;
-       }
-
-       /*
-       ** open the cowfile
-       */
-       DEBUGP(DCOW"cowloop - call opencow....\n");
-
-       if ( (rv = cowlo_opencow(cowdev, cowf, autorecover)) ) {
-               cowlo_undo_openrdo(cowdev);
-               cowlo_undo_opencow(cowdev);
-               up(&cowdevlock);
-               return rv;
-       }
-
-       /*
-       ** administer total and available size of filesystem holding cowfile
-       */
-       if (vfs_statfs(cowdev->cowfp->f_dentry, &ks)==0) {
-               cowdev->blksize  = ks.f_bsize;
-               cowdev->blktotal = ks.f_blocks;
-               cowdev->blkavail = ks.f_bavail;
-       } else {
-               cowdev->blksize  = 1024;        /* avoid division by zero */
-       }
-
-       /*
-       ** flush the (recovered) bitmaps and cowhead to the cowfile
-       */
-       DEBUGP(DCOW"cowloop - call cowsync....\n");
-
-       cowlo_sync();
-
-       /*
-       ** allocate gendisk for the cow device
-       */
-       DEBUGP(DCOW"cowloop - alloc disk....\n");
-
-       if ((cowdev->gd = alloc_disk(1)) == NULL) {
-               printk(KERN_WARNING
-                      "cowloop - unable to alloc_disk for cowloop\n");
-
-               cowlo_undo_openrdo(cowdev);
-               cowlo_undo_opencow(cowdev);
-               up(&cowdevlock);
-               return -ENOMEM;
-       }
-
-       cowdev->gd->major        = COWMAJOR;
-       cowdev->gd->first_minor  = minor;
-       cowdev->gd->minors       = 1;
-       cowdev->gd->fops         = &cowlo_fops;
-       cowdev->gd->private_data = cowdev;
-       sprintf(cowdev->gd->disk_name, "%s%d", DEVICE_NAME, minor);
-
-       /* in .5 Kb units */
-       set_capacity(cowdev->gd, (cowdev->numblocks*(MAPUNIT/512)));
-
-       DEBUGP(DCOW"cowloop - init request queue....\n");
-
-       if ((cowdev->rqueue = blk_init_queue(cowlo_request, &cowdev->rqlock))
-                                                               == NULL) {
-               printk(KERN_WARNING
-                      "cowloop - unable to get request queue for cowloop\n");
-
-               del_gendisk(cowdev->gd);
-               cowlo_undo_openrdo(cowdev);
-               cowlo_undo_opencow(cowdev);
-               up(&cowdevlock);
-               return -EINVAL;
-       }
-
-       blk_queue_logical_block_size(cowdev->rqueue, cowdev->blocksz);
-       cowdev->gd->queue = cowdev->rqueue;
-
-       /*
-       ** start kernel thread to handle requests
-       */
-       DEBUGP(DCOW"cowloop - kickoff daemon....\n");
-
-       cowdev->pid = kernel_thread((int (*)(void *))cowlo_daemon, cowdev, 0);
-
-       /*
-       ** create a file below directory /proc/cow for this new cowdevice
-       */
-       if (cowlo_procdir) {
-               char    tmpname[64];
-
-               sprintf(tmpname, "%d", minor);
-
-               create_proc_read_entry(tmpname, 0 , cowlo_procdir,
-                                               cowlo_readproc, cowdev);
-       }
-
-       cowdev->state   |= COWDEVOPEN;
-
-       cowdev->rdoname = rdof;
-       cowdev->cowname = cowf;
-
-       /*
-       ** enable the new disk; this triggers the first request!
-       */
-       DEBUGP(DCOW"cowloop - call add_disk....\n");
-
-       add_disk(cowdev->gd);
-
-       up(&cowdevlock);
-       return 0;
-}
-
-/*
-** close a cowdevice (pair of rdofile/cowfile) and release memory
-**
-** returns:
-**     0   - okay
-**    < 0   - error value
-*/
-static int
-cowlo_closepair(struct cowloop_device *cowdev)
-{
-       int minor;
-
-       down(&cowdevlock);
-
-       /*
-       ** if cowdevice is not activated at all, refuse
-       */
-       if ( !(cowdev->state & COWDEVOPEN) ) {
-               up(&cowdevlock);
-               return -ENODEV;
-       }
-
-       /*
-       ** if this cowdevice is still open, refuse
-       */
-       if (cowdev->opencnt > 0) {
-               up(&cowdevlock);
-               return -EBUSY;
-       }
-
-       up(&cowdevlock);
-
-       /*
-       ** wakeup watcher (if any)
-       */
-       if (cowdev->state & COWWATCHDOG) {
-               cowdev->watchthresh = cowdev->blkavail;
-               wake_up_interruptible(&cowdev->watchq);
-       }
-
-       /*
-       ** wakeup kernel-thread to be able to exit
-       ** and wait until it has exited
-       */
-       cowdev->closedown = 1;
-       cowdev->qfilled   = 1;
-       wake_up_interruptible(&cowdev->waitq);
-
-               while (cowdev->pid)
-                       schedule();
-
-       del_gendisk(cowdev->gd);  /* revert the alloc_disk() */
-       put_disk(cowdev->gd);     /* revert the add_disk()   */
-
-       if (cowlo_procdir) {
-               char    tmpname[64];
-
-               for (minor = 0; minor < maxcows; minor++) {
-                       if (cowdev == cowdevall[minor]) break;
-               }
-               sprintf(tmpname, "%d", minor);
-
-               remove_proc_entry(tmpname, cowlo_procdir);
-       }
-
-       blk_cleanup_queue(cowdev->rqueue);
-
-       /*
-       ** release memory for filenames if these names have
-       ** been allocated dynamically
-       */
-       if ( (cowdev->cowname) && (cowdev->cowname != cowfile))
-               kfree(cowdev->cowname);
-
-       if ( (cowdev->rdoname) && (cowdev->rdoname != rdofile))
-               kfree(cowdev->rdoname);
-
-       cowlo_undo_openrdo(cowdev);
-       cowlo_undo_opencow(cowdev);
-
-       cowdev->state &= ~COWDEVOPEN;
-
-       return 0;
-}
-
-/*
-** open the read-only file
-**
-** returns:
-**     0   - okay
-**    < 0   - error value
-*/
-static int
-cowlo_openrdo(struct cowloop_device *cowdev, char *rdof)
-{
-       struct file     *f;
-       struct inode    *inode;
-       long int        i, nrval;
-
-       DEBUGP(DCOW"cowloop - openrdo called\n");
-
-       /*
-       ** open the read-only file
-       */
-        if(*rdof == '\0') {
-               printk(KERN_ERR
-                      "cowloop - specify name for read-only file\n\n");
-               return -EINVAL;
-        }
-
-       f = filp_open(rdof, O_RDONLY|O_LARGEFILE, 0);
-
-       if ( (f == NULL) || IS_ERR(f) ) {
-               printk(KERN_ERR
-                      "cowloop - open of rdofile %s failed\n", rdof);
-               return -EINVAL;
-       }
-
-       cowdev->rdofp = f;
-
-       inode = f->f_dentry->d_inode;
-
-       if ( !S_ISREG(inode->i_mode) && !S_ISBLK(inode->i_mode) ) {
-               printk(KERN_ERR
-                      "cowloop - %s not regular file or blockdev\n", rdof);
-               return -EINVAL;
-       }
-
-       DEBUGP(DCOW"cowloop - determine size rdo....\n");
-
-       /*
-       ** determine block-size and total size of read-only file
-       */
-       if (S_ISREG(inode->i_mode)) {
-               /*
-               ** read-only file is a regular file
-               */
-               cowdev->blocksz   = 512;        /* other value fails */
-               cowdev->numblocks = inode->i_size >> MUSHIFT;
-
-               if (inode->i_size & MUMASK) {
-                       printk(KERN_WARNING
-                              "cowloop - rdofile %s truncated to multiple "
-                              "of %d bytes\n", rdof, MAPUNIT);
-               }
-
-               DEBUGP(DCOW"cowloop - RO=regular: numblocks=%d, blocksz=%d\n",
-                       cowdev->numblocks, cowdev->blocksz);
-       } else {
-               /*
-               ** read-only file is a block device
-               */
-               cowdev->belowdev  = inode->i_bdev;
-               cowdev->belowgd   = cowdev->belowdev->bd_disk; /* gendisk */
-
-               if (cowdev->belowdev->bd_part) {
-                       cowdev->numblocks = cowdev->belowdev->bd_part->nr_sects
-                                                               / (MAPUNIT/512);
-               }
-
-               if (cowdev->belowgd) {
-                       cowdev->belowq = cowdev->belowgd->queue;
-
-                       if (cowdev->numblocks == 0) {
-                               cowdev->numblocks = get_capacity(cowdev->belowgd)
-                                                               / (MAPUNIT/512);
-                       }
-               }
-
-
-               if (cowdev->belowq)
-                       cowdev->blocksz = queue_logical_block_size(cowdev->belowq);
-
-               if (cowdev->blocksz == 0)
-                       cowdev->blocksz = BLOCK_SIZE; /* default 2^10 */
-
-               DEBUGP(DCOW"cowloop - numblocks=%d, "
-                          "blocksz=%d, belowgd=%p, belowq=%p\n",
-                       cowdev->numblocks, cowdev->blocksz,
-                       cowdev->belowgd, cowdev->belowq);
-
-               DEBUGP(DCOW"cowloop - belowdev.bd_block_size=%d\n",
-                       cowdev->belowdev->bd_block_size);
-       }
-
-       if (cowdev->numblocks == 0) {
-               printk(KERN_ERR "cowloop - %s has no contents\n", rdof);
-               return -EINVAL;
-       }
-
-       /*
-       ** reserve space in memory as generic I/O buffer
-       */
-       cowdev->iobuf  = kmalloc(MAPUNIT, GFP_KERNEL);
-
-       if (!cowdev->iobuf) {
-               printk(KERN_ERR
-                      "cowloop - cannot get space for buffer %d\n", MAPUNIT);
-               return -ENOMEM;
-       }
-
-       DEBUGP(DCOW"cowloop - determine fingerprint rdo....\n");
-
-       /*
-       ** determine fingerprint for read-only file
-       **      calculate fingerprint from first four datablocks
-       **      which do not contain binary zeroes
-       */
-       for (i=0, cowdev->fingerprint=0, nrval=0;
-                       (nrval < 4)&&(i < cowdev->numblocks); i++) {
-               int             j;
-               unsigned char   cs;
-
-               /*
-               ** read next block
-               */
-               if (cowlo_readrdo(cowdev, cowdev->iobuf, MAPUNIT,
-                                               (loff_t)i << MUSHIFT) < 1)
-                       break;
-
-               /*
-               ** calculate fingerprint by adding all byte-values
-               */
-               for (j=0, cs=0; j < MAPUNIT; j++)
-                       cs += *(cowdev->iobuf+j);
-
-               if (cs == 0)    /* block probably contained zeroes */
-                       continue;
-
-               /*
-               ** shift byte-value to proper place in final fingerprint
-               */
-               cowdev->fingerprint |= cs << (nrval*8);
-               nrval++;
-       }
-
-       return 0;
-}
-
-/*
-** undo memory allocs and file opens issued so far
-** related to the read-only file
-*/
-static void
-cowlo_undo_openrdo(struct cowloop_device *cowdev)
-{
-       if(cowdev->iobuf);
-               kfree(cowdev->iobuf);
-
-       if (cowdev->rdofp)
-               filp_close(cowdev->rdofp, 0);
-}
-
-/*
-** open the cowfile
-**
-** returns:
-**     0   - okay
-**    < 0   - error value
-*/
-static int
-cowlo_opencow(struct cowloop_device *cowdev, char *cowf, int autorecover)
-{
-       long int                i, rv;
-       int                     minor;
-       unsigned long           nb;
-       struct file             *f;
-       struct inode            *inode;
-       loff_t                  offset;
-       struct cowloop_device   *cowtmp;
-
-       DEBUGP(DCOW"cowloop - opencow called\n");
-
-       /*
-       ** open copy-on-write file (read-write)
-       */
-        if (cowf[0] == '\0') {
-               printk(KERN_ERR
-                 "cowloop - specify name of copy-on-write file\n\n");
-               return -EINVAL;
-        }
-
-       f = filp_open(cowf, O_RDWR|O_LARGEFILE, 0600);
-
-       if ( (f == NULL) || IS_ERR(f) ) {
-               /*
-               ** non-existing cowfile: try to create
-               */
-               f = filp_open(cowf, O_RDWR|O_CREAT|O_LARGEFILE, 0600);
-
-               if ( (f == NULL) || IS_ERR(f) ) {
-                       printk(KERN_ERR
-                         "cowloop - failed to open file %s for read-write\n\n",
-                                                               cowf);
-                       return -EINVAL;
-               }
-       }
-
-       cowdev->cowfp = f;
-
-       inode = f->f_dentry->d_inode;
-
-       if (!S_ISREG(inode->i_mode)) {
-               printk(KERN_ERR "cowloop - %s is not regular file\n", cowf);
-               return -EINVAL;
-       }
-
-       /*
-       ** check if this cowfile is already in use for another cowdevice
-       */
-       for (minor = 0; minor < maxcows; minor++) {
-
-               cowtmp = cowdevall[minor];
-
-               if ( !(cowtmp->state & COWDEVOPEN) )
-                       continue;
-
-               if (cowtmp == cowdev)
-                       continue;
-
-               if (cowtmp->cowfp->f_dentry->d_inode == f->f_dentry->d_inode) {
-                       printk(KERN_ERR
-                              "cowloop - %s: already in use as cow\n", cowf);
-                       return -EBUSY;
-               }
-       }
-
-       /*
-       ** mark cowfile open for read-write
-       */
-       cowdev->state |= COWRWCOWOPEN;
-
-       /*
-       ** calculate size (in bytes) for total bitmap in cowfile;
-       ** when the size of the cowhead block is added, the start-offset
-       ** for the modified data blocks can be found
-       */
-       nb = cowdev->numblocks;
-
-       if (nb%8)               /* transform #bits to #bytes */
-               nb+=8;          /* rounded if necessary      */
-       nb /= 8;
-
-       if (nb & MUMASK)        /* round up #bytes to MAPUNIT chunks */
-               cowdev->mapsize = ( (nb>>MUSHIFT) +1) << MUSHIFT;
-       else
-               cowdev->mapsize = nb;
-
-       /*
-       ** reserve space in memory for the cowhead
-       */
-       cowdev->cowhead = kmalloc(MAPUNIT, GFP_KERNEL);
-
-       if (!cowdev->cowhead) {
-               printk(KERN_ERR "cowloop - cannot get space for cowhead %d\n",
-                                                                    MAPUNIT);
-               return -ENOMEM;
-       }
-
-       memset(cowdev->cowhead, 0, MAPUNIT);
-
-       DEBUGP(DCOW"cowloop - prepare cowhead....\n");
-
-       /*
-       ** check if the cowfile exists or should be created
-       */
-       if (inode->i_size != 0) {
-               /*
-               ** existing cowfile: read the cow head
-               */
-               if (inode->i_size < MAPUNIT) {
-                       printk(KERN_ERR
-                              "cowloop - existing cowfile %s too small\n",
-                               cowf);
-                       return -EINVAL;
-               }
-
-               cowlo_readcowraw(cowdev, cowdev->cowhead, MAPUNIT, (loff_t) 0);
-
-               /*
-               ** verify if the existing file is really a cowfile
-               */
-               if (cowdev->cowhead->magic != COWMAGIC) {
-                       printk(KERN_ERR
-                              "cowloop - cowfile %s has incorrect format\n",
-                               cowf);
-                       return -EINVAL;
-               }
-
-               /*
-               ** verify the cowhead version of the cowfile
-               */
-               if (cowdev->cowhead->version > COWVERSION) {
-                       printk(KERN_ERR
-                              "cowloop - cowfile %s newer than this driver\n",
-                               cowf);
-                       return -EINVAL;
-               }
-
-               /*
-               ** make sure that this is not a packed cowfile
-               */
-               if (cowdev->cowhead->flags & COWPACKED) {
-                       printk(KERN_ERR
-                           "cowloop - packed cowfile %s not accepted\n", cowf);
-                       return -EINVAL;
-               }
-
-               /*
-               ** verify if the cowfile has been properly closed
-               */
-               if (cowdev->cowhead->flags & COWDIRTY) {
-                       /*
-                       ** cowfile was not properly closed;
-                       ** check if automatic recovery is required
-                       ** (actual recovery will be done later on)
-                       */
-                       if (!autorecover) {
-                               printk(KERN_ERR
-                                      "cowloop - cowfile %s is dirty "
-                                      "(not properly closed by rmmod?)\n",
-                                       cowf);
-                               printk(KERN_ERR
-                                      "cowloop - run cowrepair or specify "
-                                      "'option=r' to recover\n");
-                               return -EINVAL;
-                       }
-               }
-
-               /*
-               ** verify if the cowfile is really related to this rdofile
-               */
-               if (cowdev->cowhead->rdoblocks != cowdev->numblocks) {
-                       printk(KERN_ERR
-                              "cowloop - cowfile %s (size %lld) not related "
-                              "to rdofile (size %lld)\n",
-                               cowf,
-                               (long long)cowdev->cowhead->rdoblocks <<MUSHIFT,
-                               (long long)cowdev->numblocks <<MUSHIFT);
-                       return -EINVAL;
-               }
-
-               if (cowdev->cowhead->rdofingerprint != cowdev->fingerprint) {
-                       printk(KERN_ERR
-                            "cowloop - cowfile %s not related to rdofile "
-                            " (fingerprint err - rdofile modified?)\n", cowf);
-                       return -EINVAL;
-               }
-       } else {
-               /*
-               ** new cowfile: determine the minimal size (cowhead+bitmap)
-               */
-               offset = (loff_t) MAPUNIT + cowdev->mapsize - 1;
-
-               if ( cowlo_writecowraw(cowdev, "", 1, offset) < 1) {
-                       printk(KERN_ERR
-                              "cowloop - cannot set cowfile to size %lld\n",
-                               offset+1);
-                       return -EINVAL;
-               }
-
-               /*
-               ** prepare new cowhead
-               */
-               cowdev->cowhead->magic          = COWMAGIC;
-               cowdev->cowhead->version        = COWVERSION;
-               cowdev->cowhead->mapunit        = MAPUNIT;
-               cowdev->cowhead->mapsize        = cowdev->mapsize;
-               cowdev->cowhead->rdoblocks      = cowdev->numblocks;
-               cowdev->cowhead->rdofingerprint = cowdev->fingerprint;
-               cowdev->cowhead->cowused        = 0;
-
-               /*
-               ** calculate start offset of data in cowfile,
-               ** rounded up to multiple of 4K to avoid
-               ** unnecessary disk-usage for written datablocks in
-               ** the sparsed cowfile on e.g. 4K filesystems
-               */
-               cowdev->cowhead->doffset =
-                       ((MAPUNIT+cowdev->mapsize+4095)>>12)<<12;
-       }
-
-       cowdev->cowhead->flags  = 0;
-
-       DEBUGP(DCOW"cowloop - reserve space bitmap....\n");
-
-       /*
-       ** reserve space in memory for the entire bitmap and
-       ** fill it with the bitmap-data from disk; the entire
-       ** bitmap is allocated in several chunks because kmalloc
-       ** has restrictions regarding the allowed size per kmalloc
-       */
-       cowdev->mapcount = (cowdev->mapsize+MAPCHUNKSZ-1)/MAPCHUNKSZ;
-
-       /*
-       ** the size of every bitmap chunk will be MAPCHUNKSZ bytes, except for
-       ** the last bitmap chunk: calculate remaining size for this chunk
-       */
-       if (cowdev->mapsize % MAPCHUNKSZ == 0)
-               cowdev->mapremain = MAPCHUNKSZ;
-       else
-               cowdev->mapremain = cowdev->mapsize % MAPCHUNKSZ;
-
-       /*
-       ** allocate space to store all pointers for the bitmap-chunks
-       ** (initialize area with zeroes to allow proper undo)
-       */
-       cowdev->mapcache = kmalloc(cowdev->mapcount * sizeof(char *),
-                                                               GFP_KERNEL);
-       if (!cowdev->mapcache) {
-               printk(KERN_ERR
-                      "cowloop - can not allocate space for bitmap ptrs\n");
-               return -ENOMEM;
-       }
-
-       memset(cowdev->mapcache, 0, cowdev->mapcount * sizeof(char *));
-
-       /*
-       ** allocate space to store the bitmap-chunks themselves
-       */
-       for (i=0; i < cowdev->mapcount; i++) {
-               if (i < (cowdev->mapcount-1))
-                       *(cowdev->mapcache+i) = kmalloc(MAPCHUNKSZ, GFP_KERNEL);
-               else
-                       *(cowdev->mapcache+i) = kmalloc(cowdev->mapremain,
-                                                                 GFP_KERNEL);
-
-               if (*(cowdev->mapcache+i) == NULL) {
-                       printk(KERN_ERR "cowloop - no space for bitmapchunk %ld"
-                                       " totmapsz=%ld, mapcnt=%d mapunit=%d\n",
-                                       i, cowdev->mapsize, cowdev->mapcount,
-                                       MAPUNIT);
-                       return -ENOMEM;
-               }
-       }
-
-       DEBUGP(DCOW"cowloop - read bitmap from cow....\n");
-
-       /*
-       ** read the entire bitmap from the cowfile into the in-memory cache;
-       ** count the number of blocks that are in use already
-       ** (statistical purposes)
-       */
-       for (i=0, offset=MAPUNIT; i < cowdev->mapcount;
-                                       i++, offset+=MAPCHUNKSZ) {
-               unsigned long   numbytes;
-
-               if (i < (cowdev->mapcount-1))
-                       /*
-                       ** full bitmap chunk
-                       */
-                       numbytes = MAPCHUNKSZ;
-               else
-                       /*
-                       ** last bitmap chunk: might be partly filled
-                       */
-                       numbytes = cowdev->mapremain;
-
-               cowlo_readcowraw(cowdev, *(cowdev->mapcache+i),
-                                                       numbytes, offset);
-       }
-
-       /*
-       ** if the cowfile was dirty and automatic recovery is required,
-       ** reconstruct a proper bitmap in memory now
-       */
-       if (cowdev->cowhead->flags & COWDIRTY) {
-               unsigned long long      blocknum;
-               char                    databuf[MAPUNIT];
-               unsigned long           mapnum, mapbyte, mapbit;
-
-               printk(KERN_NOTICE "cowloop - recover dirty cowfile %s....\n",
-                                                       cowf);
-
-               /*
-               ** read all data blocks
-               */
-               for (blocknum=0, rv=1, offset=0;
-                       cowlo_readcow(cowdev, databuf, MAPUNIT, offset) > 0;
-                       blocknum++, offset += MAPUNIT) {
-
-                       /*
-                       ** if this datablock contains real data (not binary
-                       ** zeroes), set the corresponding bit in the bitmap
-                       */
-                       if ( memcmp(databuf, allzeroes, MAPUNIT) == 0)
-                               continue;
-
-                       mapnum  = CALCMAP (blocknum);
-                       mapbyte = CALCBYTE(blocknum);
-                       mapbit  = CALCBIT (blocknum);
-
-                       *(*(cowdev->mapcache+mapnum)+mapbyte) |= (1<<mapbit);
-               }
-
-               printk(KERN_NOTICE "cowloop - cowfile recovery completed\n");
-       }
-
-       /*
-       ** count all bits set in the bitmaps for statistical purposes
-       */
-       for (i=0, cowdev->nrcowblocks = 0; i < cowdev->mapcount; i++) {
-               long    numbytes;
-               char    *p;
-
-               if (i < (cowdev->mapcount-1))
-                       numbytes = MAPCHUNKSZ;
-               else
-                       numbytes = cowdev->mapremain;
-
-               p = *(cowdev->mapcache+i);
-
-               for (numbytes--; numbytes >= 0; numbytes--, p++) {
-                       /*
-                       ** for only eight checks the following construction
-                       ** is faster than a loop-construction
-                       */
-                       if ((*p) & 0x01)        cowdev->nrcowblocks++;
-                       if ((*p) & 0x02)        cowdev->nrcowblocks++;
-                       if ((*p) & 0x04)        cowdev->nrcowblocks++;
-                       if ((*p) & 0x08)        cowdev->nrcowblocks++;
-                       if ((*p) & 0x10)        cowdev->nrcowblocks++;
-                       if ((*p) & 0x20)        cowdev->nrcowblocks++;
-                       if ((*p) & 0x40)        cowdev->nrcowblocks++;
-                       if ((*p) & 0x80)        cowdev->nrcowblocks++;
-               }
-       }
-
-       /*
-       ** consistency-check for number of bits set in bitmap
-       */
-       if ( !(cowdev->cowhead->flags & COWDIRTY) &&
-           (cowdev->cowhead->cowused != cowdev->nrcowblocks) ) {
-               printk(KERN_ERR "cowloop - inconsistent cowfile admi\n");
-               return -EINVAL;
-       }
-
-       return 0;
-}
-
-/*
-** undo memory allocs and file opens issued so far
-** related to the cowfile
-*/
-static void
-cowlo_undo_opencow(struct cowloop_device *cowdev)
-{
-       int     i;
-
-       if (cowdev->mapcache) {
-               for (i=0; i < cowdev->mapcount; i++) {
-                       if (*(cowdev->mapcache+i) != NULL)
-                               kfree( *(cowdev->mapcache+i) );
-               }
-
-               kfree(cowdev->mapcache);
-       }
-
-       if (cowdev->cowhead)
-               kfree(cowdev->cowhead);
-
-       if ( (cowdev->state & COWCOWOPEN) && (cowdev->cowfp) )
-               filp_close(cowdev->cowfp, 0);
-
-       /*
-       ** mark cowfile closed
-       */
-       cowdev->state &= ~COWCOWOPEN;
-}
-
-/*
-** flush the entire bitmap and the cowhead (clean) to the cowfile
-**
-** must be called with the cowdevices-lock set
-*/
-static void
-cowlo_sync(void)
-{
-       int                     i, minor;
-       loff_t                  offset;
-       struct cowloop_device   *cowdev;
-
-       for (minor=0; minor < maxcows;  minor++) {
-               cowdev = cowdevall[minor];
-               if ( ! (cowdev->state & COWRWCOWOPEN) )
-                       continue;
-
-               for (i=0, offset=MAPUNIT; i < cowdev->mapcount;
-                                       i++, offset += MAPCHUNKSZ) {
-                       unsigned long   numbytes;
-
-                       if (i < (cowdev->mapcount-1))
-                               /*
-                               ** full bitmap chunk
-                               */
-                               numbytes = MAPCHUNKSZ;
-                       else
-                               /*
-                               ** last bitmap chunk: might be partly filled
-                               */
-                               numbytes = cowdev->mapremain;
-
-                       DEBUGP(DCOW
-                              "cowloop - flushing bitmap %2d (%3ld Kb)\n",
-                                                       i, numbytes/1024);
-
-                       if (cowlo_writecowraw(cowdev, *(cowdev->mapcache+i),
-                                               numbytes, offset) < numbytes) {
-                               break;
-                       }
-               }
-
-               /*
-               ** flush clean up-to-date cowhead to cowfile
-               */
-               cowdev->cowhead->cowused         = cowdev->nrcowblocks;
-               cowdev->cowhead->flags          &= ~COWDIRTY;
-
-               DEBUGP(DCOW "cowloop - flushing cowhead (%3d Kb)\n",
-                                                       MAPUNIT/1024);
-
-               cowlo_writecowraw(cowdev, cowdev->cowhead, MAPUNIT, (loff_t) 0);
-       }
-}
-
-/*****************************************************************************/
-/* Module loading/unloading                                                  */
-/*****************************************************************************/
-
-/*
-** called during insmod/modprobe
-*/
-static int __init
-cowlo_init_module(void)
-{
-       int     rv;
-       int     minor, uptocows;
-
-        revision[sizeof revision - 3] = '\0';
-
-        printk(KERN_NOTICE "cowloop - (C) 2009 ATComputing.nl - version: %s\n", &revision[11]);
-        printk(KERN_NOTICE "cowloop - info: www.ATComputing.nl/cowloop\n");
-
-       memset(allzeroes, 0, MAPUNIT);
-
-       /*
-       ** Setup administration for all possible cowdevices.
-        ** Note that their minor numbers go from 0 to MAXCOWS-1 inclusive
-        ** and minor == MAXCOWS-1 is reserved for the control device.
-       */
-       if ((maxcows < 1) || (maxcows > MAXCOWS)) {
-               printk(KERN_WARNING
-                      "cowloop - maxcows exceeds maximum of %d\n", MAXCOWS);
-
-                maxcows = DFLCOWS;
-        }
-
-       /* allocate room for a table with a pointer to each cowloop_device: */
-        if ( (cowdevall = kmalloc(maxcows * sizeof(struct cowloop_device *),
-                                                       GFP_KERNEL)) == NULL) {
-               printk(KERN_WARNING
-                       "cowloop - can not alloc table for %d devs\n", maxcows);
-               uptocows = 0;
-               rv = -ENOMEM;
-               goto error_out;
-       }
-       memset(cowdevall, 0, maxcows * sizeof(struct cowloop_device *));
-       /* then hook an actual cowloop_device struct to each pointer: */
-       for (minor=0; minor < maxcows; minor++) {
-               if ((cowdevall[minor] = kmalloc(sizeof(struct cowloop_device),
-                                               GFP_KERNEL)) == NULL) {
-                       printk(KERN_WARNING
-                          "cowloop - can not alloc admin-struct for dev no %d\n", minor);
-
-                       uptocows = minor; /* this is how far we got.... */
-                       rv = -ENOMEM;
-                       goto error_out;
-               }
-               memset(cowdevall[minor], 0, sizeof(struct cowloop_device));
-       }
-       uptocows = maxcows; /* we got all devices */
-
-       sema_init(&cowdevlock, 1);
-
-       /*
-       ** register cowloop module
-       */
-       if ( register_blkdev(COWMAJOR, DEVICE_NAME) < 0) {
-               printk(KERN_WARNING
-                   "cowloop - unable to get major %d for cowloop\n", COWMAJOR);
-               rv = -EIO;
-               goto error_out;
-       }
-
-       /*
-       ** create a directory below /proc to allocate a file
-       ** for each cowdevice that is allocated later on
-       */
-       cowlo_procdir = proc_mkdir("cow", NULL);
-
-       /*
-       ** check if a cowdevice has to be opened during insmod/modprobe;
-       ** two parameters should be specified then: rdofile= and cowfile=
-       */
-       if( (rdofile[0] != '\0') && (cowfile[0] != '\0') ) {
-               char    *po = option;
-               int     wantrecover = 0;
-
-               /*
-               ** check if automatic recovery is wanted
-               */
-               while (*po) {
-                       if (*po == 'r') {
-                               wantrecover = 1;
-                               break;
-                        }
-                       po++;
-               }
-
-               /*
-               ** open new cowdevice with minor number 0
-               */
-               if ( (rv = cowlo_openpair(rdofile, cowfile, wantrecover, 0))) {
-                       remove_proc_entry("cow", NULL);
-                       unregister_blkdev(COWMAJOR, DEVICE_NAME);
-                       goto error_out;
-               }
-        } else {
-               /*
-               ** check if only one parameter has been specified
-               */
-               if( (rdofile[0] != '\0') || (cowfile[0] != '\0') ) {
-                       printk(KERN_ERR
-                              "cowloop - only one filename specified\n");
-                       remove_proc_entry("cow", NULL);
-                       unregister_blkdev(COWMAJOR, DEVICE_NAME);
-                       rv = -EINVAL;
-                       goto error_out;
-               }
-       }
-
-       /*
-       ** allocate fake disk as control channel to handle the requests
-       ** to activate and deactivate cowdevices dynamically
-       */
-       if (!(cowctlgd = alloc_disk(1))) {
-               printk(KERN_WARNING
-                      "cowloop - unable to alloc_disk for cowctl\n");
-
-               remove_proc_entry("cow", NULL);
-               (void) cowlo_closepair(cowdevall[0]);
-               unregister_blkdev(COWMAJOR, DEVICE_NAME);
-               rv = -ENOMEM;
-               goto error_out;
-       }
-
-       spin_lock_init(&cowctlrqlock);
-       cowctlgd->major        = COWMAJOR;
-       cowctlgd->first_minor  = COWCTL;
-       cowctlgd->minors       = 1;
-       cowctlgd->fops         = &cowlo_fops;
-       cowctlgd->private_data = NULL;
-       /* the device has capacity 0, so there will be no q-requests */
-       cowctlgd->queue = blk_init_queue(NULL, &cowctlrqlock);
-       sprintf(cowctlgd->disk_name, "cowctl");
-       set_capacity(cowctlgd, 0);
-
-       add_disk(cowctlgd);
-
-        printk(KERN_NOTICE "cowloop - number of configured cowdevices: %d\n",
-                                                               maxcows);
-       if (rdofile[0] != '\0') {
-           printk(KERN_NOTICE "cowloop - initialized on rdofile=%s\n",
-                                                               rdofile);
-       } else {
-           printk(KERN_NOTICE "cowloop - initialized without rdofile yet\n");
-       }
-       return 0;
-
-error_out:
-       for (minor=0; minor < uptocows ; minor++) {
-               kfree(cowdevall[minor]);
-       }
-       kfree(cowdevall);
-       return rv;
-}
-
-/*
-** called during rmmod
-*/
-static void __exit
-cowlo_cleanup_module(void)
-{
-       int     minor;
-
-       /*
-       ** flush bitmaps and cowheads to the cowfiles
-       */
-       down(&cowdevlock);
-       cowlo_sync();
-       up(&cowdevlock);
-
-       /*
-       ** close all cowdevices
-       */
-       for (minor=0; minor < maxcows;  minor++)
-               (void) cowlo_closepair(cowdevall[minor]);
-
-       unregister_blkdev(COWMAJOR, DEVICE_NAME);
-
-       /*
-       ** get rid of /proc/cow and unregister the driver
-       */
-       remove_proc_entry("cow", NULL);
-
-       for (minor = 0; minor < maxcows; minor++) {
-               kfree(cowdevall[minor]);
-       }
-       kfree(cowdevall);
-
-       del_gendisk(cowctlgd);  /* revert the alloc_disk() */
-       put_disk   (cowctlgd);  /* revert the add_disk()   */
-       blk_cleanup_queue(cowctlgd->queue); /* cleanup the empty queue */
-
-       printk(KERN_NOTICE "cowloop - unloaded\n");
-}
-
-module_init(cowlo_init_module);
-module_exit(cowlo_cleanup_module);
diff --git a/drivers/staging/cowloop/cowloop.h b/drivers/staging/cowloop/cowloop.h
deleted file mode 100644 (file)
index bbd4a35..0000000
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
-** DO NOT MODIFY THESE VALUES (would make old cowfiles unusable)
-*/
-#define        MAPUNIT         1024            /* blocksize for bit in bitmap       */
-#define        MUSHIFT         10              /* bitshift  for bit in bitmap       */
-#define        MUMASK          0x3ff           /* bitmask   for bit in bitmap       */
-
-#define        COWMAGIC        0x574f437f      /* byte-swapped '7f C O W'           */
-#define        COWDIRTY        0x01
-#define        COWPACKED       0x02
-#define        COWVERSION      1
-
-struct cowhead
-{
-       int             magic;          /* identifies a cowfile              */
-       short           version;        /* version of cowhead                */
-       short           flags;          /* flags indicating status           */
-       unsigned long   mapunit;        /* blocksize per bit in bitmap       */
-       unsigned long   mapsize;        /* total size of bitmap (bytes)      */
-       unsigned long   doffset;        /* start-offset datablocks in cow    */
-       unsigned long   rdoblocks;      /* size of related read-only file    */
-       unsigned long   rdofingerprint; /* fingerprint of read-only file     */
-       unsigned long   cowused;        /* number of datablocks used in cow  */
-};
-
-#define COWDEVDIR      "/dev/cow/"
-#define COWDEVICE      COWDEVDIR "%ld"
-#define COWCONTROL     COWDEVDIR "ctl"
-
-#define MAXCOWS                1024
-#define COWCTL         (MAXCOWS-1)     /* minor number of /dev/cow/ctl     */
-
-#define COWPROCDIR     "/proc/cow/"
-#define COWPROCFILE    COWPROCDIR "%d"
-
-/*
-** ioctl related stuff
-*/
-#define ANYDEV         ((unsigned long)-1)
-
-struct cowpair
-{
-       unsigned char   *rdofile;       /* pathname of the rdofile           */
-       unsigned char   *cowfile;       /* pathname of the cowfile           */
-       unsigned short  rdoflen;        /* length of rdofile pathname        */
-       unsigned short  cowflen;        /* length of cowfile pathname        */
-       unsigned long   device;         /* requested/returned device number  */
-};
-
-struct cowwatch
-{
-       int             flags;          /* request flags                     */
-       unsigned long   device;         /* requested device number           */
-       unsigned long   threshold;      /* continue if free Kb < threshold   */
-       unsigned long   totalkb;        /* ret: total filesystem size (Kb)   */
-       unsigned long   availkb;        /* ret: free  filesystem size (Kb)   */
-};
-
-#define        WATCHWAIT       0x01            /* block until threshold reached     */
-
-#define        COWSYNC         _IO  ('C', 1)
-#define        COWMKPAIR       _IOW ('C', 2, struct cowpair)
-#define        COWRMPAIR       _IOW ('C', 3, unsigned long)
-#define        COWWATCH        _IOW ('C', 4, struct cowwatch)
-#define        COWCLOSE        _IOW ('C', 5, unsigned long)
-#define        COWRDOPEN       _IOW ('C', 6, unsigned long)
index 6294d38..2c3d65a 100644 (file)
@@ -223,7 +223,7 @@ typedef union _TXDMA_PR_NUM_DES_t {
 
 extern inline void add_10bit(u32 *v, int n)
 {
-       *v = INDEX10(*v + n);
+       *v = INDEX10(*v + n) | (*v & ET_DMA10_WRAP);
 }
 
 /*
index 8f2e91f..10e21db 100644 (file)
@@ -1177,12 +1177,20 @@ void et131x_handle_recv_interrupt(struct et131x_adapter *etdev)
 
 static inline u32 bump_fbr(u32 *fbr, u32 limit)
 {
-       u32 v = *fbr;
-       add_10bit(&v, 1);
-       if (v > limit)
-               v = (*fbr & ~ET_DMA10_MASK) ^ ET_DMA10_WRAP;
-       *fbr = v;
-       return v;
+        u32 v = *fbr;
+        v++;
+        /* This works for all cases where limit < 1024. The 1023 case
+           works because 1023++ is 1024 which means the if condition is not
+           taken but the carry of the bit into the wrap bit toggles the wrap
+           value correctly */
+        if ((v & ET_DMA10_MASK) > limit) {
+                v &= ~ET_DMA10_MASK;
+                v ^= ET_DMA10_WRAP;
+        }
+        /* For the 1023 case */
+        v &= (ET_DMA10_MASK|ET_DMA10_WRAP);
+        *fbr = v;
+        return v;
 }
 
 /**
index a839d8f..fa973d8 100644 (file)
@@ -26,6 +26,7 @@
 #define _CHANNEL_MGMT_H_
 
 #include <linux/list.h>
+#include <linux/timer.h>
 #include "RingBuffer.h"
 #include "VmbusChannelInterface.h"
 #include "VmbusPacketFormat.h"
@@ -54,7 +55,7 @@ enum vmbus_channel_message_type {
        ChannelMessageViewRangeRemove           = 18,
 #endif
        ChannelMessageCount
-} __attribute__((packed));
+};
 
 struct vmbus_channel_message_header {
        enum vmbus_channel_message_type MessageType;
index 1610b84..d384c0d 100644 (file)
@@ -1052,7 +1052,7 @@ static void NetVscOnReceive(struct hv_device *Device,
         */
        spin_lock_irqsave(&netDevice->receive_packet_list_lock, flags);
        while (!list_empty(&netDevice->ReceivePacketList)) {
-               list_move_tail(&netDevice->ReceivePacketList, &listHead);
+               list_move_tail(netDevice->ReceivePacketList.next, &listHead);
                if (++count == vmxferpagePacket->RangeCount + 1)
                        break;
        }
@@ -1071,7 +1071,7 @@ static void NetVscOnReceive(struct hv_device *Device,
                /* Return it to the freelist */
                spin_lock_irqsave(&netDevice->receive_packet_list_lock, flags);
                for (i = count; i != 0; i--) {
-                       list_move_tail(&listHead,
+                       list_move_tail(listHead.next,
                                       &netDevice->ReceivePacketList);
                }
                spin_unlock_irqrestore(&netDevice->receive_packet_list_lock,
@@ -1085,8 +1085,7 @@ static void NetVscOnReceive(struct hv_device *Device,
        }
 
        /* Remove the 1st packet to represent the xfer page packet itself */
-       xferpagePacket = list_entry(&listHead, struct xferpage_packet,
-                                   ListEntry);
+       xferpagePacket = (struct xferpage_packet*)listHead.next;
        list_del(&xferpagePacket->ListEntry);
 
        /* This is how much we can satisfy */
@@ -1102,8 +1101,7 @@ static void NetVscOnReceive(struct hv_device *Device,
 
        /* Each range represents 1 RNDIS pkt that contains 1 ethernet frame */
        for (i = 0; i < (count - 1); i++) {
-               netvscPacket = list_entry(&listHead, struct hv_netvsc_packet,
-                                         ListEntry);
+               netvscPacket = (struct hv_netvsc_packet*)listHead.next;
                list_del(&netvscPacket->ListEntry);
 
                /* Initialize the netvsc packet */
index 4d390b2..dbfbde9 100644 (file)
@@ -1,11 +1,17 @@
 TODO:
        - fix remaining checkpatch warnings and errors
+       - use of /** when it is not a kerneldoc header
        - remove RingBuffer.c to us in-kernel ringbuffer functions instead.
        - audit the vmbus to verify it is working properly with the
          driver model
+       - convert vmbus driver interface function pointer tables
+          to constant, a.k.a vmbus_ops
        - see if the vmbus can be merged with the other virtual busses
          in the kernel
        - audit the network driver
+         - use existing net_device_stats struct in network device
+         - checking for carrier inside open is wrong, network device API
+            confusion??
        - audit the block driver
        - audit the scsi driver
 
index 8fe543b..3a4793a 100644 (file)
@@ -30,6 +30,7 @@
 #include <linux/ioport.h>
 #include <linux/irq.h>
 #include <linux/interrupt.h>
+#include <linux/sched.h>
 #include <linux/wait.h>
 #include <linux/spinlock.h>
 #include <linux/workqueue.h>
index 9504604..ce064e8 100644 (file)
@@ -25,6 +25,7 @@
 #ifndef _OSD_H_
 #define _OSD_H_
 
+#include <linux/workqueue.h>
 
 /* Defines */
 #define ALIGN_UP(value, align) (((value) & (align-1)) ?                \
index 582318f..894eecf 100644 (file)
@@ -507,12 +507,12 @@ static struct hv_device *vmbus_child_device_create(struct hv_guid *type,
 
        child_device_obj = &child_device_ctx->device_obj;
        child_device_obj->context = context;
-       memcpy(&child_device_obj->deviceType, &type, sizeof(struct hv_guid));
-       memcpy(&child_device_obj->deviceInstance, &instance,
+       memcpy(&child_device_obj->deviceType, type, sizeof(struct hv_guid));
+       memcpy(&child_device_obj->deviceInstance, instance,
               sizeof(struct hv_guid));
 
-       memcpy(&child_device_ctx->class_id, &type, sizeof(struct hv_guid));
-       memcpy(&child_device_ctx->device_id, &instance, sizeof(struct hv_guid));
+       memcpy(&child_device_ctx->class_id, type, sizeof(struct hv_guid));
+       memcpy(&child_device_ctx->device_id, instance, sizeof(struct hv_guid));
 
        DPRINT_EXIT(VMBUS_DRV);
 
@@ -537,18 +537,7 @@ static int vmbus_child_device_register(struct hv_device *root_device_obj,
        DPRINT_DBG(VMBUS_DRV, "child device (%p) registering",
                   child_device_ctx);
 
-       /* Make sure we are not registered already */
-       if (strlen(dev_name(&child_device_ctx->device)) != 0) {
-               DPRINT_ERR(VMBUS_DRV,
-                          "child device (%p) already registered - busid %s",
-                          child_device_ctx,
-                          dev_name(&child_device_ctx->device));
-
-               ret = -1;
-               goto Cleanup;
-       }
-
-       /* Set the device bus id. Otherwise, device_register()will fail. */
+       /* Set the device name. Otherwise, device_register() will fail. */
        dev_set_name(&child_device_ctx->device, "vmbus_0_%d",
                     atomic_inc_return(&device_num));
 
@@ -573,7 +562,6 @@ static int vmbus_child_device_register(struct hv_device *root_device_obj,
                DPRINT_INFO(VMBUS_DRV, "child device (%p) registered",
                            &child_device_ctx->device);
 
-Cleanup:
        DPRINT_EXIT(VMBUS_DRV);
 
        return ret;
@@ -623,8 +611,6 @@ static void vmbus_child_device_destroy(struct hv_device *device_obj)
 static int vmbus_uevent(struct device *device, struct kobj_uevent_env *env)
 {
        struct device_context *device_ctx = device_to_device_context(device);
-       int i = 0;
-       int len = 0;
        int ret;
 
        DPRINT_ENTER(VMBUS_DRV);
@@ -644,8 +630,6 @@ static int vmbus_uevent(struct device *device, struct kobj_uevent_env *env)
                    device_ctx->class_id.data[14],
                    device_ctx->class_id.data[15]);
 
-       env->envp_idx = i;
-       env->buflen = len;
        ret = add_uevent_var(env, "VMBUS_DEVICE_CLASS_GUID={"
                             "%02x%02x%02x%02x-%02x%02x-%02x%02x-"
                             "%02x%02x%02x%02x%02x%02x%02x%02x}",
@@ -691,8 +675,6 @@ static int vmbus_uevent(struct device *device, struct kobj_uevent_env *env)
        if (ret)
                return ret;
 
-       env->envp[env->envp_idx] = NULL;
-
        DPRINT_EXIT(VMBUS_DRV);
 
        return 0;
index beb99a5..4586650 100644 (file)
@@ -4,6 +4,7 @@
 
 menuconfig IIO
        tristate "Industrial I/O support"
+       depends on !S390
        ---help---
          The industrial I/O subsystem provides a unified framework for
          drivers for many different types of embedded sensors using a
index 1fa18f2..768f448 100644 (file)
@@ -18,6 +18,8 @@
 #include <linux/fs.h>
 #include <linux/interrupt.h>
 #include <linux/poll.h>
+#include <linux/sched.h>
+#include <linux/wait.h>
 #include <linux/cdev.h>
 #include "iio.h"
 #include "trigger_consumer.h"
index d549d08..f6cc262 100644 (file)
@@ -1,6 +1,6 @@
 config OTUS
        tristate "Atheros OTUS 802.11n USB wireless support"
-       depends on USB && WLAN_80211 && MAC80211
+       depends on USB && WLAN && MAC80211
        default N
        ---help---
          Enable support for Atheros 802.11n USB hardware:
index 9111dcb..8ccfff7 100644 (file)
@@ -183,7 +183,7 @@ static ssize_t cap_write(struct file *filp, const char __user *buf,
        user_buf_running = NULL;
        hash_str = NULL;
        node_ptr = kmalloc(sizeof(struct cap_node), GFP_KERNEL);
-       user_buf = kzalloc(count, GFP_KERNEL);
+       user_buf = kzalloc(count+1, GFP_KERNEL);
        if (!node_ptr || !user_buf)
                goto out;
 
@@ -207,6 +207,7 @@ static ssize_t cap_write(struct file *filp, const char __user *buf,
                list_add(&(node_ptr->list), &(dev->head->list));
                node_ptr = NULL;
        } else {
+               char *tmpu;
                if (!cap_devices[0].head ||
                                list_empty(&(cap_devices[0].head->list))) {
                        retval = -EINVAL;
@@ -218,10 +219,10 @@ static ssize_t cap_write(struct file *filp, const char __user *buf,
                 * need to split it and hash 'user1@user2' using 'randomstring'
                 * as the key.
                 */
-               user_buf_running = kstrdup(user_buf, GFP_KERNEL);
-               source_user = strsep(&user_buf_running, "@");
-               target_user = strsep(&user_buf_running, "@");
-               rand_str = strsep(&user_buf_running, "@");
+               tmpu = user_buf_running = kstrdup(user_buf, GFP_KERNEL);
+               source_user = strsep(&tmpu, "@");
+               target_user = strsep(&tmpu, "@");
+               rand_str = tmpu;
                if (!source_user || !target_user || !rand_str) {
                        retval = -EINVAL;
                        goto out;
@@ -229,7 +230,8 @@ static ssize_t cap_write(struct file *filp, const char __user *buf,
 
                /* hash the string user1@user2 with rand_str as the key */
                len = strlen(source_user) + strlen(target_user) + 1;
-               hash_str = kzalloc(len, GFP_KERNEL);
+               /* src, @, len, \0 */
+               hash_str = kzalloc(len+1, GFP_KERNEL);
                strcat(hash_str, source_user);
                strcat(hash_str, "@");
                strcat(hash_str, target_user);
index dd7d3fd..4ce399b 100644 (file)
@@ -2071,11 +2071,15 @@ static void panel_detach(struct parport *port)
                return;
        }
 
-       if (keypad_enabled && keypad_initialized)
+       if (keypad_enabled && keypad_initialized) {
                misc_deregister(&keypad_dev);
+               keypad_initialized = 0;
+       }
 
-       if (lcd_enabled && lcd_initialized)
+       if (lcd_enabled && lcd_initialized) {
                misc_deregister(&lcd_dev);
+               lcd_initialized = 0;
+       }
 
        parport_release(pprt);
        parport_unregister_device(pprt);
@@ -2211,13 +2215,16 @@ static void __exit panel_cleanup_module(void)
                del_timer(&scan_timer);
 
        if (pprt != NULL) {
-               if (keypad_enabled)
+               if (keypad_enabled) {
                        misc_deregister(&keypad_dev);
+                       keypad_initialized = 0;
+               }
 
                if (lcd_enabled) {
                        panel_lcd_print("\x0cLCD driver " PANEL_VERSION
                                        "\nunloaded.\x1b[Lc\x1b[Lb\x1b[L-");
                        misc_deregister(&lcd_dev);
+                       lcd_initialized = 0;
                }
 
                /* TODO: free all input signals */
index 0d111dd..2eb8e3d 100644 (file)
@@ -20,6 +20,7 @@
 #include <linux/init.h>
 #include <linux/ioctl.h>
 #include <linux/io.h>
+#include <linux/sched.h>
 
 #include "poch.h"
 
index 7f44e5e..efe38e2 100644 (file)
@@ -1,5 +1,5 @@
 config RT2860
        tristate "Ralink 2860 wireless support"
-       depends on PCI && X86 && WLAN_80211
+       depends on PCI && X86 && WLAN
        ---help---
          This is an experimental driver for the Ralink 2860 wireless chip.
index fb17355..857ff45 100644 (file)
@@ -363,6 +363,8 @@ int RtmpPCIMgmtKickOut(
        ULONG                   SwIdx = pAd->MgmtRing.TxCpuIdx;
 
        pTxD  = (PTXD_STRUC) pAd->MgmtRing.Cell[SwIdx].AllocVa;
+       if (!pTxD)
+               return 0;
 
        pAd->MgmtRing.Cell[SwIdx].pNdisPacket = pPacket;
        pAd->MgmtRing.Cell[SwIdx].pNextNdisPacket = NULL;
index 9d589c2..019cc44 100644 (file)
@@ -25,6 +25,7 @@
  *************************************************************************
 */
 
+#include <linux/sched.h>
 #include "../rt_config.h"
 
 INT    Show_SSID_Proc(
index b396a9b..ed27b85 100644 (file)
@@ -25,6 +25,7 @@
  *************************************************************************
  */
 
+#include <linux/sched.h>
 #include "rt_config.h"
 
 ULONG  RTDebugLevel = RT_DEBUG_ERROR;
index 76841f6..aea5c82 100644 (file)
@@ -1,5 +1,5 @@
 config RT2870
        tristate "Ralink 2870/3070 wireless support"
-       depends on USB && X86 && WLAN_80211
+       depends on USB && X86 && WLAN
        ---help---
          This is an experimental driver for the Ralink xx70 wireless chips.
index 255e8ea..2b3f745 100644 (file)
@@ -1,5 +1,5 @@
 config RT3090
        tristate "Ralink 3090 wireless support"
-       depends on PCI && X86 && WLAN_80211
+       depends on PCI && X86 && WLAN
        ---help---
          This is an experimental driver for the Ralink 3090 wireless chip.
index 5be0714..3e51e98 100644 (file)
@@ -34,6 +34,7 @@
     ---------    ----------    ----------------------------------------------
  */
 
+#include <linux/sched.h>
 #include "../rt_config.h"
 
 
index d2241ec..9b94aa6 100644 (file)
@@ -25,6 +25,7 @@
  *************************************************************************
  */
 
+#include <linux/sched.h>
 #include "rt_config.h"
 
 ULONG  RTDebugLevel = RT_DEBUG_ERROR;
index 236e427..203c79b 100644 (file)
@@ -1,6 +1,6 @@
 config RTL8187SE
        tristate "RealTek RTL8187SE Wireless LAN NIC driver"
-       depends on PCI
+       depends on PCI && WLAN
        depends on WIRELESS_EXT
        default N
        ---help---
index 013c3e1..4c5d63f 100644 (file)
@@ -53,10 +53,8 @@ void ieee80211_crypt_deinit_entries(struct ieee80211_device *ieee,
 
                list_del(ptr);
 
-               if (entry->ops) {
+               if (entry->ops)
                        entry->ops->deinit(entry->priv);
-                       module_put(entry->ops->owner);
-               }
                kfree(entry);
        }
 }
index 6fbe489..18392fc 100644 (file)
@@ -189,10 +189,8 @@ void free_ieee80211(struct net_device *dev)
        for (i = 0; i < WEP_KEYS; i++) {
                struct ieee80211_crypt_data *crypt = ieee->crypt[i];
                if (crypt) {
-                       if (crypt->ops) {
+                       if (crypt->ops)
                                crypt->ops->deinit(crypt->priv);
-                               module_put(crypt->ops->owner);
-                       }
                        kfree(crypt);
                        ieee->crypt[i] = NULL;
                }
index 59b2ab4..334e4c7 100644 (file)
@@ -2839,16 +2839,12 @@ static int ieee80211_wpa_set_encryption(struct ieee80211_device *ieee,
                goto skip_host_crypt;
 
        ops = ieee80211_get_crypto_ops(param->u.crypt.alg);
-       if (ops == NULL && strcmp(param->u.crypt.alg, "WEP") == 0) {
-               request_module("ieee80211_crypt_wep");
+       if (ops == NULL && strcmp(param->u.crypt.alg, "WEP") == 0)
                ops = ieee80211_get_crypto_ops(param->u.crypt.alg);
-       } else if (ops == NULL && strcmp(param->u.crypt.alg, "TKIP") == 0) {
-               request_module("ieee80211_crypt_tkip");
+       else if (ops == NULL && strcmp(param->u.crypt.alg, "TKIP") == 0)
                ops = ieee80211_get_crypto_ops(param->u.crypt.alg);
-       } else if (ops == NULL && strcmp(param->u.crypt.alg, "CCMP") == 0) {
-               request_module("ieee80211_crypt_ccmp");
+       else if (ops == NULL && strcmp(param->u.crypt.alg, "CCMP") == 0)
                ops = ieee80211_get_crypto_ops(param->u.crypt.alg);
-       }
        if (ops == NULL) {
                printk("unknown crypto alg '%s'\n", param->u.crypt.alg);
                param->u.crypt.err = IEEE_CRYPT_ERR_UNKNOWN_ALG;
@@ -2869,7 +2865,7 @@ static int ieee80211_wpa_set_encryption(struct ieee80211_device *ieee,
                }
                memset(new_crypt, 0, sizeof(struct ieee80211_crypt_data));
                new_crypt->ops = ops;
-               if (new_crypt->ops && try_module_get(new_crypt->ops->owner))
+               if (new_crypt->ops)
                        new_crypt->priv =
                                new_crypt->ops->init(param->u.crypt.idx);
 
index 8d8bdd0..a08b97a 100644 (file)
@@ -331,12 +331,10 @@ int ieee80211_wx_set_encode(struct ieee80211_device *ieee,
                        return -ENOMEM;
                memset(new_crypt, 0, sizeof(struct ieee80211_crypt_data));
                new_crypt->ops = ieee80211_get_crypto_ops("WEP");
-               if (!new_crypt->ops) {
-                       request_module("ieee80211_crypt_wep");
+               if (!new_crypt->ops)
                        new_crypt->ops = ieee80211_get_crypto_ops("WEP");
-               }
 
-               if (new_crypt->ops && try_module_get(new_crypt->ops->owner))
+               if (new_crypt->ops)
                        new_crypt->priv = new_crypt->ops->init(key);
 
                if (!new_crypt->ops || !new_crypt->priv) {
@@ -483,7 +481,7 @@ int ieee80211_wx_set_encode_ext(struct ieee80211_device *ieee,
         struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
         int i, idx, ret = 0;
         int group_key = 0;
-        const char *alg, *module;
+        const char *alg;
         struct ieee80211_crypto_ops *ops;
         struct ieee80211_crypt_data **crypt;
 
@@ -539,15 +537,12 @@ int ieee80211_wx_set_encode_ext(struct ieee80211_device *ieee,
         switch (ext->alg) {
         case IW_ENCODE_ALG_WEP:
                 alg = "WEP";
-                module = "ieee80211_crypt_wep";
                 break;
         case IW_ENCODE_ALG_TKIP:
                 alg = "TKIP";
-                module = "ieee80211_crypt_tkip";
                 break;
         case IW_ENCODE_ALG_CCMP:
                 alg = "CCMP";
-                module = "ieee80211_crypt_ccmp";
                 break;
         default:
                 IEEE80211_DEBUG_WX("%s: unknown crypto alg %d\n",
@@ -558,10 +553,8 @@ int ieee80211_wx_set_encode_ext(struct ieee80211_device *ieee,
 //     printk("8-09-08-9=====>%s, alg name:%s\n",__func__, alg);
 
         ops = ieee80211_get_crypto_ops(alg);
-        if (ops == NULL) {
-                request_module(module);
+        if (ops == NULL)
                 ops = ieee80211_get_crypto_ops(alg);
-        }
         if (ops == NULL) {
                 IEEE80211_DEBUG_WX("%s: unknown crypto alg %d\n",
                                    dev->name, ext->alg);
@@ -581,7 +574,7 @@ int ieee80211_wx_set_encode_ext(struct ieee80211_device *ieee,
                         goto done;
                 }
                 new_crypt->ops = ops;
-                if (new_crypt->ops && try_module_get(new_crypt->ops->owner))
+                if (new_crypt->ops)
                         new_crypt->priv = new_crypt->ops->init(idx);
                 if (new_crypt->priv == NULL) {
                         kfree(new_crypt);
index 3100aa5..37e4fde 100644 (file)
@@ -1,6 +1,6 @@
 config RTL8192E
        tristate "RealTek RTL8192E Wireless LAN NIC driver"
-       depends on PCI
+       depends on PCI && WLAN
        depends on WIRELESS_EXT
        default N
        ---help---
index 1a8ea8a..b1c5493 100644 (file)
@@ -53,14 +53,8 @@ void ieee80211_crypt_deinit_entries(struct ieee80211_device *ieee,
 
                list_del(ptr);
 
-               if (entry->ops) {
+               if (entry->ops)
                        entry->ops->deinit(entry->priv);
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
-                       module_put(entry->ops->owner);
-#else
-                       __MOD_DEC_USE_COUNT(entry->ops->owner);
-#endif
-               }
                kfree(entry);
        }
 }
index 16256a3..12c2a18 100644 (file)
@@ -242,14 +242,8 @@ void free_ieee80211(struct net_device *dev)
        for (i = 0; i < WEP_KEYS; i++) {
                struct ieee80211_crypt_data *crypt = ieee->crypt[i];
                if (crypt) {
-                       if (crypt->ops) {
+                       if (crypt->ops)
                                crypt->ops->deinit(crypt->priv);
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
-                               module_put(crypt->ops->owner);
-#else
-                               __MOD_DEC_USE_COUNT(crypt->ops->owner);
-#endif
-                       }
                        kfree(crypt);
                        ieee->crypt[i] = NULL;
                }
index 2fc04df..eae7c45 100644 (file)
@@ -3284,17 +3284,14 @@ static int ieee80211_wpa_set_encryption(struct ieee80211_device *ieee,
                goto skip_host_crypt;
 
        ops = ieee80211_get_crypto_ops(param->u.crypt.alg);
-       if (ops == NULL && strcmp(param->u.crypt.alg, "WEP") == 0) {
-               request_module("ieee80211_crypt_wep");
+       if (ops == NULL && strcmp(param->u.crypt.alg, "WEP") == 0)
                ops = ieee80211_get_crypto_ops(param->u.crypt.alg);
-               //set WEP40 first, it will be modified according to WEP104 or WEP40 at other place
-       } else if (ops == NULL && strcmp(param->u.crypt.alg, "TKIP") == 0) {
-               request_module("ieee80211_crypt_tkip");
+               /* set WEP40 first, it will be modified according to WEP104 or
+                * WEP40 at other place */
+       else if (ops == NULL && strcmp(param->u.crypt.alg, "TKIP") == 0)
                ops = ieee80211_get_crypto_ops(param->u.crypt.alg);
-       } else if (ops == NULL && strcmp(param->u.crypt.alg, "CCMP") == 0) {
-               request_module("ieee80211_crypt_ccmp");
+       else if (ops == NULL && strcmp(param->u.crypt.alg, "CCMP") == 0)
                ops = ieee80211_get_crypto_ops(param->u.crypt.alg);
-       }
        if (ops == NULL) {
                printk("unknown crypto alg '%s'\n", param->u.crypt.alg);
                param->u.crypt.err = IEEE_CRYPT_ERR_UNKNOWN_ALG;
@@ -3315,11 +3312,7 @@ static int ieee80211_wpa_set_encryption(struct ieee80211_device *ieee,
                }
                memset(new_crypt, 0, sizeof(struct ieee80211_crypt_data));
                new_crypt->ops = ops;
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
-               if (new_crypt->ops && try_module_get(new_crypt->ops->owner))
-#else
-               if (new_crypt->ops && try_inc_mod_count(new_crypt->ops->owner))
-#endif
+               if (new_crypt->ops)
                        new_crypt->priv =
                                new_crypt->ops->init(param->u.crypt.idx);
 
index 2234831..4e34a1f 100644 (file)
@@ -482,15 +482,9 @@ int ieee80211_wx_set_encode(struct ieee80211_device *ieee,
                        return -ENOMEM;
                memset(new_crypt, 0, sizeof(struct ieee80211_crypt_data));
                new_crypt->ops = ieee80211_get_crypto_ops("WEP");
-               if (!new_crypt->ops) {
-                       request_module("ieee80211_crypt_wep");
+               if (!new_crypt->ops)
                        new_crypt->ops = ieee80211_get_crypto_ops("WEP");
-               }
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
-               if (new_crypt->ops && try_module_get(new_crypt->ops->owner))
-#else
-               if (new_crypt->ops && try_inc_mod_count(new_crypt->ops->owner))
-#endif
+               if (new_crypt->ops)
                        new_crypt->priv = new_crypt->ops->init(key);
 
                if (!new_crypt->ops || !new_crypt->priv) {
@@ -644,7 +638,7 @@ int ieee80211_wx_set_encode_ext(struct ieee80211_device *ieee,
         struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
         int i, idx;
         int group_key = 0;
-        const char *alg, *module;
+        const char *alg;
         struct ieee80211_crypto_ops *ops;
         struct ieee80211_crypt_data **crypt;
 
@@ -711,15 +705,12 @@ int ieee80211_wx_set_encode_ext(struct ieee80211_device *ieee,
         switch (ext->alg) {
         case IW_ENCODE_ALG_WEP:
                 alg = "WEP";
-                module = "ieee80211_crypt_wep";
                 break;
         case IW_ENCODE_ALG_TKIP:
                 alg = "TKIP";
-                module = "ieee80211_crypt_tkip";
                 break;
         case IW_ENCODE_ALG_CCMP:
                 alg = "CCMP";
-                module = "ieee80211_crypt_ccmp";
                 break;
         default:
                 IEEE80211_DEBUG_WX("%s: unknown crypto alg %d\n",
@@ -730,10 +721,8 @@ int ieee80211_wx_set_encode_ext(struct ieee80211_device *ieee,
        printk("alg name:%s\n",alg);
 
         ops = ieee80211_get_crypto_ops(alg);
-        if (ops == NULL) {
-                request_module(module);
+        if (ops == NULL)
                 ops = ieee80211_get_crypto_ops(alg);
-        }
         if (ops == NULL) {
                 IEEE80211_DEBUG_WX("%s: unknown crypto alg %d\n",
                                    dev->name, ext->alg);
@@ -758,7 +747,7 @@ int ieee80211_wx_set_encode_ext(struct ieee80211_device *ieee,
                         goto done;
                 }
                 new_crypt->ops = ops;
-                if (new_crypt->ops && try_module_get(new_crypt->ops->owner))
+                if (new_crypt->ops)
                         new_crypt->priv = new_crypt->ops->init(idx);
                 if (new_crypt->priv == NULL) {
                         kfree(new_crypt);
index d4fa654..b0802a7 100644 (file)
@@ -46,6 +46,7 @@
 #undef DEBUG_TX_DESC
 
 //#define CONFIG_RTL8192_IO_MAP
+#include <linux/vmalloc.h>
 #include <asm/uaccess.h>
 #include "r8192E_hw.h"
 #include "r8192E.h"
index 770f412..b8c95f9 100644 (file)
@@ -1,6 +1,6 @@
 config RTL8192SU
        tristate "RealTek RTL8192SU Wireless LAN NIC driver"
-       depends on PCI
+       depends on PCI && WLAN
        depends on WIRELESS_EXT
        default N
        ---help---
index d76a54d..521e7b9 100644 (file)
@@ -53,10 +53,8 @@ void ieee80211_crypt_deinit_entries(struct ieee80211_device *ieee,
 
                list_del(ptr);
 
-               if (entry->ops) {
+               if (entry->ops)
                        entry->ops->deinit(entry->priv);
-                       module_put(entry->ops->owner);
-               }
                kfree(entry);
        }
 }
index 68dc8fa..c3383bb 100644 (file)
@@ -216,10 +216,8 @@ void free_ieee80211(struct net_device *dev)
        for (i = 0; i < WEP_KEYS; i++) {
                struct ieee80211_crypt_data *crypt = ieee->crypt[i];
                if (crypt) {
-                       if (crypt->ops) {
+                       if (crypt->ops)
                                crypt->ops->deinit(crypt->priv);
-                               module_put(crypt->ops->owner);
-                       }
                        kfree(crypt);
                        ieee->crypt[i] = NULL;
                }
index c64ae03..fd8e112 100644 (file)
@@ -3026,17 +3026,14 @@ static int ieee80211_wpa_set_encryption(struct ieee80211_device *ieee,
                goto skip_host_crypt;
 
        ops = ieee80211_get_crypto_ops(param->u.crypt.alg);
-       if (ops == NULL && strcmp(param->u.crypt.alg, "WEP") == 0) {
-               request_module("ieee80211_crypt_wep");
+       if (ops == NULL && strcmp(param->u.crypt.alg, "WEP") == 0)
                ops = ieee80211_get_crypto_ops(param->u.crypt.alg);
-               //set WEP40 first, it will be modified according to WEP104 or WEP40 at other place
-       } else if (ops == NULL && strcmp(param->u.crypt.alg, "TKIP") == 0) {
-               request_module("ieee80211_crypt_tkip");
+               /* set WEP40 first, it will be modified according to WEP104 or
+                * WEP40 at other place */
+       else if (ops == NULL && strcmp(param->u.crypt.alg, "TKIP") == 0)
                ops = ieee80211_get_crypto_ops(param->u.crypt.alg);
-       } else if (ops == NULL && strcmp(param->u.crypt.alg, "CCMP") == 0) {
-               request_module("ieee80211_crypt_ccmp");
+       else if (ops == NULL && strcmp(param->u.crypt.alg, "CCMP") == 0)
                ops = ieee80211_get_crypto_ops(param->u.crypt.alg);
-       }
        if (ops == NULL) {
                printk("unknown crypto alg '%s'\n", param->u.crypt.alg);
                param->u.crypt.err = IEEE_CRYPT_ERR_UNKNOWN_ALG;
@@ -3058,7 +3055,7 @@ static int ieee80211_wpa_set_encryption(struct ieee80211_device *ieee,
                memset(new_crypt, 0, sizeof(struct ieee80211_crypt_data));
                new_crypt->ops = ops;
 
-               if (new_crypt->ops && try_module_get(new_crypt->ops->owner))
+               if (new_crypt->ops)
                        new_crypt->priv =
                                new_crypt->ops->init(param->u.crypt.idx);
 
index 1077590..6146c64 100644 (file)
@@ -358,11 +358,9 @@ int ieee80211_wx_set_encode(struct ieee80211_device *ieee,
                        return -ENOMEM;
                memset(new_crypt, 0, sizeof(struct ieee80211_crypt_data));
                new_crypt->ops = ieee80211_get_crypto_ops("WEP");
-               if (!new_crypt->ops) {
-                       request_module("ieee80211_crypt_wep");
+               if (!new_crypt->ops)
                        new_crypt->ops = ieee80211_get_crypto_ops("WEP");
-               }
-               if (new_crypt->ops && try_module_get(new_crypt->ops->owner))
+               if (new_crypt->ops)
                        new_crypt->priv = new_crypt->ops->init(key);
 
                if (!new_crypt->ops || !new_crypt->priv) {
@@ -507,7 +505,7 @@ int ieee80211_wx_set_encode_ext(struct ieee80211_device *ieee,
         struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
         int i, idx;
         int group_key = 0;
-        const char *alg, *module;
+        const char *alg;
         struct ieee80211_crypto_ops *ops;
         struct ieee80211_crypt_data **crypt;
 
@@ -570,15 +568,12 @@ int ieee80211_wx_set_encode_ext(struct ieee80211_device *ieee,
         switch (ext->alg) {
         case IW_ENCODE_ALG_WEP:
                 alg = "WEP";
-                module = "ieee80211_crypt_wep";
                 break;
         case IW_ENCODE_ALG_TKIP:
                 alg = "TKIP";
-                module = "ieee80211_crypt_tkip";
                 break;
         case IW_ENCODE_ALG_CCMP:
                 alg = "CCMP";
-                module = "ieee80211_crypt_ccmp";
                 break;
         default:
                 IEEE80211_DEBUG_WX("%s: unknown crypto alg %d\n",
@@ -589,10 +584,8 @@ int ieee80211_wx_set_encode_ext(struct ieee80211_device *ieee,
        printk("alg name:%s\n",alg);
 
         ops = ieee80211_get_crypto_ops(alg);
-        if (ops == NULL) {
-                request_module("%s", module);
+        if (ops == NULL)
                 ops = ieee80211_get_crypto_ops(alg);
-        }
         if (ops == NULL) {
                 IEEE80211_DEBUG_WX("%s: unknown crypto alg %d\n",
                                    dev->name, ext->alg);
@@ -612,7 +605,7 @@ int ieee80211_wx_set_encode_ext(struct ieee80211_device *ieee,
                         goto done;
                 }
                 new_crypt->ops = ops;
-                if (new_crypt->ops && try_module_get(new_crypt->ops->owner))
+                if (new_crypt->ops)
                         new_crypt->priv = new_crypt->ops->init(idx);
                 if (new_crypt->priv == NULL) {
                         kfree(new_crypt);
index 87f8a11..f890a16 100644 (file)
@@ -38,6 +38,7 @@
 #include <linux/mm.h>
 #include <linux/poll.h>
 #include <linux/wait.h>
+#include <linux/sched.h>
 #include <linux/pci.h>
 #include <linux/firmware.h>
 #include <asm/ioctl.h>
diff --git a/drivers/staging/stlc45xx/Kconfig b/drivers/staging/stlc45xx/Kconfig
deleted file mode 100644 (file)
index 947fb75..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-config STLC45XX
-       tristate "stlc4550/4560 support"
-       depends on MAC80211 && WLAN_80211 && SPI_MASTER && GENERIC_HARDIRQS
-       ---help---
-         This is a driver for stlc4550 and stlc4560 chipsets.
-
-         To compile this driver as a module, choose M here: the module will be
-         called stlc45xx.  If unsure, say N.
diff --git a/drivers/staging/stlc45xx/Makefile b/drivers/staging/stlc45xx/Makefile
deleted file mode 100644 (file)
index 7ee3290..0000000
+++ /dev/null
@@ -1 +0,0 @@
-obj-$(CONFIG_STLC45XX) += stlc45xx.o
diff --git a/drivers/staging/stlc45xx/stlc45xx.c b/drivers/staging/stlc45xx/stlc45xx.c
deleted file mode 100644 (file)
index be99eb3..0000000
+++ /dev/null
@@ -1,2594 +0,0 @@
-/*
- * This file is part of stlc45xx
- *
- * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies).
- *
- * Contact: Kalle Valo <kalle.valo@nokia.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA
- *
- */
-
-#include "stlc45xx.h"
-
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/interrupt.h>
-#include <linux/firmware.h>
-#include <linux/delay.h>
-#include <linux/irq.h>
-#include <linux/spi/spi.h>
-#include <linux/etherdevice.h>
-#include <linux/gpio.h>
-#include <linux/moduleparam.h>
-
-#include "stlc45xx_lmac.h"
-
-/*
- * gpios should be handled in board files and provided via platform data,
- * but because it's currently impossible for stlc45xx to have a header file
- * in include/linux, let's use module paramaters for now
- */
-static int stlc45xx_gpio_power = 97;
-module_param(stlc45xx_gpio_power, int, 0444);
-MODULE_PARM_DESC(stlc45xx_gpio_power, "stlc45xx gpio number for power line");
-
-static int stlc45xx_gpio_irq = 87;
-module_param(stlc45xx_gpio_irq, int, 0444);
-MODULE_PARM_DESC(stlc45xx_gpio_irq, "stlc45xx gpio number for irq line");
-
-static const u8 default_cal_channels[] = {
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6c, 0x09,
-       0x00, 0x00, 0xc9, 0xff, 0xd8, 0xff, 0x00, 0x00, 0x00, 0x01, 0x10,
-       0x01, 0x10, 0x01, 0x10, 0x01, 0x10, 0x01, 0xe0, 0x00, 0xe0, 0x00,
-       0xe0, 0x00, 0xe0, 0x00, 0xd0, 0x00, 0xd0, 0x00, 0xd0, 0x00, 0xd0,
-       0x00, 0x54, 0x01, 0xab, 0xf6, 0xc0, 0x42, 0xc0, 0x42, 0xc0, 0x42,
-       0xc0, 0x42, 0x00, 0xcb, 0x00, 0xcb, 0x00, 0xcb, 0x00, 0xcb, 0x00,
-       0xcb, 0x00, 0xcb, 0x00, 0xcb, 0x00, 0xcb, 0x22, 0x01, 0x37, 0xa9,
-       0xc0, 0x33, 0xc0, 0x33, 0xc0, 0x33, 0xc0, 0x33, 0x00, 0xbc, 0x00,
-       0xbc, 0x00, 0xbc, 0x00, 0xbc, 0x00, 0xbc, 0x00, 0xbc, 0x00, 0xbc,
-       0x00, 0xbc, 0xfb, 0x00, 0xca, 0x79, 0xc0, 0x2b, 0xc0, 0x2b, 0xc0,
-       0x2b, 0xc0, 0x2b, 0x00, 0xb4, 0x00, 0xb4, 0x00, 0xb4, 0x00, 0xb4,
-       0x00, 0xb4, 0x00, 0xb4, 0x00, 0xb4, 0x00, 0xb4, 0xd0, 0x00, 0x5d,
-       0x54, 0xc0, 0x21, 0xc0, 0x21, 0xc0, 0x21, 0xc0, 0x21, 0x00, 0xaa,
-       0x00, 0xaa, 0x00, 0xaa, 0x00, 0xaa, 0x00, 0xaa, 0x00, 0xaa, 0x00,
-       0xaa, 0x00, 0xaa, 0xa7, 0x00, 0xa9, 0x3d, 0xc0, 0x17, 0xc0, 0x17,
-       0xc0, 0x17, 0xc0, 0x17, 0x00, 0xa0, 0x00, 0xa0, 0x00, 0xa0, 0x00,
-       0xa0, 0x00, 0xa0, 0x00, 0xa0, 0x00, 0xa0, 0x00, 0xa0, 0x7a, 0x00,
-       0x06, 0x2c, 0xc0, 0x0d, 0xc0, 0x0d, 0xc0, 0x0d, 0xc0, 0x0d, 0x00,
-       0x96, 0x00, 0x96, 0x00, 0x96, 0x00, 0x96, 0x00, 0x96, 0x00, 0x96,
-       0x00, 0x96, 0x00, 0x96, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-       0x00, 0x00, 0x06, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-       0x00, 0x00, 0x00, 0x00, 0x71, 0x09, 0x00, 0x00, 0xc9, 0xff, 0xd8,
-       0xff, 0x00, 0x00, 0x00, 0x01, 0x10, 0x01, 0x10, 0x01, 0x10, 0x01,
-       0x10, 0x01, 0xf0, 0x00, 0xf0, 0x00, 0xf0, 0x00, 0xf0, 0x00, 0xd0,
-       0x00, 0xd0, 0x00, 0xd0, 0x00, 0xd0, 0x00, 0x54, 0x01, 0xab, 0xf6,
-       0xc0, 0x42, 0xc0, 0x42, 0xc0, 0x42, 0xc0, 0x42, 0x00, 0xcb, 0x00,
-       0xcb, 0x00, 0xcb, 0x00, 0xcb, 0x00, 0xcb, 0x00, 0xcb, 0x00, 0xcb,
-       0x00, 0xcb, 0x22, 0x01, 0x37, 0xa9, 0xc0, 0x33, 0xc0, 0x33, 0xc0,
-       0x33, 0xc0, 0x33, 0x00, 0xbc, 0x00, 0xbc, 0x00, 0xbc, 0x00, 0xbc,
-       0x00, 0xbc, 0x00, 0xbc, 0x00, 0xbc, 0x00, 0xbc, 0xfb, 0x00, 0xca,
-       0x79, 0xc0, 0x2b, 0xc0, 0x2b, 0xc0, 0x2b, 0xc0, 0x2b, 0x00, 0xb4,
-       0x00, 0xb4, 0x00, 0xb4, 0x00, 0xb4, 0x00, 0xb4, 0x00, 0xb4, 0x00,
-       0xb4, 0x00, 0xb4, 0xd0, 0x00, 0x5d, 0x54, 0xc0, 0x21, 0xc0, 0x21,
-       0xc0, 0x21, 0xc0, 0x21, 0x00, 0xaa, 0x00, 0xaa, 0x00, 0xaa, 0x00,
-       0xaa, 0x00, 0xaa, 0x00, 0xaa, 0x00, 0xaa, 0x00, 0xaa, 0xa7, 0x00,
-       0xa9, 0x3d, 0xc0, 0x17, 0xc0, 0x17, 0xc0, 0x17, 0xc0, 0x17, 0x00,
-       0xa0, 0x00, 0xa0, 0x00, 0xa0, 0x00, 0xa0, 0x00, 0xa0, 0x00, 0xa0,
-       0x00, 0xa0, 0x00, 0xa0, 0x7a, 0x00, 0x06, 0x2c, 0xc0, 0x0d, 0xc0,
-       0x0d, 0xc0, 0x0d, 0xc0, 0x0d, 0x00, 0x96, 0x00, 0x96, 0x00, 0x96,
-       0x00, 0x96, 0x00, 0x96, 0x00, 0x96, 0x00, 0x96, 0x00, 0x96, 0x00,
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x80, 0x80,
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x76,
-       0x09, 0x00, 0x00, 0xc9, 0xff, 0xd8, 0xff, 0x00, 0x00, 0x00, 0x01,
-       0x10, 0x01, 0x10, 0x01, 0x10, 0x01, 0x10, 0x01, 0xf0, 0x00, 0xf0,
-       0x00, 0xf0, 0x00, 0xf0, 0x00, 0xd0, 0x00, 0xd0, 0x00, 0xd0, 0x00,
-       0xd0, 0x00, 0x54, 0x01, 0xab, 0xf6, 0xc0, 0x42, 0xc0, 0x42, 0xc0,
-       0x42, 0xc0, 0x42, 0x00, 0xcb, 0x00, 0xcb, 0x00, 0xcb, 0x00, 0xcb,
-       0x00, 0xcb, 0x00, 0xcb, 0x00, 0xcb, 0x00, 0xcb, 0x22, 0x01, 0x37,
-       0xa9, 0xc0, 0x33, 0xc0, 0x33, 0xc0, 0x33, 0xc0, 0x33, 0x00, 0xbc,
-       0x00, 0xbc, 0x00, 0xbc, 0x00, 0xbc, 0x00, 0xbc, 0x00, 0xbc, 0x00,
-       0xbc, 0x00, 0xbc, 0xfb, 0x00, 0xca, 0x79, 0xc0, 0x2b, 0xc0, 0x2b,
-       0xc0, 0x2b, 0xc0, 0x2b, 0x00, 0xb4, 0x00, 0xb4, 0x00, 0xb4, 0x00,
-       0xb4, 0x00, 0xb4, 0x00, 0xb4, 0x00, 0xb4, 0x00, 0xb4, 0xd0, 0x00,
-       0x5d, 0x54, 0xc0, 0x21, 0xc0, 0x21, 0xc0, 0x21, 0xc0, 0x21, 0x00,
-       0xaa, 0x00, 0xaa, 0x00, 0xaa, 0x00, 0xaa, 0x00, 0xaa, 0x00, 0xaa,
-       0x00, 0xaa, 0x00, 0xaa, 0xa7, 0x00, 0xa9, 0x3d, 0xc0, 0x17, 0xc0,
-       0x17, 0xc0, 0x17, 0xc0, 0x17, 0x00, 0xa0, 0x00, 0xa0, 0x00, 0xa0,
-       0x00, 0xa0, 0x00, 0xa0, 0x00, 0xa0, 0x00, 0xa0, 0x00, 0xa0, 0x7a,
-       0x00, 0x06, 0x2c, 0xc0, 0x0d, 0xc0, 0x0d, 0xc0, 0x0d, 0xc0, 0x0d,
-       0x00, 0x96, 0x00, 0x96, 0x00, 0x96, 0x00, 0x96, 0x00, 0x96, 0x00,
-       0x96, 0x00, 0x96, 0x00, 0x96, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-       0x00, 0x00, 0x00, 0x06, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x7b, 0x09, 0x00, 0x00, 0xc9, 0xff,
-       0xd8, 0xff, 0x00, 0x00, 0x00, 0x01, 0x10, 0x01, 0x10, 0x01, 0x10,
-       0x01, 0x10, 0x01, 0xf0, 0x00, 0xf0, 0x00, 0xf0, 0x00, 0xf0, 0x00,
-       0xd0, 0x00, 0xd0, 0x00, 0xd0, 0x00, 0xd0, 0x00, 0x54, 0x01, 0xab,
-       0xf6, 0xc0, 0x42, 0xc0, 0x42, 0xc0, 0x42, 0xc0, 0x42, 0x00, 0xcb,
-       0x00, 0xcb, 0x00, 0xcb, 0x00, 0xcb, 0x00, 0xcb, 0x00, 0xcb, 0x00,
-       0xcb, 0x00, 0xcb, 0x22, 0x01, 0x37, 0xa9, 0xc0, 0x33, 0xc0, 0x33,
-       0xc0, 0x33, 0xc0, 0x33, 0x00, 0xbc, 0x00, 0xbc, 0x00, 0xbc, 0x00,
-       0xbc, 0x00, 0xbc, 0x00, 0xbc, 0x00, 0xbc, 0x00, 0xbc, 0xfb, 0x00,
-       0xca, 0x79, 0xc0, 0x2b, 0xc0, 0x2b, 0xc0, 0x2b, 0xc0, 0x2b, 0x00,
-       0xb4, 0x00, 0xb4, 0x00, 0xb4, 0x00, 0xb4, 0x00, 0xb4, 0x00, 0xb4,
-       0x00, 0xb4, 0x00, 0xb4, 0xd0, 0x00, 0x5d, 0x54, 0xc0, 0x21, 0xc0,
-       0x21, 0xc0, 0x21, 0xc0, 0x21, 0x00, 0xaa, 0x00, 0xaa, 0x00, 0xaa,
-       0x00, 0xaa, 0x00, 0xaa, 0x00, 0xaa, 0x00, 0xaa, 0x00, 0xaa, 0xa7,
-       0x00, 0xa9, 0x3d, 0xc0, 0x17, 0xc0, 0x17, 0xc0, 0x17, 0xc0, 0x17,
-       0x00, 0xa0, 0x00, 0xa0, 0x00, 0xa0, 0x00, 0xa0, 0x00, 0xa0, 0x00,
-       0xa0, 0x00, 0xa0, 0x00, 0xa0, 0x7a, 0x00, 0x06, 0x2c, 0xc0, 0x0d,
-       0xc0, 0x0d, 0xc0, 0x0d, 0xc0, 0x0d, 0x00, 0x96, 0x00, 0x96, 0x00,
-       0x96, 0x00, 0x96, 0x00, 0x96, 0x00, 0x96, 0x00, 0x96, 0x00, 0x96,
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x80,
-       0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-       0x80, 0x09, 0x00, 0x00, 0xc9, 0xff, 0xd8, 0xff, 0x00, 0x00, 0x00,
-       0x01, 0x10, 0x01, 0x10, 0x01, 0x10, 0x01, 0x10, 0x01, 0xf0, 0x00,
-       0xf0, 0x00, 0xf0, 0x00, 0xf0, 0x00, 0xd0, 0x00, 0xd0, 0x00, 0xd0,
-       0x00, 0xd0, 0x00, 0x54, 0x01, 0xab, 0xf6, 0xc0, 0x42, 0xc0, 0x42,
-       0xc0, 0x42, 0xc0, 0x42, 0x00, 0xcb, 0x00, 0xcb, 0x00, 0xcb, 0x00,
-       0xcb, 0x00, 0xcb, 0x00, 0xcb, 0x00, 0xcb, 0x00, 0xcb, 0x22, 0x01,
-       0x37, 0xa9, 0xc0, 0x33, 0xc0, 0x33, 0xc0, 0x33, 0xc0, 0x33, 0x00,
-       0xbc, 0x00, 0xbc, 0x00, 0xbc, 0x00, 0xbc, 0x00, 0xbc, 0x00, 0xbc,
-       0x00, 0xbc, 0x00, 0xbc, 0xfb, 0x00, 0xca, 0x79, 0xc0, 0x2b, 0xc0,
-       0x2b, 0xc0, 0x2b, 0xc0, 0x2b, 0x00, 0xb4, 0x00, 0xb4, 0x00, 0xb4,
-       0x00, 0xb4, 0x00, 0xb4, 0x00, 0xb4, 0x00, 0xb4, 0x00, 0xb4, 0xd0,
-       0x00, 0x5d, 0x54, 0xc0, 0x21, 0xc0, 0x21, 0xc0, 0x21, 0xc0, 0x21,
-       0x00, 0xaa, 0x00, 0xaa, 0x00, 0xaa, 0x00, 0xaa, 0x00, 0xaa, 0x00,
-       0xaa, 0x00, 0xaa, 0x00, 0xaa, 0xa7, 0x00, 0xa9, 0x3d, 0xc0, 0x17,
-       0xc0, 0x17, 0xc0, 0x17, 0xc0, 0x17, 0x00, 0xa0, 0x00, 0xa0, 0x00,
-       0xa0, 0x00, 0xa0, 0x00, 0xa0, 0x00, 0xa0, 0x00, 0xa0, 0x00, 0xa0,
-       0x7a, 0x00, 0x06, 0x2c, 0xc0, 0x0d, 0xc0, 0x0d, 0xc0, 0x0d, 0xc0,
-       0x0d, 0x00, 0x96, 0x00, 0x96, 0x00, 0x96, 0x00, 0x96, 0x00, 0x96,
-       0x00, 0x96, 0x00, 0x96, 0x00, 0x96, 0x00, 0x00, 0x00, 0x00, 0x00,
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-       0x00, 0x00, 0x00, 0x00, 0x06, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00,
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x85, 0x09, 0x00, 0x00, 0xc9,
-       0xff, 0xd8, 0xff, 0x00, 0x00, 0x00, 0x01, 0x10, 0x01, 0x10, 0x01,
-       0x10, 0x01, 0x10, 0x01, 0xf0, 0x00, 0xf0, 0x00, 0xf0, 0x00, 0xf0,
-       0x00, 0xd0, 0x00, 0xd0, 0x00, 0xd0, 0x00, 0xd0, 0x00, 0x54, 0x01,
-       0xab, 0xf6, 0xc0, 0x42, 0xc0, 0x42, 0xc0, 0x42, 0xc0, 0x42, 0x00,
-       0xcb, 0x00, 0xcb, 0x00, 0xcb, 0x00, 0xcb, 0x00, 0xcb, 0x00, 0xcb,
-       0x00, 0xcb, 0x00, 0xcb, 0x22, 0x01, 0x37, 0xa9, 0xc0, 0x33, 0xc0,
-       0x33, 0xc0, 0x33, 0xc0, 0x33, 0x00, 0xbc, 0x00, 0xbc, 0x00, 0xbc,
-       0x00, 0xbc, 0x00, 0xbc, 0x00, 0xbc, 0x00, 0xbc, 0x00, 0xbc, 0xfb,
-       0x00, 0xca, 0x79, 0xc0, 0x2b, 0xc0, 0x2b, 0xc0, 0x2b, 0xc0, 0x2b,
-       0x00, 0xb4, 0x00, 0xb4, 0x00, 0xb4, 0x00, 0xb4, 0x00, 0xb4, 0x00,
-       0xb4, 0x00, 0xb4, 0x00, 0xb4, 0xd0, 0x00, 0x5d, 0x54, 0xc0, 0x21,
-       0xc0, 0x21, 0xc0, 0x21, 0xc0, 0x21, 0x00, 0xaa, 0x00, 0xaa, 0x00,
-       0xaa, 0x00, 0xaa, 0x00, 0xaa, 0x00, 0xaa, 0x00, 0xaa, 0x00, 0xaa,
-       0xa7, 0x00, 0xa9, 0x3d, 0xc0, 0x17, 0xc0, 0x17, 0xc0, 0x17, 0xc0,
-       0x17, 0x00, 0xa0, 0x00, 0xa0, 0x00, 0xa0, 0x00, 0xa0, 0x00, 0xa0,
-       0x00, 0xa0, 0x00, 0xa0, 0x00, 0xa0, 0x7a, 0x00, 0x06, 0x2c, 0xc0,
-       0x0d, 0xc0, 0x0d, 0xc0, 0x0d, 0xc0, 0x0d, 0x00, 0x96, 0x00, 0x96,
-       0x00, 0x96, 0x00, 0x96, 0x00, 0x96, 0x00, 0x96, 0x00, 0x96, 0x00,
-       0x96, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06,
-       0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-       0x00, 0x8a, 0x09, 0x00, 0x00, 0xc9, 0xff, 0xd8, 0xff, 0x00, 0x00,
-       0x00, 0x01, 0x10, 0x01, 0x10, 0x01, 0x10, 0x01, 0x10, 0x01, 0xf0,
-       0x00, 0xf0, 0x00, 0xf0, 0x00, 0xf0, 0x00, 0xd0, 0x00, 0xd0, 0x00,
-       0xd0, 0x00, 0xd0, 0x00, 0x54, 0x01, 0xab, 0xf6, 0xc0, 0x42, 0xc0,
-       0x42, 0xc0, 0x42, 0xc0, 0x42, 0x00, 0xcb, 0x00, 0xcb, 0x00, 0xcb,
-       0x00, 0xcb, 0x00, 0xcb, 0x00, 0xcb, 0x00, 0xcb, 0x00, 0xcb, 0x22,
-       0x01, 0x37, 0xa9, 0xc0, 0x33, 0xc0, 0x33, 0xc0, 0x33, 0xc0, 0x33,
-       0x00, 0xbc, 0x00, 0xbc, 0x00, 0xbc, 0x00, 0xbc, 0x00, 0xbc, 0x00,
-       0xbc, 0x00, 0xbc, 0x00, 0xbc, 0xfb, 0x00, 0xca, 0x79, 0xc0, 0x2b,
-       0xc0, 0x2b, 0xc0, 0x2b, 0xc0, 0x2b, 0x00, 0xb4, 0x00, 0xb4, 0x00,
-       0xb4, 0x00, 0xb4, 0x00, 0xb4, 0x00, 0xb4, 0x00, 0xb4, 0x00, 0xb4,
-       0xd0, 0x00, 0x5d, 0x54, 0xc0, 0x21, 0xc0, 0x21, 0xc0, 0x21, 0xc0,
-       0x21, 0x00, 0xaa, 0x00, 0xaa, 0x00, 0xaa, 0x00, 0xaa, 0x00, 0xaa,
-       0x00, 0xaa, 0x00, 0xaa, 0x00, 0xaa, 0xa7, 0x00, 0xa9, 0x3d, 0xc0,
-       0x17, 0xc0, 0x17, 0xc0, 0x17, 0xc0, 0x17, 0x00, 0xa0, 0x00, 0xa0,
-       0x00, 0xa0, 0x00, 0xa0, 0x00, 0xa0, 0x00, 0xa0, 0x00, 0xa0, 0x00,
-       0xa0, 0x7a, 0x00, 0x06, 0x2c, 0xc0, 0x0d, 0xc0, 0x0d, 0xc0, 0x0d,
-       0xc0, 0x0d, 0x00, 0x96, 0x00, 0x96, 0x00, 0x96, 0x00, 0x96, 0x00,
-       0x96, 0x00, 0x96, 0x00, 0x96, 0x00, 0x96, 0x00, 0x00, 0x00, 0x00,
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x80, 0x80, 0x00, 0x00, 0x00,
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8f, 0x09, 0x00, 0x00,
-       0xc9, 0xff, 0xd8, 0xff, 0x00, 0x00, 0x00, 0x01, 0x10, 0x01, 0x10,
-       0x01, 0x10, 0x01, 0x10, 0x01, 0xf0, 0x00, 0xf0, 0x00, 0xf0, 0x00,
-       0xf0, 0x00, 0xd0, 0x00, 0xd0, 0x00, 0xd0, 0x00, 0xd0, 0x00, 0x54,
-       0x01, 0xab, 0xf6, 0xc0, 0x42, 0xc0, 0x42, 0xc0, 0x42, 0xc0, 0x42,
-       0x00, 0xcb, 0x00, 0xcb, 0x00, 0xcb, 0x00, 0xcb, 0x00, 0xcb, 0x00,
-       0xcb, 0x00, 0xcb, 0x00, 0xcb, 0x22, 0x01, 0x37, 0xa9, 0xc0, 0x33,
-       0xc0, 0x33, 0xc0, 0x33, 0xc0, 0x33, 0x00, 0xbc, 0x00, 0xbc, 0x00,
-       0xbc, 0x00, 0xbc, 0x00, 0xbc, 0x00, 0xbc, 0x00, 0xbc, 0x00, 0xbc,
-       0xfb, 0x00, 0xca, 0x79, 0xc0, 0x2b, 0xc0, 0x2b, 0xc0, 0x2b, 0xc0,
-       0x2b, 0x00, 0xb4, 0x00, 0xb4, 0x00, 0xb4, 0x00, 0xb4, 0x00, 0xb4,
-       0x00, 0xb4, 0x00, 0xb4, 0x00, 0xb4, 0xd0, 0x00, 0x5d, 0x54, 0xc0,
-       0x21, 0xc0, 0x21, 0xc0, 0x21, 0xc0, 0x21, 0x00, 0xaa, 0x00, 0xaa,
-       0x00, 0xaa, 0x00, 0xaa, 0x00, 0xaa, 0x00, 0xaa, 0x00, 0xaa, 0x00,
-       0xaa, 0xa7, 0x00, 0xa9, 0x3d, 0xc0, 0x17, 0xc0, 0x17, 0xc0, 0x17,
-       0xc0, 0x17, 0x00, 0xa0, 0x00, 0xa0, 0x00, 0xa0, 0x00, 0xa0, 0x00,
-       0xa0, 0x00, 0xa0, 0x00, 0xa0, 0x00, 0xa0, 0x7a, 0x00, 0x06, 0x2c,
-       0xc0, 0x0d, 0xc0, 0x0d, 0xc0, 0x0d, 0xc0, 0x0d, 0x00, 0x96, 0x00,
-       0x96, 0x00, 0x96, 0x00, 0x96, 0x00, 0x96, 0x00, 0x96, 0x00, 0x96,
-       0x00, 0x96, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-       0x06, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-       0x00, 0x00, 0x94, 0x09, 0x00, 0x00, 0xc9, 0xff, 0xd8, 0xff, 0x00,
-       0x00, 0x00, 0x01, 0x10, 0x01, 0x10, 0x01, 0x10, 0x01, 0x10, 0x01,
-       0xf0, 0x00, 0xf0, 0x00, 0xf0, 0x00, 0xf0, 0x00, 0xd0, 0x00, 0xd0,
-       0x00, 0xd0, 0x00, 0xd0, 0x00, 0x54, 0x01, 0xab, 0xf6, 0xc0, 0x42,
-       0xc0, 0x42, 0xc0, 0x42, 0xc0, 0x42, 0x00, 0xcb, 0x00, 0xcb, 0x00,
-       0xcb, 0x00, 0xcb, 0x00, 0xcb, 0x00, 0xcb, 0x00, 0xcb, 0x00, 0xcb,
-       0x22, 0x01, 0x37, 0xa9, 0xc0, 0x33, 0xc0, 0x33, 0xc0, 0x33, 0xc0,
-       0x33, 0x00, 0xbc, 0x00, 0xbc, 0x00, 0xbc, 0x00, 0xbc, 0x00, 0xbc,
-       0x00, 0xbc, 0x00, 0xbc, 0x00, 0xbc, 0xfb, 0x00, 0xca, 0x79, 0xc0,
-       0x2b, 0xc0, 0x2b, 0xc0, 0x2b, 0xc0, 0x2b, 0x00, 0xb4, 0x00, 0xb4,
-       0x00, 0xb4, 0x00, 0xb4, 0x00, 0xb4, 0x00, 0xb4, 0x00, 0xb4, 0x00,
-       0xb4, 0xd0, 0x00, 0x5d, 0x54, 0xc0, 0x21, 0xc0, 0x21, 0xc0, 0x21,
-       0xc0, 0x21, 0x00, 0xaa, 0x00, 0xaa, 0x00, 0xaa, 0x00, 0xaa, 0x00,
-       0xaa, 0x00, 0xaa, 0x00, 0xaa, 0x00, 0xaa, 0xa7, 0x00, 0xa9, 0x3d,
-       0xc0, 0x17, 0xc0, 0x17, 0xc0, 0x17, 0xc0, 0x17, 0x00, 0xa0, 0x00,
-       0xa0, 0x00, 0xa0, 0x00, 0xa0, 0x00, 0xa0, 0x00, 0xa0, 0x00, 0xa0,
-       0x00, 0xa0, 0x7a, 0x00, 0x06, 0x2c, 0xc0, 0x0d, 0xc0, 0x0d, 0xc0,
-       0x0d, 0xc0, 0x0d, 0x00, 0x96, 0x00, 0x96, 0x00, 0x96, 0x00, 0x96,
-       0x00, 0x96, 0x00, 0x96, 0x00, 0x96, 0x00, 0x96, 0x00, 0x00, 0x00,
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x80, 0x80, 0x00, 0x00,
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x99, 0x09, 0x00,
-       0x00, 0xc9, 0xff, 0xd8, 0xff, 0x00, 0x00, 0x00, 0x01, 0x10, 0x01,
-       0x10, 0x01, 0x10, 0x01, 0x10, 0x01, 0xf0, 0x00, 0xf0, 0x00, 0xf0,
-       0x00, 0xf0, 0x00, 0xd0, 0x00, 0xd0, 0x00, 0xd0, 0x00, 0xd0, 0x00,
-       0x54, 0x01, 0xab, 0xf6, 0xc0, 0x42, 0xc0, 0x42, 0xc0, 0x42, 0xc0,
-       0x42, 0x00, 0xcb, 0x00, 0xcb, 0x00, 0xcb, 0x00, 0xcb, 0x00, 0xcb,
-       0x00, 0xcb, 0x00, 0xcb, 0x00, 0xcb, 0x22, 0x01, 0x37, 0xa9, 0xc0,
-       0x33, 0xc0, 0x33, 0xc0, 0x33, 0xc0, 0x33, 0x00, 0xbc, 0x00, 0xbc,
-       0x00, 0xbc, 0x00, 0xbc, 0x00, 0xbc, 0x00, 0xbc, 0x00, 0xbc, 0x00,
-       0xbc, 0xfb, 0x00, 0xca, 0x79, 0xc0, 0x2b, 0xc0, 0x2b, 0xc0, 0x2b,
-       0xc0, 0x2b, 0x00, 0xb4, 0x00, 0xb4, 0x00, 0xb4, 0x00, 0xb4, 0x00,
-       0xb4, 0x00, 0xb4, 0x00, 0xb4, 0x00, 0xb4, 0xd0, 0x00, 0x5d, 0x54,
-       0xc0, 0x21, 0xc0, 0x21, 0xc0, 0x21, 0xc0, 0x21, 0x00, 0xaa, 0x00,
-       0xaa, 0x00, 0xaa, 0x00, 0xaa, 0x00, 0xaa, 0x00, 0xaa, 0x00, 0xaa,
-       0x00, 0xaa, 0xa7, 0x00, 0xa9, 0x3d, 0xc0, 0x17, 0xc0, 0x17, 0xc0,
-       0x17, 0xc0, 0x17, 0x00, 0xa0, 0x00, 0xa0, 0x00, 0xa0, 0x00, 0xa0,
-       0x00, 0xa0, 0x00, 0xa0, 0x00, 0xa0, 0x00, 0xa0, 0x7a, 0x00, 0x06,
-       0x2c, 0xc0, 0x0d, 0xc0, 0x0d, 0xc0, 0x0d, 0xc0, 0x0d, 0x00, 0x96,
-       0x00, 0x96, 0x00, 0x96, 0x00, 0x96, 0x00, 0x96, 0x00, 0x96, 0x00,
-       0x96, 0x00, 0x96, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-       0x00, 0x06, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-       0x00, 0x00, 0x00, 0x9e, 0x09, 0x00, 0x00, 0xc9, 0xff, 0xd8, 0xff,
-       0x00, 0x00, 0x00, 0x01, 0x10, 0x01, 0x10, 0x01, 0x10, 0x01, 0x10,
-       0x01, 0xf0, 0x00, 0xf0, 0x00, 0xf0, 0x00, 0xf0, 0x00, 0xd0, 0x00,
-       0xd0, 0x00, 0xd0, 0x00, 0xd0, 0x00, 0x54, 0x01, 0xab, 0xf6, 0xc0,
-       0x42, 0xc0, 0x42, 0xc0, 0x42, 0xc0, 0x42, 0x00, 0xcb, 0x00, 0xcb,
-       0x00, 0xcb, 0x00, 0xcb, 0x00, 0xcb, 0x00, 0xcb, 0x00, 0xcb, 0x00,
-       0xcb, 0x22, 0x01, 0x37, 0xa9, 0xc0, 0x33, 0xc0, 0x33, 0xc0, 0x33,
-       0xc0, 0x33, 0x00, 0xbc, 0x00, 0xbc, 0x00, 0xbc, 0x00, 0xbc, 0x00,
-       0xbc, 0x00, 0xbc, 0x00, 0xbc, 0x00, 0xbc, 0xfb, 0x00, 0xca, 0x79,
-       0xc0, 0x2b, 0xc0, 0x2b, 0xc0, 0x2b, 0xc0, 0x2b, 0x00, 0xb4, 0x00,
-       0xb4, 0x00, 0xb4, 0x00, 0xb4, 0x00, 0xb4, 0x00, 0xb4, 0x00, 0xb4,
-       0x00, 0xb4, 0xd0, 0x00, 0x5d, 0x54, 0xc0, 0x21, 0xc0, 0x21, 0xc0,
-       0x21, 0xc0, 0x21, 0x00, 0xaa, 0x00, 0xaa, 0x00, 0xaa, 0x00, 0xaa,
-       0x00, 0xaa, 0x00, 0xaa, 0x00, 0xaa, 0x00, 0xaa, 0xa7, 0x00, 0xa9,
-       0x3d, 0xc0, 0x17, 0xc0, 0x17, 0xc0, 0x17, 0xc0, 0x17, 0x00, 0xa0,
-       0x00, 0xa0, 0x00, 0xa0, 0x00, 0xa0, 0x00, 0xa0, 0x00, 0xa0, 0x00,
-       0xa0, 0x00, 0xa0, 0x7a, 0x00, 0x06, 0x2c, 0xc0, 0x0d, 0xc0, 0x0d,
-       0xc0, 0x0d, 0xc0, 0x0d, 0x00, 0x96, 0x00, 0x96, 0x00, 0x96, 0x00,
-       0x96, 0x00, 0x96, 0x00, 0x96, 0x00, 0x96, 0x00, 0x96, 0x00, 0x00,
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x80, 0x80, 0x00,
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-       0x00 };
-
-static const u8 default_cal_rssi[] = {
-       0x0a, 0x01, 0x72, 0xfe, 0x1a, 0x00, 0x00, 0x00, 0x0a, 0x01, 0x72,
-       0xfe, 0x1a, 0x00, 0x00, 0x00, 0x0a, 0x01, 0x72, 0xfe, 0x1a, 0x00,
-       0x00, 0x00, 0x0a, 0x01, 0x72, 0xfe, 0x1a, 0x00, 0x00, 0x00, 0x0a,
-       0x01, 0x72, 0xfe, 0x1a, 0x00, 0x00, 0x00, 0x0a, 0x01, 0x72, 0xfe,
-       0x1a, 0x00, 0x00, 0x00, 0x0a, 0x01, 0x72, 0xfe, 0x1a, 0x00, 0x00,
-       0x00, 0x0a, 0x01, 0x72, 0xfe, 0x1a, 0x00, 0x00, 0x00, 0x0a, 0x01,
-       0x72, 0xfe, 0x1a, 0x00, 0x00, 0x00, 0x0a, 0x01, 0x72, 0xfe, 0x1a,
-       0x00, 0x00, 0x00, 0x0a, 0x01, 0x72, 0xfe, 0x1a, 0x00, 0x00, 0x00,
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-       0x00, 0x00, 0x00, 0x00, 0x00 };
-
-static void stlc45xx_tx_edcf(struct stlc45xx *stlc);
-static void stlc45xx_tx_setup(struct stlc45xx *stlc);
-static void stlc45xx_tx_scan(struct stlc45xx *stlc);
-static void stlc45xx_tx_psm(struct stlc45xx *stlc, bool enable);
-static int stlc45xx_tx_nullfunc(struct stlc45xx *stlc, bool powersave);
-static int stlc45xx_tx_pspoll(struct stlc45xx *stlc, bool powersave);
-
-static ssize_t stlc45xx_sysfs_show_cal_rssi(struct device *dev,
-                                           struct device_attribute *attr,
-                                           char *buf)
-{
-       struct stlc45xx *stlc = dev_get_drvdata(dev);
-       ssize_t len;
-
-       stlc45xx_debug(DEBUG_FUNC, "%s", __func__);
-
-       len = PAGE_SIZE;
-
-       mutex_lock(&stlc->mutex);
-
-       if (stlc->cal_rssi)
-               hex_dump_to_buffer(stlc->cal_rssi, RSSI_CAL_ARRAY_LEN, 16,
-                                  2, buf, len, 0);
-       mutex_unlock(&stlc->mutex);
-
-       len = strlen(buf);
-
-       return len;
-}
-
-static ssize_t stlc45xx_sysfs_store_cal_rssi(struct device *dev,
-                                            struct device_attribute *attr,
-                                            const char *buf, size_t count)
-{
-       struct stlc45xx *stlc = dev_get_drvdata(dev);
-
-       stlc45xx_debug(DEBUG_FUNC, "%s", __func__);
-
-       mutex_lock(&stlc->mutex);
-
-       if (count != RSSI_CAL_ARRAY_LEN) {
-               stlc45xx_error("invalid cal_rssi length: %zu", count);
-               count = 0;
-               goto out_unlock;
-       }
-
-       kfree(stlc->cal_rssi);
-
-       stlc->cal_rssi = kmemdup(buf, RSSI_CAL_ARRAY_LEN, GFP_KERNEL);
-
-       if (!stlc->cal_rssi) {
-               stlc45xx_error("failed to allocate memory for cal_rssi");
-               count = 0;
-               goto out_unlock;
-       }
-
- out_unlock:
-       mutex_unlock(&stlc->mutex);
-
-       return count;
-}
-
-static ssize_t stlc45xx_sysfs_show_cal_channels(struct device *dev,
-                                               struct device_attribute *attr,
-                                               char *buf)
-{
-       struct stlc45xx *stlc = dev_get_drvdata(dev);
-       ssize_t len;
-
-       stlc45xx_debug(DEBUG_FUNC, "%s", __func__);
-
-       len = PAGE_SIZE;
-
-       mutex_lock(&stlc->mutex);
-
-       if (stlc->cal_channels)
-               hex_dump_to_buffer(stlc->cal_channels, CHANNEL_CAL_ARRAY_LEN,
-                                  16, 2, buf, len, 0);
-
-       mutex_unlock(&stlc->mutex);
-
-       len = strlen(buf);
-
-       return len;
-}
-
-static ssize_t stlc45xx_sysfs_store_cal_channels(struct device *dev,
-                                                struct device_attribute *attr,
-                                                const char *buf, size_t count)
-{
-       struct stlc45xx *stlc = dev_get_drvdata(dev);
-
-       stlc45xx_debug(DEBUG_FUNC, "%s", __func__);
-
-       mutex_lock(&stlc->mutex);
-
-       if (count != CHANNEL_CAL_ARRAY_LEN) {
-               stlc45xx_error("invalid cal_channels size: %zu ", count);
-               count = 0;
-               goto out_unlock;
-       }
-
-       kfree(stlc->cal_channels);
-
-       stlc->cal_channels = kmemdup(buf, count, GFP_KERNEL);
-
-       if (!stlc->cal_channels) {
-               stlc45xx_error("failed to allocate memory for cal_channels");
-               count = 0;
-               goto out_unlock;
-       }
-
-out_unlock:
-       mutex_unlock(&stlc->mutex);
-
-       return count;
-}
-
-static ssize_t stlc45xx_sysfs_show_tx_buf(struct device *dev,
-                                         struct device_attribute *attr,
-                                         char *buf)
-{
-       struct stlc45xx *stlc = dev_get_drvdata(dev);
-       struct txbuffer *entry;
-       ssize_t len = 0;
-
-       stlc45xx_debug(DEBUG_FUNC, "%s()", __func__);
-
-       mutex_lock(&stlc->mutex);
-
-       list_for_each_entry(entry, &stlc->tx_sent, tx_list) {
-               len += sprintf(buf + len, "0x%x: 0x%x-0x%x\n",
-                              entry->handle, entry->start,
-                              entry->end);
-       }
-
-       mutex_unlock(&stlc->mutex);
-
-       return len;
-}
-
-static DEVICE_ATTR(cal_rssi, S_IRUGO | S_IWUSR,
-                  stlc45xx_sysfs_show_cal_rssi,
-                  stlc45xx_sysfs_store_cal_rssi);
-static DEVICE_ATTR(cal_channels, S_IRUGO | S_IWUSR,
-                  stlc45xx_sysfs_show_cal_channels,
-                  stlc45xx_sysfs_store_cal_channels);
-static DEVICE_ATTR(tx_buf, S_IRUGO, stlc45xx_sysfs_show_tx_buf, NULL);
-
-static void stlc45xx_spi_read(struct stlc45xx *stlc, unsigned long addr,
-                             void *buf, size_t len)
-{
-       struct spi_transfer t[2];
-       struct spi_message m;
-
-       /* We first push the address */
-       addr = (addr << 8) | ADDR_READ_BIT_15;
-
-       spi_message_init(&m);
-       memset(t, 0, sizeof(t));
-
-       t[0].tx_buf = &addr;
-       t[0].len = 2;
-       spi_message_add_tail(&t[0], &m);
-
-       t[1].rx_buf = buf;
-       t[1].len = len;
-       spi_message_add_tail(&t[1], &m);
-
-       spi_sync(stlc->spi, &m);
-}
-
-
-static void stlc45xx_spi_write(struct stlc45xx *stlc, unsigned long addr,
-                              void *buf, size_t len)
-{
-       struct spi_transfer t[3];
-       struct spi_message m;
-       u16 last_word;
-
-       /* We first push the address */
-       addr = addr << 8;
-
-       spi_message_init(&m);
-       memset(t, 0, sizeof(t));
-
-       t[0].tx_buf = &addr;
-       t[0].len = 2;
-       spi_message_add_tail(&t[0], &m);
-
-       t[1].tx_buf = buf;
-       t[1].len = len;
-       spi_message_add_tail(&t[1], &m);
-
-       if (len % 2) {
-               last_word = ((u8 *)buf)[len - 1];
-
-               t[2].tx_buf = &last_word;
-               t[2].len = 2;
-               spi_message_add_tail(&t[2], &m);
-       }
-
-       spi_sync(stlc->spi, &m);
-}
-
-static u16 stlc45xx_read16(struct stlc45xx *stlc, unsigned long addr)
-{
-       u16 val;
-
-       stlc45xx_spi_read(stlc, addr, &val, sizeof(val));
-
-       return val;
-}
-
-static u32 stlc45xx_read32(struct stlc45xx *stlc, unsigned long addr)
-{
-       u32 val;
-
-       stlc45xx_spi_read(stlc, addr, &val, sizeof(val));
-
-       return val;
-}
-
-static void stlc45xx_write16(struct stlc45xx *stlc, unsigned long addr, u16 val)
-{
-       stlc45xx_spi_write(stlc, addr, &val, sizeof(val));
-}
-
-static void stlc45xx_write32(struct stlc45xx *stlc, unsigned long addr, u32 val)
-{
-       stlc45xx_spi_write(stlc, addr, &val, sizeof(val));
-}
-
-struct stlc45xx_spi_reg {
-       u16 address;
-       u16 length;
-       char *name;
-};
-
-/* caller must hold tx_lock */
-static void stlc45xx_txbuffer_dump(struct stlc45xx *stlc)
-{
-       struct txbuffer *txbuffer;
-       char *buf, *pos;
-       int buf_len, l, count;
-
-       if (!(DEBUG_LEVEL & DEBUG_TXBUFFER))
-               return;
-
-       stlc45xx_debug(DEBUG_FUNC, "%s()", __func__);
-
-       buf_len = 500;
-       buf = kmalloc(buf_len, GFP_ATOMIC);
-       if (!buf)
-               return;
-
-       pos = buf;
-       count = 0;
-
-       list_for_each_entry(txbuffer, &stlc->txbuffer, buffer_list) {
-               l = snprintf(pos, buf_len, "0x%x-0x%x,",
-                            txbuffer->start, txbuffer->end);
-               /* drop the null byte */
-               pos += l;
-               buf_len -= l;
-               count++;
-       }
-
-       if (count == 0)
-               *pos = '\0';
-       else
-               *--pos = '\0';
-
-       stlc45xx_debug(DEBUG_TXBUFFER, "txbuffer: in buffer %d regions: %s",
-                      count, buf);
-
-       kfree(buf);
-}
-
-/* caller must hold tx_lock */
-static int stlc45xx_txbuffer_find(struct stlc45xx *stlc, size_t len)
-{
-       struct txbuffer *txbuffer;
-       int pos;
-
-       stlc45xx_debug(DEBUG_FUNC, "%s()", __func__);
-
-       pos = FIRMWARE_TXBUFFER_START;
-
-       if (list_empty(&stlc->txbuffer))
-               goto out;
-
-       /*
-        * the entries in txbuffer must be in the same order as they are in
-        * the real buffer
-        */
-       list_for_each_entry(txbuffer, &stlc->txbuffer, buffer_list) {
-               if (pos + len < txbuffer->start)
-                       break;
-               pos = ALIGN(txbuffer->end + 1, 4);
-       }
-
-       if (pos + len > FIRMWARE_TXBUFFER_END)
-               /* not enough room */
-               pos = -1;
-
-       stlc45xx_debug(DEBUG_TXBUFFER, "txbuffer: find %zu B: 0x%x", len, pos);
-
-out:
-       return pos;
-}
-
-static int stlc45xx_txbuffer_add(struct stlc45xx *stlc,
-                                struct txbuffer *txbuffer)
-{
-       struct txbuffer *r, *prev = NULL;
-
-       if (list_empty(&stlc->txbuffer)) {
-               list_add(&txbuffer->buffer_list, &stlc->txbuffer);
-               return 0;
-       }
-
-       r = list_first_entry(&stlc->txbuffer, struct txbuffer, buffer_list);
-
-       if (txbuffer->start < r->start) {
-               /* add to the beginning of the list */
-               list_add(&txbuffer->buffer_list, &stlc->txbuffer);
-               return 0;
-       }
-
-       prev = NULL;
-       list_for_each_entry(r, &stlc->txbuffer, buffer_list) {
-               /* skip first entry, we checked for that above */
-               if (!prev) {
-                       prev = r;
-                       continue;
-               }
-
-               /* double-check overlaps */
-               WARN_ON_ONCE(txbuffer->start >= r->start &&
-                            txbuffer->start <= r->end);
-               WARN_ON_ONCE(txbuffer->end >= r->start &&
-                            txbuffer->end <= r->end);
-
-               if (prev->end < txbuffer->start &&
-                   txbuffer->end < r->start) {
-                       /* insert at this spot */
-                       list_add_tail(&txbuffer->buffer_list, &r->buffer_list);
-                       return 0;
-               }
-
-               prev = r;
-       }
-
-       /* not found */
-       list_add_tail(&txbuffer->buffer_list, &stlc->txbuffer);
-
-       return 0;
-
-}
-
-/* caller must hold tx_lock */
-static struct txbuffer *stlc45xx_txbuffer_alloc(struct stlc45xx *stlc,
-                                                size_t frame_len)
-{
-       struct txbuffer *entry = NULL;
-       size_t len;
-       int pos;
-
-       stlc45xx_debug(DEBUG_FUNC, "%s()", __func__);
-
-       len = FIRMWARE_TXBUFFER_HEADER + frame_len + FIRMWARE_TXBUFFER_TRAILER;
-       pos = stlc45xx_txbuffer_find(stlc, len);
-
-       if (pos < 0)
-               return NULL;
-
-       WARN_ON_ONCE(pos + len > FIRMWARE_TXBUFFER_END);
-       WARN_ON_ONCE(pos < FIRMWARE_TXBUFFER_START);
-
-       entry = kmalloc(sizeof(*entry), GFP_ATOMIC);
-       entry->start = pos;
-       entry->frame_start = pos + FIRMWARE_TXBUFFER_HEADER;
-       entry->end = entry->start + len - 1;
-
-       stlc45xx_debug(DEBUG_TXBUFFER, "txbuffer: allocated 0x%x-0x%x",
-                      entry->start, entry->end);
-
-       stlc45xx_txbuffer_add(stlc, entry);
-
-       stlc45xx_txbuffer_dump(stlc);
-
-       return entry;
-}
-
-/* caller must hold tx_lock */
-static void stlc45xx_txbuffer_free(struct stlc45xx *stlc,
-                                  struct txbuffer *txbuffer)
-{
-       stlc45xx_debug(DEBUG_FUNC, "%s()", __func__);
-
-       stlc45xx_debug(DEBUG_TXBUFFER, "txbuffer: freed 0x%x-0x%x",
-                      txbuffer->start, txbuffer->end);
-
-       list_del(&txbuffer->buffer_list);
-       kfree(txbuffer);
-}
-
-
-static int stlc45xx_wait_bit(struct stlc45xx *stlc, u16 reg, u32 mask,
-                            u32 expected)
-{
-       int i;
-       char buffer[4];
-
-       for (i = 0; i < 2000; i++) {
-               stlc45xx_spi_read(stlc, reg, buffer, sizeof(buffer));
-               if (((*(u32 *)buffer) & mask) == expected)
-                       return 1;
-               msleep(1);
-       }
-
-       return 0;
-}
-
-static int stlc45xx_request_firmware(struct stlc45xx *stlc)
-{
-       const struct firmware *fw;
-       int ret;
-
-       /* FIXME: should driver use it's own struct device? */
-       ret = request_firmware(&fw, "3826.arm", &stlc->spi->dev);
-
-       if (ret < 0) {
-               stlc45xx_error("request_firmware() failed: %d", ret);
-               return ret;
-       }
-
-       if (fw->size % 4) {
-               stlc45xx_error("firmware size is not multiple of 32bit: %zu",
-                              fw->size);
-               return -EILSEQ; /* Illegal byte sequence  */;
-       }
-
-       if (fw->size < 1000) {
-               stlc45xx_error("firmware is too small: %zu", fw->size);
-               return -EILSEQ;
-       }
-
-       stlc->fw = kmemdup(fw->data, fw->size, GFP_KERNEL);
-       if (!stlc->fw) {
-               stlc45xx_error("could not allocate memory for firmware");
-               return -ENOMEM;
-       }
-
-       stlc->fw_len = fw->size;
-
-       release_firmware(fw);
-
-       return 0;
-}
-
-static int stlc45xx_upload_firmware(struct stlc45xx *stlc)
-{
-       struct s_dma_regs dma_regs;
-       unsigned long fw_len, fw_addr;
-       long _fw_len;
-       int ret;
-
-       stlc45xx_debug(DEBUG_FUNC, "%s", __func__);
-
-       if (!stlc->fw) {
-               ret = stlc45xx_request_firmware(stlc);
-               if (ret < 0)
-                       return ret;
-       }
-
-       /* stop the device */
-       stlc45xx_write16(stlc, SPI_ADRS_DEV_CTRL_STAT,
-                        SPI_CTRL_STAT_HOST_OVERRIDE | SPI_CTRL_STAT_HOST_RESET
-                        | SPI_CTRL_STAT_START_HALTED);
-
-       msleep(TARGET_BOOT_SLEEP);
-
-       stlc45xx_write16(stlc, SPI_ADRS_DEV_CTRL_STAT,
-                        SPI_CTRL_STAT_HOST_OVERRIDE
-                        | SPI_CTRL_STAT_START_HALTED);
-
-       msleep(TARGET_BOOT_SLEEP);
-
-       fw_addr = FIRMWARE_ADDRESS;
-       fw_len = stlc->fw_len;
-
-       while (fw_len > 0) {
-               _fw_len = (fw_len > SPI_MAX_PACKET_SIZE)
-                       ? SPI_MAX_PACKET_SIZE : fw_len;
-               dma_regs.cmd = SPI_DMA_WRITE_CTRL_ENABLE;
-               dma_regs.len = cpu_to_le16(_fw_len);
-               dma_regs.addr = cpu_to_le32(fw_addr);
-
-               fw_len -= _fw_len;
-               fw_addr += _fw_len;
-
-               stlc45xx_write16(stlc, SPI_ADRS_DMA_WRITE_CTRL, dma_regs.cmd);
-
-               if (stlc45xx_wait_bit(stlc, SPI_ADRS_DMA_WRITE_CTRL,
-                                     HOST_ALLOWED, HOST_ALLOWED) == 0) {
-                       stlc45xx_error("fw_upload not allowed to DMA write");
-                       return -EAGAIN;
-               }
-
-               stlc45xx_write16(stlc, SPI_ADRS_DMA_WRITE_LEN, dma_regs.len);
-               stlc45xx_write32(stlc, SPI_ADRS_DMA_WRITE_BASE, dma_regs.addr);
-
-               stlc45xx_spi_write(stlc, SPI_ADRS_DMA_DATA, stlc->fw, _fw_len);
-
-               /* FIXME: I think this doesn't work if firmware is large,
-                * this loop goes to second round. fw->data is not
-                * increased at all! */
-       }
-
-       BUG_ON(fw_len != 0);
-
-       /* enable host interrupts */
-       stlc45xx_write32(stlc, SPI_ADRS_HOST_INT_EN, SPI_HOST_INTS_DEFAULT);
-
-       /* boot the device */
-       stlc45xx_write16(stlc, SPI_ADRS_DEV_CTRL_STAT,
-                        SPI_CTRL_STAT_HOST_OVERRIDE | SPI_CTRL_STAT_HOST_RESET
-                        | SPI_CTRL_STAT_RAM_BOOT);
-
-       msleep(TARGET_BOOT_SLEEP);
-
-       stlc45xx_write16(stlc, SPI_ADRS_DEV_CTRL_STAT,
-                        SPI_CTRL_STAT_HOST_OVERRIDE | SPI_CTRL_STAT_RAM_BOOT);
-       msleep(TARGET_BOOT_SLEEP);
-
-       return 0;
-}
-
-/* caller must hold tx_lock */
-static void stlc45xx_check_txsent(struct stlc45xx *stlc)
-{
-       struct txbuffer *entry, *n;
-
-       list_for_each_entry_safe(entry, n, &stlc->tx_sent, tx_list) {
-               if (time_after(jiffies, entry->lifetime)) {
-                       if (net_ratelimit())
-                               stlc45xx_warning("frame 0x%x lifetime exceeded",
-                                                entry->start);
-                       list_del(&entry->tx_list);
-                       skb_pull(entry->skb, entry->header_len);
-                       ieee80211_tx_status(stlc->hw, entry->skb);
-                       stlc45xx_txbuffer_free(stlc, entry);
-               }
-       }
-}
-
-static void stlc45xx_power_off(struct stlc45xx *stlc)
-{
-       disable_irq(gpio_to_irq(stlc45xx_gpio_irq));
-       gpio_set_value(stlc45xx_gpio_power, 0);
-}
-
-static void stlc45xx_power_on(struct stlc45xx *stlc)
-{
-       gpio_set_value(stlc45xx_gpio_power, 1);
-       enable_irq(gpio_to_irq(stlc45xx_gpio_irq));
-
-       /*
-        * need to wait a while before device can be accessed, the length
-        * is just a guess
-        */
-       msleep(10);
-}
-
-/* caller must hold tx_lock */
-static void stlc45xx_flush_queues(struct stlc45xx *stlc)
-{
-       struct txbuffer *entry;
-
-       while (!list_empty(&stlc->tx_sent)) {
-               entry = list_first_entry(&stlc->tx_sent,
-                                        struct txbuffer, tx_list);
-               list_del(&entry->tx_list);
-               dev_kfree_skb(entry->skb);
-               stlc45xx_txbuffer_free(stlc, entry);
-       }
-
-       WARN_ON(!list_empty(&stlc->tx_sent));
-
-       while (!list_empty(&stlc->tx_pending)) {
-               entry = list_first_entry(&stlc->tx_pending,
-                                        struct txbuffer, tx_list);
-               list_del(&entry->tx_list);
-               dev_kfree_skb(entry->skb);
-               stlc45xx_txbuffer_free(stlc, entry);
-       }
-
-       WARN_ON(!list_empty(&stlc->tx_pending));
-       WARN_ON(!list_empty(&stlc->txbuffer));
-}
-
-static void stlc45xx_work_reset(struct work_struct *work)
-{
-       struct stlc45xx *stlc = container_of(work, struct stlc45xx,
-                                            work_reset);
-
-       mutex_lock(&stlc->mutex);
-
-       if (stlc->fw_state != FW_STATE_RESET)
-               goto out;
-
-       stlc45xx_power_off(stlc);
-
-       mutex_unlock(&stlc->mutex);
-
-       /* wait that all work_structs have finished, we can't hold
-        * stlc->mutex to avoid deadlock */
-       cancel_work_sync(&stlc->work);
-
-       /* FIXME: find out good value to wait for chip power down */
-       msleep(100);
-
-       mutex_lock(&stlc->mutex);
-
-       /* FIXME: we should gracefully handle if the state has changed
-        * after re-acquiring mutex */
-       WARN_ON(stlc->fw_state != FW_STATE_RESET);
-
-       spin_lock_bh(&stlc->tx_lock);
-       stlc45xx_flush_queues(stlc);
-       spin_unlock_bh(&stlc->tx_lock);
-
-       stlc->fw_state = FW_STATE_RESETTING;
-
-       stlc45xx_power_on(stlc);
-       stlc45xx_upload_firmware(stlc);
-
-out:
-       mutex_unlock(&stlc->mutex);
-}
-
-/* caller must hold mutex */
-static void stlc45xx_reset(struct stlc45xx *stlc)
-{
-       stlc45xx_warning("resetting firmware");
-       stlc->fw_state = FW_STATE_RESET;
-       ieee80211_stop_queues(stlc->hw);
-       queue_work(stlc->hw->workqueue, &stlc->work_reset);
-}
-
-static void stlc45xx_work_tx_timeout(struct work_struct *work)
-{
-       struct stlc45xx *stlc = container_of(work, struct stlc45xx,
-                                            work_tx_timeout.work);
-
-       stlc45xx_warning("tx timeout");
-
-       mutex_lock(&stlc->mutex);
-
-       if (stlc->fw_state != FW_STATE_READY)
-               goto out;
-
-       stlc45xx_reset(stlc);
-
-out:
-       mutex_unlock(&stlc->mutex);
-}
-
-static void stlc45xx_int_ack(struct stlc45xx *stlc, u32 val)
-{
-       stlc45xx_debug(DEBUG_FUNC, "%s", __func__);
-
-       stlc45xx_write32(stlc, SPI_ADRS_HOST_INT_ACK, val);
-}
-
-static void stlc45xx_wakeup(struct stlc45xx *stlc)
-{
-       unsigned long timeout;
-       u32 ints;
-
-       stlc45xx_debug(DEBUG_FUNC, "%s", __func__);
-
-       /* wake the chip */
-       stlc45xx_write32(stlc, SPI_ADRS_ARM_INTERRUPTS, SPI_TARGET_INT_WAKEUP);
-
-       /* And wait for the READY interrupt */
-       timeout = jiffies + HZ;
-
-       ints = stlc45xx_read32(stlc, SPI_ADRS_HOST_INTERRUPTS);
-       while (!(ints & SPI_HOST_INT_READY)) {
-               if (time_after(jiffies, timeout))
-                               goto out;
-               ints = stlc45xx_read32(stlc, SPI_ADRS_HOST_INTERRUPTS);
-       }
-
-       stlc45xx_int_ack(stlc, SPI_HOST_INT_READY);
-
-out:
-       return;
-}
-
-static void stlc45xx_sleep(struct stlc45xx *stlc)
-{
-       stlc45xx_debug(DEBUG_FUNC, "%s", __func__);
-
-       stlc45xx_write32(stlc, SPI_ADRS_ARM_INTERRUPTS, SPI_TARGET_INT_SLEEP);
-}
-
-static void stlc45xx_int_ready(struct stlc45xx *stlc)
-{
-       stlc45xx_debug(DEBUG_FUNC, "%s", __func__);
-
-       stlc45xx_write32(stlc, SPI_ADRS_HOST_INT_EN,
-                        SPI_HOST_INT_UPDATE | SPI_HOST_INT_SW_UPDATE);
-
-       switch (stlc->fw_state) {
-       case FW_STATE_BOOTING:
-               stlc->fw_state = FW_STATE_READY;
-               complete(&stlc->fw_comp);
-               break;
-       case FW_STATE_RESETTING:
-               stlc->fw_state = FW_STATE_READY;
-
-               stlc45xx_tx_scan(stlc);
-               stlc45xx_tx_setup(stlc);
-               stlc45xx_tx_edcf(stlc);
-
-               ieee80211_wake_queues(stlc->hw);
-               break;
-       default:
-               break;
-       }
-}
-
-static int stlc45xx_rx_txack(struct stlc45xx *stlc, struct sk_buff *skb)
-{
-       struct ieee80211_tx_info *info;
-       struct s_lm_control *control;
-       struct s_lmo_tx *tx;
-       struct txbuffer *entry;
-       int found = 0;
-
-       stlc45xx_debug(DEBUG_FUNC, "%s", __func__);
-
-       control = (struct s_lm_control *) skb->data;
-       tx = (struct s_lmo_tx *) (control + 1);
-
-       if (list_empty(&stlc->tx_sent)) {
-               if (net_ratelimit())
-                       stlc45xx_warning("no frames waiting for "
-                                        "acknowledgement");
-               return -1;
-       }
-
-       list_for_each_entry(entry, &stlc->tx_sent, tx_list) {
-               if (control->handle == entry->handle) {
-                       found = 1;
-                       break;
-               }
-       }
-
-       if (!found) {
-               if (net_ratelimit())
-                       stlc45xx_warning("couldn't find frame for tx ack 0x%x",
-                                        control->handle);
-               return -1;
-       }
-
-       stlc45xx_debug(DEBUG_TX, "TX ACK 0x%x", entry->handle);
-
-       if (entry->status_needed) {
-               info = IEEE80211_SKB_CB(entry->skb);
-
-               if (!(tx->flags & LM_TX_FAILED)) {
-                       /* frame was acked */
-                       info->flags |= IEEE80211_TX_STAT_ACK;
-                       info->status.ack_signal = tx->rcpi / 2 - 110;
-               }
-
-               skb_pull(entry->skb, entry->header_len);
-
-               ieee80211_tx_status(stlc->hw, entry->skb);
-       }
-
-       list_del(&entry->tx_list);
-
-       stlc45xx_check_txsent(stlc);
-       if (list_empty(&stlc->tx_sent))
-               /* there are no pending frames, we can stop the tx timeout
-                * timer */
-               cancel_delayed_work(&stlc->work_tx_timeout);
-
-       spin_lock_bh(&stlc->tx_lock);
-
-       stlc45xx_txbuffer_free(stlc, entry);
-
-       if (stlc->tx_queue_stopped &&
-           stlc45xx_txbuffer_find(stlc, MAX_FRAME_LEN) != -1) {
-               stlc45xx_debug(DEBUG_QUEUE, "room in tx buffer, waking queues");
-               ieee80211_wake_queues(stlc->hw);
-               stlc->tx_queue_stopped = 0;
-       }
-
-       spin_unlock_bh(&stlc->tx_lock);
-
-       return 0;
-}
-
-static int stlc45xx_rx_control(struct stlc45xx *stlc, struct sk_buff *skb)
-{
-       struct s_lm_control *control;
-       int ret = 0;
-
-       stlc45xx_debug(DEBUG_FUNC, "%s", __func__);
-
-       control = (struct s_lm_control *) skb->data;
-
-       switch (control->oid) {
-       case LM_OID_TX:
-               ret = stlc45xx_rx_txack(stlc, skb);
-               break;
-       case LM_OID_SETUP:
-       case LM_OID_SCAN:
-       case LM_OID_TRAP:
-       case LM_OID_EDCF:
-       case LM_OID_KEYCACHE:
-       case LM_OID_PSM:
-       case LM_OID_STATS:
-       case LM_OID_LED:
-       default:
-               stlc45xx_warning("unhandled rx control oid %d\n",
-                                control->oid);
-               break;
-       }
-
-       dev_kfree_skb(skb);
-
-       return ret;
-}
-
-/* copied from mac80211 */
-static void stlc45xx_parse_elems(u8 *start, size_t len,
-                                struct stlc45xx_ie_tim **tim,
-                                size_t *tim_len)
-{
-       size_t left = len;
-       u8 *pos = start;
-
-       while (left >= 2) {
-               u8 id, elen;
-
-               id = *pos++;
-               elen = *pos++;
-               left -= 2;
-
-               if (elen > left)
-                       return;
-
-               switch (id) {
-               case WLAN_EID_TIM:
-                       *tim = (struct stlc45xx_ie_tim *) pos;
-                       *tim_len = elen;
-                       break;
-               default:
-                       break;
-               }
-
-               left -= elen;
-               pos += elen;
-       }
-}
-
-/*
- * mac80211 doesn't have support for asking frames with PS-Poll, so let's
- * implement in the driver for now. We have to add support to mac80211
- * later.
- */
-static int stlc45xx_check_more_data(struct stlc45xx *stlc, struct sk_buff *skb)
-{
-       struct s_lm_data_in *data = (struct s_lm_data_in *) skb->data;
-       struct ieee80211_hdr *hdr;
-       size_t len;
-       u16 fc;
-
-       hdr = (void *) skb->data + sizeof(*data);
-       len = skb->len - sizeof(*data);
-
-       /* minimum frame length is the null frame length 24 bytes */
-       if (len < 24) {
-               stlc45xx_warning("invalid frame length when checking for "
-                                "more data");
-               return -EINVAL;
-       }
-
-       fc = le16_to_cpu(hdr->frame_control);
-       if (!(fc & IEEE80211_FCTL_FROMDS))
-               /* this is not from DS */
-               return 0;
-
-       if (compare_ether_addr(hdr->addr1, stlc->mac_addr) != 0)
-               /* the frame was not for us */
-               return 0;
-
-       if (!(fc & IEEE80211_FCTL_MOREDATA)) {
-               /* AP has no more frames buffered for us */
-               stlc45xx_debug(DEBUG_PSM, "all buffered frames retrieved");
-               stlc->pspolling = false;
-               return 0;
-       }
-
-       /* MOREDATA bit is set, let's ask for a new frame from the AP */
-       stlc45xx_tx_pspoll(stlc, stlc->psm);
-
-       return 0;
-}
-
-/*
- * mac80211 cannot read TIM from beacons, so let's add a hack to the
- * driver. We have to add support to mac80211 later.
- */
-static int stlc45xx_rx_data_beacon(struct stlc45xx *stlc, struct sk_buff *skb)
-{
-       struct s_lm_data_in *data = (struct s_lm_data_in *) skb->data;
-       size_t len = skb->len, tim_len = 0, baselen, pvbmap_len;
-       struct ieee80211_mgmt *mgmt;
-       struct stlc45xx_ie_tim *tim = NULL;
-       int bmap_offset, index, aid_bit;
-
-       mgmt = (void *) skb->data + sizeof(*data);
-
-       baselen = (u8 *) mgmt->u.beacon.variable - (u8 *) mgmt;
-       if (baselen > len) {
-               stlc45xx_warning("invalid baselen in beacon");
-               return -EINVAL;
-       }
-
-       stlc45xx_parse_elems(mgmt->u.beacon.variable, len - baselen, &tim,
-                            &tim_len);
-
-       if (!tim) {
-               stlc45xx_warning("didn't find tim from a beacon");
-               return -EINVAL;
-       }
-
-       bmap_offset = tim->bmap_control & 0xfe;
-       index = stlc->aid / 8 - bmap_offset;
-
-       pvbmap_len = tim_len - 3;
-       if (index > pvbmap_len)
-               return -EINVAL;
-
-       aid_bit = !!(tim->pvbmap[index] & (1 << stlc->aid % 8));
-
-       stlc45xx_debug(DEBUG_PSM, "fc 0x%x duration %d seq %d dtim %u "
-                      "bmap_control 0x%x aid_bit %d",
-                      mgmt->frame_control, mgmt->duration, mgmt->seq_ctrl >> 4,
-                      tim->dtim_count, tim->bmap_control, aid_bit);
-
-       if (!aid_bit)
-               return 0;
-
-       stlc->pspolling = true;
-       stlc45xx_tx_pspoll(stlc, stlc->psm);
-
-       return 0;
-}
-
-static int stlc45xx_rx_data(struct stlc45xx *stlc, struct sk_buff *skb)
-{
-       struct ieee80211_rx_status status;
-       struct s_lm_data_in *data = (struct s_lm_data_in *) skb->data;
-       int align = 0;
-       u8 *p, align_len;
-       u16 len;
-
-       stlc45xx_debug(DEBUG_FUNC, "%s", __func__);
-
-       if (stlc->psm) {
-               if (data->flags & LM_IN_BEACON)
-                       stlc45xx_rx_data_beacon(stlc, skb);
-               else if (stlc->pspolling && (data->flags & LM_IN_DATA))
-                       stlc45xx_check_more_data(stlc, skb);
-       }
-
-       memset(&status, 0, sizeof(status));
-
-       status.freq = data->frequency;
-       status.signal = data->rcpi / 2 - 110;
-
-       /* let's assume that maximum rcpi value is 140 (= 35 dBm) */
-       status.qual = data->rcpi * 100 / 140;
-
-       status.band = IEEE80211_BAND_2GHZ;
-
-       /*
-        * FIXME: this gives warning from __ieee80211_rx()
-        *
-        * status.rate_idx = data->rate;
-        */
-
-       len = data->length;
-
-       if (data->flags & LM_FLAG_ALIGN)
-               align = 1;
-
-       skb_pull(skb, sizeof(*data));
-
-       if (align) {
-               p = skb->data;
-               align_len = *p;
-               skb_pull(skb, align_len);
-       }
-
-       skb_trim(skb, len);
-
-       stlc45xx_debug(DEBUG_RX, "rx data 0x%p %d B", skb->data, skb->len);
-       stlc45xx_dump(DEBUG_RX_CONTENT, skb->data, skb->len);
-
-       memcpy(IEEE80211_SKB_RXCB(skb), &status, sizeof(status));
-       ieee80211_rx(stlc->hw, skb);
-
-       return 0;
-}
-
-
-
-static int stlc45xx_rx(struct stlc45xx *stlc)
-{
-       struct s_lm_control *control;
-       struct sk_buff *skb;
-       int ret;
-       u16 len;
-
-       stlc45xx_debug(DEBUG_FUNC, "%s", __func__);
-
-       stlc45xx_wakeup(stlc);
-
-       /* dummy read to flush SPI DMA controller bug */
-       stlc45xx_read16(stlc, SPI_ADRS_GEN_PURP_1);
-
-       len = stlc45xx_read16(stlc, SPI_ADRS_DMA_DATA);
-
-       if (len == 0) {
-               stlc45xx_warning("rx request of zero bytes");
-               return 0;
-       }
-
-       skb = dev_alloc_skb(len);
-       if (!skb) {
-               stlc45xx_warning("could not alloc skb");
-               return 0;
-       }
-
-       stlc45xx_spi_read(stlc, SPI_ADRS_DMA_DATA, skb_put(skb, len), len);
-
-       stlc45xx_sleep(stlc);
-
-       stlc45xx_debug(DEBUG_RX, "rx frame 0x%p %d B", skb->data, skb->len);
-       stlc45xx_dump(DEBUG_RX_CONTENT, skb->data, skb->len);
-
-       control = (struct s_lm_control *) skb->data;
-
-       if (control->flags & LM_FLAG_CONTROL)
-               ret = stlc45xx_rx_control(stlc, skb);
-       else
-               ret = stlc45xx_rx_data(stlc, skb);
-
-       return ret;
-}
-
-
-static irqreturn_t stlc45xx_interrupt(int irq, void *config)
-{
-       struct spi_device *spi = config;
-       struct stlc45xx *stlc = dev_get_drvdata(&spi->dev);
-
-       stlc45xx_debug(DEBUG_IRQ, "IRQ");
-
-       queue_work(stlc->hw->workqueue, &stlc->work);
-
-       return IRQ_HANDLED;
-}
-
-static int stlc45xx_tx_frame(struct stlc45xx *stlc, u32 address,
-                            void *buf, size_t len)
-{
-       struct s_dma_regs dma_regs;
-       unsigned long timeout;
-       int ret = 0;
-       u32 ints;
-
-       stlc->tx_frames++;
-
-       stlc45xx_debug(DEBUG_FUNC, "%s", __func__);
-
-       stlc45xx_debug(DEBUG_TX, "tx frame 0x%p %zu B", buf, len);
-       stlc45xx_dump(DEBUG_TX_CONTENT, buf, len);
-
-       stlc45xx_wakeup(stlc);
-
-       dma_regs.cmd  = SPI_DMA_WRITE_CTRL_ENABLE;
-       dma_regs.len  = cpu_to_le16(len);
-       dma_regs.addr = cpu_to_le32(address);
-
-       stlc45xx_spi_write(stlc, SPI_ADRS_DMA_WRITE_CTRL, &dma_regs,
-                          sizeof(dma_regs));
-
-       stlc45xx_spi_write(stlc, SPI_ADRS_DMA_DATA, buf, len);
-
-       timeout = jiffies + 2 * HZ;
-       ints = stlc45xx_read32(stlc, SPI_ADRS_HOST_INTERRUPTS);
-       while (!(ints & SPI_HOST_INT_WR_READY)) {
-               if (time_after(jiffies, timeout)) {
-                       stlc45xx_warning("WR_READY timeout");
-                       ret = -1;
-                       goto out;
-               }
-               ints = stlc45xx_read32(stlc, SPI_ADRS_HOST_INTERRUPTS);
-       }
-
-       stlc45xx_int_ack(stlc, SPI_HOST_INT_WR_READY);
-
-       stlc45xx_sleep(stlc);
-
-out:
-       return ret;
-}
-
-static int stlc45xx_wq_tx(struct stlc45xx *stlc)
-{
-       struct txbuffer *entry;
-       int ret = 0;
-
-       spin_lock_bh(&stlc->tx_lock);
-
-       while (!list_empty(&stlc->tx_pending)) {
-               entry = list_entry(stlc->tx_pending.next,
-                                  struct txbuffer, tx_list);
-
-               list_del_init(&entry->tx_list);
-
-               spin_unlock_bh(&stlc->tx_lock);
-
-               ret = stlc45xx_tx_frame(stlc, entry->frame_start,
-                                       entry->skb->data, entry->skb->len);
-
-               spin_lock_bh(&stlc->tx_lock);
-
-               if (ret < 0) {
-                       /* frame transfer to firmware buffer failed */
-                       /* FIXME: report this to mac80211 */
-                       dev_kfree_skb(entry->skb);
-                       stlc45xx_txbuffer_free(stlc, entry);
-                       goto out;
-               }
-
-               list_add(&entry->tx_list, &stlc->tx_sent);
-               queue_delayed_work(stlc->hw->workqueue,
-                                  &stlc->work_tx_timeout,
-                                  msecs_to_jiffies(TX_TIMEOUT));
-       }
-
-out:
-       spin_unlock_bh(&stlc->tx_lock);
-       return ret;
-}
-
-static void stlc45xx_work(struct work_struct *work)
-{
-       struct stlc45xx *stlc = container_of(work, struct stlc45xx, work);
-       u32 ints;
-       int ret;
-
-       stlc45xx_debug(DEBUG_FUNC, "%s", __func__);
-
-       mutex_lock(&stlc->mutex);
-
-       if (stlc->fw_state == FW_STATE_OFF &&
-           stlc->fw_state == FW_STATE_RESET)
-               goto out;
-
-       ints = stlc45xx_read32(stlc, SPI_ADRS_HOST_INTERRUPTS);
-       stlc45xx_debug(DEBUG_BH, "begin host_ints 0x%08x", ints);
-
-       if (ints & SPI_HOST_INT_READY) {
-               stlc45xx_int_ready(stlc);
-               stlc45xx_int_ack(stlc, SPI_HOST_INT_READY);
-       }
-
-       if (stlc->fw_state != FW_STATE_READY)
-               goto out;
-
-       if (ints & SPI_HOST_INT_UPDATE) {
-               stlc45xx_int_ack(stlc, SPI_HOST_INT_UPDATE);
-               ret = stlc45xx_rx(stlc);
-               if (ret < 0) {
-                       stlc45xx_reset(stlc);
-                       goto out;
-               }
-       }
-       if (ints & SPI_HOST_INT_SW_UPDATE) {
-               stlc45xx_int_ack(stlc, SPI_HOST_INT_SW_UPDATE);
-               ret = stlc45xx_rx(stlc);
-               if (ret < 0) {
-                       stlc45xx_reset(stlc);
-                       goto out;
-               }
-       }
-
-       ret = stlc45xx_wq_tx(stlc);
-       if (ret < 0) {
-               stlc45xx_reset(stlc);
-               goto out;
-       }
-
-       ints = stlc45xx_read32(stlc, SPI_ADRS_HOST_INTERRUPTS);
-       stlc45xx_debug(DEBUG_BH, "end host_ints 0x%08x", ints);
-
-out:
-       mutex_unlock(&stlc->mutex);
-}
-
-static void stlc45xx_tx_edcf(struct stlc45xx *stlc)
-{
-       struct s_lm_control *control;
-       struct s_lmo_edcf *edcf;
-       size_t len, edcf_len;
-
-       stlc45xx_debug(DEBUG_FUNC, "%s", __func__);
-
-       edcf_len = sizeof(*edcf);
-       len = sizeof(*control) + edcf_len;
-       control = kzalloc(len, GFP_KERNEL);
-       edcf = (struct s_lmo_edcf *) (control + 1);
-
-       control->flags = LM_FLAG_CONTROL | LM_CTRL_OPSET;
-       control->length = edcf_len;
-       control->oid = LM_OID_EDCF;
-
-       edcf->slottime = 0x14;
-       edcf->sifs = 10;
-       edcf->eofpad = 6;
-       edcf->maxburst = 1500;
-
-       edcf->queues[0].aifs = 2;
-       edcf->queues[0].pad0 = 1;
-       edcf->queues[0].cwmin = 3;
-       edcf->queues[0].cwmax = 7;
-       edcf->queues[0].txop = 47;
-       edcf->queues[1].aifs = 2;
-       edcf->queues[1].pad0 = 0;
-       edcf->queues[1].cwmin = 7;
-       edcf->queues[1].cwmax = 15;
-       edcf->queues[1].txop = 94;
-       edcf->queues[2].aifs = 3;
-       edcf->queues[2].pad0 = 0;
-       edcf->queues[2].cwmin = 15;
-       edcf->queues[2].cwmax = 1023;
-       edcf->queues[2].txop = 0;
-       edcf->queues[3].aifs = 7;
-       edcf->queues[3].pad0 = 0;
-       edcf->queues[3].cwmin = 15;
-       edcf->queues[3].cwmax = 1023;
-       edcf->queues[3].txop = 0;
-       edcf->queues[4].aifs = 13;
-       edcf->queues[4].pad0 = 99;
-       edcf->queues[4].cwmin = 3437;
-       edcf->queues[4].cwmax = 512;
-       edcf->queues[4].txop = 12;
-       edcf->queues[5].aifs = 142;
-       edcf->queues[5].pad0 = 109;
-       edcf->queues[5].cwmin = 8756;
-       edcf->queues[5].cwmax = 6;
-       edcf->queues[5].txop = 0;
-       edcf->queues[6].aifs = 4;
-       edcf->queues[6].pad0 = 0;
-       edcf->queues[6].cwmin = 0;
-       edcf->queues[6].cwmax = 58705;
-       edcf->queues[6].txop = 25716;
-       edcf->queues[7].aifs = 0;
-       edcf->queues[7].pad0 = 0;
-       edcf->queues[7].cwmin = 0;
-       edcf->queues[7].cwmax = 0;
-       edcf->queues[7].txop = 0;
-
-       stlc45xx_tx_frame(stlc, FIRMWARE_CONFIG_START, control, len);
-
-       kfree(control);
-}
-
-static void stlc45xx_tx_setup(struct stlc45xx *stlc)
-{
-       struct s_lm_control *control;
-       struct s_lmo_setup *setup;
-       size_t len, setup_len;
-
-       stlc45xx_debug(DEBUG_FUNC, "%s", __func__);
-
-       setup_len = sizeof(*setup);
-       len = sizeof(*control) + setup_len;
-       control = kzalloc(len, GFP_KERNEL);
-       setup = (struct s_lmo_setup *) (control + 1);
-
-       control->flags = LM_FLAG_CONTROL | LM_CTRL_OPSET;
-       control->length = setup_len;
-       control->oid = LM_OID_SETUP;
-
-       setup->flags = LM_SETUP_INFRA;
-       setup->antenna = 2;
-       setup->rx_align = 0;
-       setup->rx_buffer = FIRMWARE_RXBUFFER_START;
-       setup->rx_mtu = FIRMWARE_MTU;
-       setup->frontend = 5;
-       setup->timeout = 0;
-       setup->truncate = 48896;
-       setup->bratemask = 0xffffffff;
-       setup->ref_clock = 644245094;
-       setup->lpf_bandwidth = 65535;
-       setup->osc_start_delay = 65535;
-
-       memcpy(setup->macaddr, stlc->mac_addr, ETH_ALEN);
-       memcpy(setup->bssid, stlc->bssid, ETH_ALEN);
-
-       stlc45xx_tx_frame(stlc, FIRMWARE_CONFIG_START, control, len);
-
-       kfree(control);
-}
-
-static void stlc45xx_tx_scan(struct stlc45xx *stlc)
-{
-       struct s_lm_control *control;
-       struct s_lmo_scan *scan;
-       size_t len, scan_len;
-
-       stlc45xx_debug(DEBUG_FUNC, "%s", __func__);
-
-       scan_len = sizeof(*scan);
-       len = sizeof(*control) + scan_len;
-       control = kzalloc(len, GFP_KERNEL);
-       scan = (struct s_lmo_scan *) (control + 1);
-
-       control->flags = LM_FLAG_CONTROL | LM_CTRL_OPSET;
-       control->length = scan_len;
-       control->oid = LM_OID_SCAN;
-
-       scan->flags = LM_SCAN_EXIT;
-       scan->bratemask = 0x15f;
-       scan->aloft[0] = 3;
-       scan->aloft[1] = 3;
-       scan->aloft[2] = 1;
-       scan->aloft[3] = 0;
-       scan->aloft[4] = 0;
-       scan->aloft[5] = 0;
-       scan->aloft[6] = 0;
-       scan->aloft[7] = 0;
-
-       memcpy(&scan->rssical, &stlc->cal_rssi[(stlc->channel - 1) *
-                                              RSSI_CAL_LEN],
-              RSSI_CAL_LEN);
-       memcpy(&scan->channel, &stlc->cal_channels[(stlc->channel - 1) *
-                                                  CHANNEL_CAL_LEN],
-              CHANNEL_CAL_LEN);
-
-       stlc45xx_tx_frame(stlc, FIRMWARE_CONFIG_START, control, len);
-
-       kfree(control);
-}
-
-/*
- * caller must hold mutex
- */
-static int stlc45xx_tx_pspoll(struct stlc45xx *stlc, bool powersave)
-{
-       struct ieee80211_hdr *pspoll;
-       int payload_len, padding, i;
-       struct s_lm_data_out *data;
-       struct txbuffer *entry;
-       struct sk_buff *skb;
-       char *payload;
-       u16 fc;
-
-       skb = dev_alloc_skb(stlc->hw->extra_tx_headroom + 16);
-       if (!skb) {
-               stlc45xx_warning("failed to allocate pspoll frame");
-               return -ENOMEM;
-       }
-       skb_reserve(skb, stlc->hw->extra_tx_headroom);
-
-       pspoll = (struct ieee80211_hdr *) skb_put(skb, 16);
-       memset(pspoll, 0, 16);
-       fc = IEEE80211_FTYPE_CTL | IEEE80211_STYPE_PSPOLL;
-       if (powersave)
-               fc |= IEEE80211_FCTL_PM;
-       pspoll->frame_control = cpu_to_le16(fc);
-       pspoll->duration_id = cpu_to_le16(stlc->aid);
-
-       /* aid in PS-Poll has its two MSBs each set to 1 */
-       pspoll->duration_id |= cpu_to_le16(1 << 15) | cpu_to_le16(1 << 14);
-
-       memcpy(pspoll->addr1, stlc->bssid, ETH_ALEN);
-       memcpy(pspoll->addr2, stlc->mac_addr, ETH_ALEN);
-
-       stlc45xx_debug(DEBUG_PSM, "sending PS-Poll frame to %pM (powersave %d, "
-                      "fc 0x%x, aid %d)", pspoll->addr1,
-                      powersave, fc, stlc->aid);
-
-       spin_lock_bh(&stlc->tx_lock);
-
-       entry = stlc45xx_txbuffer_alloc(stlc, skb->len);
-
-       spin_unlock_bh(&stlc->tx_lock);
-
-       if (!entry) {
-               /*
-                * The queue should be stopped before the firmware buffer
-                * is full, so firmware buffer should always have enough
-                * space.
-                *
-                * But I'm too lazy and omit it for now.
-                */
-               if (net_ratelimit())
-                       stlc45xx_warning("firmware tx buffer full is full "
-                                        "for null frame");
-               return -ENOSPC;
-       }
-
-       payload = skb->data;
-       payload_len = skb->len;
-       padding = (int) (skb->data - sizeof(*data)) & 3;
-       entry->header_len = sizeof(*data) + padding;
-
-       entry->skb = skb;
-       entry->status_needed = false;
-       entry->handle = (u32) skb;
-       entry->lifetime = jiffies + msecs_to_jiffies(TX_FRAME_LIFETIME);
-
-       stlc45xx_debug(DEBUG_TX, "tx data 0x%x (0x%p payload %d B "
-                      "padding %d header_len %d)",
-                      entry->handle, payload, payload_len, padding,
-                      entry->header_len);
-       stlc45xx_dump(DEBUG_TX_CONTENT, payload, payload_len);
-
-       data = (struct s_lm_data_out *) skb_push(skb, entry->header_len);
-
-       memset(data, 0, entry->header_len);
-
-       if (padding)
-               data->flags = LM_FLAG_ALIGN;
-
-       data->flags = LM_OUT_BURST;
-       data->length = payload_len;
-       data->handle = entry->handle;
-       data->aid = 1;
-       data->rts_retries = 7;
-       data->retries = 7;
-       data->aloft_ctrl = 0;
-       data->crypt_offset = 58;
-       data->keytype = 0;
-       data->keylen = 0;
-       data->queue = LM_QUEUE_DATA3;
-       data->backlog = 32;
-       data->antenna = 2;
-       data->cts = 3;
-       data->power = 127;
-
-       for (i = 0; i < 8; i++)
-               data->aloft[i] = 0;
-
-       /*
-        * check if there's enough space in tx buffer
-        *
-        * FIXME: ignored for now
-        */
-
-       stlc45xx_tx_frame(stlc, entry->start, skb->data, skb->len);
-
-       list_add(&entry->tx_list, &stlc->tx_sent);
-
-       return 0;
-}
-
-/*
- * caller must hold mutex
- *
- * shamelessly stolen from mac80211/ieee80211_send_nullfunc
- */
-static int stlc45xx_tx_nullfunc(struct stlc45xx *stlc, bool powersave)
-{
-       struct ieee80211_hdr *nullfunc;
-       int payload_len, padding, i;
-       struct s_lm_data_out *data;
-       struct txbuffer *entry;
-       struct sk_buff *skb;
-       char *payload;
-       u16 fc;
-
-       skb = dev_alloc_skb(stlc->hw->extra_tx_headroom + 24);
-       if (!skb) {
-               stlc45xx_warning("failed to allocate buffer for null frame\n");
-               return -ENOMEM;
-       }
-       skb_reserve(skb, stlc->hw->extra_tx_headroom);
-
-       nullfunc = (struct ieee80211_hdr *) skb_put(skb, 24);
-       memset(nullfunc, 0, 24);
-       fc = IEEE80211_FTYPE_DATA | IEEE80211_STYPE_NULLFUNC |
-            IEEE80211_FCTL_TODS;
-
-       if (powersave)
-               fc |= IEEE80211_FCTL_PM;
-
-       nullfunc->frame_control = cpu_to_le16(fc);
-       memcpy(nullfunc->addr1, stlc->bssid, ETH_ALEN);
-       memcpy(nullfunc->addr2, stlc->mac_addr, ETH_ALEN);
-       memcpy(nullfunc->addr3, stlc->bssid, ETH_ALEN);
-
-       stlc45xx_debug(DEBUG_PSM, "sending Null frame to %pM (powersave %d, "
-                      "fc 0x%x)", nullfunc->addr1, powersave, fc);
-
-       spin_lock_bh(&stlc->tx_lock);
-
-       entry = stlc45xx_txbuffer_alloc(stlc, skb->len);
-
-       spin_unlock_bh(&stlc->tx_lock);
-
-       if (!entry) {
-               /*
-                * The queue should be stopped before the firmware buffer
-                * is full, so firmware buffer should always have enough
-                * space.
-                *
-                * But I'm too lazy and omit it for now.
-                */
-               if (net_ratelimit())
-                       stlc45xx_warning("firmware tx buffer full is full "
-                                        "for null frame");
-               return -ENOSPC;
-       }
-
-       payload = skb->data;
-       payload_len = skb->len;
-       padding = (int) (skb->data - sizeof(*data)) & 3;
-       entry->header_len = sizeof(*data) + padding;
-
-       entry->skb = skb;
-       entry->status_needed = false;
-       entry->handle = (u32) skb;
-       entry->lifetime = jiffies + msecs_to_jiffies(TX_FRAME_LIFETIME);
-
-       stlc45xx_debug(DEBUG_TX, "tx data 0x%x (0x%p payload %d B "
-                      "padding %d header_len %d)",
-                      entry->handle, payload, payload_len, padding,
-                      entry->header_len);
-       stlc45xx_dump(DEBUG_TX_CONTENT, payload, payload_len);
-
-       data = (struct s_lm_data_out *) skb_push(skb, entry->header_len);
-
-       memset(data, 0, entry->header_len);
-
-       if (padding)
-               data->flags = LM_FLAG_ALIGN;
-
-       data->flags = LM_OUT_BURST;
-       data->length = payload_len;
-       data->handle = entry->handle;
-       data->aid = 1;
-       data->rts_retries = 7;
-       data->retries = 7;
-       data->aloft_ctrl = 0;
-       data->crypt_offset = 58;
-       data->keytype = 0;
-       data->keylen = 0;
-       data->queue = LM_QUEUE_DATA3;
-       data->backlog = 32;
-       data->antenna = 2;
-       data->cts = 3;
-       data->power = 127;
-
-       for (i = 0; i < 8; i++)
-               data->aloft[i] = 0;
-
-       /*
-        * check if there's enough space in tx buffer
-        *
-        * FIXME: ignored for now
-        */
-
-       stlc45xx_tx_frame(stlc, entry->start, skb->data, skb->len);
-
-       list_add(&entry->tx_list, &stlc->tx_sent);
-
-       return 0;
-}
-
-/* caller must hold mutex */
-static void stlc45xx_tx_psm(struct stlc45xx *stlc, bool enable)
-{
-       struct s_lm_control *control;
-       struct s_lmo_psm *psm;
-       size_t len, psm_len;
-
-       WARN_ON(!stlc->associated);
-       WARN_ON(stlc->aid < 1);
-       WARN_ON(stlc->aid > 2007);
-
-       psm_len = sizeof(*psm);
-       len = sizeof(*control) + psm_len;
-       control = kzalloc(len, GFP_KERNEL);
-       psm = (struct s_lmo_psm *) (control + 1);
-
-       control->flags = LM_FLAG_CONTROL | LM_CTRL_OPSET;
-       control->length = psm_len;
-       control->oid = LM_OID_PSM;
-
-       if (enable)
-               psm->flags |= LM_PSM;
-
-       psm->aid = stlc->aid;
-
-       psm->beacon_rcpi_skip_max = 60;
-
-       psm->intervals[0].interval = 1;
-       psm->intervals[0].periods = 1;
-       psm->intervals[1].interval = 1;
-       psm->intervals[1].periods = 1;
-       psm->intervals[2].interval = 1;
-       psm->intervals[2].periods = 1;
-       psm->intervals[3].interval = 1;
-       psm->intervals[3].periods = 1;
-
-       psm->nr = 0;
-       psm->exclude[0] = 0;
-
-       stlc45xx_debug(DEBUG_PSM, "sending LM_OID_PSM (aid %d, interval %d)",
-                      psm->aid, psm->intervals[0].interval);
-
-       stlc45xx_tx_frame(stlc, FIRMWARE_CONFIG_START, control, len);
-
-       kfree(control);
-}
-
-static int stlc45xx_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
-{
-       struct stlc45xx *stlc = hw->priv;
-       struct ieee80211_tx_info *info;
-       struct ieee80211_rate *rate;
-       int payload_len, padding, i;
-       struct s_lm_data_out *data;
-       struct txbuffer *entry;
-       char *payload;
-
-       stlc45xx_debug(DEBUG_FUNC, "%s", __func__);
-
-       spin_lock_bh(&stlc->tx_lock);
-
-       entry = stlc45xx_txbuffer_alloc(stlc, skb->len);
-       if (!entry) {
-               /* the queue should be stopped before the firmware buffer
-                * is full, so firmware buffer should always have enough
-                * space */
-               if (net_ratelimit())
-                       stlc45xx_warning("firmware buffer full");
-               spin_unlock_bh(&stlc->tx_lock);
-               return NETDEV_TX_BUSY;
-       }
-
-       info = IEEE80211_SKB_CB(skb);
-
-       payload = skb->data;
-       payload_len = skb->len;
-       padding = (int) (skb->data - sizeof(*data)) & 3;
-       entry->header_len = sizeof(*data) + padding;
-
-       entry->skb = skb;
-       entry->status_needed = true;
-       entry->handle = (u32) skb;
-       entry->lifetime = jiffies + msecs_to_jiffies(TX_FRAME_LIFETIME);
-
-       stlc45xx_debug(DEBUG_TX, "tx data 0x%x (0x%p payload %d B "
-                      "padding %d header_len %d)",
-                      entry->handle, payload, payload_len, padding,
-                      entry->header_len);
-       stlc45xx_dump(DEBUG_TX_CONTENT, payload, payload_len);
-
-       data = (struct s_lm_data_out *) skb_push(skb, entry->header_len);
-
-       memset(data, 0, entry->header_len);
-
-       if (padding)
-               data->flags = LM_FLAG_ALIGN;
-
-       data->flags = LM_OUT_BURST;
-       data->length = payload_len;
-       data->handle = entry->handle;
-       data->aid = 1;
-       data->rts_retries = 7;
-       data->retries = 7;
-       data->aloft_ctrl = 0;
-       data->crypt_offset = 58;
-       data->keytype = 0;
-       data->keylen = 0;
-       data->queue = 2;
-       data->backlog = 32;
-       data->antenna = 2;
-       data->cts = 3;
-       data->power = 127;
-
-       for (i = 0; i < 8; i++) {
-               rate = ieee80211_get_tx_rate(stlc->hw, info);
-               data->aloft[i] = rate->hw_value;
-       }
-
-       list_add_tail(&entry->tx_list, &stlc->tx_pending);
-
-       /* check if there's enough space in tx buffer */
-       if (stlc45xx_txbuffer_find(stlc, MAX_FRAME_LEN) == -1) {
-               stlc45xx_debug(DEBUG_QUEUE, "tx buffer full, stopping queues");
-               stlc->tx_queue_stopped = 1;
-               ieee80211_stop_queues(stlc->hw);
-       }
-
-       queue_work(stlc->hw->workqueue, &stlc->work);
-
-       spin_unlock_bh(&stlc->tx_lock);
-
-       return NETDEV_TX_OK;
-}
-
-static int stlc45xx_op_start(struct ieee80211_hw *hw)
-{
-       struct stlc45xx *stlc = hw->priv;
-       unsigned long timeout;
-       int ret = 0;
-
-       stlc45xx_debug(DEBUG_FUNC, "%s", __func__);
-
-       mutex_lock(&stlc->mutex);
-
-       stlc->fw_state = FW_STATE_BOOTING;
-       stlc->channel = 1;
-
-       stlc45xx_power_on(stlc);
-
-       ret = stlc45xx_upload_firmware(stlc);
-       if (ret < 0) {
-               stlc45xx_power_off(stlc);
-               goto out_unlock;
-       }
-
-       stlc->tx_queue_stopped = 0;
-
-       mutex_unlock(&stlc->mutex);
-
-       timeout = msecs_to_jiffies(2000);
-       timeout = wait_for_completion_interruptible_timeout(&stlc->fw_comp,
-                                                           timeout);
-       if (!timeout) {
-               stlc45xx_error("firmware boot failed");
-               stlc45xx_power_off(stlc);
-               ret = -1;
-               goto out;
-       }
-
-       stlc45xx_debug(DEBUG_BOOT, "firmware booted");
-
-       /* FIXME: should we take mutex just after wait_for_completion()? */
-       mutex_lock(&stlc->mutex);
-
-       WARN_ON(stlc->fw_state != FW_STATE_READY);
-
-out_unlock:
-       mutex_unlock(&stlc->mutex);
-
-out:
-       return ret;
-}
-
-static void stlc45xx_op_stop(struct ieee80211_hw *hw)
-{
-       struct stlc45xx *stlc = hw->priv;
-
-       stlc45xx_debug(DEBUG_FUNC, "%s", __func__);
-
-       mutex_lock(&stlc->mutex);
-
-       WARN_ON(stlc->fw_state != FW_STATE_READY);
-
-       stlc45xx_power_off(stlc);
-
-       /* FIXME: make sure that all work_structs have completed */
-
-       spin_lock_bh(&stlc->tx_lock);
-       stlc45xx_flush_queues(stlc);
-       spin_unlock_bh(&stlc->tx_lock);
-
-       stlc->fw_state = FW_STATE_OFF;
-
-       mutex_unlock(&stlc->mutex);
-}
-
-static int stlc45xx_op_add_interface(struct ieee80211_hw *hw,
-                                    struct ieee80211_if_init_conf *conf)
-{
-       struct stlc45xx *stlc = hw->priv;
-
-       stlc45xx_debug(DEBUG_FUNC, "%s", __func__);
-
-       switch (conf->type) {
-       case NL80211_IFTYPE_STATION:
-               break;
-       default:
-               return -EOPNOTSUPP;
-       }
-
-       memcpy(stlc->mac_addr, conf->mac_addr, ETH_ALEN);
-
-       return 0;
-}
-
-static void stlc45xx_op_remove_interface(struct ieee80211_hw *hw,
-                                        struct ieee80211_if_init_conf *conf)
-{
-       stlc45xx_debug(DEBUG_FUNC, "%s", __func__);
-}
-
-static int stlc45xx_op_config(struct ieee80211_hw *hw, u32 changed)
-{
-       struct stlc45xx *stlc = hw->priv;
-
-       stlc45xx_debug(DEBUG_FUNC, "%s", __func__);
-
-       mutex_lock(&stlc->mutex);
-
-       stlc->channel = hw->conf.channel->hw_value;
-       stlc45xx_tx_scan(stlc);
-       stlc45xx_tx_setup(stlc);
-       stlc45xx_tx_edcf(stlc);
-
-       if ((hw->conf.flags & IEEE80211_CONF_PS) != stlc->psm) {
-               stlc->psm = hw->conf.flags & IEEE80211_CONF_PS;
-               if (stlc->associated) {
-                       stlc45xx_tx_psm(stlc, stlc->psm);
-                       stlc45xx_tx_nullfunc(stlc, stlc->psm);
-               }
-       }
-
-       mutex_unlock(&stlc->mutex);
-
-       return 0;
-}
-
-static void stlc45xx_op_configure_filter(struct ieee80211_hw *hw,
-                                     unsigned int changed_flags,
-                                     unsigned int *total_flags,
-                                     int mc_count,
-                                     struct dev_addr_list *mc_list)
-{
-       *total_flags = 0;
-}
-
-static void stlc45xx_op_bss_info_changed(struct ieee80211_hw *hw,
-                                        struct ieee80211_vif *vif,
-                                        struct ieee80211_bss_conf *info,
-                                        u32 changed)
-{
-       struct stlc45xx *stlc = hw->priv;
-
-       stlc45xx_debug(DEBUG_FUNC, "%s", __func__);
-       mutex_lock(&stlc->mutex);
-
-       memcpy(stlc->bssid, info->bssid, ETH_ALEN);
-       stlc45xx_tx_setup(stlc);
-
-       mutex_unlock(&stlc->mutex);
-
-       if (changed & BSS_CHANGED_ASSOC) {
-               stlc->associated = info->assoc;
-               if (info->assoc)
-                       stlc->aid = info->aid;
-               else
-                       stlc->aid = -1;
-
-               if (stlc->psm) {
-                       stlc45xx_tx_psm(stlc, stlc->psm);
-                       stlc45xx_tx_nullfunc(stlc, stlc->psm);
-               }
-       }
-}
-
-
-/* can't be const, mac80211 writes to this */
-static struct ieee80211_rate stlc45xx_rates[] = {
-       { .bitrate = 10,  .hw_value = 0,    .hw_value_short = 0, },
-       { .bitrate = 20,  .hw_value = 1,    .hw_value_short = 1, },
-       { .bitrate = 55,  .hw_value = 2,    .hw_value_short = 2, },
-       { .bitrate = 110, .hw_value = 3,    .hw_value_short = 3, },
-       { .bitrate = 60,  .hw_value = 4,    .hw_value_short = 4, },
-       { .bitrate = 90,  .hw_value = 5,    .hw_value_short = 5, },
-       { .bitrate = 120, .hw_value = 6,    .hw_value_short = 6, },
-       { .bitrate = 180, .hw_value = 7,    .hw_value_short = 7, },
-       { .bitrate = 240, .hw_value = 8,    .hw_value_short = 8, },
-       { .bitrate = 360, .hw_value = 9,    .hw_value_short = 9, },
-       { .bitrate = 480, .hw_value = 10,   .hw_value_short = 10, },
-       { .bitrate = 540, .hw_value = 11,   .hw_value_short = 11, },
-};
-
-/* can't be const, mac80211 writes to this */
-static struct ieee80211_channel stlc45xx_channels[] = {
-       { .hw_value = 1, .center_freq = 2412},
-       { .hw_value = 2, .center_freq = 2417},
-       { .hw_value = 3, .center_freq = 2422},
-       { .hw_value = 4, .center_freq = 2427},
-       { .hw_value = 5, .center_freq = 2432},
-       { .hw_value = 6, .center_freq = 2437},
-       { .hw_value = 7, .center_freq = 2442},
-       { .hw_value = 8, .center_freq = 2447},
-       { .hw_value = 9, .center_freq = 2452},
-       { .hw_value = 10, .center_freq = 2457},
-       { .hw_value = 11, .center_freq = 2462},
-       { .hw_value = 12, .center_freq = 2467},
-       { .hw_value = 13, .center_freq = 2472},
-};
-
-/* can't be const, mac80211 writes to this */
-static struct ieee80211_supported_band stlc45xx_band_2ghz = {
-       .channels = stlc45xx_channels,
-       .n_channels = ARRAY_SIZE(stlc45xx_channels),
-       .bitrates = stlc45xx_rates,
-       .n_bitrates = ARRAY_SIZE(stlc45xx_rates),
-};
-
-static const struct ieee80211_ops stlc45xx_ops = {
-       .start = stlc45xx_op_start,
-       .stop = stlc45xx_op_stop,
-       .add_interface = stlc45xx_op_add_interface,
-       .remove_interface = stlc45xx_op_remove_interface,
-       .config = stlc45xx_op_config,
-       .configure_filter = stlc45xx_op_configure_filter,
-       .tx = stlc45xx_op_tx,
-       .bss_info_changed = stlc45xx_op_bss_info_changed,
-};
-
-static int stlc45xx_register_mac80211(struct stlc45xx *stlc)
-{
-       /* FIXME: SET_IEEE80211_PERM_ADDR() requires default_mac_addr
-          to be non-const for some strange reason */
-       static u8 default_mac_addr[ETH_ALEN] = {
-               0x00, 0x02, 0xee, 0xc0, 0xff, 0xee
-       };
-       int ret;
-
-       SET_IEEE80211_PERM_ADDR(stlc->hw, default_mac_addr);
-
-       ret = ieee80211_register_hw(stlc->hw);
-       if (ret) {
-               stlc45xx_error("unable to register mac80211 hw: %d", ret);
-               return ret;
-       }
-
-       return 0;
-}
-
-static void stlc45xx_device_release(struct device *dev)
-{
-
-}
-
-static struct platform_device stlc45xx_device = {
-       .name           = "stlc45xx",
-       .id             = -1,
-
-       /* device model insists to have a release function */
-       .dev            = {
-               .release = stlc45xx_device_release,
-       },
-};
-
-static int __devinit stlc45xx_probe(struct spi_device *spi)
-{
-       struct stlc45xx *stlc;
-       struct ieee80211_hw *hw;
-       int ret;
-
-       stlc45xx_debug(DEBUG_FUNC, "%s", __func__);
-
-       /* mac80211 alloc */
-       hw = ieee80211_alloc_hw(sizeof(*stlc), &stlc45xx_ops);
-       if (!hw) {
-               stlc45xx_error("could not alloc ieee80211_hw");
-               ret = -ENOMEM;
-               goto out;
-       }
-
-       /* mac80211 clears hw->priv */
-       stlc = hw->priv;
-
-       stlc->hw = hw;
-       dev_set_drvdata(&spi->dev, stlc);
-       stlc->spi = spi;
-
-       spi->bits_per_word = 16;
-       spi->max_speed_hz = 24000000;
-
-       ret = spi_setup(spi);
-       if (ret < 0)
-               stlc45xx_error("spi_setup failed");
-
-       ret = gpio_request(stlc45xx_gpio_power, "stlc45xx power");
-       if (ret < 0) {
-               stlc45xx_error("power GPIO request failed: %d", ret);
-               return ret;
-       }
-
-       ret = gpio_request(stlc45xx_gpio_irq, "stlc45xx irq");
-       if (ret < 0) {
-               stlc45xx_error("irq GPIO request failed: %d", ret);
-               goto out;
-       }
-
-       gpio_direction_output(stlc45xx_gpio_power, 0);
-       gpio_direction_input(stlc45xx_gpio_irq);
-
-       ret = request_irq(gpio_to_irq(stlc45xx_gpio_irq),
-                         stlc45xx_interrupt, IRQF_DISABLED, "stlc45xx",
-                         stlc->spi);
-       if (ret < 0)
-               /* FIXME: handle the error */
-               stlc45xx_error("request_irq() failed");
-
-       set_irq_type(gpio_to_irq(stlc45xx_gpio_irq),
-                    IRQ_TYPE_EDGE_RISING);
-
-       disable_irq(gpio_to_irq(stlc45xx_gpio_irq));
-
-       ret = platform_device_register(&stlc45xx_device);
-       if (ret) {
-               stlc45xx_error("Couldn't register wlan_omap device.");
-               return ret;
-       }
-       dev_set_drvdata(&stlc45xx_device.dev, stlc);
-
-       INIT_WORK(&stlc->work, stlc45xx_work);
-       INIT_WORK(&stlc->work_reset, stlc45xx_work_reset);
-       INIT_DELAYED_WORK(&stlc->work_tx_timeout, stlc45xx_work_tx_timeout);
-       mutex_init(&stlc->mutex);
-       init_completion(&stlc->fw_comp);
-       spin_lock_init(&stlc->tx_lock);
-       INIT_LIST_HEAD(&stlc->txbuffer);
-       INIT_LIST_HEAD(&stlc->tx_pending);
-       INIT_LIST_HEAD(&stlc->tx_sent);
-
-       hw->flags = IEEE80211_HW_RX_INCLUDES_FCS |
-               IEEE80211_HW_SIGNAL_DBM |
-               IEEE80211_HW_NOISE_DBM;
-       /* four bytes for padding */
-       hw->extra_tx_headroom = sizeof(struct s_lm_data_out) + 4;
-
-       /* unit us */
-       hw->channel_change_time = 1000;
-
-       hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION);
-       hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &stlc45xx_band_2ghz;
-
-       SET_IEEE80211_DEV(hw, &spi->dev);
-
-       BUILD_BUG_ON(sizeof(default_cal_rssi) != RSSI_CAL_ARRAY_LEN);
-       BUILD_BUG_ON(sizeof(default_cal_channels) != CHANNEL_CAL_ARRAY_LEN);
-
-       stlc->cal_rssi = kmemdup(default_cal_rssi, RSSI_CAL_ARRAY_LEN,
-                                GFP_KERNEL);
-       stlc->cal_channels = kmemdup(default_cal_channels,
-                                    CHANNEL_CAL_ARRAY_LEN,
-                                    GFP_KERNEL);
-
-       ret = device_create_file(&stlc45xx_device.dev, &dev_attr_cal_rssi);
-       if (ret < 0) {
-               stlc45xx_error("failed to create sysfs file cal_rssi");
-               goto out;
-       }
-
-       ret = device_create_file(&stlc45xx_device.dev, &dev_attr_cal_channels);
-       if (ret < 0) {
-               stlc45xx_error("failed to create sysfs file cal_channels");
-               goto out;
-       }
-
-       ret = device_create_file(&stlc45xx_device.dev, &dev_attr_tx_buf);
-       if (ret < 0) {
-               stlc45xx_error("failed to create sysfs file tx_buf");
-               goto out;
-       }
-
-       ret = stlc45xx_register_mac80211(stlc);
-       if (ret < 0)
-               goto out;
-
-       stlc45xx_info("v" DRIVER_VERSION " loaded");
-
-       stlc45xx_info("config buffer 0x%x-0x%x",
-                     FIRMWARE_CONFIG_START, FIRMWARE_CONFIG_END);
-       stlc45xx_info("tx 0x%x-0x%x, rx 0x%x-0x%x",
-                     FIRMWARE_TXBUFFER_START, FIRMWARE_TXBUFFER_END,
-                     FIRMWARE_RXBUFFER_START, FIRMWARE_RXBUFFER_END);
-
-out:
-       return ret;
-}
-
-static int __devexit stlc45xx_remove(struct spi_device *spi)
-{
-       struct stlc45xx *stlc = dev_get_drvdata(&spi->dev);
-
-       stlc45xx_debug(DEBUG_FUNC, "%s", __func__);
-
-       platform_device_unregister(&stlc45xx_device);
-
-       ieee80211_unregister_hw(stlc->hw);
-
-       free_irq(gpio_to_irq(stlc45xx_gpio_irq), spi);
-
-       gpio_free(stlc45xx_gpio_power);
-       gpio_free(stlc45xx_gpio_irq);
-
-       /* FIXME: free cal_channels and cal_rssi? */
-
-       kfree(stlc->fw);
-
-       mutex_destroy(&stlc->mutex);
-
-       /* frees also stlc */
-       ieee80211_free_hw(stlc->hw);
-       stlc = NULL;
-
-       return 0;
-}
-
-
-static struct spi_driver stlc45xx_spi_driver = {
-       .driver = {
-               /* use cx3110x name because board-n800.c uses that for the
-                * SPI port */
-               .name           = "cx3110x",
-               .bus            = &spi_bus_type,
-               .owner          = THIS_MODULE,
-       },
-
-       .probe          = stlc45xx_probe,
-       .remove         = __devexit_p(stlc45xx_remove),
-};
-
-static int __init stlc45xx_init(void)
-{
-       int ret;
-
-       stlc45xx_debug(DEBUG_FUNC, "%s", __func__);
-
-       ret = spi_register_driver(&stlc45xx_spi_driver);
-       if (ret < 0) {
-               stlc45xx_error("failed to register SPI driver: %d", ret);
-               goto out;
-       }
-
-out:
-       return ret;
-}
-
-static void __exit stlc45xx_exit(void)
-{
-       stlc45xx_debug(DEBUG_FUNC, "%s", __func__);
-
-       spi_unregister_driver(&stlc45xx_spi_driver);
-
-       stlc45xx_info("unloaded");
-}
-
-module_init(stlc45xx_init);
-module_exit(stlc45xx_exit);
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Kalle Valo <kalle.valo@nokia.com>");
-MODULE_ALIAS("spi:cx3110x");
diff --git a/drivers/staging/stlc45xx/stlc45xx.h b/drivers/staging/stlc45xx/stlc45xx.h
deleted file mode 100644 (file)
index ac96bbb..0000000
+++ /dev/null
@@ -1,283 +0,0 @@
-/*
- * This file is part of stlc45xx
- *
- * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies).
- *
- * Contact: Kalle Valo <kalle.valo@nokia.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA
- *
- */
-
-#include <linux/mutex.h>
-#include <linux/list.h>
-#include <net/mac80211.h>
-
-#include "stlc45xx_lmac.h"
-
-#define DRIVER_NAME "stlc45xx"
-#define DRIVER_VERSION "0.1.3"
-
-#define DRIVER_PREFIX DRIVER_NAME ": "
-
-enum {
-       DEBUG_NONE = 0,
-       DEBUG_FUNC = 1 << 0,
-       DEBUG_IRQ = 1 << 1,
-       DEBUG_BH = 1 << 2,
-       DEBUG_RX = 1 << 3,
-       DEBUG_RX_CONTENT = 1 << 5,
-       DEBUG_TX = 1 << 6,
-       DEBUG_TX_CONTENT = 1 << 8,
-       DEBUG_TXBUFFER = 1 << 9,
-       DEBUG_QUEUE = 1 << 10,
-       DEBUG_BOOT = 1 << 11,
-       DEBUG_PSM = 1 << 12,
-       DEBUG_ALL = ~0,
-};
-
-#define DEBUG_LEVEL DEBUG_NONE
-/* #define DEBUG_LEVEL DEBUG_ALL */
-/* #define DEBUG_LEVEL (DEBUG_TX | DEBUG_RX | DEBUG_IRQ) */
-/* #define DEBUG_LEVEL (DEBUG_TX | DEBUG_MEMREGION | DEBUG_QUEUE) */
-/* #define DEBUG_LEVEL (DEBUG_MEMREGION | DEBUG_QUEUE) */
-
-#define stlc45xx_error(fmt, arg...) \
-       printk(KERN_ERR DRIVER_PREFIX "ERROR " fmt "\n", ##arg)
-
-#define stlc45xx_warning(fmt, arg...) \
-       printk(KERN_WARNING DRIVER_PREFIX "WARNING " fmt "\n", ##arg)
-
-#define stlc45xx_info(fmt, arg...) \
-       printk(KERN_INFO DRIVER_PREFIX fmt "\n", ##arg)
-
-#define stlc45xx_debug(level, fmt, arg...) \
-       do { \
-               if (level & DEBUG_LEVEL) \
-                       printk(KERN_DEBUG DRIVER_PREFIX fmt "\n", ##arg); \
-       } while (0)
-
-#define stlc45xx_dump(level, buf, len)         \
-       do { \
-               if (level & DEBUG_LEVEL) \
-                       print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_OFFSET, \
-                                      16, 1, buf, len, 1);             \
-       } while (0)
-
-#define MAC2STR(a) ((a)[0], (a)[1], (a)[2], (a)[3], (a)[4], (a)[5])
-#define MACSTR "%02x:%02x:%02x:%02x:%02x:%02x"
-
-/* Bit 15 is read/write bit; ON = READ, OFF = WRITE */
-#define ADDR_READ_BIT_15  0x8000
-
-#define SPI_ADRS_ARM_INTERRUPTS     0x00
-#define SPI_ADRS_ARM_INT_EN        0x04
-
-#define SPI_ADRS_HOST_INTERRUPTS    0x08
-#define SPI_ADRS_HOST_INT_EN       0x0c
-#define SPI_ADRS_HOST_INT_ACK      0x10
-
-#define SPI_ADRS_GEN_PURP_1        0x14
-#define SPI_ADRS_GEN_PURP_2        0x18
-
-/* high word */
-#define SPI_ADRS_DEV_CTRL_STAT      0x26
-
-#define SPI_ADRS_DMA_DATA                  0x28
-
-#define SPI_ADRS_DMA_WRITE_CTRL     0x2c
-#define SPI_ADRS_DMA_WRITE_LEN      0x2e
-#define SPI_ADRS_DMA_WRITE_BASE     0x30
-
-#define SPI_ADRS_DMA_READ_CTRL      0x34
-#define SPI_ADRS_DMA_READ_LEN       0x36
-#define SPI_ADRS_DMA_READ_BASE      0x38
-
-#define SPI_CTRL_STAT_HOST_OVERRIDE 0x8000
-#define SPI_CTRL_STAT_START_HALTED  0x4000
-#define SPI_CTRL_STAT_RAM_BOOT      0x2000
-#define SPI_CTRL_STAT_HOST_RESET    0x1000
-#define SPI_CTRL_STAT_HOST_CPU_EN   0x0800
-
-#define SPI_DMA_WRITE_CTRL_ENABLE   0x0001
-#define SPI_DMA_READ_CTRL_ENABLE    0x0001
-#define HOST_ALLOWED                (1 << 7)
-
-#define FIRMWARE_ADDRESS                        0x20000
-
-#define SPI_TIMEOUT                             100         /* msec */
-
-#define SPI_MAX_TX_PACKETS                      32
-
-#define SPI_MAX_PACKET_SIZE                     32767
-
-#define SPI_TARGET_INT_WAKEUP                   0x00000001
-#define SPI_TARGET_INT_SLEEP                    0x00000002
-#define SPI_TARGET_INT_RDDONE                   0x00000004
-
-#define SPI_TARGET_INT_CTS                      0x00004000
-#define SPI_TARGET_INT_DR                       0x00008000
-
-#define SPI_HOST_INT_READY                      0x00000001
-#define SPI_HOST_INT_WR_READY                   0x00000002
-#define SPI_HOST_INT_SW_UPDATE                  0x00000004
-#define SPI_HOST_INT_UPDATE                     0x10000000
-
-/* clear to send */
-#define SPI_HOST_INT_CTS                       0x00004000
-
-/* data ready */
-#define SPI_HOST_INT_DR                                0x00008000
-
-#define SPI_HOST_INTS_DEFAULT \
-       (SPI_HOST_INT_READY | SPI_HOST_INT_UPDATE | SPI_HOST_INT_SW_UPDATE)
-
-#define TARGET_BOOT_SLEEP 50
-
-/* The firmware buffer is divided into three areas:
- *
- * o config area (for control commands)
- * o tx buffer
- * o rx buffer
- */
-#define FIRMWARE_BUFFER_START 0x20200
-#define FIRMWARE_BUFFER_END 0x27c60
-#define FIRMWARE_BUFFER_LEN (FIRMWARE_BUFFER_END - FIRMWARE_BUFFER_START)
-#define FIRMWARE_MTU 3240
-#define FIRMWARE_CONFIG_PAYLOAD_LEN 1024
-#define FIRMWARE_CONFIG_START FIRMWARE_BUFFER_START
-#define FIRMWARE_CONFIG_LEN (sizeof(struct s_lm_control) + \
-                            FIRMWARE_CONFIG_PAYLOAD_LEN)
-#define FIRMWARE_CONFIG_END (FIRMWARE_CONFIG_START + FIRMWARE_CONFIG_LEN - 1)
-#define FIRMWARE_RXBUFFER_LEN (5 * FIRMWARE_MTU + 1024)
-#define FIRMWARE_RXBUFFER_START (FIRMWARE_BUFFER_END - FIRMWARE_RXBUFFER_LEN)
-#define FIRMWARE_RXBUFFER_END (FIRMWARE_RXBUFFER_START + \
-                              FIRMWARE_RXBUFFER_LEN - 1)
-#define FIRMWARE_TXBUFFER_START (FIRMWARE_BUFFER_START + FIRMWARE_CONFIG_LEN)
-#define FIRMWARE_TXBUFFER_LEN (FIRMWARE_BUFFER_LEN - FIRMWARE_CONFIG_LEN - \
-                              FIRMWARE_RXBUFFER_LEN)
-#define FIRMWARE_TXBUFFER_END (FIRMWARE_TXBUFFER_START + \
-                              FIRMWARE_TXBUFFER_LEN - 1)
-
-#define FIRMWARE_TXBUFFER_HEADER 100
-#define FIRMWARE_TXBUFFER_TRAILER 4
-
-/* FIXME: come up with a proper value */
-#define MAX_FRAME_LEN 2500
-
-/* unit is ms */
-#define TX_FRAME_LIFETIME 2000
-#define TX_TIMEOUT 4000
-
-#define SUPPORTED_CHANNELS 13
-
-/* FIXME */
-/* #define CHANNEL_CAL_LEN offsetof(struct s_lmo_scan, bratemask) - \ */
-/*     offsetof(struct s_lmo_scan, channel) */
-#define CHANNEL_CAL_LEN 292
-#define CHANNEL_CAL_ARRAY_LEN (SUPPORTED_CHANNELS * CHANNEL_CAL_LEN)
-/* FIXME */
-/* #define RSSI_CAL_LEN sizeof(struct s_lmo_scan) - \ */
-/*     offsetof(struct s_lmo_scan, rssical) */
-#define RSSI_CAL_LEN 8
-#define RSSI_CAL_ARRAY_LEN (SUPPORTED_CHANNELS * RSSI_CAL_LEN)
-
-struct s_dma_regs {
-       unsigned short cmd;
-       unsigned short len;
-       unsigned long addr;
-};
-
-struct stlc45xx_ie_tim {
-       u8 dtim_count;
-       u8 dtim_period;
-       u8 bmap_control;
-       u8 pvbmap[251];
-};
-
-struct txbuffer {
-       /* can be removed when switched to skb queue */
-       struct list_head tx_list;
-
-       struct list_head buffer_list;
-
-       int start;
-       int frame_start;
-       int end;
-
-       struct sk_buff *skb;
-       u32 handle;
-
-       bool status_needed;
-
-       int header_len;
-
-       /* unit jiffies */
-       unsigned long lifetime;
-};
-
-enum fw_state {
-       FW_STATE_OFF,
-       FW_STATE_BOOTING,
-       FW_STATE_READY,
-       FW_STATE_RESET,
-       FW_STATE_RESETTING,
-};
-
-struct stlc45xx {
-       struct ieee80211_hw *hw;
-       struct spi_device *spi;
-       struct work_struct work;
-       struct work_struct work_reset;
-       struct delayed_work work_tx_timeout;
-       struct mutex mutex;
-       struct completion fw_comp;
-
-
-       u8 bssid[ETH_ALEN];
-       u8 mac_addr[ETH_ALEN];
-       int channel;
-
-       u8 *cal_rssi;
-       u8 *cal_channels;
-
-       enum fw_state fw_state;
-
-       spinlock_t tx_lock;
-
-       /* protected by tx_lock */
-       struct list_head txbuffer;
-
-       /* protected by tx_lock */
-       struct list_head tx_pending;
-
-       /* protected by tx_lock */
-       int tx_queue_stopped;
-
-       /* protected by mutex */
-       struct list_head tx_sent;
-
-       int tx_frames;
-
-       u8 *fw;
-       int fw_len;
-
-       bool psm;
-       bool associated;
-       int aid;
-       bool pspolling;
-};
-
-
diff --git a/drivers/staging/stlc45xx/stlc45xx_lmac.h b/drivers/staging/stlc45xx/stlc45xx_lmac.h
deleted file mode 100644 (file)
index af5db80..0000000
+++ /dev/null
@@ -1,434 +0,0 @@
-/************************************************************************
-*  This is the LMAC API interface header file for STLC4560.            *
-*  Copyright (C) 2007 Conexant Systems, Inc.                            *
-*  This program is free software; you can redistribute it and/or        *
-*  modify it under the terms of the GNU General Public License          *
-*  as published by the Free Software Foundation; either version 2      *
-*  of the License, or (at your option) any later version.               *
-*                                                                       *
-*  This program is distributed in the hope that it will be useful,      *
-*  but WITHOUT ANY WARRANTY; without even the implied warranty of      *
-*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the        *
-*  GNU General Public License for more details.                         *
-*                                                                       *
-*  You should have received a copy of the GNU General Public License    *
-*  along with this program.  If not, see <http://www.gnu.org/licenses/>.*
-*************************************************************************/
-
-#ifndef __lmac_h__
-#define __lmac_h__
-
-#define LM_TOP_VARIANT      0x0506
-#define LM_BOTTOM_VARIANT   0x0506
-
-/*
- * LMAC - UMAC interface definition:
- */
-
-#define LM_FLAG_CONTROL     0x8000
-#define LM_FLAG_ALIGN       0x4000
-
-#define LM_CTRL_OPSET       0x0001
-
-#define LM_OUT_PROMISC      0x0001
-#define LM_OUT_TIMESTAMP    0x0002
-#define LM_OUT_SEQNR        0x0004
-#define LM_OUT_BURST        0x0010
-#define LM_OUT_NOCANCEL     0x0020
-#define LM_OUT_CLEARTIM     0x0040
-#define LM_OUT_HITCHHIKE    0x0080
-#define LM_OUT_COMPRESS     0x0100
-#define LM_OUT_CONCAT       0x0200
-#define LM_OUT_PCS_ACCEPT   0x0400
-#define LM_OUT_WAITEOSP     0x0800
-
-
-#define LM_ALOFT_SP         0x10
-#define LM_ALOFT_CTS        0x20
-#define LM_ALOFT_RTS        0x40
-#define LM_ALOFT_MASK       0x1f
-#define LM_ALOFT_RATE       0x0f
-
-#define LM_IN_FCS_GOOD      0x0001
-#define LM_IN_MATCH_MAC     0x0002
-#define LM_IN_MCBC          0x0004
-#define LM_IN_BEACON        0x0008
-#define LM_IN_MATCH_BSS     0x0010
-#define LM_IN_BCAST_BSS     0x0020
-#define LM_IN_DATA          0x0040
-#define LM_IN_TRUNCATED     0x0080
-
-#define LM_IN_TRANSPARENT   0x0200
-
-#define LM_QUEUE_BEACON     0
-#define LM_QUEUE_SCAN       1
-#define LM_QUEUE_MGT        2
-#define LM_QUEUE_MCBC       3
-#define LM_QUEUE_DATA       4
-#define LM_QUEUE_DATA0      4
-#define LM_QUEUE_DATA1      5
-#define LM_QUEUE_DATA2      6
-#define LM_QUEUE_DATA3      7
-
-#define LM_SETUP_INFRA          0x0001
-#define LM_SETUP_IBSS           0x0002
-#define LM_SETUP_TRANSPARENT    0x0008
-#define LM_SETUP_PROMISCUOUS    0x0010
-#define LM_SETUP_HIBERNATE      0x0020
-#define LM_SETUP_NOACK          0x0040
-#define LM_SETUP_RX_DISABLED    0x0080
-
-#define LM_ANTENNA_0            0
-#define LM_ANTENNA_1            1
-#define LM_ANTENNA_DIVERSITY    2
-
-#define LM_TX_FAILED            0x0001
-#define LM_TX_PSM               0x0002
-#define LM_TX_PSM_CANCELLED    0x0004
-
-#define LM_SCAN_EXIT            0x0001
-#define LM_SCAN_TRAP            0x0002
-#define LM_SCAN_ACTIVE          0x0004
-#define LM_SCAN_FILTER          0x0008
-
-#define LM_PSM                  0x0001
-#define LM_PSM_DTIM             0x0002
-#define LM_PSM_MCBC             0x0004
-#define LM_PSM_CHECKSUM         0x0008
-#define LM_PSM_SKIP_MORE_DATA   0x0010
-#define LM_PSM_BEACON_TIMEOUT   0x0020
-#define LM_PSM_HFOSLEEP         0x0040
-#define LM_PSM_AUTOSWITCH_SLEEP 0x0080
-#define        LM_PSM_LPIT             0x0100
-#define LM_PSM_BF_UCAST_SKIP    0x0200
-#define LM_PSM_BF_MCAST_SKIP    0x0400
-
-/* hfosleep */
-#define LM_PSM_SLEEP_OPTION_MASK (LM_PSM_AUTOSWITCH_SLEEP | LM_PSM_HFOSLEEP)
-#define LM_PSM_SLEEP_OPTION_SHIFT       6
-/* hfosleepend */
-#define LM_PSM_BF_OPTION_MASK (LM_PSM_BF_MCAST_SKIP | LM_PSM_BF_UCAST_SKIP)
-#define LM_PSM_BF_OPTION_SHIFT  9
-
-
-#define LM_PRIVACC_WEP          0x01
-#define LM_PRIVACC_TKIP         0x02
-#define LM_PRIVACC_MICHAEL      0x04
-#define LM_PRIVACC_CCX_KP       0x08
-#define LM_PRIVACC_CCX_MIC      0x10
-#define LM_PRIVACC_AES_CCMP     0x20
-
-/* size of s_lm_descr in words */
-#define LM_DESCR_SIZE_WORDS     11
-
-#ifndef __ASSEMBLER__
-
-enum {
-    LM_MODE_CLIENT = 0,
-    LM_MODE_AP
-};
-
-struct s_lm_descr {
-    uint16_t modes;
-    uint16_t flags;
-    uint32_t buffer_start;
-    uint32_t buffer_end;
-    uint8_t header;
-    uint8_t trailer;
-    uint8_t tx_queues;
-    uint8_t tx_depth;
-    uint8_t privacy;
-    uint8_t rx_keycache;
-    uint8_t tim_size;
-    uint8_t pad1;
-    uint8_t rates[16];
-    uint32_t link;
-       uint16_t mtu;
-};
-
-
-struct s_lm_control {
-    uint16_t flags;
-    uint16_t length;
-    uint32_t handle;
-    uint16_t oid;
-    uint16_t pad;
-    /* uint8_t data[]; */
-};
-
-enum {
-    LM_PRIV_NONE = 0,
-    LM_PRIV_WEP,
-    LM_PRIV_TKIP,
-    LM_PRIV_TKIPMICHAEL,
-    LM_PRIV_CCX_WEPMIC,
-    LM_PRIV_CCX_KPMIC,
-    LM_PRIV_CCX_KP,
-    LM_PRIV_AES_CCMP
-};
-
-enum {
-    LM_DECRYPT_NONE,
-    LM_DECRYPT_OK,
-    LM_DECRYPT_NOKEY,
-    LM_DECRYPT_NOMICHAEL,
-    LM_DECRYPT_NOCKIPMIC,
-    LM_DECRYPT_FAIL_WEP,
-    LM_DECRYPT_FAIL_TKIP,
-    LM_DECRYPT_FAIL_MICHAEL,
-    LM_DECRYPT_FAIL_CKIPKP,
-    LM_DECRYPT_FAIL_CKIPMIC,
-    LM_DECRYPT_FAIL_AESCCMP
-};
-
-struct s_lm_data_out {
-    uint16_t flags;
-    uint16_t length;
-    uint32_t handle;
-    uint16_t aid;
-    uint8_t rts_retries;
-    uint8_t retries;
-    uint8_t aloft[8];
-    uint8_t aloft_ctrl;
-    uint8_t crypt_offset;
-    uint8_t keytype;
-    uint8_t keylen;
-    uint8_t key[16];
-    uint8_t queue;
-    uint8_t backlog;
-    uint16_t durations[4];
-    uint8_t antenna;
-    uint8_t cts;
-    int16_t power;
-    uint8_t pad[2];
-    /*uint8_t data[];*/
-};
-
-#define LM_RCPI_INVALID         (0xff)
-
-struct s_lm_data_in {
-    uint16_t flags;
-    uint16_t length;
-    uint16_t frequency;
-    uint8_t antenna;
-    uint8_t rate;
-    uint8_t rcpi;
-    uint8_t sq;
-    uint8_t decrypt;
-    uint8_t rssi_raw;
-    uint32_t clock[2];
-    /*uint8_t data[];*/
-};
-
-union u_lm_data {
-    struct s_lm_data_out out;
-    struct s_lm_data_in in;
-};
-
-enum {
-    LM_OID_SETUP       = 0,
-    LM_OID_SCAN                = 1,
-    LM_OID_TRAP                = 2,
-    LM_OID_EDCF                = 3,
-    LM_OID_KEYCACHE    = 4,
-    LM_OID_PSM         = 6,
-    LM_OID_TXCANCEL    = 7,
-    LM_OID_TX          = 8,
-    LM_OID_BURST       = 9,
-    LM_OID_STATS       = 10,
-    LM_OID_LED         = 13,
-    LM_OID_TIMER       = 15,
-    LM_OID_NAV         = 20,
-    LM_OID_PCS         = 22,
-    LM_OID_BT_BALANCER  = 28,
-    LM_OID_GROUP_ADDRESS_TABLE = 30,
-    LM_OID_ARPTABLE     = 31,
-    LM_OID_BT_OPTIONS = 35
-};
-
-enum {
-    LM_FRONTEND_UNKNOWN = 0,
-    LM_FRONTEND_DUETTE3,
-    LM_FRONTEND_DUETTE2,
-    LM_FRONTEND_FRISBEE,
-    LM_FRONTEND_CROSSBOW,
-    LM_FRONTEND_LONGBOW
-};
-
-
-#define INVALID_LPF_BANDWIDTH   0xffff
-#define INVALID_OSC_START_DELAY 0xffff
-
-struct s_lmo_setup {
-    uint16_t flags;
-    uint8_t  macaddr[6];
-    uint8_t  bssid[6];
-    uint8_t  antenna;
-    uint8_t  rx_align;
-    uint32_t rx_buffer;
-    uint16_t rx_mtu;
-    uint16_t frontend;
-    uint16_t timeout;
-    uint16_t truncate;
-    uint32_t bratemask;
-    uint8_t  sbss_offset;
-    uint8_t  mcast_window;
-    uint8_t  rx_rssi_threshold;
-    uint8_t  rx_ed_threshold;
-    uint32_t ref_clock;
-    uint16_t lpf_bandwidth;
-    uint16_t osc_start_delay;
-};
-
-
-struct s_lmo_scan {
-    uint16_t flags;
-    uint16_t dwell;
-    uint8_t channel[292];
-    uint32_t bratemask;
-    uint8_t  aloft[8];
-    uint8_t  rssical[8];
-};
-
-
-enum {
-    LM_TRAP_SCAN = 0,
-    LM_TRAP_TIMER,
-    LM_TRAP_BEACON_TX,
-    LM_TRAP_FAA_RADIO_ON,
-    LM_TRAP_FAA_RADIO_OFF,
-    LM_TRAP_RADAR,
-    LM_TRAP_NO_BEACON,
-    LM_TRAP_TBTT,
-    LM_TRAP_SCO_ENTER,
-    LM_TRAP_SCO_EXIT
-};
-
-struct s_lmo_trap {
-    uint16_t event;
-    uint16_t frequency;
-};
-
-struct s_lmo_timer {
-    uint32_t interval;
-};
-
-struct s_lmo_nav {
-    uint32_t period;
-};
-
-
-struct s_lmo_edcf_queue;
-
-struct s_lmo_edcf {
-    uint8_t  flags;
-    uint8_t  slottime;
-    uint8_t  sifs;
-    uint8_t  eofpad;
-    struct s_lmo_edcf_queue {
-           uint8_t  aifs;
-           uint8_t  pad0;
-           uint16_t cwmin;
-           uint16_t cwmax;
-           uint16_t txop;
-    } queues[8];
-    uint8_t  mapping[4];
-    uint16_t maxburst;
-    uint16_t round_trip_delay;
-};
-
-struct s_lmo_keycache {
-    uint8_t entry;
-    uint8_t keyid;
-    uint8_t address[6];
-    uint8_t pad[2];
-    uint8_t keytype;
-    uint8_t keylen;
-    uint8_t key[24];
-};
-
-
-struct s_lm_interval;
-
-struct s_lmo_psm {
-    uint16_t    flags;
-    uint16_t    aid;
-    struct s_lm_interval {
-           uint16_t interval;
-           uint16_t periods;
-    } intervals[4];
-    /* uint16_t    pad; */
-    uint8_t     beacon_rcpi_skip_max;
-    uint8_t     rcpi_delta_threshold;
-    uint8_t     nr;
-    uint8_t     exclude[1];
-};
-
-#define MC_FILTER_ADDRESS_NUM   4
-
-struct s_lmo_group_address_table {
-    uint16_t    filter_enable;
-    uint16_t    num_address;
-    uint8_t     macaddr_list[MC_FILTER_ADDRESS_NUM][6];
-};
-
-struct s_lmo_txcancel {
-    uint32_t address[1];
-};
-
-
-struct s_lmo_tx {
-    uint8_t  flags;
-    uint8_t  retries;
-    uint8_t  rcpi;
-    uint8_t  sq;
-    uint16_t seqctrl;
-    uint8_t  antenna;
-    uint8_t  pad;
-};
-
-struct s_lmo_burst {
-    uint8_t  flags;
-    uint8_t  queue;
-    uint8_t  backlog;
-    uint8_t  pad;
-    uint16_t durations[32];
-};
-
-struct s_lmo_stats {
-    uint32_t valid;
-    uint32_t fcs;
-    uint32_t abort;
-    uint32_t phyabort;
-    uint32_t rts_success;
-    uint32_t rts_fail;
-    uint32_t timestamp;
-    uint32_t time_tx;
-    uint32_t noisefloor;
-    uint32_t sample_noise[8];
-    uint32_t sample_cca;
-    uint32_t sample_tx;
-};
-
-
-struct s_lmo_led {
-    uint16_t flags;
-    uint16_t mask[2];
-    uint16_t delay/*[2]*/;
-};
-
-
-struct s_lmo_bt_balancer {
-    uint16_t prio_thresh;
-    uint16_t acl_thresh;
-};
-
-
-struct s_lmo_arp_table {
-    uint16_t    filter_enable;
-    uint32_t    ipaddr;
-};
-
-#endif /* __ASSEMBLER__ */
-
-#endif /* __lmac_h__ */
index 3d2a84c..e139eae 100644 (file)
@@ -25,6 +25,7 @@
 #include <linux/poll.h>
 #include <linux/interrupt.h>
 #include <linux/spinlock.h>
+#include <linux/sched.h>
 #include <asm/time.h>
 #include <asm/io.h>
 #include <asm/uaccess.h>
index 8960fa9..00fe080 100644 (file)
@@ -25,6 +25,7 @@
 #include <linux/dma-mapping.h>
 #include <linux/interrupt.h>
 #include <linux/spinlock.h>
+#include <linux/sched.h>
 #include <asm/time.h>
 #include <asm/io.h>
 #include <asm/uaccess.h>
index 7f96bca..0518611 100644 (file)
@@ -1332,7 +1332,6 @@ device_release_WPADEV(pDevice);
         free_netdev(pDevice->dev);
     }
 
-       kfree(pDevice);
     DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "device_disconnect3.. \n");
 }
 
index 940460c..132671d 100644 (file)
@@ -1,6 +1,6 @@
 config W35UND
        tristate "IS89C35 WLAN USB driver"
-       depends on MAC80211 && WLAN_80211 && USB && EXPERIMENTAL
+       depends on MAC80211 && WLAN && USB && EXPERIMENTAL
        default n
        ---help---
          This is highly experimental driver for Winbond WIFI card.
index 8950724..067082a 100644 (file)
@@ -51,10 +51,26 @@ static struct ieee80211_supported_band wbsoft_band_2GHz = {
        .n_bitrates     = ARRAY_SIZE(wbsoft_rates),
 };
 
+static void hal_set_beacon_period(struct hw_data *pHwData, u16 beacon_period)
+{
+       u32 tmp;
+
+       if (pHwData->SurpriseRemove)
+               return;
+
+       pHwData->BeaconPeriod = beacon_period;
+       tmp = pHwData->BeaconPeriod << 16;
+       tmp |= pHwData->ProbeDelay;
+       Wb35Reg_Write(pHwData, 0x0848, tmp);
+}
+
 static int wbsoft_add_interface(struct ieee80211_hw *dev,
                                struct ieee80211_if_init_conf *conf)
 {
-       printk("wbsoft_add interface called\n");
+       struct wbsoft_priv *priv = dev->priv;
+
+       hal_set_beacon_period(&priv->sHwData, conf->vif->bss_conf.beacon_int);
+
        return 0;
 }
 
@@ -83,10 +99,16 @@ static int wbsoft_get_tx_stats(struct ieee80211_hw *hw,
        return 0;
 }
 
+static u64 wbsoft_prepare_multicast(struct ieee80211_hw *hw, int mc_count,
+                                   struct dev_addr_list *mc_list)
+{
+       return mc_count;
+}
+
 static void wbsoft_configure_filter(struct ieee80211_hw *dev,
                                    unsigned int changed_flags,
                                    unsigned int *total_flags,
-                                   int mc_count, struct dev_mc_list *mclist)
+                                   u64 multicast)
 {
        unsigned int new_flags;
 
@@ -94,7 +116,7 @@ static void wbsoft_configure_filter(struct ieee80211_hw *dev,
 
        if (*total_flags & FIF_PROMISC_IN_BSS)
                new_flags |= FIF_PROMISC_IN_BSS;
-       else if ((*total_flags & FIF_ALLMULTI) || (mc_count > 32))
+       else if ((*total_flags & FIF_ALLMULTI) || (multicast > 32))
                new_flags |= FIF_ALLMULTI;
 
        dev->flags &= ~IEEE80211_HW_RX_INCLUDES_FCS;
@@ -138,19 +160,6 @@ static void hal_set_radio_mode(struct hw_data *pHwData, unsigned char radio_off)
        Wb35Reg_Write(pHwData, 0x0824, reg->M24_MacControl);
 }
 
-static void hal_set_beacon_period(struct hw_data *pHwData, u16 beacon_period)
-{
-       u32 tmp;
-
-       if (pHwData->SurpriseRemove)
-               return;
-
-       pHwData->BeaconPeriod = beacon_period;
-       tmp = pHwData->BeaconPeriod << 16;
-       tmp |= pHwData->ProbeDelay;
-       Wb35Reg_Write(pHwData, 0x0848, tmp);
-}
-
 static void
 hal_set_current_channel_ex(struct hw_data *pHwData, ChanInfo channel)
 {
@@ -244,7 +253,6 @@ static void hal_set_accept_beacon(struct hw_data *pHwData, u8 enable)
 static int wbsoft_config(struct ieee80211_hw *dev, u32 changed)
 {
        struct wbsoft_priv *priv = dev->priv;
-       struct ieee80211_conf *conf = &dev->conf;
        ChanInfo ch;
 
        printk("wbsoft_config called\n");
@@ -254,7 +262,6 @@ static int wbsoft_config(struct ieee80211_hw *dev, u32 changed)
        ch.ChanNo = 1;
 
        hal_set_current_channel(&priv->sHwData, ch);
-       hal_set_beacon_period(&priv->sHwData, conf->beacon_int);
        hal_set_accept_broadcast(&priv->sHwData, 1);
        hal_set_accept_promiscuous(&priv->sHwData, 1);
        hal_set_accept_multicast(&priv->sHwData, 1);
@@ -277,6 +284,7 @@ static const struct ieee80211_ops wbsoft_ops = {
        .add_interface          = wbsoft_add_interface,
        .remove_interface       = wbsoft_remove_interface,
        .config                 = wbsoft_config,
+       .prepare_multicast      = wbsoft_prepare_multicast,
        .configure_filter       = wbsoft_configure_filter,
        .get_stats              = wbsoft_get_stats,
        .get_tx_stats           = wbsoft_get_tx_stats,
index 9959b65..f44294b 100644 (file)
@@ -1,6 +1,6 @@
 config PRISM2_USB
        tristate "Prism2.5/3 USB driver"
-       depends on WLAN_80211 && USB && WIRELESS_EXT
+       depends on WLAN && USB && WIRELESS_EXT
        default n
        ---help---
          This is the wlan-ng prism 2.5/3 USB driver for a wide range of
index a9d7070..e941367 100644 (file)
@@ -19,6 +19,7 @@
 #include <linux/device.h>
 #include <linux/mm.h>
 #include <linux/idr.h>
+#include <linux/sched.h>
 #include <linux/string.h>
 #include <linux/kobject.h>
 #include <linux/uio_driver.h>
index 864f0ba..2473cf0 100644 (file)
@@ -39,7 +39,7 @@
 #define USBTMC_SIZE_IOBUFFER   2048
 
 /* Default USB timeout (in milliseconds) */
-#define USBTMC_TIMEOUT         10
+#define USBTMC_TIMEOUT         5000
 
 /*
  * Maximum number of read cycles to empty bulk in endpoint during CLEAR and
index 3335131..a18e3c5 100644 (file)
@@ -223,6 +223,7 @@ config USB_OTG
 config USB_GADGET_PXA25X
        boolean "PXA 25x or IXP 4xx"
        depends on (ARCH_PXA && PXA25x) || ARCH_IXP4XX
+       select USB_OTG_UTILS
        help
           Intel's PXA 25x series XScale ARM-5TE processors include
           an integrated full speed USB 1.1 device controller.  The
index f37de28..167cb2a 100644 (file)
  * simpler, Microsoft pushes their own approach: RNDIS.  The published
  * RNDIS specs are ambiguous and appear to be incomplete, and are also
  * needlessly complex.  They borrow more from CDC ACM than CDC ECM.
- *
- * While CDC ECM, CDC Subset, and RNDIS are designed to extend the ethernet
- * interface to the target, CDC EEM was designed to use ethernet over the USB
- * link between the host and target.  CDC EEM is implemented as an alternative
- * to those other protocols when that communication model is more appropriate
  */
 
 #define DRIVER_DESC            "Ethernet Gadget"
@@ -157,8 +152,8 @@ static inline bool has_rndis(void)
 #define RNDIS_PRODUCT_NUM      0xa4a2  /* Ethernet/RNDIS Gadget */
 
 /* For EEM gadgets */
-#define EEM_VENDOR_NUM 0x0525  /* INVALID - NEEDS TO BE ALLOCATED */
-#define EEM_PRODUCT_NUM        0xa4a1  /* INVALID - NEEDS TO BE ALLOCATED */
+#define EEM_VENDOR_NUM         0x1d6b  /* Linux Foundation */
+#define EEM_PRODUCT_NUM                0x0102  /* EEM Gadget */
 
 /*-------------------------------------------------------------------------*/
 
index 42a74b8..fa3d142 100644 (file)
@@ -2139,7 +2139,7 @@ static int fsl_proc_read(char *page, char **start, off_t off, int count,
 static void fsl_udc_release(struct device *dev)
 {
        complete(udc_controller->done);
-       dma_free_coherent(dev, udc_controller->ep_qh_size,
+       dma_free_coherent(dev->parent, udc_controller->ep_qh_size,
                        udc_controller->ep_qh, udc_controller->ep_qh_dma);
        kfree(udc_controller);
 }
index c52a681..01ee0b9 100644 (file)
@@ -1402,7 +1402,8 @@ static int __init imx_udc_probe(struct platform_device *pdev)
        struct clk *clk;
        void __iomem *base;
        int ret = 0;
-       int i, res_size;
+       int i;
+       resource_size_t res_size;
 
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        if (!res) {
@@ -1416,7 +1417,7 @@ static int __init imx_udc_probe(struct platform_device *pdev)
                return -ENODEV;
        }
 
-       res_size = res->end - res->start + 1;
+       res_size = resource_size(res);
        if (!request_mem_region(res->start, res_size, res->name)) {
                dev_err(&pdev->dev, "can't allocate %d bytes at %d address\n",
                        res_size, res->start);
@@ -1527,8 +1528,7 @@ static int __exit imx_udc_remove(struct platform_device *pdev)
        clk_disable(imx_usb->clk);
        iounmap(imx_usb->base);
 
-       release_mem_region(imx_usb->res->start,
-               imx_usb->res->end - imx_usb->res->start + 1);
+       release_mem_region(imx_usb->res->start, resource_size(imx_usb->res));
 
        if (pdata->exit)
                pdata->exit(&pdev->dev);
index 03087e7..9a537aa 100644 (file)
@@ -131,31 +131,48 @@ static inline u16 r8a66597_read(struct r8a66597 *r8a66597, unsigned long offset)
 }
 
 static inline void r8a66597_read_fifo(struct r8a66597 *r8a66597,
-                                     unsigned long offset, u16 *buf,
+                                     unsigned long offset,
+                                     unsigned char *buf,
                                      int len)
 {
+       unsigned long fifoaddr = r8a66597->reg + offset;
+       unsigned int data;
+       int i;
+
        if (r8a66597->pdata->on_chip) {
-               unsigned long fifoaddr = r8a66597->reg + offset;
-               unsigned long count;
-               union {
-                       unsigned long dword;
-                       unsigned char byte[4];
-               } data;
-               unsigned char *pb;
-               int i;
-
-               count = len / 4;
-               insl(fifoaddr, buf, count);
-
-               if (len & 0x00000003) {
-                       data.dword = inl(fifoaddr);
-                       pb = (unsigned char *)buf + count * 4;
-                       for (i = 0; i < (len & 0x00000003); i++)
-                               pb[i] = data.byte[i];
+               /* 32-bit accesses for on_chip controllers */
+
+               /* aligned buf case */
+               if (len >= 4 && !((unsigned long)buf & 0x03)) {
+                       insl(fifoaddr, buf, len / 4);
+                       buf += len & ~0x03;
+                       len &= 0x03;
+               }
+
+               /* unaligned buf case */
+               for (i = 0; i < len; i++) {
+                       if (!(i & 0x03))
+                               data = inl(fifoaddr);
+
+                       buf[i] = (data >> ((i & 0x03) * 8)) & 0xff;
                }
        } else {
-               len = (len + 1) / 2;
-               insw(r8a66597->reg + offset, buf, len);
+               /* 16-bit accesses for external controllers */
+
+               /* aligned buf case */
+               if (len >= 2 && !((unsigned long)buf & 0x01)) {
+                       insw(fifoaddr, buf, len / 2);
+                       buf += len & ~0x01;
+                       len &= 0x01;
+               }
+
+               /* unaligned buf case */
+               for (i = 0; i < len; i++) {
+                       if (!(i & 0x01))
+                               data = inw(fifoaddr);
+
+                       buf[i] = (data >> ((i & 0x01) * 8)) & 0xff;
+               }
        }
 }
 
@@ -166,38 +183,40 @@ static inline void r8a66597_write(struct r8a66597 *r8a66597, u16 val,
 }
 
 static inline void r8a66597_write_fifo(struct r8a66597 *r8a66597,
-                                      unsigned long offset, u16 *buf,
+                                      unsigned long offset,
+                                      unsigned char *buf,
                                       int len)
 {
        unsigned long fifoaddr = r8a66597->reg + offset;
+       int adj = 0;
+       int i;
 
        if (r8a66597->pdata->on_chip) {
-               unsigned long count;
-               unsigned char *pb;
-               int i;
-
-               count = len / 4;
-               outsl(fifoaddr, buf, count);
-
-               if (len & 0x00000003) {
-                       pb = (unsigned char *)buf + count * 4;
-                       for (i = 0; i < (len & 0x00000003); i++) {
-                               if (r8a66597_read(r8a66597, CFIFOSEL) & BIGEND)
-                                       outb(pb[i], fifoaddr + i);
-                               else
-                                       outb(pb[i], fifoaddr + 3 - i);
-                       }
+               /* 32-bit access only if buf is 32-bit aligned */
+               if (len >= 4 && !((unsigned long)buf & 0x03)) {
+                       outsl(fifoaddr, buf, len / 4);
+                       buf += len & ~0x03;
+                       len &= 0x03;
                }
        } else {
-               int odd = len & 0x0001;
-
-               len = len / 2;
-               outsw(fifoaddr, buf, len);
-               if (unlikely(odd)) {
-                       buf = &buf[len];
-                       outb((unsigned char)*buf, fifoaddr);
+               /* 16-bit access only if buf is 16-bit aligned */
+               if (len >= 2 && !((unsigned long)buf & 0x01)) {
+                       outsw(fifoaddr, buf, len / 2);
+                       buf += len & ~0x01;
+                       len &= 0x01;
                }
        }
+
+       /* adjust fifo address in the little endian case */
+       if (!(r8a66597_read(r8a66597, CFIFOSEL) & BIGEND)) {
+               if (r8a66597->pdata->on_chip)
+                       adj = 0x03; /* 32-bit wide */
+               else
+                       adj = 0x01; /* 16-bit wide */
+       }
+
+       for (i = 0; i < len; i++)
+               outb(buf[i], fifoaddr + adj - (i & adj));
 }
 
 static inline void r8a66597_mdfy(struct r8a66597 *r8a66597,
index 3ea0593..b25cdea 100644 (file)
@@ -1400,6 +1400,10 @@ iso_stream_schedule (
                goto fail;
        }
 
+       period = urb->interval;
+       if (!stream->highspeed)
+               period <<= 3;
+
        now = ehci_readl(ehci, &ehci->regs->frame_index) % mod;
 
        /* when's the last uframe this urb could start? */
@@ -1417,14 +1421,15 @@ iso_stream_schedule (
 
                /* Fell behind (by up to twice the slop amount)? */
                if (start >= max - 2 * 8 * SCHEDULE_SLOP)
-                       start += stream->interval * DIV_ROUND_UP(
-                                       max - start, stream->interval) - mod;
+                       start += period * DIV_ROUND_UP(
+                                       max - start, period) - mod;
 
                /* Tried to schedule too far into the future? */
                if (unlikely((start + sched->span) >= max)) {
                        status = -EFBIG;
                        goto fail;
                }
+               stream->next_uframe = start;
                goto ready;
        }
 
@@ -1440,10 +1445,6 @@ iso_stream_schedule (
 
        /* NOTE:  assumes URB_ISO_ASAP, to limit complexity/bugs */
 
-       period = urb->interval;
-       if (!stream->highspeed)
-               period <<= 3;
-
        /* find a uframe slot with enough bandwidth */
        for (; start < (stream->next_uframe + period); start++) {
                int             enough_space;
index e35d828..5c774ab 100644 (file)
@@ -2284,10 +2284,10 @@ static int isp1362_mem_config(struct usb_hcd *hcd)
        dev_info(hcd->self.controller, "ISP1362 Memory usage:\n");
        dev_info(hcd->self.controller, "  ISTL:    2 * %4d:     %4d @ $%04x:$%04x\n",
                 istl_size / 2, istl_size, 0, istl_size / 2);
-       dev_info(hcd->self.controller, "  INTL: %4d * (%3u+8):  %4d @ $%04x\n",
+       dev_info(hcd->self.controller, "  INTL: %4d * (%3lu+8):  %4d @ $%04x\n",
                 ISP1362_INTL_BUFFERS, intl_blksize - PTD_HEADER_SIZE,
                 intl_size, istl_size);
-       dev_info(hcd->self.controller, "  ATL : %4d * (%3u+8):  %4d @ $%04x\n",
+       dev_info(hcd->self.controller, "  ATL : %4d * (%3lu+8):  %4d @ $%04x\n",
                 atl_buffers, atl_blksize - PTD_HEADER_SIZE,
                 atl_size, istl_size + intl_size);
        dev_info(hcd->self.controller, "  USED/FREE:   %4d      %4d\n", total,
@@ -2677,12 +2677,12 @@ static int __devexit isp1362_remove(struct platform_device *pdev)
        DBG(0, "%s: Removing HCD\n", __func__);
        usb_remove_hcd(hcd);
 
-       DBG(0, "%s: Unmapping data_reg @ %08x\n", __func__,
-           (u32)isp1362_hcd->data_reg);
+       DBG(0, "%s: Unmapping data_reg @ %p\n", __func__,
+           isp1362_hcd->data_reg);
        iounmap(isp1362_hcd->data_reg);
 
-       DBG(0, "%s: Unmapping addr_reg @ %08x\n", __func__,
-           (u32)isp1362_hcd->addr_reg);
+       DBG(0, "%s: Unmapping addr_reg @ %p\n", __func__,
+           isp1362_hcd->addr_reg);
        iounmap(isp1362_hcd->addr_reg);
 
        res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
@@ -2810,16 +2810,16 @@ static int __init isp1362_probe(struct platform_device *pdev)
        return 0;
 
  err6:
-       DBG(0, "%s: Freeing dev %08x\n", __func__, (u32)isp1362_hcd);
+       DBG(0, "%s: Freeing dev %p\n", __func__, isp1362_hcd);
        usb_put_hcd(hcd);
  err5:
-       DBG(0, "%s: Unmapping data_reg @ %08x\n", __func__, (u32)data_reg);
+       DBG(0, "%s: Unmapping data_reg @ %p\n", __func__, data_reg);
        iounmap(data_reg);
  err4:
        DBG(0, "%s: Releasing mem region %08lx\n", __func__, (long unsigned int)data->start);
        release_mem_region(data->start, resource_len(data));
  err3:
-       DBG(0, "%s: Unmapping addr_reg @ %08x\n", __func__, (u32)addr_reg);
+       DBG(0, "%s: Unmapping addr_reg @ %p\n", __func__, addr_reg);
        iounmap(addr_reg);
  err2:
        DBG(0, "%s: Releasing mem region %08lx\n", __func__, (long unsigned int)addr->start);
index fe60f62..1a253eb 100644 (file)
@@ -580,7 +580,7 @@ static inline const char *ISP1362_INT_NAME(int n)
 
 static inline void ALIGNSTAT(struct isp1362_hcd *isp1362_hcd, void *ptr)
 {
-       unsigned p = (unsigned)ptr;
+       unsigned long p = (unsigned long)ptr;
        if (!(p & 0xf))
                isp1362_hcd->stat16++;
        else if (!(p & 0x7))
@@ -770,7 +770,7 @@ static void isp1362_write_fifo(struct isp1362_hcd *isp1362_hcd, void *buf, u16 l
        if (!len)
                return;
 
-       if ((unsigned)dp & 0x1) {
+       if ((unsigned long)dp & 0x1) {
                /* not aligned */
                for (; len > 1; len -= 2) {
                        data = *dp++;
@@ -962,8 +962,8 @@ static void isp1362_read_buffer(struct isp1362_hcd *isp1362_hcd, void *buf, u16
 
        isp1362_write_diraddr(isp1362_hcd, offset, len);
 
-       DBG(3, "%s: Reading %d byte from buffer @%04x to memory @ %08x\n", __func__,
-           len, offset, (u32)buf);
+       DBG(3, "%s: Reading %d byte from buffer @%04x to memory @ %p\n",
+           __func__, len, offset, buf);
 
        isp1362_write_reg16(isp1362_hcd, HCuPINT, HCuPINT_EOT);
        _WARN_ON((isp1362_read_reg16(isp1362_hcd, HCuPINT) & HCuPINT_EOT));
@@ -982,8 +982,8 @@ static void isp1362_write_buffer(struct isp1362_hcd *isp1362_hcd, void *buf, u16
 
        isp1362_write_diraddr(isp1362_hcd, offset, len);
 
-       DBG(3, "%s: Writing %d byte to buffer @%04x from memory @ %08x\n", __func__,
-           len, offset, (u32)buf);
+       DBG(3, "%s: Writing %d byte to buffer @%04x from memory @ %p\n",
+           __func__, len, offset, buf);
 
        isp1362_write_reg16(isp1362_hcd, HCuPINT, HCuPINT_EOT);
        _WARN_ON((isp1362_read_reg16(isp1362_hcd, HCuPINT) & HCuPINT_EOT));
index 23cf3bd..83b5f9c 100644 (file)
@@ -475,4 +475,4 @@ static void __devinit quirk_usb_early_handoff(struct pci_dev *pdev)
        else if (pdev->class == PCI_CLASS_SERIAL_USB_XHCI)
                quirk_usb_handoff_xhci(pdev);
 }
-DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, quirk_usb_early_handoff);
+DECLARE_PCI_FIXUP_FINAL(PCI_ANY_ID, PCI_ANY_ID, quirk_usb_early_handoff);
index 749b537..e33d362 100644 (file)
@@ -1003,19 +1003,20 @@ static void r8a66597_check_syssts(struct r8a66597 *r8a66597, int port,
        if (syssts == SE0) {
                r8a66597_write(r8a66597, ~ATTCH, get_intsts_reg(port));
                r8a66597_bset(r8a66597, ATTCHE, get_intenb_reg(port));
-               return;
-       }
+       } else {
+               if (syssts == FS_JSTS)
+                       r8a66597_bset(r8a66597, HSE, get_syscfg_reg(port));
+               else if (syssts == LS_JSTS)
+                       r8a66597_bclr(r8a66597, HSE, get_syscfg_reg(port));
 
-       if (syssts == FS_JSTS)
-               r8a66597_bset(r8a66597, HSE, get_syscfg_reg(port));
-       else if (syssts == LS_JSTS)
-               r8a66597_bclr(r8a66597, HSE, get_syscfg_reg(port));
+               r8a66597_write(r8a66597, ~DTCH, get_intsts_reg(port));
+               r8a66597_bset(r8a66597, DTCHE, get_intenb_reg(port));
 
-       r8a66597_write(r8a66597, ~DTCH, get_intsts_reg(port));
-       r8a66597_bset(r8a66597, DTCHE, get_intenb_reg(port));
+               if (r8a66597->bus_suspended)
+                       usb_hcd_resume_root_hub(r8a66597_to_hcd(r8a66597));
+       }
 
-       if (r8a66597->bus_suspended)
-               usb_hcd_resume_root_hub(r8a66597_to_hcd(r8a66597));
+       usb_hcd_poll_rh_status(r8a66597_to_hcd(r8a66597));
 }
 
 /* this function must be called with interrupt disabled */
@@ -1024,6 +1025,8 @@ static void r8a66597_usb_connect(struct r8a66597 *r8a66597, int port)
        u16 speed = get_rh_usb_speed(r8a66597, port);
        struct r8a66597_root_hub *rh = &r8a66597->root_hub[port];
 
+       rh->port &= ~((1 << USB_PORT_FEAT_HIGHSPEED) |
+                     (1 << USB_PORT_FEAT_LOWSPEED));
        if (speed == HSMODE)
                rh->port |= (1 << USB_PORT_FEAT_HIGHSPEED);
        else if (speed == LSMODE)
index c632437..562eba1 100644 (file)
@@ -115,6 +115,10 @@ static uint32_t process_qset(struct whc *whc, struct whc_qset *qset)
                if (status & QTD_STS_HALTED) {
                        /* Ug, an error. */
                        process_halted_qtd(whc, qset, td);
+                       /* A halted qTD always triggers an update
+                          because the qset was either removed or
+                          reactivated. */
+                       update |= WHC_UPDATE_UPDATED;
                        goto done;
                }
 
@@ -305,6 +309,7 @@ int asl_urb_dequeue(struct whc *whc, struct urb *urb, int status)
        struct whc_urb *wurb = urb->hcpriv;
        struct whc_qset *qset = wurb->qset;
        struct whc_std *std, *t;
+       bool has_qtd = false;
        int ret;
        unsigned long flags;
 
@@ -315,17 +320,21 @@ int asl_urb_dequeue(struct whc *whc, struct urb *urb, int status)
                goto out;
 
        list_for_each_entry_safe(std, t, &qset->stds, list_node) {
-               if (std->urb == urb)
+               if (std->urb == urb) {
+                       if (std->qtd)
+                               has_qtd = true;
                        qset_free_std(whc, std);
-               else
+               else
                        std->qtd = NULL; /* so this std is re-added when the qset is */
        }
 
-       asl_qset_remove(whc, qset);
-       wurb->status = status;
-       wurb->is_async = true;
-       queue_work(whc->workqueue, &wurb->dequeue_work);
-
+       if (has_qtd) {
+               asl_qset_remove(whc, qset);
+               wurb->status = status;
+               wurb->is_async = true;
+               queue_work(whc->workqueue, &wurb->dequeue_work);
+       } else
+               qset_remove_urb(whc, qset, urb, status);
 out:
        spin_unlock_irqrestore(&whc->lock, flags);
 
index a9e05ba..0db3fb2 100644 (file)
@@ -121,6 +121,10 @@ static enum whc_update pzl_process_qset(struct whc *whc, struct whc_qset *qset)
                if (status & QTD_STS_HALTED) {
                        /* Ug, an error. */
                        process_halted_qtd(whc, qset, td);
+                       /* A halted qTD always triggers an update
+                          because the qset was either removed or
+                          reactivated. */
+                       update |= WHC_UPDATE_UPDATED;
                        goto done;
                }
 
@@ -333,6 +337,7 @@ int pzl_urb_dequeue(struct whc *whc, struct urb *urb, int status)
        struct whc_urb *wurb = urb->hcpriv;
        struct whc_qset *qset = wurb->qset;
        struct whc_std *std, *t;
+       bool has_qtd = false;
        int ret;
        unsigned long flags;
 
@@ -343,17 +348,22 @@ int pzl_urb_dequeue(struct whc *whc, struct urb *urb, int status)
                goto out;
 
        list_for_each_entry_safe(std, t, &qset->stds, list_node) {
-               if (std->urb == urb)
+               if (std->urb == urb) {
+                       if (std->qtd)
+                               has_qtd = true;
                        qset_free_std(whc, std);
-               else
+               else
                        std->qtd = NULL; /* so this std is re-added when the qset is */
        }
 
-       pzl_qset_remove(whc, qset);
-       wurb->status = status;
-       wurb->is_async = false;
-       queue_work(whc->workqueue, &wurb->dequeue_work);
-
+       if (has_qtd) {
+               pzl_qset_remove(whc, qset);
+               update_pzl_hw_view(whc);
+               wurb->status = status;
+               wurb->is_async = false;
+               queue_work(whc->workqueue, &wurb->dequeue_work);
+       } else
+               qset_remove_urb(whc, qset, urb, status);
 out:
        spin_unlock_irqrestore(&whc->lock, flags);
 
index 99911e7..932f999 100644 (file)
@@ -335,6 +335,12 @@ void xhci_event_ring_work(unsigned long arg)
        spin_lock_irqsave(&xhci->lock, flags);
        temp = xhci_readl(xhci, &xhci->op_regs->status);
        xhci_dbg(xhci, "op reg status = 0x%x\n", temp);
+       if (temp == 0xffffffff) {
+               xhci_dbg(xhci, "HW died, polling stopped.\n");
+               spin_unlock_irqrestore(&xhci->lock, flags);
+               return;
+       }
+
        temp = xhci_readl(xhci, &xhci->ir_set->irq_pending);
        xhci_dbg(xhci, "ir_set 0 pending = 0x%x\n", temp);
        xhci_dbg(xhci, "No-op commands handled = %d\n", xhci->noops_handled);
@@ -776,6 +782,7 @@ int xhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
 {
        unsigned long flags;
        int ret;
+       u32 temp;
        struct xhci_hcd *xhci;
        struct xhci_td *td;
        unsigned int ep_index;
@@ -788,6 +795,17 @@ int xhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
        ret = usb_hcd_check_unlink_urb(hcd, urb, status);
        if (ret || !urb->hcpriv)
                goto done;
+       temp = xhci_readl(xhci, &xhci->op_regs->status);
+       if (temp == 0xffffffff) {
+               xhci_dbg(xhci, "HW died, freeing TD.\n");
+               td = (struct xhci_td *) urb->hcpriv;
+
+               usb_hcd_unlink_urb_from_ep(hcd, urb);
+               spin_unlock_irqrestore(&xhci->lock, flags);
+               usb_hcd_giveback_urb(xhci_to_hcd(xhci), urb, -ESHUTDOWN);
+               kfree(td);
+               return ret;
+       }
 
        xhci_dbg(xhci, "Cancel URB %p\n", urb);
        xhci_dbg(xhci, "Event ring:\n");
@@ -877,7 +895,7 @@ int xhci_drop_endpoint(struct usb_hcd *hcd, struct usb_device *udev,
        ctrl_ctx->drop_flags |= drop_flag;
        new_drop_flags = ctrl_ctx->drop_flags;
 
-       ctrl_ctx->add_flags = ~drop_flag;
+       ctrl_ctx->add_flags &= ~drop_flag;
        new_add_flags = ctrl_ctx->add_flags;
 
        last_ctx = xhci_last_valid_endpoint(ctrl_ctx->add_flags);
@@ -1410,11 +1428,20 @@ void xhci_free_dev(struct usb_hcd *hcd, struct usb_device *udev)
 {
        struct xhci_hcd *xhci = hcd_to_xhci(hcd);
        unsigned long flags;
+       u32 state;
 
        if (udev->slot_id == 0)
                return;
 
        spin_lock_irqsave(&xhci->lock, flags);
+       /* Don't disable the slot if the host controller is dead. */
+       state = xhci_readl(xhci, &xhci->op_regs->status);
+       if (state == 0xffffffff) {
+               xhci_free_virt_device(xhci, udev->slot_id);
+               spin_unlock_irqrestore(&xhci->lock, flags);
+               return;
+       }
+
        if (xhci_queue_slot_control(xhci, TRB_DISABLE_SLOT, udev->slot_id)) {
                spin_unlock_irqrestore(&xhci->lock, flags);
                xhci_dbg(xhci, "FIXME: allocate a command ring segment\n");
index 29092b8..4fb1203 100644 (file)
@@ -313,7 +313,8 @@ static int lcd_probe(struct usb_interface *interface, const struct usb_device_id
 
        if (le16_to_cpu(dev->udev->descriptor.idProduct) != 0x0001) {
                dev_warn(&interface->dev, "USBLCD model not supported.\n");
-               return -ENODEV;
+               retval = -ENODEV;
+               goto error;
        }
        
        /* set up the endpoint information */
index 803adcb..b84abd8 100644 (file)
@@ -8,8 +8,8 @@ comment "Enable Host or Gadget support to see Inventra options"
 
 # (M)HDRC = (Multipoint) Highspeed Dual-Role Controller
 config USB_MUSB_HDRC
-       depends on (USB || USB_GADGET) && HAVE_CLK
-       depends on !SUPERH
+       depends on (USB || USB_GADGET)
+       depends on (ARM || BLACKFIN)
        select NOP_USB_XCEIV if ARCH_DAVINCI
        select TWL4030_USB if MACH_OMAP_3430SDP
        select NOP_USB_XCEIV if MACH_OMAP3EVM
index f2f66eb..fcec87e 100644 (file)
@@ -14,7 +14,6 @@
 #include <linux/slab.h>
 #include <linux/init.h>
 #include <linux/list.h>
-#include <linux/clk.h>
 #include <linux/gpio.h>
 #include <linux/io.h>
 
index 381d648..6aa5f22 100644 (file)
@@ -95,6 +95,13 @@ struct musb_ep;
 #endif
 #endif /* need MUSB gadget selection */
 
+#ifndef CONFIG_HAVE_CLK
+/* Dummy stub for clk framework */
+#define clk_get(dev, id)       NULL
+#define clk_put(clock)         do {} while (0)
+#define clk_enable(clock)      do {} while (0)
+#define clk_disable(clock)     do {} while (0)
+#endif
 
 #ifdef CONFIG_PROC_FS
 #include <linux/fs.h>
index fbfd3fd..cc1d71b 100644 (file)
@@ -439,15 +439,6 @@ static inline void  musb_write_txhubport(void __iomem *mbase, u8 epnum,
 /* Not implemented - HW has seperate Tx/Rx FIFO */
 #define MUSB_TXCSR_MODE                        0x0000
 
-/*
- * Dummy stub for clk framework, it will be removed
- * until Blackfin supports clk framework
- */
-#define clk_get(dev, id)       NULL
-#define clk_put(clock)         do {} while (0)
-#define clk_enable(clock)      do {} while (0)
-#define clk_disable(clock)     do {} while (0)
-
 static inline void musb_write_txfifosz(void __iomem *mbase, u8 c_size)
 {
 }
index 2cbfab3..b10ac84 100644 (file)
@@ -554,13 +554,12 @@ static void aircable_throttle(struct tty_struct *tty)
 {
        struct usb_serial_port *port = tty->driver_data;
        struct aircable_private *priv = usb_get_serial_port_data(port);
-       unsigned long flags;
 
        dbg("%s - port %d", __func__, port->number);
 
-       spin_lock_irqsave(&priv->rx_lock, flags);
+       spin_lock_irq(&priv->rx_lock);
        priv->rx_flags |= THROTTLED;
-       spin_unlock_irqrestore(&priv->rx_lock, flags);
+       spin_unlock_irq(&priv->rx_lock);
 }
 
 /* Based on ftdi_sio.c unthrottle */
@@ -569,14 +568,13 @@ static void aircable_unthrottle(struct tty_struct *tty)
        struct usb_serial_port *port = tty->driver_data;
        struct aircable_private *priv = usb_get_serial_port_data(port);
        int actually_throttled;
-       unsigned long flags;
 
        dbg("%s - port %d", __func__, port->number);
 
-       spin_lock_irqsave(&priv->rx_lock, flags);
+       spin_lock_irq(&priv->rx_lock);
        actually_throttled = priv->rx_flags & ACTUALLY_THROTTLED;
        priv->rx_flags &= ~(THROTTLED | ACTUALLY_THROTTLED);
-       spin_unlock_irqrestore(&priv->rx_lock, flags);
+       spin_unlock_irq(&priv->rx_lock);
 
        if (actually_throttled)
                schedule_work(&priv->rx_work);
index 4a208fe..698252a 100644 (file)
@@ -113,6 +113,7 @@ static struct usb_device_id id_table [] = {
        { USB_DEVICE(0x166A, 0x0303) }, /* Clipsal 5500PCU C-Bus USB interface */
        { USB_DEVICE(0x16D6, 0x0001) }, /* Jablotron serial interface */
        { USB_DEVICE(0x18EF, 0xE00F) }, /* ELV USB-I2C-Interface */
+       { USB_DEVICE(0x413C, 0x9500) }, /* DW700 GPS USB interface */
        { } /* Terminating Entry */
 };
 
index e0a8b71..a591ebe 100644 (file)
@@ -1155,13 +1155,12 @@ static void cypress_throttle(struct tty_struct *tty)
 {
        struct usb_serial_port *port = tty->driver_data;
        struct cypress_private *priv = usb_get_serial_port_data(port);
-       unsigned long flags;
 
        dbg("%s - port %d", __func__, port->number);
 
-       spin_lock_irqsave(&priv->lock, flags);
+       spin_lock_irq(&priv->lock);
        priv->rx_flags = THROTTLED;
-       spin_unlock_irqrestore(&priv->lock, flags);
+       spin_unlock_irq(&priv->lock);
 }
 
 
@@ -1170,14 +1169,13 @@ static void cypress_unthrottle(struct tty_struct *tty)
        struct usb_serial_port *port = tty->driver_data;
        struct cypress_private *priv = usb_get_serial_port_data(port);
        int actually_throttled, result;
-       unsigned long flags;
 
        dbg("%s - port %d", __func__, port->number);
 
-       spin_lock_irqsave(&priv->lock, flags);
+       spin_lock_irq(&priv->lock);
        actually_throttled = priv->rx_flags & ACTUALLY_THROTTLED;
        priv->rx_flags = 0;
-       spin_unlock_irqrestore(&priv->lock, flags);
+       spin_unlock_irq(&priv->lock);
 
        if (!priv->comm_is_ok)
                return;
@@ -1185,7 +1183,7 @@ static void cypress_unthrottle(struct tty_struct *tty)
        if (actually_throttled) {
                port->interrupt_in_urb->dev = port->serial->dev;
 
-               result = usb_submit_urb(port->interrupt_in_urb, GFP_ATOMIC);
+               result = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL);
                if (result) {
                        dev_err(&port->dev, "%s - failed submitting read urb, "
                                        "error %d\n", __func__, result);
index ab3dd99..68e80be 100644 (file)
@@ -898,16 +898,16 @@ static void digi_rx_unthrottle(struct tty_struct *tty)
 
        spin_lock_irqsave(&priv->dp_port_lock, flags);
 
-       /* turn throttle off */
-       priv->dp_throttled = 0;
-       priv->dp_throttle_restart = 0;
-
        /* restart read chain */
        if (priv->dp_throttle_restart) {
                port->read_urb->dev = port->serial->dev;
                ret = usb_submit_urb(port->read_urb, GFP_ATOMIC);
        }
 
+       /* turn throttle off */
+       priv->dp_throttled = 0;
+       priv->dp_throttle_restart = 0;
+
        spin_unlock_irqrestore(&priv->dp_port_lock, flags);
 
        if (ret)
index 33c9e9c..7dd0e3e 100644 (file)
@@ -391,7 +391,7 @@ static void empeg_unthrottle(struct tty_struct *tty)
        dbg("%s - port %d", __func__, port->number);
 
        port->read_urb->dev = port->serial->dev;
-       result = usb_submit_urb(port->read_urb, GFP_ATOMIC);
+       result = usb_submit_urb(port->read_urb, GFP_KERNEL);
        if (result)
                dev_err(&port->dev,
                        "%s - failed submitting read urb, error %d\n",
index 4f883b1..9c60d6d 100644 (file)
@@ -76,13 +76,7 @@ struct ftdi_private {
        unsigned long last_dtr_rts;     /* saved modem control outputs */
        wait_queue_head_t delta_msr_wait; /* Used for TIOCMIWAIT */
        char prev_status, diff_status;        /* Used for TIOCMIWAIT */
-       __u8 rx_flags;          /* receive state flags (throttling) */
-       spinlock_t rx_lock;     /* spinlock for receive state */
-       struct delayed_work rx_work;
        struct usb_serial_port *port;
-       int rx_processed;
-       unsigned long rx_bytes;
-
        __u16 interface;        /* FT2232C, FT2232H or FT4232H port interface
                                   (0 for FT232/245) */
 
@@ -737,10 +731,6 @@ static const char *ftdi_chip_name[] = {
 /* Constants for read urb and write urb */
 #define BUFSZ 512
 
-/* rx_flags */
-#define THROTTLED              0x01
-#define ACTUALLY_THROTTLED     0x02
-
 /* Used for TIOCMIWAIT */
 #define FTDI_STATUS_B0_MASK    (FTDI_RS0_CTS | FTDI_RS0_DSR | FTDI_RS0_RI | FTDI_RS0_RLSD)
 #define FTDI_STATUS_B1_MASK    (FTDI_RS_BI)
@@ -763,7 +753,7 @@ static int  ftdi_write_room(struct tty_struct *tty);
 static int  ftdi_chars_in_buffer(struct tty_struct *tty);
 static void ftdi_write_bulk_callback(struct urb *urb);
 static void ftdi_read_bulk_callback(struct urb *urb);
-static void ftdi_process_read(struct work_struct *work);
+static void ftdi_process_read(struct usb_serial_port *port);
 static void ftdi_set_termios(struct tty_struct *tty,
                        struct usb_serial_port *port, struct ktermios *old);
 static int  ftdi_tiocmget(struct tty_struct *tty, struct file *file);
@@ -1234,7 +1224,6 @@ static int set_serial_info(struct tty_struct *tty,
                                        (new_serial.flags & ASYNC_FLAGS));
        priv->custom_divisor = new_serial.custom_divisor;
 
-       tty->low_latency = (priv->flags & ASYNC_LOW_LATENCY) ? 1 : 0;
        write_latency_timer(port);
 
 check_and_exit:
@@ -1527,7 +1516,6 @@ static int ftdi_sio_port_probe(struct usb_serial_port *port)
        }
 
        kref_init(&priv->kref);
-       spin_lock_init(&priv->rx_lock);
        spin_lock_init(&priv->tx_lock);
        init_waitqueue_head(&priv->delta_msr_wait);
        /* This will push the characters through immediately rather
@@ -1549,7 +1537,6 @@ static int ftdi_sio_port_probe(struct usb_serial_port *port)
                port->read_urb->transfer_buffer_length = BUFSZ;
        }
 
-       INIT_DELAYED_WORK(&priv->rx_work, ftdi_process_read);
        priv->port = port;
 
        /* Free port's existing write urb and transfer buffer. */
@@ -1686,6 +1673,26 @@ static int ftdi_sio_port_remove(struct usb_serial_port *port)
        return 0;
 }
 
+static int ftdi_submit_read_urb(struct usb_serial_port *port, gfp_t mem_flags)
+{
+       struct urb *urb = port->read_urb;
+       struct usb_serial *serial = port->serial;
+       int result;
+
+       usb_fill_bulk_urb(urb, serial->dev,
+                          usb_rcvbulkpipe(serial->dev,
+                                       port->bulk_in_endpointAddress),
+                          urb->transfer_buffer,
+                          urb->transfer_buffer_length,
+                          ftdi_read_bulk_callback, port);
+       result = usb_submit_urb(urb, mem_flags);
+       if (result)
+               dev_err(&port->dev,
+                       "%s - failed submitting read urb, error %d\n",
+                                                       __func__, result);
+       return result;
+}
+
 static int ftdi_open(struct tty_struct *tty, struct usb_serial_port *port)
 { /* ftdi_open */
        struct usb_device *dev = port->serial->dev;
@@ -1700,12 +1707,6 @@ static int ftdi_open(struct tty_struct *tty, struct usb_serial_port *port)
        spin_lock_irqsave(&priv->tx_lock, flags);
        priv->tx_bytes = 0;
        spin_unlock_irqrestore(&priv->tx_lock, flags);
-       spin_lock_irqsave(&priv->rx_lock, flags);
-       priv->rx_bytes = 0;
-       spin_unlock_irqrestore(&priv->rx_lock, flags);
-
-       if (tty)
-               tty->low_latency = (priv->flags & ASYNC_LOW_LATENCY) ? 1 : 0;
 
        write_latency_timer(port);
 
@@ -1725,23 +1726,14 @@ static int ftdi_open(struct tty_struct *tty, struct usb_serial_port *port)
                ftdi_set_termios(tty, port, tty->termios);
 
        /* Not throttled */
-       spin_lock_irqsave(&priv->rx_lock, flags);
-       priv->rx_flags &= ~(THROTTLED | ACTUALLY_THROTTLED);
-       spin_unlock_irqrestore(&priv->rx_lock, flags);
+       spin_lock_irqsave(&port->lock, flags);
+       port->throttled = 0;
+       port->throttle_req = 0;
+       spin_unlock_irqrestore(&port->lock, flags);
 
        /* Start reading from the device */
-       priv->rx_processed = 0;
-       usb_fill_bulk_urb(port->read_urb, dev,
-                       usb_rcvbulkpipe(dev, port->bulk_in_endpointAddress),
-                       port->read_urb->transfer_buffer,
-                               port->read_urb->transfer_buffer_length,
-                       ftdi_read_bulk_callback, port);
-       result = usb_submit_urb(port->read_urb, GFP_KERNEL);
-       if (result)
-               dev_err(&port->dev,
-                       "%s - failed submitting read urb, error %d\n",
-                       __func__, result);
-       else
+       result = ftdi_submit_read_urb(port, GFP_KERNEL);
+       if (!result)
                kref_get(&priv->kref);
 
        return result;
@@ -1787,10 +1779,6 @@ static void ftdi_close(struct usb_serial_port *port)
 
        dbg("%s", __func__);
 
-
-       /* cancel any scheduled reading */
-       cancel_delayed_work_sync(&priv->rx_work);
-
        /* shutdown our bulk read */
        usb_kill_urb(port->read_urb);
        kref_put(&priv->kref, ftdi_sio_priv_release);
@@ -2013,271 +2001,121 @@ static int ftdi_chars_in_buffer(struct tty_struct *tty)
        return buffered;
 }
 
-static void ftdi_read_bulk_callback(struct urb *urb)
+static int ftdi_process_packet(struct tty_struct *tty,
+               struct usb_serial_port *port, struct ftdi_private *priv,
+               char *packet, int len)
 {
-       struct usb_serial_port *port = urb->context;
-       struct tty_struct *tty;
-       struct ftdi_private *priv;
-       unsigned long countread;
-       unsigned long flags;
-       int status = urb->status;
-
-       if (urb->number_of_packets > 0) {
-               dev_err(&port->dev, "%s transfer_buffer_length %d "
-                       "actual_length %d number of packets %d\n", __func__,
-                       urb->transfer_buffer_length,
-                       urb->actual_length, urb->number_of_packets);
-               dev_err(&port->dev, "%s transfer_flags %x\n", __func__,
-                       urb->transfer_flags);
-       }
+       int i;
+       char status;
+       char flag;
+       char *ch;
 
        dbg("%s - port %d", __func__, port->number);
 
-       if (port->port.count <= 0)
-               return;
-
-       tty = tty_port_tty_get(&port->port);
-       if (!tty) {
-               dbg("%s - bad tty pointer - exiting", __func__);
-               return;
+       if (len < 2) {
+               dbg("malformed packet");
+               return 0;
        }
 
-       priv = usb_get_serial_port_data(port);
-       if (!priv) {
-               dbg("%s - bad port private data pointer - exiting", __func__);
-               goto out;
+       /* Compare new line status to the old one, signal if different/
+          N.B. packet may be processed more than once, but differences
+          are only processed once.  */
+       status = packet[0] & FTDI_STATUS_B0_MASK;
+       if (status != priv->prev_status) {
+               priv->diff_status |= status ^ priv->prev_status;
+               wake_up_interruptible(&priv->delta_msr_wait);
+               priv->prev_status = status;
        }
 
-       if (urb != port->read_urb)
-               dev_err(&port->dev, "%s - Not my urb!\n", __func__);
-
-       if (status) {
-               /* This will happen at close every time so it is a dbg not an
-                  err */
-               dbg("(this is ok on close) nonzero read bulk status received: %d", status);
-               goto out;
+       /*
+        * Although the device uses a bitmask and hence can have multiple
+        * errors on a packet - the order here sets the priority the error is
+        * returned to the tty layer.
+        */
+       flag = TTY_NORMAL;
+       if (packet[1] & FTDI_RS_OE) {
+               flag = TTY_OVERRUN;
+               dbg("OVERRRUN error");
+       }
+       if (packet[1] & FTDI_RS_BI) {
+               flag = TTY_BREAK;
+               dbg("BREAK received");
+               usb_serial_handle_break(port);
+       }
+       if (packet[1] & FTDI_RS_PE) {
+               flag = TTY_PARITY;
+               dbg("PARITY error");
+       }
+       if (packet[1] & FTDI_RS_FE) {
+               flag = TTY_FRAME;
+               dbg("FRAMING error");
        }
 
-       /* count data bytes, but not status bytes */
-       countread = urb->actual_length;
-       countread -= 2 * DIV_ROUND_UP(countread, priv->max_packet_size);
-       spin_lock_irqsave(&priv->rx_lock, flags);
-       priv->rx_bytes += countread;
-       spin_unlock_irqrestore(&priv->rx_lock, flags);
-
-       ftdi_process_read(&priv->rx_work.work);
-out:
-       tty_kref_put(tty);
-} /* ftdi_read_bulk_callback */
-
+       len -= 2;
+       if (!len)
+               return 0;       /* status only */
+       ch = packet + 2;
+
+       if (!(port->console && port->sysrq) && flag == TTY_NORMAL)
+               tty_insert_flip_string(tty, ch, len);
+       else {
+               for (i = 0; i < len; i++, ch++) {
+                       if (!usb_serial_handle_sysrq_char(tty, port, *ch))
+                               tty_insert_flip_char(tty, *ch, flag);
+               }
+       }
+       return len;
+}
 
-static void ftdi_process_read(struct work_struct *work)
-{ /* ftdi_process_read */
-       struct ftdi_private *priv =
-               container_of(work, struct ftdi_private, rx_work.work);
-       struct usb_serial_port *port = priv->port;
-       struct urb *urb;
+static void ftdi_process_read(struct usb_serial_port *port)
+{
+       struct urb *urb = port->read_urb;
        struct tty_struct *tty;
-       char error_flag;
-       unsigned char *data;
-
+       struct ftdi_private *priv = usb_get_serial_port_data(port);
+       char *data = (char *)urb->transfer_buffer;
        int i;
-       int result;
-       int need_flip;
-       int packet_offset;
-       unsigned long flags;
-
-       dbg("%s - port %d", __func__, port->number);
-
-       if (port->port.count <= 0)
-               return;
+       int len;
+       int count = 0;
 
        tty = tty_port_tty_get(&port->port);
-       if (!tty) {
-               dbg("%s - bad tty pointer - exiting", __func__);
+       if (!tty)
                return;
-       }
-
-       priv = usb_get_serial_port_data(port);
-       if (!priv) {
-               dbg("%s - bad port private data pointer - exiting", __func__);
-               goto out;
-       }
-
-       urb = port->read_urb;
-       if (!urb) {
-               dbg("%s - bad read_urb pointer - exiting", __func__);
-               goto out;
-       }
-
-       data = urb->transfer_buffer;
 
-       if (priv->rx_processed) {
-               dbg("%s - already processed: %d bytes, %d remain", __func__,
-                               priv->rx_processed,
-                               urb->actual_length - priv->rx_processed);
-       } else {
-               /* The first two bytes of every read packet are status */
-               if (urb->actual_length > 2)
-                       usb_serial_debug_data(debug, &port->dev, __func__,
-                                               urb->actual_length, data);
-               else
-                       dbg("Status only: %03oo %03oo", data[0], data[1]);
+       for (i = 0; i < urb->actual_length; i += priv->max_packet_size) {
+               len = min_t(int, urb->actual_length - i, priv->max_packet_size);
+               count += ftdi_process_packet(tty, port, priv, &data[i], len);
        }
 
-
-       /* TO DO -- check for hung up line and handle appropriately: */
-       /*   send hangup  */
-       /* See acm.c - you do a tty_hangup  - eg tty_hangup(tty) */
-       /* if CD is dropped and the line is not CLOCAL then we should hangup */
-
-       need_flip = 0;
-       for (packet_offset = priv->rx_processed;
-               packet_offset < urb->actual_length; packet_offset += priv->max_packet_size) {
-               int length;
-
-               /* Compare new line status to the old one, signal if different/
-                  N.B. packet may be processed more than once, but differences
-                  are only processed once.  */
-               char new_status = data[packet_offset + 0] &
-                                               FTDI_STATUS_B0_MASK;
-               if (new_status != priv->prev_status) {
-                       priv->diff_status |=
-                               new_status ^ priv->prev_status;
-                       wake_up_interruptible(&priv->delta_msr_wait);
-                       priv->prev_status = new_status;
-               }
-
-               length = min_t(u32, priv->max_packet_size, urb->actual_length-packet_offset)-2;
-               if (length < 0) {
-                       dev_err(&port->dev, "%s - bad packet length: %d\n",
-                               __func__, length+2);
-                       length = 0;
-               }
-
-               if (priv->rx_flags & THROTTLED) {
-                       dbg("%s - throttled", __func__);
-                       break;
-               }
-               if (tty_buffer_request_room(tty, length) < length) {
-                       /* break out & wait for throttling/unthrottling to
-                          happen */
-                       dbg("%s - receive room low", __func__);
-                       break;
-               }
-
-               /* Handle errors and break */
-               error_flag = TTY_NORMAL;
-               /* Although the device uses a bitmask and hence can have
-                  multiple errors on a packet - the order here sets the
-                  priority the error is returned to the tty layer  */
-
-               if (data[packet_offset+1] & FTDI_RS_OE) {
-                       error_flag = TTY_OVERRUN;
-                       dbg("OVERRRUN error");
-               }
-               if (data[packet_offset+1] & FTDI_RS_BI) {
-                       error_flag = TTY_BREAK;
-                       dbg("BREAK received");
-                       usb_serial_handle_break(port);
-               }
-               if (data[packet_offset+1] & FTDI_RS_PE) {
-                       error_flag = TTY_PARITY;
-                       dbg("PARITY error");
-               }
-               if (data[packet_offset+1] & FTDI_RS_FE) {
-                       error_flag = TTY_FRAME;
-                       dbg("FRAMING error");
-               }
-               if (length > 0) {
-                       for (i = 2; i < length+2; i++) {
-                               /* Note that the error flag is duplicated for
-                                  every character received since we don't know
-                                  which character it applied to */
-                               if (!usb_serial_handle_sysrq_char(tty, port,
-                                               data[packet_offset + i]))
-                                       tty_insert_flip_char(tty,
-                                               data[packet_offset + i],
-                                               error_flag);
-                       }
-                       need_flip = 1;
-               }
-
-#ifdef NOT_CORRECT_BUT_KEEPING_IT_FOR_NOW
-               /* if a parity error is detected you get status packets forever
-                  until a character is sent without a parity error.
-                  This doesn't work well since the application receives a
-                  never ending stream of bad data - even though new data
-                  hasn't been sent. Therefore I (bill) have taken this out.
-                  However - this might make sense for framing errors and so on
-                  so I am leaving the code in for now.
-               */
-               else {
-                       if (error_flag != TTY_NORMAL) {
-                               dbg("error_flag is not normal");
-                               /* In this case it is just status - if that is
-                                  an error send a bad character */
-                               if (tty->flip.count >= TTY_FLIPBUF_SIZE)
-                                       tty_flip_buffer_push(tty);
-                               tty_insert_flip_char(tty, 0xff, error_flag);
-                               need_flip = 1;
-                       }
-               }
-#endif
-       } /* "for(packet_offset=0..." */
-
-       /* Low latency */
-       if (need_flip)
+       if (count)
                tty_flip_buffer_push(tty);
+       tty_kref_put(tty);
+}
 
-       if (packet_offset < urb->actual_length) {
-               /* not completely processed - record progress */
-               priv->rx_processed = packet_offset;
-               dbg("%s - incomplete, %d bytes processed, %d remain",
-                               __func__, packet_offset,
-                               urb->actual_length - packet_offset);
-               /* check if we were throttled while processing */
-               spin_lock_irqsave(&priv->rx_lock, flags);
-               if (priv->rx_flags & THROTTLED) {
-                       priv->rx_flags |= ACTUALLY_THROTTLED;
-                       spin_unlock_irqrestore(&priv->rx_lock, flags);
-                       dbg("%s - deferring remainder until unthrottled",
-                                       __func__);
-                       goto out;
-               }
-               spin_unlock_irqrestore(&priv->rx_lock, flags);
-               /* if the port is closed stop trying to read */
-               if (port->port.count > 0)
-                       /* delay processing of remainder */
-                       schedule_delayed_work(&priv->rx_work, 1);
-               else
-                       dbg("%s - port is closed", __func__);
-               goto out;
-       }
-
-       /* urb is completely processed */
-       priv->rx_processed = 0;
+static void ftdi_read_bulk_callback(struct urb *urb)
+{
+       struct usb_serial_port *port = urb->context;
+       unsigned long flags;
 
-       /* if the port is closed stop trying to read */
-       if (port->port.count > 0) {
-               /* Continue trying to always read  */
-               usb_fill_bulk_urb(port->read_urb, port->serial->dev,
-                       usb_rcvbulkpipe(port->serial->dev,
-                                       port->bulk_in_endpointAddress),
-                       port->read_urb->transfer_buffer,
-                       port->read_urb->transfer_buffer_length,
-                       ftdi_read_bulk_callback, port);
+       dbg("%s - port %d", __func__, port->number);
 
-               result = usb_submit_urb(port->read_urb, GFP_ATOMIC);
-               if (result)
-                       dev_err(&port->dev,
-                               "%s - failed resubmitting read urb, error %d\n",
-                               __func__, result);
+       if (urb->status) {
+               dbg("%s - nonzero read bulk status received: %d",
+                                               __func__, urb->status);
+               return;
        }
-out:
-       tty_kref_put(tty);
-} /* ftdi_process_read */
 
+       usb_serial_debug_data(debug, &port->dev, __func__,
+                               urb->actual_length, urb->transfer_buffer);
+       ftdi_process_read(port);
+
+       spin_lock_irqsave(&port->lock, flags);
+       port->throttled = port->throttle_req;
+       if (!port->throttled) {
+               spin_unlock_irqrestore(&port->lock, flags);
+               ftdi_submit_read_urb(port, GFP_ATOMIC);
+       } else
+               spin_unlock_irqrestore(&port->lock, flags);
+}
 
 static void ftdi_break_ctl(struct tty_struct *tty, int break_state)
 {
@@ -2609,33 +2447,31 @@ static int ftdi_ioctl(struct tty_struct *tty, struct file *file,
 static void ftdi_throttle(struct tty_struct *tty)
 {
        struct usb_serial_port *port = tty->driver_data;
-       struct ftdi_private *priv = usb_get_serial_port_data(port);
        unsigned long flags;
 
        dbg("%s - port %d", __func__, port->number);
 
-       spin_lock_irqsave(&priv->rx_lock, flags);
-       priv->rx_flags |= THROTTLED;
-       spin_unlock_irqrestore(&priv->rx_lock, flags);
+       spin_lock_irqsave(&port->lock, flags);
+       port->throttle_req = 1;
+       spin_unlock_irqrestore(&port->lock, flags);
 }
 
-
-static void ftdi_unthrottle(struct tty_struct *tty)
+void ftdi_unthrottle(struct tty_struct *tty)
 {
        struct usb_serial_port *port = tty->driver_data;
-       struct ftdi_private *priv = usb_get_serial_port_data(port);
-       int actually_throttled;
+       int was_throttled;
        unsigned long flags;
 
        dbg("%s - port %d", __func__, port->number);
 
-       spin_lock_irqsave(&priv->rx_lock, flags);
-       actually_throttled = priv->rx_flags & ACTUALLY_THROTTLED;
-       priv->rx_flags &= ~(THROTTLED | ACTUALLY_THROTTLED);
-       spin_unlock_irqrestore(&priv->rx_lock, flags);
+       spin_lock_irqsave(&port->lock, flags);
+       was_throttled = port->throttled;
+       port->throttled = port->throttle_req = 0;
+       spin_unlock_irqrestore(&port->lock, flags);
 
-       if (actually_throttled)
-               schedule_delayed_work(&priv->rx_work, 0);
+       /* Resubmit urb if throttled and open. */
+       if (was_throttled && test_bit(ASYNCB_INITIALIZED, &port->port.flags))
+               ftdi_submit_read_urb(port, GFP_KERNEL);
 }
 
 static int __init ftdi_init(void)
index 20432d3..5ac900e 100644 (file)
@@ -1390,14 +1390,13 @@ static void garmin_throttle(struct tty_struct *tty)
 {
        struct usb_serial_port *port = tty->driver_data;
        struct garmin_data *garmin_data_p = usb_get_serial_port_data(port);
-       unsigned long flags;
 
        dbg("%s - port %d", __func__, port->number);
        /* set flag, data received will be put into a queue
           for later processing */
-       spin_lock_irqsave(&garmin_data_p->lock, flags);
+       spin_lock_irq(&garmin_data_p->lock);
        garmin_data_p->flags |= FLAGS_QUEUING|FLAGS_THROTTLED;
-       spin_unlock_irqrestore(&garmin_data_p->lock, flags);
+       spin_unlock_irq(&garmin_data_p->lock);
 }
 
 
@@ -1405,13 +1404,12 @@ static void garmin_unthrottle(struct tty_struct *tty)
 {
        struct usb_serial_port *port = tty->driver_data;
        struct garmin_data *garmin_data_p = usb_get_serial_port_data(port);
-       unsigned long flags;
        int status;
 
        dbg("%s - port %d", __func__, port->number);
-       spin_lock_irqsave(&garmin_data_p->lock, flags);
+       spin_lock_irq(&garmin_data_p->lock);
        garmin_data_p->flags &= ~FLAGS_THROTTLED;
-       spin_unlock_irqrestore(&garmin_data_p->lock, flags);
+       spin_unlock_irq(&garmin_data_p->lock);
 
        /* in native mode send queued data to tty, in
           serial mode nothing needs to be done here */
@@ -1419,7 +1417,7 @@ static void garmin_unthrottle(struct tty_struct *tty)
                garmin_flush_queue(garmin_data_p);
 
        if (0 != (garmin_data_p->flags & FLAGS_BULK_IN_ACTIVE)) {
-               status = usb_submit_urb(port->read_urb, GFP_ATOMIC);
+               status = usb_submit_urb(port->read_urb, GFP_KERNEL);
                if (status)
                        dev_err(&port->dev,
                                "%s - failed resubmitting read urb, error %d\n",
index deba08c..bbe005c 100644 (file)
@@ -546,7 +546,7 @@ void usb_serial_generic_unthrottle(struct tty_struct *tty)
 
        if (was_throttled) {
                /* Resume reading from device */
-               usb_serial_generic_resubmit_read_urb(port, GFP_KERNEL);
+               flush_and_resubmit_read_urb(port);
        }
 }
 
index 24fcc64..d6231c3 100644 (file)
@@ -966,6 +966,15 @@ static int ipaq_calc_num_ports(struct usb_serial *serial)
 static int ipaq_startup(struct usb_serial *serial)
 {
        dbg("%s", __func__);
+
+       /* Some of the devices in ipaq_id_table[] are composite, and we
+        * shouldn't bind to all the interfaces.  This test will rule out
+        * some obviously invalid possibilities.
+        */
+       if (serial->num_bulk_in < serial->num_ports ||
+                       serial->num_bulk_out < serial->num_ports)
+               return -ENODEV;
+
        if (serial->dev->actconfig->desc.bConfigurationValue != 1) {
                /*
                 * FIXME: HP iPaq rx3715, possibly others, have 1 config that
index 257c16c..1296a09 100644 (file)
@@ -290,7 +290,7 @@ static void keyspan_pda_rx_unthrottle(struct tty_struct *tty)
        /* just restart the receive interrupt URB */
        dbg("keyspan_pda_rx_unthrottle port %d", port->number);
        port->interrupt_in_urb->dev = port->serial->dev;
-       if (usb_submit_urb(port->interrupt_in_urb, GFP_ATOMIC))
+       if (usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL))
                dbg(" usb_submit_urb(read urb) failed");
        return;
 }
index f737337..3a78738 100644 (file)
@@ -951,7 +951,7 @@ static void klsi_105_unthrottle(struct tty_struct *tty)
        dbg("%s - port %d", __func__, port->number);
 
        port->read_urb->dev = port->serial->dev;
-       result = usb_submit_urb(port->read_urb, GFP_ATOMIC);
+       result = usb_submit_urb(port->read_urb, GFP_KERNEL);
        if (result)
                dev_err(&port->dev,
                        "%s - failed submitting read urb, error %d\n",
index ad4998b..cd009cb 100644 (file)
@@ -777,20 +777,19 @@ static void mct_u232_throttle(struct tty_struct *tty)
 {
        struct usb_serial_port *port = tty->driver_data;
        struct mct_u232_private *priv = usb_get_serial_port_data(port);
-       unsigned long flags;
        unsigned int control_state;
 
        dbg("%s - port %d", __func__, port->number);
 
-       spin_lock_irqsave(&priv->lock, flags);
+       spin_lock_irq(&priv->lock);
        priv->rx_flags |= THROTTLED;
        if (C_CRTSCTS(tty)) {
                priv->control_state &= ~TIOCM_RTS;
                control_state = priv->control_state;
-               spin_unlock_irqrestore(&priv->lock, flags);
+               spin_unlock_irq(&priv->lock);
                (void) mct_u232_set_modem_ctrl(port->serial, control_state);
        } else {
-               spin_unlock_irqrestore(&priv->lock, flags);
+               spin_unlock_irq(&priv->lock);
        }
 }
 
@@ -799,20 +798,19 @@ static void mct_u232_unthrottle(struct tty_struct *tty)
 {
        struct usb_serial_port *port = tty->driver_data;
        struct mct_u232_private *priv = usb_get_serial_port_data(port);
-       unsigned long flags;
        unsigned int control_state;
 
        dbg("%s - port %d", __func__, port->number);
 
-       spin_lock_irqsave(&priv->lock, flags);
+       spin_lock_irq(&priv->lock);
        if ((priv->rx_flags & THROTTLED) && C_CRTSCTS(tty)) {
                priv->rx_flags &= ~THROTTLED;
                priv->control_state |= TIOCM_RTS;
                control_state = priv->control_state;
-               spin_unlock_irqrestore(&priv->lock, flags);
+               spin_unlock_irq(&priv->lock);
                (void) mct_u232_set_modem_ctrl(port->serial, control_state);
        } else {
-               spin_unlock_irqrestore(&priv->lock, flags);
+               spin_unlock_irq(&priv->lock);
        }
 }
 
index 1085a57..80f59b6 100644 (file)
@@ -314,21 +314,24 @@ static void opticon_unthrottle(struct tty_struct *tty)
        struct usb_serial_port *port = tty->driver_data;
        struct opticon_private *priv = usb_get_serial_data(port->serial);
        unsigned long flags;
-       int result;
+       int result, was_throttled;
 
        dbg("%s - port %d", __func__, port->number);
 
        spin_lock_irqsave(&priv->lock, flags);
        priv->throttled = false;
+       was_throttled = priv->actually_throttled;
        priv->actually_throttled = false;
        spin_unlock_irqrestore(&priv->lock, flags);
 
        priv->bulk_read_urb->dev = port->serial->dev;
-       result = usb_submit_urb(priv->bulk_read_urb, GFP_ATOMIC);
-       if (result)
-               dev_err(&port->dev,
-                       "%s - failed submitting read urb, error %d\n",
+       if (was_throttled) {
+               result = usb_submit_urb(priv->bulk_read_urb, GFP_ATOMIC);
+               if (result)
+                       dev_err(&port->dev,
+                               "%s - failed submitting read urb, error %d\n",
                                                        __func__, result);
+       }
 }
 
 static int opticon_tiocmget(struct tty_struct *tty, struct file *file)
index f66e398..cd44c68 100644 (file)
@@ -165,6 +165,7 @@ static int  option_resume(struct usb_serial *serial);
 #define HUAWEI_PRODUCT_E143D                   0x143D
 #define HUAWEI_PRODUCT_E143E                   0x143E
 #define HUAWEI_PRODUCT_E143F                   0x143F
+#define HUAWEI_PRODUCT_E14AC                   0x14AC
 
 #define QUANTA_VENDOR_ID                       0x0408
 #define QUANTA_PRODUCT_Q101                    0xEA02
@@ -314,10 +315,14 @@ static int  option_resume(struct usb_serial *serial);
 #define QISDA_PRODUCT_H20_4515                 0x4515
 #define QISDA_PRODUCT_H20_4519                 0x4519
 
+/* TLAYTECH PRODUCTS */
+#define TLAYTECH_VENDOR_ID                     0x20B9
+#define TLAYTECH_PRODUCT_TEU800                        0x1682
 
 /* TOSHIBA PRODUCTS */
 #define TOSHIBA_VENDOR_ID                      0x0930
 #define TOSHIBA_PRODUCT_HSDPA_MINICARD         0x1302
+#define TOSHIBA_PRODUCT_G450                   0x0d45
 
 #define ALINK_VENDOR_ID                                0x1e0e
 #define ALINK_PRODUCT_3GU                      0x9200
@@ -326,6 +331,9 @@ static int  option_resume(struct usb_serial *serial);
 #define ALCATEL_VENDOR_ID                      0x1bbb
 #define ALCATEL_PRODUCT_X060S                  0x0000
 
+/* Airplus products */
+#define AIRPLUS_VENDOR_ID                      0x1011
+#define AIRPLUS_PRODUCT_MCD650                 0x3198
 
 static struct usb_device_id option_ids[] = {
        { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_COLT) },
@@ -424,6 +432,7 @@ static struct usb_device_id option_ids[] = {
        { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E143D, 0xff, 0xff, 0xff) },
        { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E143E, 0xff, 0xff, 0xff) },
        { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E143F, 0xff, 0xff, 0xff) },
+       { USB_DEVICE(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E14AC) },
        { USB_DEVICE(AMOI_VENDOR_ID, AMOI_PRODUCT_9508) },
        { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_V640) }, /* Novatel Merlin V640/XV620 */
        { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_V620) }, /* Novatel Merlin V620/S620 */
@@ -581,10 +590,13 @@ static struct usb_device_id option_ids[] = {
        { USB_DEVICE(QISDA_VENDOR_ID, QISDA_PRODUCT_H21_4523) },
        { USB_DEVICE(QISDA_VENDOR_ID, QISDA_PRODUCT_H20_4515) },
        { USB_DEVICE(QISDA_VENDOR_ID, QISDA_PRODUCT_H20_4519) },
+       { USB_DEVICE(TOSHIBA_VENDOR_ID, TOSHIBA_PRODUCT_G450) },
        { USB_DEVICE(TOSHIBA_VENDOR_ID, TOSHIBA_PRODUCT_HSDPA_MINICARD ) }, /* Toshiba 3G HSDPA == Novatel Expedite EU870D MiniCard */
        { USB_DEVICE(ALINK_VENDOR_ID, 0x9000) },
        { USB_DEVICE_AND_INTERFACE_INFO(ALINK_VENDOR_ID, ALINK_PRODUCT_3GU, 0xff, 0xff, 0xff) },
        { USB_DEVICE(ALCATEL_VENDOR_ID, ALCATEL_PRODUCT_X060S) },
+       { USB_DEVICE(AIRPLUS_VENDOR_ID, AIRPLUS_PRODUCT_MCD650) },
+       { USB_DEVICE(TLAYTECH_VENDOR_ID, TLAYTECH_PRODUCT_TEU800) },
        { } /* Terminating entry */
 };
 MODULE_DEVICE_TABLE(usb, option_ids);
index 0f4a70c..c644e26 100644 (file)
@@ -288,7 +288,7 @@ static void setup_line(struct work_struct *work)
 
        dbg("%s(): submitting interrupt urb", __func__);
        port->interrupt_in_urb->dev = port->serial->dev;
-       result = usb_submit_urb(port->interrupt_in_urb, GFP_ATOMIC);
+       result = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL);
        if (result != 0) {
                dev_err(&port->dev, "%s(): usb_submit_urb() failed"
                                " with error %d\n", __func__, result);
@@ -335,7 +335,7 @@ void send_data(struct work_struct *work)
 
                dbg("%s(): submitting interrupt urb", __func__);
                port->interrupt_in_urb->dev = port->serial->dev;
-               result = usb_submit_urb(port->interrupt_in_urb, GFP_ATOMIC);
+               result = usb_submit_urb(port->interrupt_in_urb, GFP_NOIO);
                if (result != 0) {
                        dev_err(&port->dev, "%s(): usb_submit_urb() failed"
                                " with error %d\n", __func__, result);
@@ -349,7 +349,7 @@ void send_data(struct work_struct *work)
 
        port->write_urb->transfer_buffer_length = count;
        port->write_urb->dev = port->serial->dev;
-       result = usb_submit_urb(port->write_urb, GFP_ATOMIC);
+       result = usb_submit_urb(port->write_urb, GFP_NOIO);
        if (result != 0) {
                dev_err(&port->dev, "%s(): usb_submit_urb() failed"
                               " with error %d\n", __func__, result);
index 1128e01..9ec1a49 100644 (file)
@@ -1046,13 +1046,15 @@ static void pl2303_push_data(struct tty_struct *tty,
        /* overrun is special, not associated with a char */
        if (line_status & UART_OVERRUN_ERROR)
                tty_insert_flip_char(tty, 0, TTY_OVERRUN);
-       if (port->console && port->sysrq) {
+
+       if (tty_flag == TTY_NORMAL && !(port->console && port->sysrq))
+               tty_insert_flip_string(tty, data, urb->actual_length);
+       else {
                int i;
                for (i = 0; i < urb->actual_length; ++i)
                        if (!usb_serial_handle_sysrq_char(tty, port, data[i]))
                                tty_insert_flip_char(tty, data[i], tty_flag);
-       } else
-               tty_insert_flip_string(tty, data, urb->actual_length);
+       }
        tty_flip_buffer_push(tty);
 }
 
index 8c075b2..5019325 100644 (file)
@@ -17,7 +17,7 @@
   Whom based his on the Keyspan driver by Hugh Blemings <hugh@blemings.org>
 */
 
-#define DRIVER_VERSION "v.1.3.7"
+#define DRIVER_VERSION "v.1.3.8"
 #define DRIVER_AUTHOR "Kevin Lloyd, Elina Pasheva, Matthew Safar, Rory Filer"
 #define DRIVER_DESC "USB Driver for Sierra Wireless USB modems"
 
@@ -296,7 +296,6 @@ struct sierra_port_private {
        int dsr_state;
        int dcd_state;
        int ri_state;
-
        unsigned int opened:1;
 };
 
@@ -306,6 +305,8 @@ static int sierra_send_setup(struct usb_serial_port *port)
        struct sierra_port_private *portdata;
        __u16 interface = 0;
        int val = 0;
+       int do_send = 0;
+       int retval;
 
        dev_dbg(&port->dev, "%s\n", __func__);
 
@@ -324,10 +325,7 @@ static int sierra_send_setup(struct usb_serial_port *port)
                 */
                if (port->interrupt_in_urb) {
                        /* send control message */
-                       return usb_control_msg(serial->dev,
-                               usb_rcvctrlpipe(serial->dev, 0),
-                               0x22, 0x21, val, interface,
-                               NULL, 0, USB_CTRL_SET_TIMEOUT);
+                       do_send = 1;
                }
        }
 
@@ -339,12 +337,18 @@ static int sierra_send_setup(struct usb_serial_port *port)
                        interface = 1;
                else if (port->bulk_out_endpointAddress == 5)
                        interface = 2;
-               return usb_control_msg(serial->dev,
-                       usb_rcvctrlpipe(serial->dev, 0),
-                       0x22, 0x21, val, interface,
-                       NULL, 0, USB_CTRL_SET_TIMEOUT);
+
+               do_send = 1;
        }
-       return 0;
+       if (!do_send)
+               return 0;
+
+       usb_autopm_get_interface(serial->interface);
+       retval = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0),
+               0x22, 0x21, val, interface, NULL, 0, USB_CTRL_SET_TIMEOUT);
+       usb_autopm_put_interface(serial->interface);
+
+       return retval;
 }
 
 static void sierra_set_termios(struct tty_struct *tty,
@@ -773,8 +777,11 @@ static void sierra_close(struct usb_serial_port *port)
 
        if (serial->dev) {
                mutex_lock(&serial->disc_mutex);
-               if (!serial->disconnected)
+               if (!serial->disconnected) {
+                       serial->interface->needs_remote_wakeup = 0;
+                       usb_autopm_get_interface(serial->interface);
                        sierra_send_setup(port);
+               }
                mutex_unlock(&serial->disc_mutex);
                spin_lock_irq(&intfdata->susp_lock);
                portdata->opened = 0;
@@ -788,8 +795,6 @@ static void sierra_close(struct usb_serial_port *port)
                        sierra_release_urb(portdata->in_urbs[i]);
                        portdata->in_urbs[i] = NULL;
                }
-               usb_autopm_get_interface(serial->interface);
-               serial->interface->needs_remote_wakeup = 0;
        }
 }
 
@@ -827,6 +832,8 @@ static int sierra_open(struct tty_struct *tty, struct usb_serial_port *port)
        if (err) {
                /* get rid of everything as in close */
                sierra_close(port);
+               /* restore balance for autopm */
+               usb_autopm_put_interface(serial->interface);
                return err;
        }
        sierra_send_setup(port);
@@ -915,7 +922,7 @@ static void sierra_release(struct usb_serial *serial)
 #ifdef CONFIG_PM
 static void stop_read_write_urbs(struct usb_serial *serial)
 {
-       int i, j;
+       int i;
        struct usb_serial_port *port;
        struct sierra_port_private *portdata;
 
@@ -923,8 +930,7 @@ static void stop_read_write_urbs(struct usb_serial *serial)
        for (i = 0; i < serial->num_ports; ++i) {
                port = serial->port[i];
                portdata = usb_get_serial_port_data(port);
-               for (j = 0; j < N_IN_URB; j++)
-                       usb_kill_urb(portdata->in_urbs[j]);
+               sierra_stop_rx_urbs(port);
                usb_kill_anchored_urbs(&portdata->active);
        }
 }
index cb7e95f..b282c0f 100644 (file)
@@ -165,34 +165,36 @@ static void symbol_throttle(struct tty_struct *tty)
 {
        struct usb_serial_port *port = tty->driver_data;
        struct symbol_private *priv = usb_get_serial_data(port->serial);
-       unsigned long flags;
 
        dbg("%s - port %d", __func__, port->number);
-       spin_lock_irqsave(&priv->lock, flags);
+       spin_lock_irq(&priv->lock);
        priv->throttled = true;
-       spin_unlock_irqrestore(&priv->lock, flags);
+       spin_unlock_irq(&priv->lock);
 }
 
 static void symbol_unthrottle(struct tty_struct *tty)
 {
        struct usb_serial_port *port = tty->driver_data;
        struct symbol_private *priv = usb_get_serial_data(port->serial);
-       unsigned long flags;
        int result;
+       bool was_throttled;
 
        dbg("%s - port %d", __func__, port->number);
 
-       spin_lock_irqsave(&priv->lock, flags);
+       spin_lock_irq(&priv->lock);
        priv->throttled = false;
+       was_throttled = priv->actually_throttled;
        priv->actually_throttled = false;
-       spin_unlock_irqrestore(&priv->lock, flags);
+       spin_unlock_irq(&priv->lock);
 
        priv->int_urb->dev = port->serial->dev;
-       result = usb_submit_urb(priv->int_urb, GFP_ATOMIC);
-       if (result)
-               dev_err(&port->dev,
-                       "%s - failed submitting read urb, error %d\n",
+       if (was_throttled) {
+               result = usb_submit_urb(priv->int_urb, GFP_KERNEL);
+               if (result)
+                       dev_err(&port->dev,
+                               "%s - failed submitting read urb, error %d\n",
                                                        __func__, result);
+       }
 }
 
 static int symbol_startup(struct usb_serial *serial)
index aa6b2ae..bd3fa7f 100644 (file)
@@ -156,7 +156,8 @@ static void destroy_serial(struct kref *kref)
        if (serial->minor != SERIAL_TTY_NO_MINOR)
                return_serial(serial);
 
-       serial->type->release(serial);
+       if (serial->attached)
+               serial->type->release(serial);
 
        /* Now that nothing is using the ports, they can be freed */
        for (i = 0; i < serial->num_port_pointers; ++i) {
@@ -1059,12 +1060,15 @@ int usb_serial_probe(struct usb_interface *interface,
                module_put(type->driver.owner);
                if (retval < 0)
                        goto probe_error;
+               serial->attached = 1;
                if (retval > 0) {
                        /* quietly accept this device, but don't bind to a
                           serial port as it's about to disappear */
                        serial->num_ports = 0;
                        goto exit;
                }
+       } else {
+               serial->attached = 1;
        }
 
        if (get_free_serial(serial, num_ports, &minor) == NULL) {
@@ -1164,8 +1168,10 @@ int usb_serial_suspend(struct usb_interface *intf, pm_message_t message)
 
        if (serial->type->suspend) {
                r = serial->type->suspend(serial, message);
-               if (r < 0)
+               if (r < 0) {
+                       serial->suspending = 0;
                        goto err_out;
+               }
        }
 
        for (i = 0; i < serial->num_ports; ++i) {
index 1aa5d20..ad1f923 100644 (file)
@@ -513,7 +513,8 @@ static void visor_read_bulk_callback(struct urb *urb)
                        tty_kref_put(tty);
                }
                spin_lock(&priv->lock);
-               priv->bytes_in += available_room;
+               if (tty)
+                       priv->bytes_in += available_room;
 
        } else {
                spin_lock(&priv->lock);
@@ -582,12 +583,11 @@ static void visor_throttle(struct tty_struct *tty)
 {
        struct usb_serial_port *port = tty->driver_data;
        struct visor_private *priv = usb_get_serial_port_data(port);
-       unsigned long flags;
 
        dbg("%s - port %d", __func__, port->number);
-       spin_lock_irqsave(&priv->lock, flags);
+       spin_lock_irq(&priv->lock);
        priv->throttled = 1;
-       spin_unlock_irqrestore(&priv->lock, flags);
+       spin_unlock_irq(&priv->lock);
 }
 
 
@@ -595,21 +595,23 @@ static void visor_unthrottle(struct tty_struct *tty)
 {
        struct usb_serial_port *port = tty->driver_data;
        struct visor_private *priv = usb_get_serial_port_data(port);
-       unsigned long flags;
-       int result;
+       int result, was_throttled;
 
        dbg("%s - port %d", __func__, port->number);
-       spin_lock_irqsave(&priv->lock, flags);
+       spin_lock_irq(&priv->lock);
        priv->throttled = 0;
+       was_throttled = priv->actually_throttled;
        priv->actually_throttled = 0;
-       spin_unlock_irqrestore(&priv->lock, flags);
+       spin_unlock_irq(&priv->lock);
 
-       port->read_urb->dev = port->serial->dev;
-       result = usb_submit_urb(port->read_urb, GFP_ATOMIC);
-       if (result)
-               dev_err(&port->dev,
-                       "%s - failed submitting read urb, error %d\n",
+       if (was_throttled) {
+               port->read_urb->dev = port->serial->dev;
+               result = usb_submit_urb(port->read_urb, GFP_KERNEL);
+               if (result)
+                       dev_err(&port->dev,
+                               "%s - failed submitting read urb, error %d\n",
                                                        __func__, result);
+       }
 }
 
 static int palm_os_3_probe(struct usb_serial *serial,
index 62424ee..1093d2e 100644 (file)
@@ -949,13 +949,12 @@ static void whiteheat_throttle(struct tty_struct *tty)
 {
        struct usb_serial_port *port = tty->driver_data;
        struct whiteheat_private *info = usb_get_serial_port_data(port);
-       unsigned long flags;
 
        dbg("%s - port %d", __func__, port->number);
 
-       spin_lock_irqsave(&info->lock, flags);
+       spin_lock_irq(&info->lock);
        info->flags |= THROTTLED;
-       spin_unlock_irqrestore(&info->lock, flags);
+       spin_unlock_irq(&info->lock);
 
        return;
 }
@@ -966,14 +965,13 @@ static void whiteheat_unthrottle(struct tty_struct *tty)
        struct usb_serial_port *port = tty->driver_data;
        struct whiteheat_private *info = usb_get_serial_port_data(port);
        int actually_throttled;
-       unsigned long flags;
 
        dbg("%s - port %d", __func__, port->number);
 
-       spin_lock_irqsave(&info->lock, flags);
+       spin_lock_irq(&info->lock);
        actually_throttled = info->flags & ACTUALLY_THROTTLED;
        info->flags &= ~(THROTTLED | ACTUALLY_THROTTLED);
-       spin_unlock_irqrestore(&info->lock, flags);
+       spin_unlock_irq(&info->lock);
 
        if (actually_throttled)
                rx_data_softint(&info->rx_work);
index e20dc52..589f6b4 100644 (file)
@@ -696,7 +696,7 @@ void usb_stor_invoke_transport(struct scsi_cmnd *srb, struct us_data *us)
                /* device supports and needs bigger sense buffer */
                if (us->fflags & US_FL_SANE_SENSE)
                        sense_size = ~0;
-
+Retry_Sense:
                US_DEBUGP("Issuing auto-REQUEST_SENSE\n");
 
                scsi_eh_prep_cmnd(srb, &ses, NULL, 0, sense_size);
@@ -720,6 +720,21 @@ void usb_stor_invoke_transport(struct scsi_cmnd *srb, struct us_data *us)
                        srb->result = DID_ABORT << 16;
                        goto Handle_Errors;
                }
+
+               /* Some devices claim to support larger sense but fail when
+                * trying to request it. When a transport failure happens
+                * using US_FS_SANE_SENSE, we always retry with a standard
+                * (small) sense request. This fixes some USB GSM modems
+                */
+               if (temp_result == USB_STOR_TRANSPORT_FAILED &&
+                   (us->fflags & US_FL_SANE_SENSE) &&
+                   sense_size != US_SENSE_SIZE) {
+                       US_DEBUGP("-- auto-sense failure, retry small sense\n");
+                       sense_size = US_SENSE_SIZE;
+                       goto Retry_Sense;
+               }
+
+               /* Other failures */
                if (temp_result != USB_STOR_TRANSPORT_GOOD) {
                        US_DEBUGP("-- auto-sense failure\n");
 
@@ -768,17 +783,32 @@ void usb_stor_invoke_transport(struct scsi_cmnd *srb, struct us_data *us)
                /* set the result so the higher layers expect this data */
                srb->result = SAM_STAT_CHECK_CONDITION;
 
-               /* If things are really okay, then let's show that.  Zero
-                * out the sense buffer so the higher layers won't realize
-                * we did an unsolicited auto-sense. */
-               if (result == USB_STOR_TRANSPORT_GOOD &&
-                       /* Filemark 0, ignore EOM, ILI 0, no sense */
+               /* We often get empty sense data.  This could indicate that
+                * everything worked or that there was an unspecified
+                * problem.  We have to decide which.
+                */
+               if (    /* Filemark 0, ignore EOM, ILI 0, no sense */
                                (srb->sense_buffer[2] & 0xaf) == 0 &&
                        /* No ASC or ASCQ */
                                srb->sense_buffer[12] == 0 &&
                                srb->sense_buffer[13] == 0) {
-                       srb->result = SAM_STAT_GOOD;
-                       srb->sense_buffer[0] = 0x0;
+
+                       /* If things are really okay, then let's show that.
+                        * Zero out the sense buffer so the higher layers
+                        * won't realize we did an unsolicited auto-sense.
+                        */
+                       if (result == USB_STOR_TRANSPORT_GOOD) {
+                               srb->result = SAM_STAT_GOOD;
+                               srb->sense_buffer[0] = 0x0;
+
+                       /* If there was a problem, report an unspecified
+                        * hardware error to prevent the higher layers from
+                        * entering an infinite retry loop.
+                        */
+                       } else {
+                               srb->result = DID_ERROR << 16;
+                               srb->sense_buffer[2] = HARDWARE_ERROR;
+                       }
                }
        }
 
index 079ae0f..d4f034e 100644 (file)
@@ -1823,6 +1823,13 @@ UNUSUAL_DEV(  0x4102, 0x1020, 0x0100,  0x0100,
                US_SC_DEVICE, US_PR_DEVICE, NULL,
                US_FL_IGNORE_RESIDUE ),
 
+/* Reported by Sergey Pinaev <dfo@antex.ru> */
+UNUSUAL_DEV(  0x4102, 0x1059, 0x0000,  0x0000,
+               "iRiver",
+               "P7K",
+               US_SC_DEVICE, US_PR_DEVICE, NULL,
+               US_FL_MAX_SECTORS_64 ),
+
 /*
  * David Härdeman <david@2gen.com>
  * The key makes the SCSI stack print confusing (but harmless) messages
index b2f149f..4516c36 100644 (file)
@@ -200,35 +200,40 @@ int wusb_dev_sec_add(struct wusbhc *wusbhc,
 {
        int result, bytes, secd_size;
        struct device *dev = &usb_dev->dev;
-       struct usb_security_descriptor secd;
+       struct usb_security_descriptor *secd;
        const struct usb_encryption_descriptor *etd, *ccm1_etd = NULL;
-       void *secd_buf;
        const void *itr, *top;
        char buf[64];
 
+       secd = kmalloc(sizeof(struct usb_security_descriptor), GFP_KERNEL);
+       if (secd == NULL) {
+               result = -ENOMEM;
+               goto out;
+       }
+
        result = usb_get_descriptor(usb_dev, USB_DT_SECURITY,
-                                   0, &secd, sizeof(secd));
+                                   0, secd, sizeof(struct usb_security_descriptor));
        if (result < sizeof(secd)) {
                dev_err(dev, "Can't read security descriptor or "
                        "not enough data: %d\n", result);
-               goto error_secd;
+               goto out;
        }
-       secd_size = le16_to_cpu(secd.wTotalLength);
-       secd_buf = kmalloc(secd_size, GFP_KERNEL);
-       if (secd_buf == NULL) {
+       secd_size = le16_to_cpu(secd->wTotalLength);
+       secd = krealloc(secd, secd_size, GFP_KERNEL);
+       if (secd == NULL) {
                dev_err(dev, "Can't allocate space for security descriptors\n");
-               goto error_secd_alloc;
+               goto out;
        }
        result = usb_get_descriptor(usb_dev, USB_DT_SECURITY,
-                                   0, secd_buf, secd_size);
+                                   0, secd, secd_size);
        if (result < secd_size) {
                dev_err(dev, "Can't read security descriptor or "
                        "not enough data: %d\n", result);
-               goto error_secd_all;
+               goto out;
        }
        bytes = 0;
-       itr = secd_buf + sizeof(secd);
-       top = secd_buf + result;
+       itr = &secd[1];
+       top = (void *)secd + result;
        while (itr < top) {
                etd = itr;
                if (top - itr < sizeof(*etd)) {
@@ -259,24 +264,16 @@ int wusb_dev_sec_add(struct wusbhc *wusbhc,
                dev_err(dev, "WUSB device doesn't support CCM1 encryption, "
                        "can't use!\n");
                result = -EINVAL;
-               goto error_no_ccm1;
+               goto out;
        }
        wusb_dev->ccm1_etd = *ccm1_etd;
        dev_dbg(dev, "supported encryption: %s; using %s (0x%02x/%02x)\n",
                buf, wusb_et_name(ccm1_etd->bEncryptionType),
                ccm1_etd->bEncryptionValue, ccm1_etd->bAuthKeyIndex);
        result = 0;
-       kfree(secd_buf);
 out:
+       kfree(secd);
        return result;
-
-
-error_no_ccm1:
-error_secd_all:
-       kfree(secd_buf);
-error_secd_alloc:
-error_secd:
-       goto out;
 }
 
 void wusb_dev_sec_rm(struct wusb_dev *wusb_dev)
index 1d9a6f5..01950c6 100644 (file)
@@ -42,6 +42,7 @@
 #include <linux/init.h>
 #include <linux/module.h>
 #include <linux/pci.h>
+#include <linux/sched.h>
 #include <linux/dma-mapping.h>
 #include <linux/interrupt.h>
 #include <linux/workqueue.h>
index 42e1005..d065894 100644 (file)
@@ -26,7 +26,6 @@
 #include <linux/device.h>
 #include <linux/platform_device.h>
 #include <linux/uaccess.h>
-#include <linux/device.h>
 #include <linux/interrupt.h>
 #include <linux/clk.h>
 #include <video/da8xx-fb.h>
index f2de5a1..5c5a1ad 100644 (file)
@@ -27,8 +27,6 @@
 #include <mach/msm_iomap.h>
 #include <mach/irqs.h>
 #include <mach/board.h>
-#include <linux/delay.h>
-
 #include <mach/msm_fb.h>
 #include "mddi_hw.h"
 
index d5e5955..70dadf9 100644 (file)
@@ -93,7 +93,7 @@ struct blizzard_reg_list {
 };
 
 /* These need to be saved / restored separately from the rest. */
-static struct blizzard_reg_list blizzard_pll_regs[] = {
+static const struct blizzard_reg_list blizzard_pll_regs[] = {
        {
                .start  = 0x04,         /* Don't save PLL ctrl (0x0C) */
                .end    = 0x0a,
@@ -104,7 +104,7 @@ static struct blizzard_reg_list blizzard_pll_regs[] = {
        },
 };
 
-static struct blizzard_reg_list blizzard_gen_regs[] = {
+static const struct blizzard_reg_list blizzard_gen_regs[] = {
        {
                .start  = 0x18,         /* SDRAM control */
                .end    = 0x20,
@@ -191,7 +191,7 @@ struct blizzard_struct {
 
        struct omapfb_device    *fbdev;
        struct lcd_ctrl_extif   *extif;
-       struct lcd_ctrl         *int_ctrl;
+       const struct lcd_ctrl   *int_ctrl;
 
        void                    (*power_up)(struct device *dev);
        void                    (*power_down)(struct device *dev);
@@ -1372,7 +1372,7 @@ static void blizzard_get_caps(int plane, struct omapfb_caps *caps)
                           (1 << OMAPFB_COLOR_YUV420);
 }
 
-static void _save_regs(struct blizzard_reg_list *list, int cnt)
+static void _save_regs(const struct blizzard_reg_list *list, int cnt)
 {
        int i;
 
@@ -1383,7 +1383,7 @@ static void _save_regs(struct blizzard_reg_list *list, int cnt)
        }
 }
 
-static void _restore_regs(struct blizzard_reg_list *list, int cnt)
+static void _restore_regs(const struct blizzard_reg_list *list, int cnt)
 {
        int i;
 
index 125e605..0d0c8c8 100644 (file)
@@ -393,7 +393,7 @@ static void omapfb_sync(struct fb_info *fbi)
  * Set fb_info.fix fields and also updates fbdev.
  * When calling this fb_info.var must be set up already.
  */
-static void set_fb_fix(struct fb_info *fbi)
+static void set_fb_fix(struct fb_info *fbi, int from_init)
 {
        struct fb_fix_screeninfo *fix = &fbi->fix;
        struct fb_var_screeninfo *var = &fbi->var;
@@ -403,10 +403,16 @@ static void set_fb_fix(struct fb_info *fbi)
 
        rg = &plane->fbdev->mem_desc.region[plane->idx];
        fbi->screen_base        = rg->vaddr;
-       mutex_lock(&fbi->mm_lock);
-       fix->smem_start         = rg->paddr;
-       fix->smem_len           = rg->size;
-       mutex_unlock(&fbi->mm_lock);
+
+       if (!from_init) {
+               mutex_lock(&fbi->mm_lock);
+               fix->smem_start         = rg->paddr;
+               fix->smem_len           = rg->size;
+               mutex_unlock(&fbi->mm_lock);
+       } else {
+               fix->smem_start         = rg->paddr;
+               fix->smem_len           = rg->size;
+       }
 
        fix->type = FB_TYPE_PACKED_PIXELS;
        bpp = var->bits_per_pixel;
@@ -704,7 +710,7 @@ static int omapfb_set_par(struct fb_info *fbi)
        int r = 0;
 
        omapfb_rqueue_lock(fbdev);
-       set_fb_fix(fbi);
+       set_fb_fix(fbi, 0);
        r = ctrl_change_mode(fbi);
        omapfb_rqueue_unlock(fbdev);
 
@@ -904,7 +910,7 @@ static int omapfb_setup_mem(struct fb_info *fbi, struct omapfb_mem_info *mi)
                if (old_size != size) {
                        if (size) {
                                memcpy(&fbi->var, new_var, sizeof(fbi->var));
-                               set_fb_fix(fbi);
+                               set_fb_fix(fbi, 0);
                        } else {
                                /*
                                 * Set these explicitly to indicate that the
@@ -1504,7 +1510,7 @@ static int fbinfo_init(struct omapfb_device *fbdev, struct fb_info *info)
        var->bits_per_pixel = fbdev->panel->bpp;
 
        set_fb_var(info, var);
-       set_fb_fix(info);
+       set_fb_fix(info, 1);
 
        r = fb_alloc_cmap(&info->cmap, 16, 0);
        if (r != 0)
index 200c22f..9dd5880 100644 (file)
@@ -19,7 +19,6 @@
  */
 //#define DEBUG
 #include <linux/virtio.h>
-#include <linux/virtio_ids.h>
 #include <linux/virtio_balloon.h>
 #include <linux/swap.h>
 #include <linux/kthread.h>
@@ -248,7 +247,7 @@ out:
        return err;
 }
 
-static void virtballoon_remove(struct virtio_device *vdev)
+static void __devexit virtballoon_remove(struct virtio_device *vdev)
 {
        struct virtio_balloon *vb = vdev->priv;
 
index 4a1f1eb..28d9cf7 100644 (file)
@@ -530,19 +530,22 @@ static int vp_try_to_find_vqs(struct virtio_device *vdev, unsigned nvqs,
                        err = PTR_ERR(vqs[i]);
                        goto error_find;
                }
+
+               if (!vp_dev->per_vq_vectors || msix_vec == VIRTIO_MSI_NO_VECTOR)
+                       continue;
+
                /* allocate per-vq irq if available and necessary */
-               if (vp_dev->per_vq_vectors) {
-                       snprintf(vp_dev->msix_names[msix_vec],
-                                sizeof *vp_dev->msix_names,
-                                "%s-%s",
-                                dev_name(&vp_dev->vdev.dev), names[i]);
-                       err = request_irq(msix_vec, vring_interrupt, 0,
-                                         vp_dev->msix_names[msix_vec],
-                                         vqs[i]);
-                       if (err) {
-                               vp_del_vq(vqs[i]);
-                               goto error_find;
-                       }
+               snprintf(vp_dev->msix_names[msix_vec],
+                        sizeof *vp_dev->msix_names,
+                        "%s-%s",
+                        dev_name(&vp_dev->vdev.dev), names[i]);
+               err = request_irq(vp_dev->msix_entries[msix_vec].vector,
+                                 vring_interrupt, 0,
+                                 vp_dev->msix_names[msix_vec],
+                                 vqs[i]);
+               if (err) {
+                       vp_del_vq(vqs[i]);
+                       goto error_find;
                }
        }
        return 0;
index f536005..fbd2ecd 100644 (file)
@@ -285,6 +285,9 @@ static void *vring_get_buf(struct virtqueue *_vq, unsigned int *len)
                return NULL;
        }
 
+       /* Only get used array entries after they have been exposed by host. */
+       rmb();
+
        i = vq->vring.used->ring[vq->last_used_idx%vq->vring.num].id;
        *len = vq->vring.used->ring[vq->last_used_idx%vq->vring.num].len;
 
index 1e8f02f..d3c824d 100644 (file)
@@ -206,7 +206,7 @@ static int __devinit riowd_probe(struct of_device *op,
 
        dev_set_drvdata(&op->dev, p);
        riowd_device = p;
-       err = 0;
+       return 0;
 
 out_iounmap:
        of_iounmap(&op->resource[0], p->regs, 2);
index 5ea80b1..f4ca0c7 100644 (file)
@@ -67,10 +67,15 @@ fw-shipped-$(CONFIG_DVB_TTUSB_BUDGET) += ttusb-budget/dspbootcode.bin
 fw-shipped-$(CONFIG_E100) += e100/d101m_ucode.bin e100/d101s_ucode.bin \
                             e100/d102e_ucode.bin
 fw-shipped-$(CONFIG_MYRI_SBUS) += myricom/lanai.bin
-fw-shipped-$(CONFIG_PCMCIA_PCNET) += cis/LA-PCM.cis cis/PCMLM28.cis
+fw-shipped-$(CONFIG_PCMCIA_PCNET) += cis/LA-PCM.cis cis/PCMLM28.cis \
+                                    cis/DP83903.cis cis/NE2K.cis \
+                                    cis/tamarack.cis cis/PE-200.cis
 fw-shipped-$(CONFIG_PCMCIA_3C589) += cis/3CXEM556.cis
 fw-shipped-$(CONFIG_PCMCIA_3C574) += cis/3CCFEM556.cis
-fw-shipped-$(CONFIG_SERIAL_8250_CS) += cis/MT5634ZLX.cis cis/RS-COM-2P.cis
+fw-shipped-$(CONFIG_SERIAL_8250_CS) += cis/MT5634ZLX.cis cis/RS-COM-2P.cis \
+                                      cis/COMpad2.cis cis/COMpad4.cis \
+                                      cis/SW_555_SER.cis cis/SW_7xx_SER.cis \
+                                      cis/SW_8xx_SER.cis
 fw-shipped-$(CONFIG_PCMCIA_SMC91C92) += ositech/Xilinx7OD.bin
 fw-shipped-$(CONFIG_SCSI_ADVANSYS) += advansys/mcode.bin advansys/38C1600.bin \
                                      advansys/3550.bin advansys/38C0800.bin
index 3f8c4f6..7a8adc0 100644 (file)
@@ -597,6 +597,10 @@ Driver: PCMCIA_PCNET - NE2000 compatible PCMCIA adapter
 
 File: cis/LA-PCM.cis
       cis/PCMLM28.cis
+      cis/DP83903.cis
+      cis/NE2K.cis
+      cis/tamarack.cis
+      cis/PE-200.cis
 
 Licence: GPL
 
@@ -628,6 +632,11 @@ Driver: SERIAL_8250_CS - Serial PCMCIA adapter
 
 File: cis/MT5634ZLX.cis
       cis/RS-COM-2P.cis
+      cis/COMpad2.cis
+      cis/COMpad4.cis
+      cis/SW_555_SER.cis
+      cis/SW_7xx_SER.cis
+      cis/SW_8xx_SER.cis
 
 Licence: GPL
 
diff --git a/firmware/cis/COMpad2.cis.ihex b/firmware/cis/COMpad2.cis.ihex
new file mode 100644 (file)
index 0000000..1671c5e
--- /dev/null
@@ -0,0 +1,11 @@
+:1000000001030000FF151F0401414456414E5445B1
+:10001000434800434F4D7061642D33322F38350013
+:10002000312E300000FF210202011A0501050001F6
+:10003000031B0EC18118AA61E80207E8030730B864
+:100040009E1B08820108AA6030030F1B0883010869
+:10005000AA6040030F1B08840108AA6050030F1B0D
+:0D00600008850108AA6060030F1400FF006E
+:00000001FF
+#
+# Replacement CIS for Advantech COMpad-32/85
+#
diff --git a/firmware/cis/COMpad4.cis.ihex b/firmware/cis/COMpad4.cis.ihex
new file mode 100644 (file)
index 0000000..27bbec1
--- /dev/null
@@ -0,0 +1,9 @@
+:1000000001030000FF151F0401414456414E5445B1
+:10001000434800434F4D7061642D33322F383542D1
+:100020002D34000000FF210202011A050102000127
+:10003000011B0BC18118AA6040021F30B89E1B082B
+:0C004000820108AA6040031F1400FF00AA
+:00000001FF
+#
+# Replacement CIS for Advantech COMpad-32/85B-4
+#
diff --git a/firmware/cis/DP83903.cis.ihex b/firmware/cis/DP83903.cis.ihex
new file mode 100644 (file)
index 0000000..6d73ea3
--- /dev/null
@@ -0,0 +1,14 @@
+:1000000001030000FF152904014D756C74696675C4
+:100010006E6374696F6E20436172640000004E531A
+:1000200043204D46204C414E2F4D6F64656D00FFBF
+:1000300020047501000021020000060B02004900A7
+:100040000000006A000000FF00130343495321022F
+:1000500006001A060517201077021B0C970179017C
+:10006000556530FFFF284000FF001303434953212B
+:100070000202001A060507401077021B09870119C2
+:0800800001552330FFFFFF00D2
+:00000001FF
+#
+# This CIS is for cards based on the National Semiconductor
+# DP83903 Multiple Function Interface Chip
+#
diff --git a/firmware/cis/NE2K.cis.ihex b/firmware/cis/NE2K.cis.ihex
new file mode 100644 (file)
index 0000000..1bb40fc
--- /dev/null
@@ -0,0 +1,8 @@
+:1000000001030000FF1515040150434D4349410011
+:1000100045746865726E6574000000FF2102060079
+:100020001A050120F803031B09E001190155653089
+:06003000FFFF1400FF00B9
+:00000001FF
+#
+# Replacement CIS for various busted NE2000-compatible cards
+#
diff --git a/firmware/cis/PE-200.cis.ihex b/firmware/cis/PE-200.cis.ihex
new file mode 100644 (file)
index 0000000..e6dbdab
--- /dev/null
@@ -0,0 +1,9 @@
+:1000000001030000FF151E0401504D582020200060
+:1000100050452D3230300045544845524E4554002D
+:1000200052303100FF210206031A050101000101CF
+:100030001B0EC181190155E051000F100F30FFFF59
+:040040001400FF00A9
+:00000001FF
+#
+# Replacement CIS for PE-200 ethernet card
+#
diff --git a/firmware/cis/SW_555_SER.cis.ihex b/firmware/cis/SW_555_SER.cis.ihex
new file mode 100644 (file)
index 0000000..9b9348a
--- /dev/null
@@ -0,0 +1,12 @@
+:100000000101FF17034100FF20043F0110072102F7
+:100010000200152A070053696572726120576972E0
+:10002000656C657373004169724361726420353594
+:1000300035004135353500526576203100FF1A050F
+:1000400001030007731B0BE00118A360F8030730DE
+:10005000BC3F1B08A10108A360F802071B08A2010E
+:1000600008A360E803071B08A30108A360E80207D0
+:0A0070001B04A40108231400FF0084
+:00000001FF
+#
+# Replacement CIS for AC555 provided by Sierra Wireless
+#
diff --git a/firmware/cis/SW_7xx_SER.cis.ihex b/firmware/cis/SW_7xx_SER.cis.ihex
new file mode 100644 (file)
index 0000000..11e44ad
--- /dev/null
@@ -0,0 +1,13 @@
+:100000000101FF17034100FF2004920110072102A4
+:1000100002001537070053696572726120576972D3
+:10002000656C6573730041433731302F4143373579
+:10003000300047505253204E6574776F726B2041E9
+:1000400064617074657200523100FF1A050103008B
+:1000500007731B10E00119784D555D25A360F80367
+:100060000730BC861B08A10108A360F802071B0823
+:10007000A20108A360E803071B08A30108A360E826
+:0C00800002071B04A40108231400FF0069
+:00000001FF
+#
+# Replacement CIS for AC7xx provided by Sierra Wireless
+#
diff --git a/firmware/cis/SW_8xx_SER.cis.ihex b/firmware/cis/SW_8xx_SER.cis.ihex
new file mode 100644 (file)
index 0000000..bbcfe63
--- /dev/null
@@ -0,0 +1,13 @@
+:100000000101FF17034100FF2004920110072102A4
+:100010000200152F070053696572726120576972DB
+:10002000656C657373004143383530003347204EAB
+:100030006574776F726B20416461707465720052F1
+:100040003100FF1A0501030007731B10E001197846
+:100050004D555D25A360F8480730BC861B08A101FB
+:1000600008A360F847071B08A20108A360E8480737
+:100070001B08A30108A360E847071B04A401082389
+:040080001400FF0069
+:00000001FF
+#
+# Replacement CIS for AC8xx provided by Sierra Wireless
+#
diff --git a/firmware/cis/tamarack.cis.ihex b/firmware/cis/tamarack.cis.ihex
new file mode 100644 (file)
index 0000000..1e86547
--- /dev/null
@@ -0,0 +1,10 @@
+:100000000103D400FF17034100FF152404015441EC
+:100010004D415241434B0045746865726E657400F2
+:10002000410030303437343331313830303100FF33
+:10003000210206001A050120F803031B14E08119B0
+:100040003F554D5D06864626E551000F100F30FFE7
+:05005000FF1400FF0099
+:00000001FF
+#
+# Replacement CIS for Surecom, Tamarack NE2000 cards
+#
index 873cd31..15cce53 100644 (file)
 #include "fid.h"
 
 /**
+ * struct p9_rdir - readdir accounting
+ * @mutex: mutex protecting readdir
+ * @head: start offset of current dirread buffer
+ * @tail: end offset of current dirread buffer
+ * @buf: dirread buffer
+ *
+ * private structure for keeping track of readdir
+ * allocated on demand
+ */
+
+struct p9_rdir {
+       struct mutex mutex;
+       int head;
+       int tail;
+       uint8_t *buf;
+};
+
+/**
  * dt_type - return file type
  * @mistat: mistat structure
  *
@@ -70,56 +88,79 @@ static int v9fs_dir_readdir(struct file *filp, void *dirent, filldir_t filldir)
 {
        int over;
        struct p9_wstat st;
-       int err;
+       int err = 0;
        struct p9_fid *fid;
        int buflen;
-       char *statbuf;
-       int n, i = 0;
+       int reclen = 0;
+       struct p9_rdir *rdir;
 
        P9_DPRINTK(P9_DEBUG_VFS, "name %s\n", filp->f_path.dentry->d_name.name);
        fid = filp->private_data;
 
        buflen = fid->clnt->msize - P9_IOHDRSZ;
-       statbuf = kmalloc(buflen, GFP_KERNEL);
-       if (!statbuf)
-               return -ENOMEM;
-
-       while (1) {
-               err = v9fs_file_readn(filp, statbuf, NULL, buflen,
-                                                               fid->rdir_fpos);
-               if (err <= 0)
-                       break;
-
-               n = err;
-               while (i < n) {
-                       err = p9stat_read(statbuf + i, buflen-i, &st,
-                                                       fid->clnt->dotu);
+
+       /* allocate rdir on demand */
+       if (!fid->rdir) {
+               rdir = kmalloc(sizeof(struct p9_rdir) + buflen, GFP_KERNEL);
+
+               if (rdir == NULL) {
+                       err = -ENOMEM;
+                       goto exit;
+               }
+               spin_lock(&filp->f_dentry->d_lock);
+               if (!fid->rdir) {
+                       rdir->buf = (uint8_t *)rdir + sizeof(struct p9_rdir);
+                       mutex_init(&rdir->mutex);
+                       rdir->head = rdir->tail = 0;
+                       fid->rdir = (void *) rdir;
+                       rdir = NULL;
+               }
+               spin_unlock(&filp->f_dentry->d_lock);
+               kfree(rdir);
+       }
+       rdir = (struct p9_rdir *) fid->rdir;
+
+       err = mutex_lock_interruptible(&rdir->mutex);
+       while (err == 0) {
+               if (rdir->tail == rdir->head) {
+                       err = v9fs_file_readn(filp, rdir->buf, NULL,
+                                                       buflen, filp->f_pos);
+                       if (err <= 0)
+                               goto unlock_and_exit;
+
+                       rdir->head = 0;
+                       rdir->tail = err;
+               }
+
+               while (rdir->head < rdir->tail) {
+                       err = p9stat_read(rdir->buf + rdir->head,
+                                               buflen - rdir->head, &st,
+                                               fid->clnt->dotu);
                        if (err) {
                                P9_DPRINTK(P9_DEBUG_VFS, "returned %d\n", err);
                                err = -EIO;
                                p9stat_free(&st);
-                               goto free_and_exit;
+                               goto unlock_and_exit;
                        }
-
-                       i += st.size+2;
-                       fid->rdir_fpos += st.size+2;
+                       reclen = st.size+2;
 
                        over = filldir(dirent, st.name, strlen(st.name),
                            filp->f_pos, v9fs_qid2ino(&st.qid), dt_type(&st));
 
-                       filp->f_pos += st.size+2;
-
                        p9stat_free(&st);
 
                        if (over) {
                                err = 0;
-                               goto free_and_exit;
+                               goto unlock_and_exit;
                        }
+                       rdir->head += reclen;
+                       filp->f_pos += reclen;
                }
        }
 
-free_and_exit:
-       kfree(statbuf);
+unlock_and_exit:
+       mutex_unlock(&rdir->mutex);
+exit:
        return err;
 }
 
index 5947628..18f74ec 100644 (file)
@@ -994,8 +994,7 @@ static int v9fs_readlink(struct dentry *dentry, char *buffer, int buflen)
        P9_DPRINTK(P9_DEBUG_VFS,
                "%s -> %s (%s)\n", dentry->d_name.name, st->extension, buffer);
 
-       retval = buflen;
-
+       retval = strnlen(buffer, buflen);
 done:
        kfree(st);
        return retval;
@@ -1062,7 +1061,7 @@ static void *v9fs_vfs_follow_link(struct dentry *dentry, struct nameidata *nd)
                        __putname(link);
                        link = ERR_PTR(len);
                } else
-                       link[len] = 0;
+                       link[min(len, PATH_MAX-1)] = 0;
        }
        nd_set_link(nd, link);
 
index d4bf8ca..2126078 100644 (file)
@@ -135,8 +135,8 @@ config TMPFS_POSIX_ACL
 
 config HUGETLBFS
        bool "HugeTLB file system support"
-       depends on X86 || IA64 || PPC64 || SPARC64 || (SUPERH && MMU) || \
-                  (S390 && 64BIT) || SYS_SUPPORTS_HUGETLBFS || BROKEN
+       depends on X86 || IA64 || PPC_BOOK3S_64 || SPARC64 || (S390 && 64BIT) || \
+                  SYS_SUPPORTS_HUGETLBFS || BROKEN
        help
          hugetlbfs is a filesystem backing for HugeTLB pages, based on
          ramfs. For architectures that support it, say Y here and read
index 9cf4b92..8bed055 100644 (file)
@@ -1248,8 +1248,8 @@ static int __blkdev_get(struct block_device *bdev, fmode_t mode, int for_part)
                        bd_set_size(bdev, (loff_t)bdev->bd_part->nr_sects << 9);
                }
        } else {
-               put_disk(disk);
                module_put(disk->fops->owner);
+               put_disk(disk);
                disk = NULL;
                if (bdev->bd_contains == bdev) {
                        if (bdev->bd_disk->fops->open) {
index 69b355a..3616042 100644 (file)
@@ -27,7 +27,7 @@
 #include "btrfs_inode.h"
 #include "xattr.h"
 
-#ifdef CONFIG_BTRFS_POSIX_ACL
+#ifdef CONFIG_BTRFS_FS_POSIX_ACL
 
 static struct posix_acl *btrfs_get_acl(struct inode *inode, int type)
 {
@@ -313,7 +313,7 @@ struct xattr_handler btrfs_xattr_acl_access_handler = {
        .set    = btrfs_xattr_acl_access_set,
 };
 
-#else /* CONFIG_BTRFS_POSIX_ACL */
+#else /* CONFIG_BTRFS_FS_POSIX_ACL */
 
 int btrfs_acl_chmod(struct inode *inode)
 {
@@ -325,4 +325,4 @@ int btrfs_init_acl(struct inode *inode, struct inode *dir)
        return 0;
 }
 
-#endif /* CONFIG_BTRFS_POSIX_ACL */
+#endif /* CONFIG_BTRFS_FS_POSIX_ACL */
index 282ca08..c0861e7 100644 (file)
@@ -64,6 +64,51 @@ struct btrfs_worker_thread {
 };
 
 /*
+ * btrfs_start_workers uses kthread_run, which can block waiting for memory
+ * for a very long time.  It will actually throttle on page writeback,
+ * and so it may not make progress until after our btrfs worker threads
+ * process all of the pending work structs in their queue
+ *
+ * This means we can't use btrfs_start_workers from inside a btrfs worker
+ * thread that is used as part of cleaning dirty memory, which pretty much
+ * involves all of the worker threads.
+ *
+ * Instead we have a helper queue who never has more than one thread
+ * where we scheduler thread start operations.  This worker_start struct
+ * is used to contain the work and hold a pointer to the queue that needs
+ * another worker.
+ */
+struct worker_start {
+       struct btrfs_work work;
+       struct btrfs_workers *queue;
+};
+
+static void start_new_worker_func(struct btrfs_work *work)
+{
+       struct worker_start *start;
+       start = container_of(work, struct worker_start, work);
+       btrfs_start_workers(start->queue, 1);
+       kfree(start);
+}
+
+static int start_new_worker(struct btrfs_workers *queue)
+{
+       struct worker_start *start;
+       int ret;
+
+       start = kzalloc(sizeof(*start), GFP_NOFS);
+       if (!start)
+               return -ENOMEM;
+
+       start->work.func = start_new_worker_func;
+       start->queue = queue;
+       ret = btrfs_queue_worker(queue->atomic_worker_start, &start->work);
+       if (ret)
+               kfree(start);
+       return ret;
+}
+
+/*
  * helper function to move a thread onto the idle list after it
  * has finished some requests.
  */
@@ -118,11 +163,13 @@ static void check_pending_worker_creates(struct btrfs_worker_thread *worker)
                goto out;
 
        workers->atomic_start_pending = 0;
-       if (workers->num_workers >= workers->max_workers)
+       if (workers->num_workers + workers->num_workers_starting >=
+           workers->max_workers)
                goto out;
 
+       workers->num_workers_starting += 1;
        spin_unlock_irqrestore(&workers->lock, flags);
-       btrfs_start_workers(workers, 1);
+       start_new_worker(workers);
        return;
 
 out:
@@ -390,9 +437,11 @@ int btrfs_stop_workers(struct btrfs_workers *workers)
 /*
  * simple init on struct btrfs_workers
  */
-void btrfs_init_workers(struct btrfs_workers *workers, char *name, int max)
+void btrfs_init_workers(struct btrfs_workers *workers, char *name, int max,
+                       struct btrfs_workers *async_helper)
 {
        workers->num_workers = 0;
+       workers->num_workers_starting = 0;
        INIT_LIST_HEAD(&workers->worker_list);
        INIT_LIST_HEAD(&workers->idle_list);
        INIT_LIST_HEAD(&workers->order_list);
@@ -404,14 +453,15 @@ void btrfs_init_workers(struct btrfs_workers *workers, char *name, int max)
        workers->name = name;
        workers->ordered = 0;
        workers->atomic_start_pending = 0;
-       workers->atomic_worker_start = 0;
+       workers->atomic_worker_start = async_helper;
 }
 
 /*
  * starts new worker threads.  This does not enforce the max worker
  * count in case you need to temporarily go past it.
  */
-int btrfs_start_workers(struct btrfs_workers *workers, int num_workers)
+static int __btrfs_start_workers(struct btrfs_workers *workers,
+                                int num_workers)
 {
        struct btrfs_worker_thread *worker;
        int ret = 0;
@@ -444,6 +494,8 @@ int btrfs_start_workers(struct btrfs_workers *workers, int num_workers)
                list_add_tail(&worker->worker_list, &workers->idle_list);
                worker->idle = 1;
                workers->num_workers++;
+               workers->num_workers_starting--;
+               WARN_ON(workers->num_workers_starting < 0);
                spin_unlock_irq(&workers->lock);
        }
        return 0;
@@ -452,6 +504,14 @@ fail:
        return ret;
 }
 
+int btrfs_start_workers(struct btrfs_workers *workers, int num_workers)
+{
+       spin_lock_irq(&workers->lock);
+       workers->num_workers_starting += num_workers;
+       spin_unlock_irq(&workers->lock);
+       return __btrfs_start_workers(workers, num_workers);
+}
+
 /*
  * run through the list and find a worker thread that doesn't have a lot
  * to do right now.  This can return null if we aren't yet at the thread
@@ -461,7 +521,10 @@ static struct btrfs_worker_thread *next_worker(struct btrfs_workers *workers)
 {
        struct btrfs_worker_thread *worker;
        struct list_head *next;
-       int enforce_min = workers->num_workers < workers->max_workers;
+       int enforce_min;
+
+       enforce_min = (workers->num_workers + workers->num_workers_starting) <
+               workers->max_workers;
 
        /*
         * if we find an idle thread, don't move it to the end of the
@@ -509,15 +572,17 @@ again:
        worker = next_worker(workers);
 
        if (!worker) {
-               if (workers->num_workers >= workers->max_workers) {
+               if (workers->num_workers + workers->num_workers_starting >=
+                   workers->max_workers) {
                        goto fallback;
                } else if (workers->atomic_worker_start) {
                        workers->atomic_start_pending = 1;
                        goto fallback;
                } else {
+                       workers->num_workers_starting++;
                        spin_unlock_irqrestore(&workers->lock, flags);
                        /* we're below the limit, start another worker */
-                       btrfs_start_workers(workers, 1);
+                       __btrfs_start_workers(workers, 1);
                        goto again;
                }
        }
index fc089b9..5077746 100644 (file)
@@ -64,6 +64,8 @@ struct btrfs_workers {
        /* current number of running workers */
        int num_workers;
 
+       int num_workers_starting;
+
        /* max number of workers allowed.  changed by btrfs_start_workers */
        int max_workers;
 
@@ -78,9 +80,10 @@ struct btrfs_workers {
 
        /*
         * are we allowed to sleep while starting workers or are we required
-        * to start them at a later time?
+        * to start them at a later time?  If we can't sleep, this indicates
+        * which queue we need to use to schedule thread creation.
         */
-       int atomic_worker_start;
+       struct btrfs_workers *atomic_worker_start;
 
        /* list with all the work threads.  The workers on the idle thread
         * may be actively servicing jobs, but they haven't yet hit the
@@ -109,7 +112,8 @@ struct btrfs_workers {
 int btrfs_queue_worker(struct btrfs_workers *workers, struct btrfs_work *work);
 int btrfs_start_workers(struct btrfs_workers *workers, int num_workers);
 int btrfs_stop_workers(struct btrfs_workers *workers);
-void btrfs_init_workers(struct btrfs_workers *workers, char *name, int max);
+void btrfs_init_workers(struct btrfs_workers *workers, char *name, int max,
+                       struct btrfs_workers *async_starter);
 int btrfs_requeue_work(struct btrfs_work *work);
 void btrfs_set_work_high_prio(struct btrfs_work *work);
 #endif
index a54d354..f6783a4 100644 (file)
@@ -86,6 +86,12 @@ struct btrfs_inode {
         * transid of the trans_handle that last modified this inode
         */
        u64 last_trans;
+
+       /*
+        * log transid when this inode was last modified
+        */
+       u64 last_sub_trans;
+
        /*
         * transid that last logged this inode
         */
@@ -128,12 +134,14 @@ struct btrfs_inode {
        u64 last_unlink_trans;
 
        /*
-        * These two counters are for delalloc metadata reservations.  We keep
-        * track of how many extents we've accounted for vs how many extents we
-        * have.
+        * Counters to keep track of the number of extent item's we may use due
+        * to delalloc and such.  outstanding_extents is the number of extent
+        * items we think we'll end up using, and reserved_extents is the number
+        * of extent items we've reserved metadata for.
         */
-       int delalloc_reserved_extents;
-       int delalloc_extents;
+       spinlock_t accounting_lock;
+       int reserved_extents;
+       int outstanding_extents;
 
        /*
         * ordered_data_close is set by truncate when a file that used
index dd8ced9..444b3e9 100644 (file)
@@ -691,14 +691,17 @@ struct btrfs_space_info {
 
        struct list_head list;
 
+       /* for controlling how we free up space for allocations */
+       wait_queue_head_t allocate_wait;
+       wait_queue_head_t flush_wait;
+       int allocating_chunk;
+       int flushing;
+
        /* for block groups in our same type */
        struct list_head block_groups;
        spinlock_t lock;
        struct rw_semaphore groups_sem;
        atomic_t caching_threads;
-
-       int allocating_chunk;
-       wait_queue_head_t wait;
 };
 
 /*
@@ -907,6 +910,7 @@ struct btrfs_fs_info {
         * A third pool does submit_bio to avoid deadlocking with the other
         * two
         */
+       struct btrfs_workers generic_worker;
        struct btrfs_workers workers;
        struct btrfs_workers delalloc_workers;
        struct btrfs_workers endio_workers;
@@ -914,6 +918,7 @@ struct btrfs_fs_info {
        struct btrfs_workers endio_meta_write_workers;
        struct btrfs_workers endio_write_workers;
        struct btrfs_workers submit_workers;
+       struct btrfs_workers enospc_workers;
        /*
         * fixup workers take dirty pages that didn't properly go through
         * the cow mechanism and make them safe to write.  It happens
@@ -1004,7 +1009,10 @@ struct btrfs_root {
        atomic_t log_writers;
        atomic_t log_commit[2];
        unsigned long log_transid;
+       unsigned long last_log_commit;
        unsigned long log_batch;
+       pid_t log_start_pid;
+       bool log_multiple_pids;
 
        u64 objectid;
        u64 last_trans;
@@ -1145,6 +1153,7 @@ struct btrfs_root {
 #define BTRFS_MOUNT_FLUSHONCOMMIT       (1 << 7)
 #define BTRFS_MOUNT_SSD_SPREAD         (1 << 8)
 #define BTRFS_MOUNT_NOSSD              (1 << 9)
+#define BTRFS_MOUNT_DISCARD            (1 << 10)
 
 #define btrfs_clear_opt(o, opt)                ((o) &= ~BTRFS_MOUNT_##opt)
 #define btrfs_set_opt(o, opt)          ((o) |= BTRFS_MOUNT_##opt)
@@ -2323,7 +2332,7 @@ int btrfs_orphan_del(struct btrfs_trans_handle *trans, struct inode *inode);
 void btrfs_orphan_cleanup(struct btrfs_root *root);
 int btrfs_cont_expand(struct inode *inode, loff_t size);
 int btrfs_invalidate_inodes(struct btrfs_root *root);
-extern struct dentry_operations btrfs_dentry_operations;
+extern const struct dentry_operations btrfs_dentry_operations;
 
 /* ioctl.c */
 long btrfs_ioctl(struct file *file, unsigned int cmd, unsigned long arg);
@@ -2366,7 +2375,7 @@ int btrfs_parse_options(struct btrfs_root *root, char *options);
 int btrfs_sync_fs(struct super_block *sb, int wait);
 
 /* acl.c */
-#ifdef CONFIG_BTRFS_POSIX_ACL
+#ifdef CONFIG_BTRFS_FS_POSIX_ACL
 int btrfs_check_acl(struct inode *inode, int mask);
 #else
 #define btrfs_check_acl NULL
index af0435f..02b6afb 100644 (file)
@@ -917,6 +917,7 @@ static int __setup_root(u32 nodesize, u32 leafsize, u32 sectorsize,
        atomic_set(&root->log_writers, 0);
        root->log_batch = 0;
        root->log_transid = 0;
+       root->last_log_commit = 0;
        extent_io_tree_init(&root->dirty_log_pages,
                             fs_info->btree_inode->i_mapping, GFP_NOFS);
 
@@ -1087,6 +1088,7 @@ int btrfs_add_log_tree(struct btrfs_trans_handle *trans,
        WARN_ON(root->log_root);
        root->log_root = log_root;
        root->log_transid = 0;
+       root->last_log_commit = 0;
        return 0;
 }
 
@@ -1746,21 +1748,25 @@ struct btrfs_root *open_ctree(struct super_block *sb,
                err = -EINVAL;
                goto fail_iput;
        }
-printk("thread pool is %d\n", fs_info->thread_pool_size);
-       /*
-        * we need to start all the end_io workers up front because the
-        * queue work function gets called at interrupt time, and so it
-        * cannot dynamically grow.
-        */
+
+       btrfs_init_workers(&fs_info->generic_worker,
+                          "genwork", 1, NULL);
+
        btrfs_init_workers(&fs_info->workers, "worker",
-                          fs_info->thread_pool_size);
+                          fs_info->thread_pool_size,
+                          &fs_info->generic_worker);
 
        btrfs_init_workers(&fs_info->delalloc_workers, "delalloc",
-                          fs_info->thread_pool_size);
+                          fs_info->thread_pool_size,
+                          &fs_info->generic_worker);
 
        btrfs_init_workers(&fs_info->submit_workers, "submit",
                           min_t(u64, fs_devices->num_devices,
-                          fs_info->thread_pool_size));
+                          fs_info->thread_pool_size),
+                          &fs_info->generic_worker);
+       btrfs_init_workers(&fs_info->enospc_workers, "enospc",
+                          fs_info->thread_pool_size,
+                          &fs_info->generic_worker);
 
        /* a higher idle thresh on the submit workers makes it much more
         * likely that bios will be send down in a sane order to the
@@ -1774,15 +1780,20 @@ printk("thread pool is %d\n", fs_info->thread_pool_size);
        fs_info->delalloc_workers.idle_thresh = 2;
        fs_info->delalloc_workers.ordered = 1;
 
-       btrfs_init_workers(&fs_info->fixup_workers, "fixup", 1);
+       btrfs_init_workers(&fs_info->fixup_workers, "fixup", 1,
+                          &fs_info->generic_worker);
        btrfs_init_workers(&fs_info->endio_workers, "endio",
-                          fs_info->thread_pool_size);
+                          fs_info->thread_pool_size,
+                          &fs_info->generic_worker);
        btrfs_init_workers(&fs_info->endio_meta_workers, "endio-meta",
-                          fs_info->thread_pool_size);
+                          fs_info->thread_pool_size,
+                          &fs_info->generic_worker);
        btrfs_init_workers(&fs_info->endio_meta_write_workers,
-                          "endio-meta-write", fs_info->thread_pool_size);
+                          "endio-meta-write", fs_info->thread_pool_size,
+                          &fs_info->generic_worker);
        btrfs_init_workers(&fs_info->endio_write_workers, "endio-write",
-                          fs_info->thread_pool_size);
+                          fs_info->thread_pool_size,
+                          &fs_info->generic_worker);
 
        /*
         * endios are largely parallel and should have a very
@@ -1794,12 +1805,8 @@ printk("thread pool is %d\n", fs_info->thread_pool_size);
        fs_info->endio_write_workers.idle_thresh = 2;
        fs_info->endio_meta_write_workers.idle_thresh = 2;
 
-       fs_info->endio_workers.atomic_worker_start = 1;
-       fs_info->endio_meta_workers.atomic_worker_start = 1;
-       fs_info->endio_write_workers.atomic_worker_start = 1;
-       fs_info->endio_meta_write_workers.atomic_worker_start = 1;
-
        btrfs_start_workers(&fs_info->workers, 1);
+       btrfs_start_workers(&fs_info->generic_worker, 1);
        btrfs_start_workers(&fs_info->submit_workers, 1);
        btrfs_start_workers(&fs_info->delalloc_workers, 1);
        btrfs_start_workers(&fs_info->fixup_workers, 1);
@@ -1807,6 +1814,7 @@ printk("thread pool is %d\n", fs_info->thread_pool_size);
        btrfs_start_workers(&fs_info->endio_meta_workers, 1);
        btrfs_start_workers(&fs_info->endio_meta_write_workers, 1);
        btrfs_start_workers(&fs_info->endio_write_workers, 1);
+       btrfs_start_workers(&fs_info->enospc_workers, 1);
 
        fs_info->bdi.ra_pages *= btrfs_super_num_devices(disk_super);
        fs_info->bdi.ra_pages = max(fs_info->bdi.ra_pages,
@@ -2012,6 +2020,7 @@ fail_chunk_root:
        free_extent_buffer(chunk_root->node);
        free_extent_buffer(chunk_root->commit_root);
 fail_sb_buffer:
+       btrfs_stop_workers(&fs_info->generic_worker);
        btrfs_stop_workers(&fs_info->fixup_workers);
        btrfs_stop_workers(&fs_info->delalloc_workers);
        btrfs_stop_workers(&fs_info->workers);
@@ -2020,6 +2029,7 @@ fail_sb_buffer:
        btrfs_stop_workers(&fs_info->endio_meta_write_workers);
        btrfs_stop_workers(&fs_info->endio_write_workers);
        btrfs_stop_workers(&fs_info->submit_workers);
+       btrfs_stop_workers(&fs_info->enospc_workers);
 fail_iput:
        invalidate_inode_pages2(fs_info->btree_inode->i_mapping);
        iput(fs_info->btree_inode);
@@ -2437,6 +2447,7 @@ int close_ctree(struct btrfs_root *root)
 
        iput(fs_info->btree_inode);
 
+       btrfs_stop_workers(&fs_info->generic_worker);
        btrfs_stop_workers(&fs_info->fixup_workers);
        btrfs_stop_workers(&fs_info->delalloc_workers);
        btrfs_stop_workers(&fs_info->workers);
@@ -2445,6 +2456,7 @@ int close_ctree(struct btrfs_root *root)
        btrfs_stop_workers(&fs_info->endio_meta_write_workers);
        btrfs_stop_workers(&fs_info->endio_write_workers);
        btrfs_stop_workers(&fs_info->submit_workers);
+       btrfs_stop_workers(&fs_info->enospc_workers);
 
        btrfs_close_devices(fs_info->fs_devices);
        btrfs_mapping_tree_free(&fs_info->mapping_tree);
index 359a754..e238a0c 100644 (file)
@@ -1568,23 +1568,23 @@ static int remove_extent_backref(struct btrfs_trans_handle *trans,
        return ret;
 }
 
-#ifdef BIO_RW_DISCARD
 static void btrfs_issue_discard(struct block_device *bdev,
                                u64 start, u64 len)
 {
        blkdev_issue_discard(bdev, start >> 9, len >> 9, GFP_KERNEL,
                             DISCARD_FL_BARRIER);
 }
-#endif
 
 static int btrfs_discard_extent(struct btrfs_root *root, u64 bytenr,
                                u64 num_bytes)
 {
-#ifdef BIO_RW_DISCARD
        int ret;
        u64 map_length = num_bytes;
        struct btrfs_multi_bio *multi = NULL;
 
+       if (!btrfs_test_opt(root, DISCARD))
+               return 0;
+
        /* Tell the block device(s) that the sectors can be discarded */
        ret = btrfs_map_block(&root->fs_info->mapping_tree, READ,
                              bytenr, &map_length, &multi, 0);
@@ -1604,9 +1604,6 @@ static int btrfs_discard_extent(struct btrfs_root *root, u64 bytenr,
        }
 
        return ret;
-#else
-       return 0;
-#endif
 }
 
 int btrfs_inc_extent_ref(struct btrfs_trans_handle *trans,
@@ -2824,14 +2821,17 @@ int btrfs_unreserve_metadata_for_delalloc(struct btrfs_root *root,
                                           num_items);
 
        spin_lock(&meta_sinfo->lock);
-       if (BTRFS_I(inode)->delalloc_reserved_extents <=
-           BTRFS_I(inode)->delalloc_extents) {
+       spin_lock(&BTRFS_I(inode)->accounting_lock);
+       if (BTRFS_I(inode)->reserved_extents <=
+           BTRFS_I(inode)->outstanding_extents) {
+               spin_unlock(&BTRFS_I(inode)->accounting_lock);
                spin_unlock(&meta_sinfo->lock);
                return 0;
        }
+       spin_unlock(&BTRFS_I(inode)->accounting_lock);
 
-       BTRFS_I(inode)->delalloc_reserved_extents--;
-       BUG_ON(BTRFS_I(inode)->delalloc_reserved_extents < 0);
+       BTRFS_I(inode)->reserved_extents--;
+       BUG_ON(BTRFS_I(inode)->reserved_extents < 0);
 
        if (meta_sinfo->bytes_delalloc < num_bytes) {
                bug = true;
@@ -2864,6 +2864,107 @@ static void check_force_delalloc(struct btrfs_space_info *meta_sinfo)
                meta_sinfo->force_delalloc = 0;
 }
 
+struct async_flush {
+       struct btrfs_root *root;
+       struct btrfs_space_info *info;
+       struct btrfs_work work;
+};
+
+static noinline void flush_delalloc_async(struct btrfs_work *work)
+{
+       struct async_flush *async;
+       struct btrfs_root *root;
+       struct btrfs_space_info *info;
+
+       async = container_of(work, struct async_flush, work);
+       root = async->root;
+       info = async->info;
+
+       btrfs_start_delalloc_inodes(root);
+       wake_up(&info->flush_wait);
+       btrfs_wait_ordered_extents(root, 0);
+
+       spin_lock(&info->lock);
+       info->flushing = 0;
+       spin_unlock(&info->lock);
+       wake_up(&info->flush_wait);
+
+       kfree(async);
+}
+
+static void wait_on_flush(struct btrfs_space_info *info)
+{
+       DEFINE_WAIT(wait);
+       u64 used;
+
+       while (1) {
+               prepare_to_wait(&info->flush_wait, &wait,
+                               TASK_UNINTERRUPTIBLE);
+               spin_lock(&info->lock);
+               if (!info->flushing) {
+                       spin_unlock(&info->lock);
+                       break;
+               }
+
+               used = info->bytes_used + info->bytes_reserved +
+                       info->bytes_pinned + info->bytes_readonly +
+                       info->bytes_super + info->bytes_root +
+                       info->bytes_may_use + info->bytes_delalloc;
+               if (used < info->total_bytes) {
+                       spin_unlock(&info->lock);
+                       break;
+               }
+               spin_unlock(&info->lock);
+               schedule();
+       }
+       finish_wait(&info->flush_wait, &wait);
+}
+
+static void flush_delalloc(struct btrfs_root *root,
+                                struct btrfs_space_info *info)
+{
+       struct async_flush *async;
+       bool wait = false;
+
+       spin_lock(&info->lock);
+
+       if (!info->flushing) {
+               info->flushing = 1;
+               init_waitqueue_head(&info->flush_wait);
+       } else {
+               wait = true;
+       }
+
+       spin_unlock(&info->lock);
+
+       if (wait) {
+               wait_on_flush(info);
+               return;
+       }
+
+       async = kzalloc(sizeof(*async), GFP_NOFS);
+       if (!async)
+               goto flush;
+
+       async->root = root;
+       async->info = info;
+       async->work.func = flush_delalloc_async;
+
+       btrfs_queue_worker(&root->fs_info->enospc_workers,
+                          &async->work);
+       wait_on_flush(info);
+       return;
+
+flush:
+       btrfs_start_delalloc_inodes(root);
+       btrfs_wait_ordered_extents(root, 0);
+
+       spin_lock(&info->lock);
+       info->flushing = 0;
+       spin_unlock(&info->lock);
+       wake_up(&info->flush_wait);
+}
+
 static int maybe_allocate_chunk(struct btrfs_root *root,
                                 struct btrfs_space_info *info)
 {
@@ -2894,7 +2995,7 @@ static int maybe_allocate_chunk(struct btrfs_root *root,
        if (!info->allocating_chunk) {
                info->force_alloc = 1;
                info->allocating_chunk = 1;
-               init_waitqueue_head(&info->wait);
+               init_waitqueue_head(&info->allocate_wait);
        } else {
                wait = true;
        }
@@ -2902,7 +3003,7 @@ static int maybe_allocate_chunk(struct btrfs_root *root,
        spin_unlock(&info->lock);
 
        if (wait) {
-               wait_event(info->wait,
+               wait_event(info->allocate_wait,
                           !info->allocating_chunk);
                return 1;
        }
@@ -2923,7 +3024,7 @@ out:
        spin_lock(&info->lock);
        info->allocating_chunk = 0;
        spin_unlock(&info->lock);
-       wake_up(&info->wait);
+       wake_up(&info->allocate_wait);
 
        if (ret)
                return 0;
@@ -2981,21 +3082,20 @@ again:
                        filemap_flush(inode->i_mapping);
                        goto again;
                } else if (flushed == 3) {
-                       btrfs_start_delalloc_inodes(root);
-                       btrfs_wait_ordered_extents(root, 0);
+                       flush_delalloc(root, meta_sinfo);
                        goto again;
                }
                spin_lock(&meta_sinfo->lock);
                meta_sinfo->bytes_delalloc -= num_bytes;
                spin_unlock(&meta_sinfo->lock);
                printk(KERN_ERR "enospc, has %d, reserved %d\n",
-                      BTRFS_I(inode)->delalloc_extents,
-                      BTRFS_I(inode)->delalloc_reserved_extents);
+                      BTRFS_I(inode)->outstanding_extents,
+                      BTRFS_I(inode)->reserved_extents);
                dump_space_info(meta_sinfo, 0, 0);
                return -ENOSPC;
        }
 
-       BTRFS_I(inode)->delalloc_reserved_extents++;
+       BTRFS_I(inode)->reserved_extents++;
        check_force_delalloc(meta_sinfo);
        spin_unlock(&meta_sinfo->lock);
 
@@ -3094,8 +3194,7 @@ again:
                }
 
                if (retries == 2) {
-                       btrfs_start_delalloc_inodes(root);
-                       btrfs_wait_ordered_extents(root, 0);
+                       flush_delalloc(root, meta_sinfo);
                        goto again;
                }
                spin_lock(&meta_sinfo->lock);
@@ -3588,6 +3687,14 @@ static int pin_down_bytes(struct btrfs_trans_handle *trans,
        if (is_data)
                goto pinit;
 
+       /*
+        * discard is sloooow, and so triggering discards on
+        * individual btree blocks isn't a good plan.  Just
+        * pin everything in discard mode.
+        */
+       if (btrfs_test_opt(root, DISCARD))
+               goto pinit;
+
        buf = btrfs_find_tree_block(root, bytenr, num_bytes);
        if (!buf)
                goto pinit;
@@ -4029,6 +4136,7 @@ static noinline int find_free_extent(struct btrfs_trans_handle *trans,
        int loop = 0;
        bool found_uncached_bg = false;
        bool failed_cluster_refill = false;
+       bool failed_alloc = false;
 
        WARN_ON(num_bytes < root->sectorsize);
        btrfs_set_key_type(ins, BTRFS_EXTENT_ITEM_KEY);
@@ -4233,14 +4341,23 @@ refill_cluster:
 
                offset = btrfs_find_space_for_alloc(block_group, search_start,
                                                    num_bytes, empty_size);
-               if (!offset && (cached || (!cached &&
-                                          loop == LOOP_CACHING_NOWAIT))) {
-                       goto loop;
-               } else if (!offset && (!cached &&
-                                      loop > LOOP_CACHING_NOWAIT)) {
+               /*
+                * If we didn't find a chunk, and we haven't failed on this
+                * block group before, and this block group is in the middle of
+                * caching and we are ok with waiting, then go ahead and wait
+                * for progress to be made, and set failed_alloc to true.
+                *
+                * If failed_alloc is true then we've already waited on this
+                * block group once and should move on to the next block group.
+                */
+               if (!offset && !failed_alloc && !cached &&
+                   loop > LOOP_CACHING_NOWAIT) {
                        wait_block_group_cache_progress(block_group,
-                                       num_bytes + empty_size);
+                                               num_bytes + empty_size);
+                       failed_alloc = true;
                        goto have_block_group;
+               } else if (!offset) {
+                       goto loop;
                }
 checks:
                search_start = stripe_align(root, offset);
@@ -4288,6 +4405,7 @@ checks:
                break;
 loop:
                failed_cluster_refill = false;
+               failed_alloc = false;
                btrfs_put_block_group(block_group);
        }
        up_read(&space_info->groups_sem);
@@ -4799,6 +4917,7 @@ static noinline void reada_walk_down(struct btrfs_trans_handle *trans,
        u64 bytenr;
        u64 generation;
        u64 refs;
+       u64 flags;
        u64 last = 0;
        u32 nritems;
        u32 blocksize;
@@ -4836,15 +4955,19 @@ static noinline void reada_walk_down(struct btrfs_trans_handle *trans,
                    generation <= root->root_key.offset)
                        continue;
 
+               /* We don't lock the tree block, it's OK to be racy here */
+               ret = btrfs_lookup_extent_info(trans, root, bytenr, blocksize,
+                                              &refs, &flags);
+               BUG_ON(ret);
+               BUG_ON(refs == 0);
+
                if (wc->stage == DROP_REFERENCE) {
-                       ret = btrfs_lookup_extent_info(trans, root,
-                                               bytenr, blocksize,
-                                               &refs, NULL);
-                       BUG_ON(ret);
-                       BUG_ON(refs == 0);
                        if (refs == 1)
                                goto reada;
 
+                       if (wc->level == 1 &&
+                           (flags & BTRFS_BLOCK_FLAG_FULL_BACKREF))
+                               continue;
                        if (!wc->update_ref ||
                            generation <= root->root_key.offset)
                                continue;
@@ -4853,6 +4976,10 @@ static noinline void reada_walk_down(struct btrfs_trans_handle *trans,
                                                  &wc->update_progress);
                        if (ret < 0)
                                continue;
+               } else {
+                       if (wc->level == 1 &&
+                           (flags & BTRFS_BLOCK_FLAG_FULL_BACKREF))
+                               continue;
                }
 reada:
                ret = readahead_tree_block(root, bytenr, blocksize,
@@ -4876,7 +5003,7 @@ reada:
 static noinline int walk_down_proc(struct btrfs_trans_handle *trans,
                                   struct btrfs_root *root,
                                   struct btrfs_path *path,
-                                  struct walk_control *wc)
+                                  struct walk_control *wc, int lookup_info)
 {
        int level = wc->level;
        struct extent_buffer *eb = path->nodes[level];
@@ -4891,8 +5018,9 @@ static noinline int walk_down_proc(struct btrfs_trans_handle *trans,
         * when reference count of tree block is 1, it won't increase
         * again. once full backref flag is set, we never clear it.
         */
-       if ((wc->stage == DROP_REFERENCE && wc->refs[level] != 1) ||
-           (wc->stage == UPDATE_BACKREF && !(wc->flags[level] & flag))) {
+       if (lookup_info &&
+           ((wc->stage == DROP_REFERENCE && wc->refs[level] != 1) ||
+            (wc->stage == UPDATE_BACKREF && !(wc->flags[level] & flag)))) {
                BUG_ON(!path->locks[level]);
                ret = btrfs_lookup_extent_info(trans, root,
                                               eb->start, eb->len,
@@ -4953,7 +5081,7 @@ static noinline int walk_down_proc(struct btrfs_trans_handle *trans,
 static noinline int do_walk_down(struct btrfs_trans_handle *trans,
                                 struct btrfs_root *root,
                                 struct btrfs_path *path,
-                                struct walk_control *wc)
+                                struct walk_control *wc, int *lookup_info)
 {
        u64 bytenr;
        u64 generation;
@@ -4973,8 +5101,10 @@ static noinline int do_walk_down(struct btrfs_trans_handle *trans,
         * for the subtree
         */
        if (wc->stage == UPDATE_BACKREF &&
-           generation <= root->root_key.offset)
+           generation <= root->root_key.offset) {
+               *lookup_info = 1;
                return 1;
+       }
 
        bytenr = btrfs_node_blockptr(path->nodes[level], path->slots[level]);
        blocksize = btrfs_level_size(root, level - 1);
@@ -4987,14 +5117,19 @@ static noinline int do_walk_down(struct btrfs_trans_handle *trans,
        btrfs_tree_lock(next);
        btrfs_set_lock_blocking(next);
 
-       if (wc->stage == DROP_REFERENCE) {
-               ret = btrfs_lookup_extent_info(trans, root, bytenr, blocksize,
-                                              &wc->refs[level - 1],
-                                              &wc->flags[level - 1]);
-               BUG_ON(ret);
-               BUG_ON(wc->refs[level - 1] == 0);
+       ret = btrfs_lookup_extent_info(trans, root, bytenr, blocksize,
+                                      &wc->refs[level - 1],
+                                      &wc->flags[level - 1]);
+       BUG_ON(ret);
+       BUG_ON(wc->refs[level - 1] == 0);
+       *lookup_info = 0;
 
+       if (wc->stage == DROP_REFERENCE) {
                if (wc->refs[level - 1] > 1) {
+                       if (level == 1 &&
+                           (wc->flags[0] & BTRFS_BLOCK_FLAG_FULL_BACKREF))
+                               goto skip;
+
                        if (!wc->update_ref ||
                            generation <= root->root_key.offset)
                                goto skip;
@@ -5008,12 +5143,17 @@ static noinline int do_walk_down(struct btrfs_trans_handle *trans,
                        wc->stage = UPDATE_BACKREF;
                        wc->shared_level = level - 1;
                }
+       } else {
+               if (level == 1 &&
+                   (wc->flags[0] & BTRFS_BLOCK_FLAG_FULL_BACKREF))
+                       goto skip;
        }
 
        if (!btrfs_buffer_uptodate(next, generation)) {
                btrfs_tree_unlock(next);
                free_extent_buffer(next);
                next = NULL;
+               *lookup_info = 1;
        }
 
        if (!next) {
@@ -5036,21 +5176,22 @@ static noinline int do_walk_down(struct btrfs_trans_handle *trans,
 skip:
        wc->refs[level - 1] = 0;
        wc->flags[level - 1] = 0;
+       if (wc->stage == DROP_REFERENCE) {
+               if (wc->flags[level] & BTRFS_BLOCK_FLAG_FULL_BACKREF) {
+                       parent = path->nodes[level]->start;
+               } else {
+                       BUG_ON(root->root_key.objectid !=
+                              btrfs_header_owner(path->nodes[level]));
+                       parent = 0;
+               }
 
-       if (wc->flags[level] & BTRFS_BLOCK_FLAG_FULL_BACKREF) {
-               parent = path->nodes[level]->start;
-       } else {
-               BUG_ON(root->root_key.objectid !=
-                      btrfs_header_owner(path->nodes[level]));
-               parent = 0;
+               ret = btrfs_free_extent(trans, root, bytenr, blocksize, parent,
+                                       root->root_key.objectid, level - 1, 0);
+               BUG_ON(ret);
        }
-
-       ret = btrfs_free_extent(trans, root, bytenr, blocksize, parent,
-                               root->root_key.objectid, level - 1, 0);
-       BUG_ON(ret);
-
        btrfs_tree_unlock(next);
        free_extent_buffer(next);
+       *lookup_info = 1;
        return 1;
 }
 
@@ -5164,6 +5305,7 @@ static noinline int walk_down_tree(struct btrfs_trans_handle *trans,
                                   struct walk_control *wc)
 {
        int level = wc->level;
+       int lookup_info = 1;
        int ret;
 
        while (level >= 0) {
@@ -5171,14 +5313,14 @@ static noinline int walk_down_tree(struct btrfs_trans_handle *trans,
                    btrfs_header_nritems(path->nodes[level]))
                        break;
 
-               ret = walk_down_proc(trans, root, path, wc);
+               ret = walk_down_proc(trans, root, path, wc, lookup_info);
                if (ret > 0)
                        break;
 
                if (level == 0)
                        break;
 
-               ret = do_walk_down(trans, root, path, wc);
+               ret = do_walk_down(trans, root, path, wc, &lookup_info);
                if (ret > 0) {
                        path->slots[level]++;
                        continue;
index de1793b..96577e8 100644 (file)
@@ -460,7 +460,8 @@ static int clear_state_bit(struct extent_io_tree *tree,
                            struct extent_state *state, int bits, int wake,
                            int delete)
 {
-       int ret = state->state & bits;
+       int bits_to_clear = bits & ~EXTENT_DO_ACCOUNTING;
+       int ret = state->state & bits_to_clear;
 
        if ((bits & EXTENT_DIRTY) && (state->state & EXTENT_DIRTY)) {
                u64 range = state->end - state->start + 1;
@@ -468,7 +469,7 @@ static int clear_state_bit(struct extent_io_tree *tree,
                tree->dirty_bytes -= range;
        }
        clear_state_cb(tree, state, bits);
-       state->state &= ~bits;
+       state->state &= ~bits_to_clear;
        if (wake)
                wake_up(&state->wq);
        if (delete || state->state == 0) {
@@ -956,7 +957,8 @@ int clear_extent_dirty(struct extent_io_tree *tree, u64 start, u64 end,
                       gfp_t mask)
 {
        return clear_extent_bit(tree, start, end,
-                               EXTENT_DIRTY | EXTENT_DELALLOC, 0, 0,
+                               EXTENT_DIRTY | EXTENT_DELALLOC |
+                               EXTENT_DO_ACCOUNTING, 0, 0,
                                NULL, mask);
 }
 
@@ -1401,12 +1403,7 @@ out_failed:
 int extent_clear_unlock_delalloc(struct inode *inode,
                                struct extent_io_tree *tree,
                                u64 start, u64 end, struct page *locked_page,
-                               int unlock_pages,
-                               int clear_unlock,
-                               int clear_delalloc, int clear_dirty,
-                               int set_writeback,
-                               int end_writeback,
-                               int set_private2)
+                               unsigned long op)
 {
        int ret;
        struct page *pages[16];
@@ -1416,17 +1413,21 @@ int extent_clear_unlock_delalloc(struct inode *inode,
        int i;
        int clear_bits = 0;
 
-       if (clear_unlock)
+       if (op & EXTENT_CLEAR_UNLOCK)
                clear_bits |= EXTENT_LOCKED;
-       if (clear_dirty)
+       if (op & EXTENT_CLEAR_DIRTY)
                clear_bits |= EXTENT_DIRTY;
 
-       if (clear_delalloc)
+       if (op & EXTENT_CLEAR_DELALLOC)
                clear_bits |= EXTENT_DELALLOC;
 
+       if (op & EXTENT_CLEAR_ACCOUNTING)
+               clear_bits |= EXTENT_DO_ACCOUNTING;
+
        clear_extent_bit(tree, start, end, clear_bits, 1, 0, NULL, GFP_NOFS);
-       if (!(unlock_pages || clear_dirty || set_writeback || end_writeback ||
-             set_private2))
+       if (!(op & (EXTENT_CLEAR_UNLOCK_PAGE | EXTENT_CLEAR_DIRTY |
+                   EXTENT_SET_WRITEBACK | EXTENT_END_WRITEBACK |
+                   EXTENT_SET_PRIVATE2)))
                return 0;
 
        while (nr_pages > 0) {
@@ -1435,20 +1436,20 @@ int extent_clear_unlock_delalloc(struct inode *inode,
                                     nr_pages, ARRAY_SIZE(pages)), pages);
                for (i = 0; i < ret; i++) {
 
-                       if (set_private2)
+                       if (op & EXTENT_SET_PRIVATE2)
                                SetPagePrivate2(pages[i]);
 
                        if (pages[i] == locked_page) {
                                page_cache_release(pages[i]);
                                continue;
                        }
-                       if (clear_dirty)
+                       if (op & EXTENT_CLEAR_DIRTY)
                                clear_page_dirty_for_io(pages[i]);
-                       if (set_writeback)
+                       if (op & EXTENT_SET_WRITEBACK)
                                set_page_writeback(pages[i]);
-                       if (end_writeback)
+                       if (op & EXTENT_END_WRITEBACK)
                                end_page_writeback(pages[i]);
-                       if (unlock_pages)
+                       if (op & EXTENT_CLEAR_UNLOCK_PAGE)
                                unlock_page(pages[i]);
                        page_cache_release(pages[i]);
                }
@@ -2714,7 +2715,8 @@ int extent_invalidatepage(struct extent_io_tree *tree,
        lock_extent(tree, start, end, GFP_NOFS);
        wait_on_page_writeback(page);
        clear_extent_bit(tree, start, end,
-                        EXTENT_LOCKED | EXTENT_DIRTY | EXTENT_DELALLOC,
+                        EXTENT_LOCKED | EXTENT_DIRTY | EXTENT_DELALLOC |
+                        EXTENT_DO_ACCOUNTING,
                         1, 1, NULL, GFP_NOFS);
        return 0;
 }
index 4794ec8..36de250 100644 (file)
@@ -15,6 +15,7 @@
 #define EXTENT_BUFFER_FILLED (1 << 8)
 #define EXTENT_BOUNDARY (1 << 9)
 #define EXTENT_NODATASUM (1 << 10)
+#define EXTENT_DO_ACCOUNTING (1 << 11)
 #define EXTENT_IOBITS (EXTENT_LOCKED | EXTENT_WRITEBACK)
 
 /* flags for bio submission */
 #define EXTENT_BUFFER_BLOCKING 1
 #define EXTENT_BUFFER_DIRTY 2
 
+/* these are flags for extent_clear_unlock_delalloc */
+#define EXTENT_CLEAR_UNLOCK_PAGE 0x1
+#define EXTENT_CLEAR_UNLOCK     0x2
+#define EXTENT_CLEAR_DELALLOC   0x4
+#define EXTENT_CLEAR_DIRTY      0x8
+#define EXTENT_SET_WRITEBACK    0x10
+#define EXTENT_END_WRITEBACK    0x20
+#define EXTENT_SET_PRIVATE2     0x40
+#define EXTENT_CLEAR_ACCOUNTING  0x80
+
 /*
  * page->private values.  Every page that is controlled by the extent
  * map has page->private set to one.
@@ -288,10 +299,5 @@ int extent_range_uptodate(struct extent_io_tree *tree,
 int extent_clear_unlock_delalloc(struct inode *inode,
                                struct extent_io_tree *tree,
                                u64 start, u64 end, struct page *locked_page,
-                               int unlock_page,
-                               int clear_unlock,
-                               int clear_delalloc, int clear_dirty,
-                               int set_writeback,
-                               int end_writeback,
-                               int set_private2);
+                               unsigned long op);
 #endif
index f19e125..06550af 100644 (file)
@@ -878,7 +878,8 @@ again:
                        btrfs_put_ordered_extent(ordered);
 
                clear_extent_bits(&BTRFS_I(inode)->io_tree, start_pos,
-                                 last_pos - 1, EXTENT_DIRTY | EXTENT_DELALLOC,
+                                 last_pos - 1, EXTENT_DIRTY | EXTENT_DELALLOC |
+                                 EXTENT_DO_ACCOUNTING,
                                  GFP_NOFS);
                unlock_extent(&BTRFS_I(inode)->io_tree,
                              start_pos, last_pos - 1, GFP_NOFS);
@@ -1085,8 +1086,10 @@ out_nolock:
                                        btrfs_end_transaction(trans, root);
                                else
                                        btrfs_commit_transaction(trans, root);
-                       } else {
+                       } else if (ret != BTRFS_NO_LOG_SYNC) {
                                btrfs_commit_transaction(trans, root);
+                       } else {
+                               btrfs_end_transaction(trans, root);
                        }
                }
                if (file->f_flags & O_DIRECT) {
@@ -1136,6 +1139,13 @@ int btrfs_sync_file(struct file *file, struct dentry *dentry, int datasync)
        int ret = 0;
        struct btrfs_trans_handle *trans;
 
+
+       /* we wait first, since the writeback may change the inode */
+       root->log_batch++;
+       /* the VFS called filemap_fdatawrite for us */
+       btrfs_wait_ordered_range(inode, 0, (u64)-1);
+       root->log_batch++;
+
        /*
         * check the transaction that last modified this inode
         * and see if its already been committed
@@ -1143,6 +1153,11 @@ int btrfs_sync_file(struct file *file, struct dentry *dentry, int datasync)
        if (!BTRFS_I(inode)->last_trans)
                goto out;
 
+       /*
+        * if the last transaction that changed this file was before
+        * the current transaction, we can bail out now without any
+        * syncing
+        */
        mutex_lock(&root->fs_info->trans_mutex);
        if (BTRFS_I(inode)->last_trans <=
            root->fs_info->last_trans_committed) {
@@ -1152,13 +1167,6 @@ int btrfs_sync_file(struct file *file, struct dentry *dentry, int datasync)
        }
        mutex_unlock(&root->fs_info->trans_mutex);
 
-       root->log_batch++;
-       filemap_fdatawrite(inode->i_mapping);
-       btrfs_wait_ordered_range(inode, 0, (u64)-1);
-       root->log_batch++;
-
-       if (datasync && !(inode->i_state & I_DIRTY_PAGES))
-               goto out;
        /*
         * ok we haven't committed the transaction yet, lets do a commit
         */
@@ -1187,14 +1195,18 @@ int btrfs_sync_file(struct file *file, struct dentry *dentry, int datasync)
         */
        mutex_unlock(&dentry->d_inode->i_mutex);
 
-       if (ret > 0) {
-               ret = btrfs_commit_transaction(trans, root);
-       } else {
-               ret = btrfs_sync_log(trans, root);
-               if (ret == 0)
-                       ret = btrfs_end_transaction(trans, root);
-               else
+       if (ret != BTRFS_NO_LOG_SYNC) {
+               if (ret > 0) {
                        ret = btrfs_commit_transaction(trans, root);
+               } else {
+                       ret = btrfs_sync_log(trans, root);
+                       if (ret == 0)
+                               ret = btrfs_end_transaction(trans, root);
+                       else
+                               ret = btrfs_commit_transaction(trans, root);
+               }
+       } else {
+               ret = btrfs_end_transaction(trans, root);
        }
        mutex_lock(&dentry->d_inode->i_mutex);
 out:
index 112e5aa..dae12dc 100644 (file)
@@ -424,9 +424,12 @@ again:
                         * and free up our temp pages.
                         */
                        extent_clear_unlock_delalloc(inode,
-                                                    &BTRFS_I(inode)->io_tree,
-                                                    start, end, NULL, 1, 0,
-                                                    0, 1, 1, 1, 0);
+                            &BTRFS_I(inode)->io_tree,
+                            start, end, NULL,
+                            EXTENT_CLEAR_UNLOCK_PAGE | EXTENT_CLEAR_DIRTY |
+                            EXTENT_CLEAR_DELALLOC |
+                            EXTENT_CLEAR_ACCOUNTING |
+                            EXTENT_SET_WRITEBACK | EXTENT_END_WRITEBACK);
                        ret = 0;
                        goto free_pages_out;
                }
@@ -637,11 +640,14 @@ static noinline int submit_compressed_extents(struct inode *inode,
                 * clear dirty, set writeback and unlock the pages.
                 */
                extent_clear_unlock_delalloc(inode,
-                                            &BTRFS_I(inode)->io_tree,
-                                            async_extent->start,
-                                            async_extent->start +
-                                            async_extent->ram_size - 1,
-                                            NULL, 1, 1, 0, 1, 1, 0, 0);
+                               &BTRFS_I(inode)->io_tree,
+                               async_extent->start,
+                               async_extent->start +
+                               async_extent->ram_size - 1,
+                               NULL, EXTENT_CLEAR_UNLOCK_PAGE |
+                               EXTENT_CLEAR_UNLOCK |
+                               EXTENT_CLEAR_DELALLOC |
+                               EXTENT_CLEAR_DIRTY | EXTENT_SET_WRITEBACK);
 
                ret = btrfs_submit_compressed_write(inode,
                                    async_extent->start,
@@ -712,9 +718,15 @@ static noinline int cow_file_range(struct inode *inode,
                                            start, end, 0, NULL);
                if (ret == 0) {
                        extent_clear_unlock_delalloc(inode,
-                                                    &BTRFS_I(inode)->io_tree,
-                                                    start, end, NULL, 1, 1,
-                                                    1, 1, 1, 1, 0);
+                                    &BTRFS_I(inode)->io_tree,
+                                    start, end, NULL,
+                                    EXTENT_CLEAR_UNLOCK_PAGE |
+                                    EXTENT_CLEAR_UNLOCK |
+                                    EXTENT_CLEAR_DELALLOC |
+                                    EXTENT_CLEAR_ACCOUNTING |
+                                    EXTENT_CLEAR_DIRTY |
+                                    EXTENT_SET_WRITEBACK |
+                                    EXTENT_END_WRITEBACK);
                        *nr_written = *nr_written +
                             (end - start + PAGE_CACHE_SIZE) / PAGE_CACHE_SIZE;
                        *page_started = 1;
@@ -738,6 +750,8 @@ static noinline int cow_file_range(struct inode *inode,
        btrfs_drop_extent_cache(inode, start, start + num_bytes - 1, 0);
 
        while (disk_num_bytes > 0) {
+               unsigned long op;
+
                cur_alloc_size = min(disk_num_bytes, root->fs_info->max_extent);
                ret = btrfs_reserve_extent(trans, root, cur_alloc_size,
                                           root->sectorsize, 0, alloc_hint,
@@ -789,10 +803,13 @@ static noinline int cow_file_range(struct inode *inode,
                 * Do set the Private2 bit so we know this page was properly
                 * setup for writepage
                 */
+               op = unlock ? EXTENT_CLEAR_UNLOCK_PAGE : 0;
+               op |= EXTENT_CLEAR_UNLOCK | EXTENT_CLEAR_DELALLOC |
+                       EXTENT_SET_PRIVATE2;
+
                extent_clear_unlock_delalloc(inode, &BTRFS_I(inode)->io_tree,
                                             start, start + ram_size - 1,
-                                            locked_page, unlock, 1,
-                                            1, 0, 0, 0, 1);
+                                            locked_page, op);
                disk_num_bytes -= cur_alloc_size;
                num_bytes -= cur_alloc_size;
                alloc_hint = ins.objectid + ins.offset;
@@ -864,8 +881,8 @@ static int cow_file_range_async(struct inode *inode, struct page *locked_page,
        u64 cur_end;
        int limit = 10 * 1024 * 1042;
 
-       clear_extent_bit(&BTRFS_I(inode)->io_tree, start, end, EXTENT_LOCKED |
-                        EXTENT_DELALLOC, 1, 0, NULL, GFP_NOFS);
+       clear_extent_bit(&BTRFS_I(inode)->io_tree, start, end, EXTENT_LOCKED,
+                        1, 0, NULL, GFP_NOFS);
        while (start < end) {
                async_cow = kmalloc(sizeof(*async_cow), GFP_NOFS);
                async_cow->inode = inode;
@@ -1006,6 +1023,7 @@ next_slot:
 
                if (found_key.offset > cur_offset) {
                        extent_end = found_key.offset;
+                       extent_type = 0;
                        goto out_check;
                }
 
@@ -1112,8 +1130,10 @@ out_check:
                BUG_ON(ret);
 
                extent_clear_unlock_delalloc(inode, &BTRFS_I(inode)->io_tree,
-                                       cur_offset, cur_offset + num_bytes - 1,
-                                       locked_page, 1, 1, 1, 0, 0, 0, 1);
+                               cur_offset, cur_offset + num_bytes - 1,
+                               locked_page, EXTENT_CLEAR_UNLOCK_PAGE |
+                               EXTENT_CLEAR_UNLOCK | EXTENT_CLEAR_DELALLOC |
+                               EXTENT_SET_PRIVATE2);
                cur_offset = extent_end;
                if (cur_offset > end)
                        break;
@@ -1178,15 +1198,17 @@ static int btrfs_split_extent_hook(struct inode *inode,
                                        root->fs_info->max_extent);
 
                /*
-                * if we break a large extent up then leave delalloc_extents be,
-                * since we've already accounted for the large extent.
+                * if we break a large extent up then leave oustanding_extents
+                * be, since we've already accounted for the large extent.
                 */
                if (div64_u64(new_size + root->fs_info->max_extent - 1,
                              root->fs_info->max_extent) < num_extents)
                        return 0;
        }
 
-       BTRFS_I(inode)->delalloc_extents++;
+       spin_lock(&BTRFS_I(inode)->accounting_lock);
+       BTRFS_I(inode)->outstanding_extents++;
+       spin_unlock(&BTRFS_I(inode)->accounting_lock);
 
        return 0;
 }
@@ -1217,7 +1239,9 @@ static int btrfs_merge_extent_hook(struct inode *inode,
 
        /* we're not bigger than the max, unreserve the space and go */
        if (new_size <= root->fs_info->max_extent) {
-               BTRFS_I(inode)->delalloc_extents--;
+               spin_lock(&BTRFS_I(inode)->accounting_lock);
+               BTRFS_I(inode)->outstanding_extents--;
+               spin_unlock(&BTRFS_I(inode)->accounting_lock);
                return 0;
        }
 
@@ -1231,7 +1255,9 @@ static int btrfs_merge_extent_hook(struct inode *inode,
                      root->fs_info->max_extent) > num_extents)
                return 0;
 
-       BTRFS_I(inode)->delalloc_extents--;
+       spin_lock(&BTRFS_I(inode)->accounting_lock);
+       BTRFS_I(inode)->outstanding_extents--;
+       spin_unlock(&BTRFS_I(inode)->accounting_lock);
 
        return 0;
 }
@@ -1253,7 +1279,9 @@ static int btrfs_set_bit_hook(struct inode *inode, u64 start, u64 end,
        if (!(old & EXTENT_DELALLOC) && (bits & EXTENT_DELALLOC)) {
                struct btrfs_root *root = BTRFS_I(inode)->root;
 
-               BTRFS_I(inode)->delalloc_extents++;
+               spin_lock(&BTRFS_I(inode)->accounting_lock);
+               BTRFS_I(inode)->outstanding_extents++;
+               spin_unlock(&BTRFS_I(inode)->accounting_lock);
                btrfs_delalloc_reserve_space(root, inode, end - start + 1);
                spin_lock(&root->fs_info->delalloc_lock);
                BTRFS_I(inode)->delalloc_bytes += end - start + 1;
@@ -1281,8 +1309,12 @@ static int btrfs_clear_bit_hook(struct inode *inode,
        if ((state->state & EXTENT_DELALLOC) && (bits & EXTENT_DELALLOC)) {
                struct btrfs_root *root = BTRFS_I(inode)->root;
 
-               BTRFS_I(inode)->delalloc_extents--;
-               btrfs_unreserve_metadata_for_delalloc(root, inode, 1);
+               if (bits & EXTENT_DO_ACCOUNTING) {
+                       spin_lock(&BTRFS_I(inode)->accounting_lock);
+                       BTRFS_I(inode)->outstanding_extents--;
+                       spin_unlock(&BTRFS_I(inode)->accounting_lock);
+                       btrfs_unreserve_metadata_for_delalloc(root, inode, 1);
+               }
 
                spin_lock(&root->fs_info->delalloc_lock);
                if (state->end - state->start + 1 >
@@ -3000,12 +3032,22 @@ static int btrfs_truncate_page(struct address_space *mapping, loff_t from)
 
        if ((offset & (blocksize - 1)) == 0)
                goto out;
+       ret = btrfs_check_data_free_space(root, inode, PAGE_CACHE_SIZE);
+       if (ret)
+               goto out;
+
+       ret = btrfs_reserve_metadata_for_delalloc(root, inode, 1);
+       if (ret)
+               goto out;
 
        ret = -ENOMEM;
 again:
        page = grab_cache_page(mapping, index);
-       if (!page)
+       if (!page) {
+               btrfs_free_reserved_data_space(root, inode, PAGE_CACHE_SIZE);
+               btrfs_unreserve_metadata_for_delalloc(root, inode, 1);
                goto out;
+       }
 
        page_start = page_offset(page);
        page_end = page_start + PAGE_CACHE_SIZE - 1;
@@ -3038,6 +3080,10 @@ again:
                goto again;
        }
 
+       clear_extent_bits(&BTRFS_I(inode)->io_tree, page_start, page_end,
+                         EXTENT_DIRTY | EXTENT_DELALLOC | EXTENT_DO_ACCOUNTING,
+                         GFP_NOFS);
+
        ret = btrfs_set_extent_delalloc(inode, page_start, page_end);
        if (ret) {
                unlock_extent(io_tree, page_start, page_end, GFP_NOFS);
@@ -3056,6 +3102,9 @@ again:
        unlock_extent(io_tree, page_start, page_end, GFP_NOFS);
 
 out_unlock:
+       if (ret)
+               btrfs_free_reserved_data_space(root, inode, PAGE_CACHE_SIZE);
+       btrfs_unreserve_metadata_for_delalloc(root, inode, 1);
        unlock_page(page);
        page_cache_release(page);
 out:
@@ -3079,7 +3128,9 @@ int btrfs_cont_expand(struct inode *inode, loff_t size)
        if (size <= hole_start)
                return 0;
 
-       btrfs_truncate_page(inode->i_mapping, inode->i_size);
+       err = btrfs_truncate_page(inode->i_mapping, inode->i_size);
+       if (err)
+               return err;
 
        while (1) {
                struct btrfs_ordered_extent *ordered;
@@ -3448,6 +3499,7 @@ static noinline void init_btrfs_i(struct inode *inode)
        bi->generation = 0;
        bi->sequence = 0;
        bi->last_trans = 0;
+       bi->last_sub_trans = 0;
        bi->logged_trans = 0;
        bi->delalloc_bytes = 0;
        bi->reserved_bytes = 0;
@@ -3598,12 +3650,14 @@ static int btrfs_dentry_delete(struct dentry *dentry)
 {
        struct btrfs_root *root;
 
-       if (!dentry->d_inode)
-               return 0;
+       if (!dentry->d_inode && !IS_ROOT(dentry))
+               dentry = dentry->d_parent;
 
-       root = BTRFS_I(dentry->d_inode)->root;
-       if (btrfs_root_refs(&root->root_item) == 0)
-               return 1;
+       if (dentry->d_inode) {
+               root = BTRFS_I(dentry->d_inode)->root;
+               if (btrfs_root_refs(&root->root_item) == 0)
+                       return 1;
+       }
        return 0;
 }
 
@@ -4808,7 +4862,8 @@ static void btrfs_invalidatepage(struct page *page, unsigned long offset)
                 */
                clear_extent_bit(tree, page_start, page_end,
                                 EXTENT_DIRTY | EXTENT_DELALLOC |
-                                EXTENT_LOCKED, 1, 0, NULL, GFP_NOFS);
+                                EXTENT_LOCKED | EXTENT_DO_ACCOUNTING, 1, 0,
+                                NULL, GFP_NOFS);
                /*
                 * whoever cleared the private bit is responsible
                 * for the finish_ordered_io
@@ -4821,8 +4876,8 @@ static void btrfs_invalidatepage(struct page *page, unsigned long offset)
                lock_extent(tree, page_start, page_end, GFP_NOFS);
        }
        clear_extent_bit(tree, page_start, page_end,
-                EXTENT_LOCKED | EXTENT_DIRTY | EXTENT_DELALLOC,
-                1, 1, NULL, GFP_NOFS);
+                EXTENT_LOCKED | EXTENT_DIRTY | EXTENT_DELALLOC |
+                EXTENT_DO_ACCOUNTING, 1, 1, NULL, GFP_NOFS);
        __btrfs_releasepage(page, GFP_NOFS);
 
        ClearPageChecked(page);
@@ -4917,7 +4972,8 @@ again:
         * prepare_pages in the normal write path.
         */
        clear_extent_bits(&BTRFS_I(inode)->io_tree, page_start, page_end,
-                         EXTENT_DIRTY | EXTENT_DELALLOC, GFP_NOFS);
+                         EXTENT_DIRTY | EXTENT_DELALLOC | EXTENT_DO_ACCOUNTING,
+                         GFP_NOFS);
 
        ret = btrfs_set_extent_delalloc(inode, page_start, page_end);
        if (ret) {
@@ -4944,7 +5000,9 @@ again:
        set_page_dirty(page);
        SetPageUptodate(page);
 
-       BTRFS_I(inode)->last_trans = root->fs_info->generation + 1;
+       BTRFS_I(inode)->last_trans = root->fs_info->generation;
+       BTRFS_I(inode)->last_sub_trans = BTRFS_I(inode)->root->log_transid;
+
        unlock_extent(io_tree, page_start, page_end, GFP_NOFS);
 
 out_unlock:
@@ -4969,7 +5027,9 @@ static void btrfs_truncate(struct inode *inode)
        if (IS_APPEND(inode) || IS_IMMUTABLE(inode))
                return;
 
-       btrfs_truncate_page(inode->i_mapping, inode->i_size);
+       ret = btrfs_truncate_page(inode->i_mapping, inode->i_size);
+       if (ret)
+               return;
        btrfs_wait_ordered_range(inode, inode->i_size & (~mask), (u64)-1);
 
        trans = btrfs_start_transaction(root, 1);
@@ -5064,9 +5124,11 @@ struct inode *btrfs_alloc_inode(struct super_block *sb)
        if (!ei)
                return NULL;
        ei->last_trans = 0;
+       ei->last_sub_trans = 0;
        ei->logged_trans = 0;
-       ei->delalloc_extents = 0;
-       ei->delalloc_reserved_extents = 0;
+       ei->outstanding_extents = 0;
+       ei->reserved_extents = 0;
+       spin_lock_init(&ei->accounting_lock);
        btrfs_ordered_inode_tree_init(&ei->ordered_tree);
        INIT_LIST_HEAD(&ei->i_orphan);
        INIT_LIST_HEAD(&ei->ordered_operations);
@@ -5805,6 +5867,6 @@ static const struct inode_operations btrfs_symlink_inode_operations = {
        .removexattr    = btrfs_removexattr,
 };
 
-struct dentry_operations btrfs_dentry_operations = {
+const struct dentry_operations btrfs_dentry_operations = {
        .d_delete       = btrfs_dentry_delete,
 };
index 9a780c8..cdbb054 100644 (file)
@@ -830,6 +830,7 @@ out_up_write:
 out_unlock:
        mutex_unlock(&inode->i_mutex);
        if (!err) {
+               shrink_dcache_sb(root->fs_info->sb);
                btrfs_invalidate_inodes(dest);
                d_delete(dentry);
        }
@@ -1122,8 +1123,10 @@ static noinline long btrfs_ioctl_clone(struct file *file, unsigned long srcfd,
                                        datao += off - key.offset;
                                        datal -= off - key.offset;
                                }
-                               if (key.offset + datao + datal > off + len)
-                                       datal = off + len - key.offset - datao;
+
+                               if (key.offset + datal > off + len)
+                                       datal = off + len - key.offset;
+
                                /* disko == 0 means it's a hole */
                                if (!disko)
                                        datao = 0;
index 897fba8..5799bc4 100644 (file)
@@ -306,6 +306,12 @@ int btrfs_remove_ordered_extent(struct inode *inode,
        tree->last = NULL;
        set_bit(BTRFS_ORDERED_COMPLETE, &entry->flags);
 
+       spin_lock(&BTRFS_I(inode)->accounting_lock);
+       BTRFS_I(inode)->outstanding_extents--;
+       spin_unlock(&BTRFS_I(inode)->accounting_lock);
+       btrfs_unreserve_metadata_for_delalloc(BTRFS_I(inode)->root,
+                                             inode, 1);
+
        spin_lock(&BTRFS_I(inode)->root->fs_info->ordered_extent_lock);
        list_del_init(&entry->root_extent_list);
 
index 361ad32..cfcc93c 100644 (file)
@@ -3518,7 +3518,7 @@ int btrfs_relocate_block_group(struct btrfs_root *extent_root, u64 group_start)
        BUG_ON(!rc->block_group);
 
        btrfs_init_workers(&rc->workers, "relocate",
-                          fs_info->thread_pool_size);
+                          fs_info->thread_pool_size, NULL);
 
        rc->extent_root = extent_root;
        btrfs_prepare_block_group_relocation(extent_root, rc->block_group);
@@ -3701,7 +3701,7 @@ int btrfs_recover_relocation(struct btrfs_root *root)
        mapping_tree_init(&rc->reloc_root_tree);
        INIT_LIST_HEAD(&rc->reloc_roots);
        btrfs_init_workers(&rc->workers, "relocate",
-                          root->fs_info->thread_pool_size);
+                          root->fs_info->thread_pool_size, NULL);
        rc->extent_root = root->fs_info->extent_root;
 
        set_reloc_control(rc);
index 9de9b22..752a546 100644 (file)
@@ -66,7 +66,8 @@ enum {
        Opt_degraded, Opt_subvol, Opt_device, Opt_nodatasum, Opt_nodatacow,
        Opt_max_extent, Opt_max_inline, Opt_alloc_start, Opt_nobarrier,
        Opt_ssd, Opt_nossd, Opt_ssd_spread, Opt_thread_pool, Opt_noacl,
-       Opt_compress, Opt_notreelog, Opt_ratio, Opt_flushoncommit, Opt_err,
+       Opt_compress, Opt_notreelog, Opt_ratio, Opt_flushoncommit,
+       Opt_discard, Opt_err,
 };
 
 static match_table_t tokens = {
@@ -88,6 +89,7 @@ static match_table_t tokens = {
        {Opt_notreelog, "notreelog"},
        {Opt_flushoncommit, "flushoncommit"},
        {Opt_ratio, "metadata_ratio=%d"},
+       {Opt_discard, "discard"},
        {Opt_err, NULL},
 };
 
@@ -257,6 +259,9 @@ int btrfs_parse_options(struct btrfs_root *root, char *options)
                                       info->metadata_ratio);
                        }
                        break;
+               case Opt_discard:
+                       btrfs_set_opt(info->mount_opt, DISCARD);
+                       break;
                default:
                        break;
                }
@@ -344,7 +349,7 @@ static int btrfs_fill_super(struct super_block *sb,
        sb->s_export_op = &btrfs_export_ops;
        sb->s_xattr = btrfs_xattr_handlers;
        sb->s_time_gran = 1;
-#ifdef CONFIG_BTRFS_POSIX_ACL
+#ifdef CONFIG_BTRFS_FS_POSIX_ACL
        sb->s_flags |= MS_POSIXACL;
 #endif
 
index 0b8f36d..bca82a4 100644 (file)
@@ -344,10 +344,10 @@ int btrfs_end_transaction_throttle(struct btrfs_trans_handle *trans,
 /*
  * when btree blocks are allocated, they have some corresponding bits set for
  * them in one of two extent_io trees.  This is used to make sure all of
- * those extents are on disk for transaction or log commit
+ * those extents are sent to disk but does not wait on them
  */
-int btrfs_write_and_wait_marked_extents(struct btrfs_root *root,
-                                       struct extent_io_tree *dirty_pages)
+int btrfs_write_marked_extents(struct btrfs_root *root,
+                              struct extent_io_tree *dirty_pages)
 {
        int ret;
        int err = 0;
@@ -394,6 +394,29 @@ int btrfs_write_and_wait_marked_extents(struct btrfs_root *root,
                        page_cache_release(page);
                }
        }
+       if (err)
+               werr = err;
+       return werr;
+}
+
+/*
+ * when btree blocks are allocated, they have some corresponding bits set for
+ * them in one of two extent_io trees.  This is used to make sure all of
+ * those extents are on disk for transaction or log commit.  We wait
+ * on all the pages and clear them from the dirty pages state tree
+ */
+int btrfs_wait_marked_extents(struct btrfs_root *root,
+                             struct extent_io_tree *dirty_pages)
+{
+       int ret;
+       int err = 0;
+       int werr = 0;
+       struct page *page;
+       struct inode *btree_inode = root->fs_info->btree_inode;
+       u64 start = 0;
+       u64 end;
+       unsigned long index;
+
        while (1) {
                ret = find_first_extent_bit(dirty_pages, 0, &start, &end,
                                            EXTENT_DIRTY);
@@ -424,6 +447,22 @@ int btrfs_write_and_wait_marked_extents(struct btrfs_root *root,
        return werr;
 }
 
+/*
+ * when btree blocks are allocated, they have some corresponding bits set for
+ * them in one of two extent_io trees.  This is used to make sure all of
+ * those extents are on disk for transaction or log commit
+ */
+int btrfs_write_and_wait_marked_extents(struct btrfs_root *root,
+                                       struct extent_io_tree *dirty_pages)
+{
+       int ret;
+       int ret2;
+
+       ret = btrfs_write_marked_extents(root, dirty_pages);
+       ret2 = btrfs_wait_marked_extents(root, dirty_pages);
+       return ret || ret2;
+}
+
 int btrfs_write_and_wait_transaction(struct btrfs_trans_handle *trans,
                                     struct btrfs_root *root)
 {
index 663c674..d4e3e7a 100644 (file)
@@ -79,6 +79,7 @@ static inline void btrfs_set_inode_last_trans(struct btrfs_trans_handle *trans,
                                              struct inode *inode)
 {
        BTRFS_I(inode)->last_trans = trans->transaction->transid;
+       BTRFS_I(inode)->last_sub_trans = BTRFS_I(inode)->root->log_transid;
 }
 
 int btrfs_end_transaction(struct btrfs_trans_handle *trans,
@@ -107,5 +108,9 @@ int btrfs_record_root_in_trans(struct btrfs_trans_handle *trans,
                                struct btrfs_root *root);
 int btrfs_write_and_wait_marked_extents(struct btrfs_root *root,
                                        struct extent_io_tree *dirty_pages);
+int btrfs_write_marked_extents(struct btrfs_root *root,
+                                       struct extent_io_tree *dirty_pages);
+int btrfs_wait_marked_extents(struct btrfs_root *root,
+                                       struct extent_io_tree *dirty_pages);
 int btrfs_transaction_in_commit(struct btrfs_fs_info *info);
 #endif
index 7827841..741666a 100644 (file)
@@ -137,11 +137,20 @@ static int start_log_trans(struct btrfs_trans_handle *trans,
 
        mutex_lock(&root->log_mutex);
        if (root->log_root) {
+               if (!root->log_start_pid) {
+                       root->log_start_pid = current->pid;
+                       root->log_multiple_pids = false;
+               } else if (root->log_start_pid != current->pid) {
+                       root->log_multiple_pids = true;
+               }
+
                root->log_batch++;
                atomic_inc(&root->log_writers);
                mutex_unlock(&root->log_mutex);
                return 0;
        }
+       root->log_multiple_pids = false;
+       root->log_start_pid = current->pid;
        mutex_lock(&root->fs_info->tree_log_mutex);
        if (!root->fs_info->log_root_tree) {
                ret = btrfs_init_log_root_tree(trans, root->fs_info);
@@ -1971,6 +1980,7 @@ int btrfs_sync_log(struct btrfs_trans_handle *trans,
        int ret;
        struct btrfs_root *log = root->log_root;
        struct btrfs_root *log_root_tree = root->fs_info->log_root_tree;
+       u64 log_transid = 0;
 
        mutex_lock(&root->log_mutex);
        index1 = root->log_transid % 2;
@@ -1987,10 +1997,11 @@ int btrfs_sync_log(struct btrfs_trans_handle *trans,
 
        while (1) {
                unsigned long batch = root->log_batch;
-               mutex_unlock(&root->log_mutex);
-               schedule_timeout_uninterruptible(1);
-               mutex_lock(&root->log_mutex);
-
+               if (root->log_multiple_pids) {
+                       mutex_unlock(&root->log_mutex);
+                       schedule_timeout_uninterruptible(1);
+                       mutex_lock(&root->log_mutex);
+               }
                wait_for_writer(trans, root);
                if (batch == root->log_batch)
                        break;
@@ -2003,14 +2014,19 @@ int btrfs_sync_log(struct btrfs_trans_handle *trans,
                goto out;
        }
 
-       ret = btrfs_write_and_wait_marked_extents(log, &log->dirty_log_pages);
+       /* we start IO on  all the marked extents here, but we don't actually
+        * wait for them until later.
+        */
+       ret = btrfs_write_marked_extents(log, &log->dirty_log_pages);
        BUG_ON(ret);
 
        btrfs_set_root_node(&log->root_item, log->node);
 
        root->log_batch = 0;
+       log_transid = root->log_transid;
        root->log_transid++;
        log->log_transid = root->log_transid;
+       root->log_start_pid = 0;
        smp_mb();
        /*
         * log tree has been flushed to disk, new modifications of
@@ -2036,6 +2052,7 @@ int btrfs_sync_log(struct btrfs_trans_handle *trans,
 
        index2 = log_root_tree->log_transid % 2;
        if (atomic_read(&log_root_tree->log_commit[index2])) {
+               btrfs_wait_marked_extents(log, &log->dirty_log_pages);
                wait_log_commit(trans, log_root_tree,
                                log_root_tree->log_transid);
                mutex_unlock(&log_root_tree->log_mutex);
@@ -2055,6 +2072,7 @@ int btrfs_sync_log(struct btrfs_trans_handle *trans,
         * check the full commit flag again
         */
        if (root->fs_info->last_trans_log_full_commit == trans->transid) {
+               btrfs_wait_marked_extents(log, &log->dirty_log_pages);
                mutex_unlock(&log_root_tree->log_mutex);
                ret = -EAGAIN;
                goto out_wake_log_root;
@@ -2063,6 +2081,7 @@ int btrfs_sync_log(struct btrfs_trans_handle *trans,
        ret = btrfs_write_and_wait_marked_extents(log_root_tree,
                                &log_root_tree->dirty_log_pages);
        BUG_ON(ret);
+       btrfs_wait_marked_extents(log, &log->dirty_log_pages);
 
        btrfs_set_super_log_root(&root->fs_info->super_for_commit,
                                log_root_tree->node->start);
@@ -2082,9 +2101,14 @@ int btrfs_sync_log(struct btrfs_trans_handle *trans,
         * the running transaction open, so a full commit can't hop
         * in and cause problems either.
         */
-       write_ctree_super(trans, root->fs_info->tree_root, 2);
+       write_ctree_super(trans, root->fs_info->tree_root, 1);
        ret = 0;
 
+       mutex_lock(&root->log_mutex);
+       if (root->last_log_commit < log_transid)
+               root->last_log_commit = log_transid;
+       mutex_unlock(&root->log_mutex);
+
 out_wake_log_root:
        atomic_set(&log_root_tree->log_commit[index2], 0);
        smp_mb();
@@ -2852,6 +2876,21 @@ out:
        return ret;
 }
 
+static int inode_in_log(struct btrfs_trans_handle *trans,
+                struct inode *inode)
+{
+       struct btrfs_root *root = BTRFS_I(inode)->root;
+       int ret = 0;
+
+       mutex_lock(&root->log_mutex);
+       if (BTRFS_I(inode)->logged_trans == trans->transid &&
+           BTRFS_I(inode)->last_sub_trans <= root->last_log_commit)
+               ret = 1;
+       mutex_unlock(&root->log_mutex);
+       return ret;
+}
+
+
 /*
  * helper function around btrfs_log_inode to make sure newly created
  * parent directories also end up in the log.  A minimal inode and backref
@@ -2891,6 +2930,11 @@ int btrfs_log_inode_parent(struct btrfs_trans_handle *trans,
        if (ret)
                goto end_no_trans;
 
+       if (inode_in_log(trans, inode)) {
+               ret = BTRFS_NO_LOG_SYNC;
+               goto end_no_trans;
+       }
+
        start_log_trans(trans, root);
 
        ret = btrfs_log_inode(trans, root, inode, inode_only);
index d09c760..0776eac 100644 (file)
@@ -19,6 +19,9 @@
 #ifndef __TREE_LOG_
 #define __TREE_LOG_
 
+/* return value for btrfs_log_dentry_safe that means we don't need to log it at all */
+#define BTRFS_NO_LOG_SYNC 256
+
 int btrfs_sync_log(struct btrfs_trans_handle *trans,
                   struct btrfs_root *root);
 int btrfs_free_log(struct btrfs_trans_handle *trans, struct btrfs_root *root);
index b0fc93f..b6dd596 100644 (file)
@@ -260,7 +260,7 @@ err:
  * attributes are handled directly.
  */
 struct xattr_handler *btrfs_xattr_handlers[] = {
-#ifdef CONFIG_BTRFS_POSIX_ACL
+#ifdef CONFIG_BTRFS_FS_POSIX_ACL
        &btrfs_xattr_acl_access_handler,
        &btrfs_xattr_acl_default_handler,
 #endif
index 43003e0..b090980 100644 (file)
@@ -1577,7 +1577,8 @@ cifs_get_tcp_session(struct smb_vol *volume_info)
 
 out_err:
        if (tcp_ses) {
-               kfree(tcp_ses->hostname);
+               if (!IS_ERR(tcp_ses->hostname))
+                       kfree(tcp_ses->hostname);
                if (tcp_ses->ssocket)
                        sock_release(tcp_ses->ssocket);
                kfree(tcp_ses);
index 240cef1..70736eb 100644 (file)
@@ -316,6 +316,10 @@ int dlm_lowcomms_connect_node(int nodeid)
 {
        struct connection *con;
 
+       /* with sctp there's no connecting without sending */
+       if (dlm_config.ci_protocol != 0)
+               return 0;
+
        if (nodeid == dlm_our_nodeid())
                return 0;
 
@@ -455,9 +459,9 @@ static void process_sctp_notification(struct connection *con,
                        int prim_len, ret;
                        int addr_len;
                        struct connection *new_con;
-                       struct file *file;
                        sctp_peeloff_arg_t parg;
                        int parglen = sizeof(parg);
+                       int err;
 
                        /*
                         * We get this before any data for an association.
@@ -512,19 +516,22 @@ static void process_sctp_notification(struct connection *con,
                        ret = kernel_getsockopt(con->sock, IPPROTO_SCTP,
                                                SCTP_SOCKOPT_PEELOFF,
                                                (void *)&parg, &parglen);
-                       if (ret) {
+                       if (ret < 0) {
                                log_print("Can't peel off a socket for "
-                                         "connection %d to node %d: err=%d\n",
+                                         "connection %d to node %d: err=%d",
                                          parg.associd, nodeid, ret);
+                               return;
+                       }
+                       new_con->sock = sockfd_lookup(parg.sd, &err);
+                       if (!new_con->sock) {
+                               log_print("sockfd_lookup error %d", err);
+                               return;
                        }
-                       file = fget(parg.sd);
-                       new_con->sock = SOCKET_I(file->f_dentry->d_inode);
                        add_sock(new_con->sock, new_con);
-                       fput(file);
-                       put_unused_fd(parg.sd);
+                       sockfd_put(new_con->sock);
 
-                       log_print("got new/restarted association %d nodeid %d",
-                                (int)sn->sn_assoc_change.sac_assoc_id, nodeid);
+                       log_print("connecting to %d sctp association %d",
+                                nodeid, (int)sn->sn_assoc_change.sac_assoc_id);
 
                        /* Send any pending writes */
                        clear_bit(CF_CONNECT_PENDING, &new_con->flags);
@@ -837,8 +844,6 @@ static void sctp_init_assoc(struct connection *con)
        if (con->retries++ > MAX_CONNECT_RETRIES)
                return;
 
-       log_print("Initiating association with node %d", con->nodeid);
-
        if (nodeid_to_addr(con->nodeid, (struct sockaddr *)&rem_addr)) {
                log_print("no address for nodeid %d", con->nodeid);
                return;
@@ -855,11 +860,14 @@ static void sctp_init_assoc(struct connection *con)
        outmessage.msg_flags = MSG_EOR;
 
        spin_lock(&con->writequeue_lock);
-       e = list_entry(con->writequeue.next, struct writequeue_entry,
-                      list);
 
-       BUG_ON((struct list_head *) e == &con->writequeue);
+       if (list_empty(&con->writequeue)) {
+               spin_unlock(&con->writequeue_lock);
+               log_print("writequeue empty for nodeid %d", con->nodeid);
+               return;
+       }
 
+       e = list_first_entry(&con->writequeue, struct writequeue_entry, list);
        len = e->len;
        offset = e->offset;
        spin_unlock(&con->writequeue_lock);
index 8aadb99..1cd6d9d 100644 (file)
@@ -1,8 +1,9 @@
 config ECRYPT_FS
        tristate "eCrypt filesystem layer support (EXPERIMENTAL)"
-       depends on EXPERIMENTAL && KEYS && NET
+       depends on EXPERIMENTAL && KEYS && CRYPTO
        select CRYPTO_ECB
        select CRYPTO_CBC
+       select CRYPTO_MD5
        help
          Encrypted filesystem that operates on the VFS layer.  See
          <file:Documentation/filesystems/ecryptfs.txt> to learn more about
index 101fe4c..c6ac85d 100644 (file)
@@ -35,6 +35,7 @@
 #include <linux/key.h>
 #include <linux/parser.h>
 #include <linux/fs_stack.h>
+#include <linux/ima.h>
 #include "ecryptfs_kernel.h"
 
 /**
@@ -118,6 +119,7 @@ int ecryptfs_init_persistent_file(struct dentry *ecryptfs_dentry)
        const struct cred *cred = current_cred();
        struct ecryptfs_inode_info *inode_info =
                ecryptfs_inode_to_private(ecryptfs_dentry->d_inode);
+       int opened_lower_file = 0;
        int rc = 0;
 
        mutex_lock(&inode_info->lower_file_mutex);
@@ -134,9 +136,12 @@ int ecryptfs_init_persistent_file(struct dentry *ecryptfs_dentry)
                               "for lower_dentry [0x%p] and lower_mnt [0x%p]; "
                               "rc = [%d]\n", lower_dentry, lower_mnt, rc);
                        inode_info->lower_file = NULL;
-               }
+               } else
+                       opened_lower_file = 1;
        }
        mutex_unlock(&inode_info->lower_file_mutex);
+       if (opened_lower_file)
+               ima_counts_get(inode_info->lower_file);
        return rc;
 }
 
index 72743d3..7a520a8 100644 (file)
@@ -2321,7 +2321,18 @@ static int ext3_commit_super(struct super_block *sb,
 
        if (!sbh)
                return error;
-       es->s_wtime = cpu_to_le32(get_seconds());
+       /*
+        * If the file system is mounted read-only, don't update the
+        * superblock write time.  This avoids updating the superblock
+        * write time when we are mounting the root file system
+        * read/only but we need to replay the journal; at that point,
+        * for people who are east of GMT and who make their clock
+        * tick in localtime for Windows bug-for-bug compatibility,
+        * the clock is set in the future, and this will cause e2fsck
+        * to complain and force a full file system check.
+        */
+       if (!(sb->s_flags & MS_RDONLY))
+               es->s_wtime = cpu_to_le32(get_seconds());
        es->s_free_blocks_count = cpu_to_le32(ext3_count_free_blocks(sb));
        es->s_free_inodes_count = cpu_to_le32(ext3_count_free_inodes(sb));
        BUFFER_TRACE(sbh, "marking dirty");
index 984ca0c..00d153f 100644 (file)
@@ -743,6 +743,7 @@ struct ext4_inode_info {
 #define EXT4_MOUNT_QUOTA               0x80000 /* Some quota option set */
 #define EXT4_MOUNT_USRQUOTA            0x100000 /* "old" user quota */
 #define EXT4_MOUNT_GRPQUOTA            0x200000 /* "old" group quota */
+#define EXT4_MOUNT_JOURNAL_CHECKSUM    0x800000 /* Journal checksums */
 #define EXT4_MOUNT_JOURNAL_ASYNC_COMMIT        0x1000000 /* Journal Async Commit */
 #define EXT4_MOUNT_I_VERSION            0x2000000 /* i_version support */
 #define EXT4_MOUNT_DELALLOC            0x8000000 /* Delalloc support */
index 312211e..d4ca92a 100644 (file)
@@ -1300,9 +1300,11 @@ static int parse_options(char *options, struct super_block *sb,
                        *journal_devnum = option;
                        break;
                case Opt_journal_checksum:
-                       break;  /* Kept for backwards compatibility */
+                       set_opt(sbi->s_mount_opt, JOURNAL_CHECKSUM);
+                       break;
                case Opt_journal_async_commit:
                        set_opt(sbi->s_mount_opt, JOURNAL_ASYNC_COMMIT);
+                       set_opt(sbi->s_mount_opt, JOURNAL_CHECKSUM);
                        break;
                case Opt_noload:
                        set_opt(sbi->s_mount_opt, NOLOAD);
@@ -2759,14 +2761,20 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
                goto failed_mount4;
        }
 
-       jbd2_journal_set_features(sbi->s_journal,
-                                 JBD2_FEATURE_COMPAT_CHECKSUM, 0, 0);
-       if (test_opt(sb, JOURNAL_ASYNC_COMMIT))
-               jbd2_journal_set_features(sbi->s_journal, 0, 0,
+       if (test_opt(sb, JOURNAL_ASYNC_COMMIT)) {
+               jbd2_journal_set_features(sbi->s_journal,
+                               JBD2_FEATURE_COMPAT_CHECKSUM, 0,
                                JBD2_FEATURE_INCOMPAT_ASYNC_COMMIT);
-       else
+       } else if (test_opt(sb, JOURNAL_CHECKSUM)) {
+               jbd2_journal_set_features(sbi->s_journal,
+                               JBD2_FEATURE_COMPAT_CHECKSUM, 0, 0);
                jbd2_journal_clear_features(sbi->s_journal, 0, 0,
                                JBD2_FEATURE_INCOMPAT_ASYNC_COMMIT);
+       } else {
+               jbd2_journal_clear_features(sbi->s_journal,
+                               JBD2_FEATURE_COMPAT_CHECKSUM, 0,
+                               JBD2_FEATURE_INCOMPAT_ASYNC_COMMIT);
+       }
 
        /* We have now updated the journal if required, so we can
         * validate the data journaling mode. */
index f313314..87e1290 100644 (file)
--- a/fs/file.c
+++ b/fs/file.c
@@ -10,6 +10,7 @@
 #include <linux/fs.h>
 #include <linux/mm.h>
 #include <linux/time.h>
+#include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/vmalloc.h>
 #include <linux/file.h>
index 9b9d639..052f214 100644 (file)
@@ -58,6 +58,11 @@ struct hfs_btree *hfs_btree_open(struct super_block *sb, u32 id, btree_keycmp ke
        }
        unlock_new_inode(tree->inode);
 
+       if (!HFS_I(tree->inode)->first_blocks) {
+               printk(KERN_ERR "hfs: invalid btree extent records (0 size).\n");
+               goto free_inode;
+       }
+
        mapping = tree->inode->i_mapping;
        page = read_mapping_page(mapping, 0, NULL);
        if (IS_ERR(page))
index 175d08e..bed78ac 100644 (file)
@@ -99,6 +99,10 @@ int hfsplus_read_wrapper(struct super_block *sb)
 
        if (hfsplus_get_last_session(sb, &part_start, &part_size))
                return -EINVAL;
+       if ((u64)part_start + part_size > 0x100000000ULL) {
+               pr_err("hfs: volumes larger than 2TB are not supported yet\n");
+               return -EINVAL;
+       }
        while (1) {
                bh = sb_bread512(sb, part_start + HFSPLUS_VOLHEAD_SECTOR, vhdr);
                if (!bh)
index 63976c0..99ea196 100644 (file)
@@ -1180,7 +1180,7 @@ static int nfs4_init_client(struct nfs_client *clp,
                                      1, flags & NFS_MOUNT_NORESVPORT);
        if (error < 0)
                goto error;
-       memcpy(clp->cl_ipaddr, ip_addr, sizeof(clp->cl_ipaddr));
+       strlcpy(clp->cl_ipaddr, ip_addr, sizeof(clp->cl_ipaddr));
 
        error = nfs_idmap_new(clp);
        if (error < 0) {
index 32062c3..7cb2985 100644 (file)
@@ -1536,6 +1536,8 @@ nfs_link(struct dentry *old_dentry, struct inode *dir, struct dentry *dentry)
                old_dentry->d_parent->d_name.name, old_dentry->d_name.name,
                dentry->d_parent->d_name.name, dentry->d_name.name);
 
+       nfs_inode_return_delegation(inode);
+
        d_drop(dentry);
        error = NFS_PROTO(dir)->link(inode, dir, &dentry->d_name);
        if (error == 0) {
index 6c32100..e1d415e 100644 (file)
@@ -457,6 +457,7 @@ static void nfs_direct_write_reschedule(struct nfs_direct_req *dreq)
        };
        struct rpc_task_setup task_setup_data = {
                .rpc_client = NFS_CLIENT(inode),
+               .rpc_message = &msg,
                .callback_ops = &nfs_write_direct_ops,
                .workqueue = nfsiod_workqueue,
                .flags = RPC_TASK_ASYNC,
index 2636c26..fa3408f 100644 (file)
@@ -121,7 +121,7 @@ static struct vfsmount *try_location(struct nfs_clone_mount *mountdata,
 
        mnt_path = nfs4_pathname_string(&location->rootpath, page2, PAGE_SIZE);
        if (IS_ERR(mnt_path))
-               return mnt;
+               return ERR_CAST(mnt_path);
        mountdata->mnt_path = mnt_path;
        maxbuflen = mnt_path - 1 - page2;
 
@@ -132,15 +132,15 @@ static struct vfsmount *try_location(struct nfs_clone_mount *mountdata,
                if (buf->len <= 0 || buf->len >= maxbuflen)
                        continue;
 
-               mountdata->addr = (struct sockaddr *)&addr;
-
                if (memchr(buf->data, IPV6_SCOPE_DELIMITER, buf->len))
                        continue;
-               mountdata->addrlen = nfs_parse_server_name(buf->data,
-                               buf->len,
-                               mountdata->addr, mountdata->addrlen);
+
+               mountdata->addrlen = nfs_parse_server_name(buf->data, buf->len,
+                               (struct sockaddr *)&addr, sizeof(addr));
                if (mountdata->addrlen == 0)
                        continue;
+
+               mountdata->addr = (struct sockaddr *)&addr;
                rpc_set_port(mountdata->addr, NFS_PORT);
 
                memcpy(page2, buf->data, buf->len);
index ed7c269..ff37454 100644 (file)
@@ -72,12 +72,17 @@ static int _nfs4_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle,
 /* Prevent leaks of NFSv4 errors into userland */
 static int nfs4_map_errors(int err)
 {
-       if (err < -1000) {
+       if (err >= -1000)
+               return err;
+       switch (err) {
+       case -NFS4ERR_RESOURCE:
+               return -EREMOTEIO;
+       default:
                dprintk("%s could not handle NFSv4 error %d\n",
                                __func__, -err);
-               return -EIO;
+               break;
        }
-       return err;
+       return -EIO;
 }
 
 /*
@@ -3060,9 +3065,6 @@ static void nfs4_renew_done(struct rpc_task *task, void *data)
        if (time_before(clp->cl_last_renewal,timestamp))
                clp->cl_last_renewal = timestamp;
        spin_unlock(&clp->cl_lock);
-       dprintk("%s calling put_rpccred on rpc_cred %p\n", __func__,
-                               task->tk_msg.rpc_cred);
-       put_rpccred(task->tk_msg.rpc_cred);
 }
 
 static const struct rpc_call_ops nfs4_renew_ops = {
@@ -4877,7 +4879,6 @@ void nfs41_sequence_call_done(struct rpc_task *task, void *data)
        nfs41_sequence_free_slot(clp, task->tk_msg.rpc_resp);
        dprintk("%s rpc_cred %p\n", __func__, task->tk_msg.rpc_cred);
 
-       put_rpccred(task->tk_msg.rpc_cred);
        kfree(task->tk_msg.rpc_argp);
        kfree(task->tk_msg.rpc_resp);
 
index e27c6ce..0156c01 100644 (file)
@@ -127,12 +127,6 @@ nfs4_schedule_state_renewal(struct nfs_client *clp)
 }
 
 void
-nfs4_renewd_prepare_shutdown(struct nfs_server *server)
-{
-       cancel_delayed_work(&server->nfs_client->cl_renewd);
-}
-
-void
 nfs4_kill_renewd(struct nfs_client *clp)
 {
        cancel_delayed_work_sync(&clp->cl_renewd);
index 83ad47c..20b4e30 100644 (file)
@@ -5681,7 +5681,6 @@ static struct {
        { NFS4ERR_SERVERFAULT,  -ESERVERFAULT   },
        { NFS4ERR_BADTYPE,      -EBADTYPE       },
        { NFS4ERR_LOCKED,       -EAGAIN         },
-       { NFS4ERR_RESOURCE,     -EREMOTEIO      },
        { NFS4ERR_SYMLINK,      -ELOOP          },
        { NFS4ERR_OP_ILLEGAL,   -EOPNOTSUPP     },
        { NFS4ERR_DEADLOCK,     -EDEADLK        },
index 29786d3..90be551 100644 (file)
@@ -728,22 +728,24 @@ static void nfs_umount_begin(struct super_block *sb)
        unlock_kernel();
 }
 
-static struct nfs_parsed_mount_data *nfs_alloc_parsed_mount_data(int flags)
+static struct nfs_parsed_mount_data *nfs_alloc_parsed_mount_data(unsigned int version)
 {
        struct nfs_parsed_mount_data *data;
 
        data = kzalloc(sizeof(*data), GFP_KERNEL);
        if (data) {
-               data->flags             = flags;
                data->rsize             = NFS_MAX_FILE_IO_SIZE;
                data->wsize             = NFS_MAX_FILE_IO_SIZE;
                data->acregmin          = NFS_DEF_ACREGMIN;
                data->acregmax          = NFS_DEF_ACREGMAX;
                data->acdirmin          = NFS_DEF_ACDIRMIN;
                data->acdirmax          = NFS_DEF_ACDIRMAX;
+               data->mount_server.port = NFS_UNSPEC_PORT;
                data->nfs_server.port   = NFS_UNSPEC_PORT;
+               data->nfs_server.protocol = XPRT_TRANSPORT_TCP;
                data->auth_flavors[0]   = RPC_AUTH_UNIX;
                data->auth_flavor_len   = 1;
+               data->version           = version;
                data->minorversion      = 0;
        }
        return data;
@@ -776,15 +778,13 @@ static int nfs_verify_server_address(struct sockaddr *addr)
  * Select between a default port value and a user-specified port value.
  * If a zero value is set, then autobind will be used.
  */
-static void nfs_set_default_port(struct sockaddr *sap, const int parsed_port,
+static void nfs_set_port(struct sockaddr *sap, int *port,
                                 const unsigned short default_port)
 {
-       unsigned short port = default_port;
+       if (*port == NFS_UNSPEC_PORT)
+               *port = default_port;
 
-       if (parsed_port != NFS_UNSPEC_PORT)
-               port = parsed_port;
-
-       rpc_set_port(sap, port);
+       rpc_set_port(sap, *port);
 }
 
 /*
@@ -1253,6 +1253,7 @@ static int nfs_parse_mount_options(char *raw,
                        default:
                                dfprintk(MOUNT, "NFS:   unrecognized "
                                                "transport protocol\n");
+                               kfree(string);
                                return 0;
                        }
                        break;
@@ -1475,7 +1476,7 @@ static int nfs_try_mount(struct nfs_parsed_mount_data *args,
                args->mount_server.addrlen = args->nfs_server.addrlen;
        }
        request.salen = args->mount_server.addrlen;
-       nfs_set_default_port(request.sap, args->mount_server.port, 0);
+       nfs_set_port(request.sap, &args->mount_server.port, 0);
 
        /*
         * Now ask the mount server to map our export path
@@ -1711,8 +1712,6 @@ static int nfs_validate_mount_data(void *options,
 
                if (!(data->flags & NFS_MOUNT_TCP))
                        args->nfs_server.protocol = XPRT_TRANSPORT_UDP;
-               else
-                       args->nfs_server.protocol = XPRT_TRANSPORT_TCP;
                /* N.B. caller will free nfs_server.hostname in all cases */
                args->nfs_server.hostname = kstrdup(data->hostname, GFP_KERNEL);
                args->namlen            = data->namlen;
@@ -1767,7 +1766,7 @@ static int nfs_validate_mount_data(void *options,
                        goto out_v4_not_compiled;
 #endif
 
-               nfs_set_default_port(sap, args->nfs_server.port, 0);
+               nfs_set_port(sap, &args->nfs_server.port, 0);
 
                nfs_set_mount_transport_protocol(args);
 
@@ -1848,9 +1847,10 @@ nfs_compare_remount_data(struct nfs_server *nfss,
            data->acdirmin != nfss->acdirmin / HZ ||
            data->acdirmax != nfss->acdirmax / HZ ||
            data->timeo != (10U * nfss->client->cl_timeout->to_initval / HZ) ||
+           data->nfs_server.port != nfss->port ||
            data->nfs_server.addrlen != nfss->nfs_client->cl_addrlen ||
-           memcmp(&data->nfs_server.address, &nfss->nfs_client->cl_addr,
-                  data->nfs_server.addrlen) != 0)
+           !rpc_cmp_addr((struct sockaddr *)&data->nfs_server.address,
+                         (struct sockaddr *)&nfss->nfs_client->cl_addr))
                return -EINVAL;
 
        return 0;
@@ -1893,6 +1893,7 @@ nfs_remount(struct super_block *sb, int *flags, char *raw_data)
        data->acdirmin = nfss->acdirmin / HZ;
        data->acdirmax = nfss->acdirmax / HZ;
        data->timeo = 10U * nfss->client->cl_timeout->to_initval / HZ;
+       data->nfs_server.port = nfss->port;
        data->nfs_server.addrlen = nfss->nfs_client->cl_addrlen;
        memcpy(&data->nfs_server.address, &nfss->nfs_client->cl_addr,
                data->nfs_server.addrlen);
@@ -2106,7 +2107,7 @@ static int nfs_get_sb(struct file_system_type *fs_type,
        };
        int error = -ENOMEM;
 
-       data = nfs_alloc_parsed_mount_data(NFS_MOUNT_VER3 | NFS_MOUNT_TCP);
+       data = nfs_alloc_parsed_mount_data(3);
        mntfh = kzalloc(sizeof(*mntfh), GFP_KERNEL);
        if (data == NULL || mntfh == NULL)
                goto out_free_fh;
@@ -2331,7 +2332,7 @@ static int nfs4_validate_text_mount_data(void *options,
 {
        struct sockaddr *sap = (struct sockaddr *)&args->nfs_server.address;
 
-       nfs_set_default_port(sap, args->nfs_server.port, NFS_PORT);
+       nfs_set_port(sap, &args->nfs_server.port, NFS_PORT);
 
        nfs_validate_transport_protocol(args);
 
@@ -2376,7 +2377,6 @@ static int nfs4_validate_mount_data(void *options,
        if (data == NULL)
                goto out_no_data;
 
-       args->version           = 4;
        switch (data->version) {
        case 1:
                if (data->host_addrlen > sizeof(args->nfs_server.address))
@@ -2660,7 +2660,7 @@ static int nfs4_get_sb(struct file_system_type *fs_type,
        struct nfs_parsed_mount_data *data;
        int error = -ENOMEM;
 
-       data = nfs_alloc_parsed_mount_data(0);
+       data = nfs_alloc_parsed_mount_data(4);
        if (data == NULL)
                goto out_free_data;
 
@@ -2690,7 +2690,6 @@ static void nfs4_kill_super(struct super_block *sb)
        dprintk("--> %s\n", __func__);
        nfs_super_return_all_delegations(sb);
        kill_anon_super(sb);
-       nfs4_renewd_prepare_shutdown(server);
        nfs_fscache_release_super_cookie(sb);
        nfs_free_server(server);
        dprintk("<-- %s\n", __func__);
index 5941958..84c2538 100644 (file)
@@ -87,6 +87,7 @@ int nilfs_btnode_submit_block(struct address_space *btnc, __u64 blocknr,
                        brelse(bh);
                        BUG();
                }
+               memset(bh->b_data, 0, 1 << inode->i_blkbits);
                bh->b_bdev = NILFS_I_NILFS(inode)->ns_bdev;
                bh->b_blocknr = blocknr;
                set_buffer_mapped(bh);
@@ -276,8 +277,7 @@ void nilfs_btnode_commit_change_key(struct address_space *btnc,
                                       "invalid oldkey %lld (newkey=%lld)",
                                       (unsigned long long)oldkey,
                                       (unsigned long long)newkey);
-               if (!test_set_buffer_dirty(obh) && TestSetPageDirty(opage))
-                       BUG();
+               nilfs_btnode_mark_dirty(obh);
 
                spin_lock_irq(&btnc->tree_lock);
                radix_tree_delete(&btnc->page_tree, oldkey);
index 683df89..6eff66a 100644 (file)
@@ -2468,17 +2468,22 @@ static void nilfs_segctor_notify(struct nilfs_sc_info *sci,
        /* Clear requests (even when the construction failed) */
        spin_lock(&sci->sc_state_lock);
 
-       sci->sc_state &= ~NILFS_SEGCTOR_COMMIT;
-
        if (req->mode == SC_LSEG_SR) {
+               sci->sc_state &= ~NILFS_SEGCTOR_COMMIT;
                sci->sc_seq_done = req->seq_accepted;
                nilfs_segctor_wakeup(sci, req->sc_err ? : req->sb_err);
                sci->sc_flush_request = 0;
-       } else if (req->mode == SC_FLUSH_FILE)
-               sci->sc_flush_request &= ~FLUSH_FILE_BIT;
-       else if (req->mode == SC_FLUSH_DAT)
-               sci->sc_flush_request &= ~FLUSH_DAT_BIT;
+       } else {
+               if (req->mode == SC_FLUSH_FILE)
+                       sci->sc_flush_request &= ~FLUSH_FILE_BIT;
+               else if (req->mode == SC_FLUSH_DAT)
+                       sci->sc_flush_request &= ~FLUSH_DAT_BIT;
 
+               /* re-enable timer if checkpoint creation was not done */
+               if (sci->sc_timer && (sci->sc_state & NILFS_SEGCTOR_COMMIT) &&
+                   time_before(jiffies, sci->sc_timer->expires))
+                       add_timer(sci->sc_timer);
+       }
        spin_unlock(&sci->sc_state_lock);
 }
 
index 828a889..7e54e52 100644 (file)
@@ -91,6 +91,7 @@ static int dnotify_handle_event(struct fsnotify_group *group,
        struct dnotify_struct *dn;
        struct dnotify_struct **prev;
        struct fown_struct *fown;
+       __u32 test_mask = event->mask & ~FS_EVENT_ON_CHILD;
 
        to_tell = event->to_tell;
 
@@ -106,7 +107,7 @@ static int dnotify_handle_event(struct fsnotify_group *group,
        spin_lock(&entry->lock);
        prev = &dnentry->dn;
        while ((dn = *prev) != NULL) {
-               if ((dn->dn_mask & event->mask) == 0) {
+               if ((dn->dn_mask & test_mask) == 0) {
                        prev = &dn->dn_next;
                        continue;
                }
index c8a07c6..3165d85 100644 (file)
@@ -324,11 +324,11 @@ int fsnotify_add_mark(struct fsnotify_mark_entry *entry,
        spin_lock(&group->mark_lock);
        spin_lock(&inode->i_lock);
 
-       entry->group = group;
-       entry->inode = inode;
-
        lentry = fsnotify_find_mark_entry(group, inode);
        if (!lentry) {
+               entry->group = group;
+               entry->inode = inode;
+
                hlist_add_head(&entry->i_list, &inode->i_fsnotify_mark_entries);
                list_add(&entry->g_list, &group->mark_entries);
 
index 3816d57..b8bf53b 100644 (file)
@@ -143,7 +143,7 @@ static bool event_compare(struct fsnotify_event *old, struct fsnotify_event *new
                        /* remember, after old was put on the wait_q we aren't
                         * allowed to look at the inode any more, only thing
                         * left to check was if the file_name is the same */
-                       if (old->name_len &&
+                       if (!old->name_len ||
                            !strcmp(old->file_name, new->file_name))
                                return true;
                        break;
index f38fee0..7b685e1 100644 (file)
@@ -248,11 +248,19 @@ ssize_t part_stat_show(struct device *dev,
                part_stat_read(p, merges[WRITE]),
                (unsigned long long)part_stat_read(p, sectors[WRITE]),
                jiffies_to_msecs(part_stat_read(p, ticks[WRITE])),
-               p->in_flight,
+               part_in_flight(p),
                jiffies_to_msecs(part_stat_read(p, io_ticks)),
                jiffies_to_msecs(part_stat_read(p, time_in_queue)));
 }
 
+ssize_t part_inflight_show(struct device *dev,
+                       struct device_attribute *attr, char *buf)
+{
+       struct hd_struct *p = dev_to_part(dev);
+
+       return sprintf(buf, "%8u %8u\n", p->in_flight[0], p->in_flight[1]);
+}
+
 #ifdef CONFIG_FAIL_MAKE_REQUEST
 ssize_t part_fail_show(struct device *dev,
                       struct device_attribute *attr, char *buf)
@@ -281,6 +289,7 @@ static DEVICE_ATTR(start, S_IRUGO, part_start_show, NULL);
 static DEVICE_ATTR(size, S_IRUGO, part_size_show, NULL);
 static DEVICE_ATTR(alignment_offset, S_IRUGO, part_alignment_offset_show, NULL);
 static DEVICE_ATTR(stat, S_IRUGO, part_stat_show, NULL);
+static DEVICE_ATTR(inflight, S_IRUGO, part_inflight_show, NULL);
 #ifdef CONFIG_FAIL_MAKE_REQUEST
 static struct device_attribute dev_attr_fail =
        __ATTR(make-it-fail, S_IRUGO|S_IWUSR, part_fail_show, part_fail_store);
@@ -292,6 +301,7 @@ static struct attribute *part_attrs[] = {
        &dev_attr_size.attr,
        &dev_attr_alignment_offset.attr,
        &dev_attr_stat.attr,
+       &dev_attr_inflight.attr,
 #ifdef CONFIG_FAIL_MAKE_REQUEST
        &dev_attr_fail.attr,
 #endif
index 52c4151..ae17d02 100644 (file)
--- a/fs/pipe.c
+++ b/fs/pipe.c
@@ -777,36 +777,55 @@ pipe_rdwr_release(struct inode *inode, struct file *filp)
 static int
 pipe_read_open(struct inode *inode, struct file *filp)
 {
-       /* We could have perhaps used atomic_t, but this and friends
-          below are the only places.  So it doesn't seem worthwhile.  */
+       int ret = -ENOENT;
+
        mutex_lock(&inode->i_mutex);
-       inode->i_pipe->readers++;
+
+       if (inode->i_pipe) {
+               ret = 0;
+               inode->i_pipe->readers++;
+       }
+
        mutex_unlock(&inode->i_mutex);
 
-       return 0;
+       return ret;
 }
 
 static int
 pipe_write_open(struct inode *inode, struct file *filp)
 {
+       int ret = -ENOENT;
+
        mutex_lock(&inode->i_mutex);
-       inode->i_pipe->writers++;
+
+       if (inode->i_pipe) {
+               ret = 0;
+               inode->i_pipe->writers++;
+       }
+
        mutex_unlock(&inode->i_mutex);
 
-       return 0;
+       return ret;
 }
 
 static int
 pipe_rdwr_open(struct inode *inode, struct file *filp)
 {
+       int ret = -ENOENT;
+
        mutex_lock(&inode->i_mutex);
-       if (filp->f_mode & FMODE_READ)
-               inode->i_pipe->readers++;
-       if (filp->f_mode & FMODE_WRITE)
-               inode->i_pipe->writers++;
+
+       if (inode->i_pipe) {
+               ret = 0;
+               if (filp->f_mode & FMODE_READ)
+                       inode->i_pipe->readers++;
+               if (filp->f_mode & FMODE_WRITE)
+                       inode->i_pipe->writers++;
+       }
+
        mutex_unlock(&inode->i_mutex);
 
-       return 0;
+       return ret;
 }
 
 /*
index 5601337..a44a789 100644 (file)
@@ -23,7 +23,6 @@
 #include <asm/io.h>
 #include <linux/list.h>
 #include <linux/ioport.h>
-#include <linux/mm.h>
 #include <linux/memory.h>
 #include <asm/sections.h>
 
index c7bff4f..a65239c 100644 (file)
@@ -99,7 +99,7 @@ static int meminfo_proc_show(struct seq_file *m, void *v)
                "VmallocUsed:    %8lu kB\n"
                "VmallocChunk:   %8lu kB\n"
 #ifdef CONFIG_MEMORY_FAILURE
-               "HardwareCorrupted: %8lu kB\n"
+               "HardwareCorrupted: %5lu kB\n"
 #endif
                ,
                K(i.totalram),
index 2281c2c..5033ce0 100644 (file)
@@ -94,6 +94,7 @@ static const struct file_operations proc_kpagecount_operations = {
 #define KPF_COMPOUND_TAIL      16
 #define KPF_HUGE               17
 #define KPF_UNEVICTABLE                18
+#define KPF_HWPOISON           19
 #define KPF_NOPAGE             20
 
 #define KPF_KSM                        21
@@ -180,6 +181,10 @@ static u64 get_uflags(struct page *page)
        u |= kpf_copy_bit(k, KPF_UNEVICTABLE,   PG_unevictable);
        u |= kpf_copy_bit(k, KPF_MLOCKED,       PG_mlocked);
 
+#ifdef CONFIG_MEMORY_FAILURE
+       u |= kpf_copy_bit(k, KPF_HWPOISON,      PG_hwpoison);
+#endif
+
 #ifdef CONFIG_IA64_UNCACHED_ALLOCATOR
        u |= kpf_copy_bit(k, KPF_UNCACHED,      PG_uncached);
 #endif
index b3208ad..71e2b4d 100644 (file)
@@ -253,11 +253,11 @@ ssize_t romfs_dev_strnlen(struct super_block *sb,
 
 #ifdef CONFIG_ROMFS_ON_MTD
        if (sb->s_mtd)
-               return romfs_mtd_strnlen(sb, pos, limit);
+               return romfs_mtd_strnlen(sb, pos, maxlen);
 #endif
 #ifdef CONFIG_ROMFS_ON_BLOCK
        if (sb->s_bdev)
-               return romfs_blk_strnlen(sb, pos, limit);
+               return romfs_blk_strnlen(sb, pos, maxlen);
 #endif
        return -EIO;
 }
index 0050fc4..5fad489 100644 (file)
@@ -894,7 +894,8 @@ int sysfs_move_dir(struct kobject *kobj, struct kobject *new_parent_kobj)
 
        mutex_lock(&sysfs_rename_mutex);
        BUG_ON(!sd->s_parent);
-       new_parent_sd = new_parent_kobj->sd ? new_parent_kobj->sd : &sysfs_root;
+       new_parent_sd = (new_parent_kobj && new_parent_kobj->sd) ?
+               new_parent_kobj->sd : &sysfs_root;
 
        error = 0;
        if (sd->s_parent == new_parent_sd)
index 561a9c0..f5ea468 100644 (file)
@@ -268,7 +268,7 @@ static int sysfs_get_open_dirent(struct sysfs_dirent *sd,
        struct sysfs_open_dirent *od, *new_od = NULL;
 
  retry:
-       spin_lock(&sysfs_open_dirent_lock);
+       spin_lock_irq(&sysfs_open_dirent_lock);
 
        if (!sd->s_attr.open && new_od) {
                sd->s_attr.open = new_od;
@@ -281,7 +281,7 @@ static int sysfs_get_open_dirent(struct sysfs_dirent *sd,
                list_add_tail(&buffer->list, &od->buffers);
        }
 
-       spin_unlock(&sysfs_open_dirent_lock);
+       spin_unlock_irq(&sysfs_open_dirent_lock);
 
        if (od) {
                kfree(new_od);
@@ -315,8 +315,9 @@ static void sysfs_put_open_dirent(struct sysfs_dirent *sd,
                                  struct sysfs_buffer *buffer)
 {
        struct sysfs_open_dirent *od = sd->s_attr.open;
+       unsigned long flags;
 
-       spin_lock(&sysfs_open_dirent_lock);
+       spin_lock_irqsave(&sysfs_open_dirent_lock, flags);
 
        list_del(&buffer->list);
        if (atomic_dec_and_test(&od->refcnt))
@@ -324,7 +325,7 @@ static void sysfs_put_open_dirent(struct sysfs_dirent *sd,
        else
                od = NULL;
 
-       spin_unlock(&sysfs_open_dirent_lock);
+       spin_unlock_irqrestore(&sysfs_open_dirent_lock, flags);
 
        kfree(od);
 }
@@ -456,8 +457,9 @@ static unsigned int sysfs_poll(struct file *filp, poll_table *wait)
 void sysfs_notify_dirent(struct sysfs_dirent *sd)
 {
        struct sysfs_open_dirent *od;
+       unsigned long flags;
 
-       spin_lock(&sysfs_open_dirent_lock);
+       spin_lock_irqsave(&sysfs_open_dirent_lock, flags);
 
        od = sd->s_attr.open;
        if (od) {
@@ -465,7 +467,7 @@ void sysfs_notify_dirent(struct sysfs_dirent *sd)
                wake_up_interruptible(&od->poll);
        }
 
-       spin_unlock(&sysfs_open_dirent_lock);
+       spin_unlock_irqrestore(&sysfs_open_dirent_lock, flags);
 }
 EXPORT_SYMBOL_GPL(sysfs_notify_dirent);
 
index 3818544..c2e30ee 100644 (file)
@@ -186,19 +186,37 @@ xfs_destroy_ioend(
 }
 
 /*
+ * If the end of the current ioend is beyond the current EOF,
+ * return the new EOF value, otherwise zero.
+ */
+STATIC xfs_fsize_t
+xfs_ioend_new_eof(
+       xfs_ioend_t             *ioend)
+{
+       xfs_inode_t             *ip = XFS_I(ioend->io_inode);
+       xfs_fsize_t             isize;
+       xfs_fsize_t             bsize;
+
+       bsize = ioend->io_offset + ioend->io_size;
+       isize = MAX(ip->i_size, ip->i_new_size);
+       isize = MIN(isize, bsize);
+       return isize > ip->i_d.di_size ? isize : 0;
+}
+
+/*
  * Update on-disk file size now that data has been written to disk.
  * The current in-memory file size is i_size.  If a write is beyond
  * eof i_new_size will be the intended file size until i_size is
  * updated.  If this write does not extend all the way to the valid
  * file size then restrict this update to the end of the write.
  */
+
 STATIC void
 xfs_setfilesize(
        xfs_ioend_t             *ioend)
 {
        xfs_inode_t             *ip = XFS_I(ioend->io_inode);
        xfs_fsize_t             isize;
-       xfs_fsize_t             bsize;
 
        ASSERT((ip->i_d.di_mode & S_IFMT) == S_IFREG);
        ASSERT(ioend->io_type != IOMAP_READ);
@@ -206,16 +224,10 @@ xfs_setfilesize(
        if (unlikely(ioend->io_error))
                return;
 
-       bsize = ioend->io_offset + ioend->io_size;
-
        xfs_ilock(ip, XFS_ILOCK_EXCL);
-
-       isize = MAX(ip->i_size, ip->i_new_size);
-       isize = MIN(isize, bsize);
-
-       if (ip->i_d.di_size < isize) {
+       isize = xfs_ioend_new_eof(ioend);
+       if (isize) {
                ip->i_d.di_size = isize;
-               ip->i_update_core = 1;
                xfs_mark_inode_dirty_sync(ip);
        }
 
@@ -404,10 +416,16 @@ xfs_submit_ioend_bio(
        struct bio      *bio)
 {
        atomic_inc(&ioend->io_remaining);
-
        bio->bi_private = ioend;
        bio->bi_end_io = xfs_end_bio;
 
+       /*
+        * If the I/O is beyond EOF we mark the inode dirty immediately
+        * but don't update the inode size until I/O completion.
+        */
+       if (xfs_ioend_new_eof(ioend))
+               xfs_mark_inode_dirty_sync(XFS_I(ioend->io_inode));
+
        submit_bio(WRITE, bio);
        ASSERT(!bio_flagged(bio, BIO_EOPNOTSUPP));
        bio_put(bio);
index 6293709..eff61e2 100644 (file)
@@ -176,14 +176,7 @@ xfs_file_fsync(
        struct dentry           *dentry,
        int                     datasync)
 {
-       struct inode            *inode = dentry->d_inode;
-       struct xfs_inode        *ip = XFS_I(inode);
-       int                     error;
-
-       /* capture size updates in I/O completion before writing the inode. */
-       error = filemap_fdatawait(inode->i_mapping);
-       if (error)
-               return error;
+       struct xfs_inode        *ip = XFS_I(dentry->d_inode);
 
        xfs_iflags_clear(ip, XFS_ITRUNCATED);
        return -xfs_fsync(ip);
index da0159d..cd42ef7 100644 (file)
 #include <linux/fiemap.h>
 
 /*
- * Bring the atime in the XFS inode uptodate.
- * Used before logging the inode to disk or when the Linux inode goes away.
+ * Bring the timestamps in the XFS inode uptodate.
+ *
+ * Used before writing the inode to disk.
  */
 void
-xfs_synchronize_atime(
+xfs_synchronize_times(
        xfs_inode_t     *ip)
 {
        struct inode    *inode = VFS_I(ip);
 
-       if (!(inode->i_state & I_CLEAR)) {
-               ip->i_d.di_atime.t_sec = (__int32_t)inode->i_atime.tv_sec;
-               ip->i_d.di_atime.t_nsec = (__int32_t)inode->i_atime.tv_nsec;
-       }
+       ip->i_d.di_atime.t_sec = (__int32_t)inode->i_atime.tv_sec;
+       ip->i_d.di_atime.t_nsec = (__int32_t)inode->i_atime.tv_nsec;
+       ip->i_d.di_ctime.t_sec = (__int32_t)inode->i_ctime.tv_sec;
+       ip->i_d.di_ctime.t_nsec = (__int32_t)inode->i_ctime.tv_nsec;
+       ip->i_d.di_mtime.t_sec = (__int32_t)inode->i_mtime.tv_sec;
+       ip->i_d.di_mtime.t_nsec = (__int32_t)inode->i_mtime.tv_nsec;
 }
 
 /*
@@ -106,32 +109,20 @@ xfs_ichgtime(
        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_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;
        }
 
        /*
-        * 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.
+        * Update complete - now make sure everyone knows that the inode
+        * is dirty.
         */
-       if (sync_it) {
-               SYNCHRONIZE();
-               ip->i_update_core = 1;
+       if (sync_it)
                xfs_mark_inode_dirty_sync(ip);
-       }
 }
 
 /*
@@ -506,10 +497,8 @@ xfs_vn_getattr(
        stat->gid = ip->i_d.di_gid;
        stat->ino = ip->i_ino;
        stat->atime = inode->i_atime;
-       stat->mtime.tv_sec = ip->i_d.di_mtime.t_sec;
-       stat->mtime.tv_nsec = ip->i_d.di_mtime.t_nsec;
-       stat->ctime.tv_sec = ip->i_d.di_ctime.t_sec;
-       stat->ctime.tv_nsec = ip->i_d.di_ctime.t_nsec;
+       stat->mtime = inode->i_mtime;
+       stat->ctime = inode->i_ctime;
        stat->blocks =
                XFS_FSB_TO_BB(mp, ip->i_d.di_nblocks + ip->i_delayed_blks);
 
index 49e4a6a..072050f 100644 (file)
@@ -667,7 +667,7 @@ start:
                xip->i_new_size = new_size;
 
        if (likely(!(ioflags & IO_INVIS)))
-               xfs_ichgtime(xip, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
+               file_update_time(file);
 
        /*
         * If the offset is beyond the size of the file, we have a couple
index 9e41f91..3d4a0c8 100644 (file)
@@ -80,7 +80,7 @@ xfs_fs_set_xstate(
 
        if (sb->s_flags & MS_RDONLY)
                return -EROFS;
-       if (!XFS_IS_QUOTA_RUNNING(mp))
+       if (op != Q_XQUOTARM && !XFS_IS_QUOTA_RUNNING(mp))
                return -ENOSYS;
        if (!capable(CAP_SYS_ADMIN))
                return -EPERM;
index bdd41c8..18a4b8e 100644 (file)
@@ -977,6 +977,28 @@ xfs_fs_inode_init_once(
 }
 
 /*
+ * Dirty the XFS inode when mark_inode_dirty_sync() is called so that
+ * we catch unlogged VFS level updates to the inode. Care must be taken
+ * here - the transaction code calls mark_inode_dirty_sync() to mark the
+ * VFS inode dirty in a transaction and clears the i_update_core field;
+ * it must clear the field after calling mark_inode_dirty_sync() to
+ * correctly indicate that the dirty state has been propagated into the
+ * inode log item.
+ *
+ * We need the barrier() to maintain correct ordering between unlogged
+ * updates and the transaction commit code that clears the i_update_core
+ * field. This requires all updates to be completed before marking the
+ * inode dirty.
+ */
+STATIC void
+xfs_fs_dirty_inode(
+       struct inode    *inode)
+{
+       barrier();
+       XFS_I(inode)->i_update_core = 1;
+}
+
+/*
  * Attempt to flush the inode, this will actually fail
  * if the inode is pinned, but we dirty the inode again
  * at the point when it is unpinned after a log write,
@@ -1126,7 +1148,7 @@ xfs_fs_put_super(
 }
 
 STATIC int
-xfs_fs_sync_super(
+xfs_fs_sync_fs(
        struct super_block      *sb,
        int                     wait)
 {
@@ -1134,23 +1156,23 @@ xfs_fs_sync_super(
        int                     error;
 
        /*
-        * Treat a sync operation like a freeze.  This is to work
-        * around a race in sync_inodes() which works in two phases
-        * - an asynchronous flush, which can write out an inode
-        * without waiting for file size updates to complete, and a
-        * synchronous flush, which wont do anything because the
-        * async flush removed the inode's dirty flag.  Also
-        * sync_inodes() will not see any files that just have
-        * outstanding transactions to be flushed because we don't
-        * dirty the Linux inode until after the transaction I/O
-        * completes.
+        * Not much we can do for the first async pass.  Writing out the
+        * superblock would be counter-productive as we are going to redirty
+        * when writing out other data and metadata (and writing out a single
+        * block is quite fast anyway).
+        *
+        * Try to asynchronously kick off quota syncing at least.
         */
-       if (wait || unlikely(sb->s_frozen == SB_FREEZE_WRITE))
-               error = xfs_quiesce_data(mp);
-       else
-               error = xfs_sync_fsdata(mp, 0);
+       if (!wait) {
+               xfs_qm_sync(mp, SYNC_TRYLOCK);
+               return 0;
+       }
+
+       error = xfs_quiesce_data(mp);
+       if (error)
+               return -error;
 
-       if (unlikely(laptop_mode)) {
+       if (laptop_mode) {
                int     prev_sync_seq = mp->m_sync_seq;
 
                /*
@@ -1169,7 +1191,7 @@ xfs_fs_sync_super(
                                mp->m_sync_seq != prev_sync_seq);
        }
 
-       return -error;
+       return 0;
 }
 
 STATIC int
@@ -1539,10 +1561,11 @@ xfs_fs_get_sb(
 static const struct super_operations xfs_super_operations = {
        .alloc_inode            = xfs_fs_alloc_inode,
        .destroy_inode          = xfs_fs_destroy_inode,
+       .dirty_inode            = xfs_fs_dirty_inode,
        .write_inode            = xfs_fs_write_inode,
        .clear_inode            = xfs_fs_clear_inode,
        .put_super              = xfs_fs_put_super,
-       .sync_fs                = xfs_fs_sync_super,
+       .sync_fs                = xfs_fs_sync_fs,
        .freeze_fs              = xfs_fs_freeze,
        .statfs                 = xfs_fs_statfs,
        .remount_fs             = xfs_fs_remount,
index 320be6a..961df0a 100644 (file)
@@ -309,11 +309,15 @@ xfs_sync_attr(
 STATIC int
 xfs_commit_dummy_trans(
        struct xfs_mount        *mp,
-       uint                    log_flags)
+       uint                    flags)
 {
        struct xfs_inode        *ip = mp->m_rootip;
        struct xfs_trans        *tp;
        int                     error;
+       int                     log_flags = XFS_LOG_FORCE;
+
+       if (flags & SYNC_WAIT)
+               log_flags |= XFS_LOG_SYNC;
 
        /*
         * Put a dummy transaction in the log to tell recovery
@@ -331,13 +335,12 @@ xfs_commit_dummy_trans(
        xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL);
        xfs_trans_ihold(tp, ip);
        xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
-       /* XXX(hch): ignoring the error here.. */
        error = xfs_trans_commit(tp, 0);
-
        xfs_iunlock(ip, XFS_ILOCK_EXCL);
 
+       /* the log force ensures this transaction is pushed to disk */
        xfs_log_force(mp, 0, log_flags);
-       return 0;
+       return error;
 }
 
 int
@@ -385,7 +388,20 @@ xfs_sync_fsdata(
        else
                XFS_BUF_ASYNC(bp);
 
-       return xfs_bwrite(mp, bp);
+       error = xfs_bwrite(mp, bp);
+       if (error)
+               return error;
+
+       /*
+        * If this is a data integrity sync make sure all pending buffers
+        * are flushed out for the log coverage check below.
+        */
+       if (flags & SYNC_WAIT)
+               xfs_flush_buftarg(mp->m_ddev_targp, 1);
+
+       if (xfs_log_need_covered(mp))
+               error = xfs_commit_dummy_trans(mp, flags);
+       return error;
 
  out_brelse:
        xfs_buf_relse(bp);
@@ -419,14 +435,16 @@ xfs_quiesce_data(
        /* push non-blocking */
        xfs_sync_data(mp, 0);
        xfs_qm_sync(mp, SYNC_TRYLOCK);
-       xfs_filestream_flush(mp);
 
-       /* push and block */
+       /* push and block till complete */
        xfs_sync_data(mp, SYNC_WAIT);
        xfs_qm_sync(mp, SYNC_WAIT);
 
+       /* drop inode references pinned by filestreams */
+       xfs_filestream_flush(mp);
+
        /* write superblock and hoover up shutdown errors */
-       error = xfs_sync_fsdata(mp, 0);
+       error = xfs_sync_fsdata(mp, SYNC_WAIT);
 
        /* flush data-only devices */
        if (mp->m_rtdev_targp)
@@ -570,8 +588,6 @@ xfs_sync_worker(
                /* dgc: errors ignored here */
                error = xfs_qm_sync(mp, SYNC_TRYLOCK);
                error = xfs_sync_fsdata(mp, SYNC_TRYLOCK);
-               if (xfs_log_need_covered(mp))
-                       error = xfs_commit_dummy_trans(mp, XFS_LOG_FORCE);
        }
        mp->m_sync_seq++;
        wake_up(&mp->m_wait_single_sync_task);
index 4e4276b..5d1a3b9 100644 (file)
@@ -876,7 +876,6 @@ xfs_dqrele_inode(
                ip->i_gdquot = NULL;
        }
        xfs_iput(ip, XFS_ILOCK_EXCL);
-       IRELE(ip);
 
        return 0;
 }
index 7465f9e..ab89a7e 100644 (file)
@@ -206,10 +206,10 @@ xfs_swap_extents(
         * process that the file was not changed out from
         * under it.
         */
-       if ((sbp->bs_ctime.tv_sec != ip->i_d.di_ctime.t_sec) ||
-           (sbp->bs_ctime.tv_nsec != ip->i_d.di_ctime.t_nsec) ||
-           (sbp->bs_mtime.tv_sec != ip->i_d.di_mtime.t_sec) ||
-           (sbp->bs_mtime.tv_nsec != ip->i_d.di_mtime.t_nsec)) {
+       if ((sbp->bs_ctime.tv_sec != VFS_I(ip)->i_ctime.tv_sec) ||
+           (sbp->bs_ctime.tv_nsec != VFS_I(ip)->i_ctime.tv_nsec) ||
+           (sbp->bs_mtime.tv_sec != VFS_I(ip)->i_mtime.tv_sec) ||
+           (sbp->bs_mtime.tv_nsec != VFS_I(ip)->i_mtime.tv_nsec)) {
                error = XFS_ERROR(EBUSY);
                goto out_unlock;
        }
index fa913e4..41ad537 100644 (file)
@@ -854,6 +854,7 @@ xfs_dir2_leaf_getdents(
                         */
                        ra_want = howmany(bufsize + mp->m_dirblksize,
                                          mp->m_sb.sb_blocksize) - 1;
+                       ASSERT(ra_want >= 0);
 
                        /*
                         * If we don't have as many as we want, and we haven't
@@ -1088,7 +1089,8 @@ xfs_dir2_leaf_getdents(
                 */
                ptr += length;
                curoff += length;
-               bufsize -= length;
+               /* bufsize may have just been a guess; don't go negative */
+               bufsize = bufsize > length ? bufsize - length : 0;
        }
 
        /*
index ab64f3e..0785797 100644 (file)
@@ -880,6 +880,7 @@ nextag:
                                 * Not in range - save last search
                                 * location and allocate a new inode
                                 */
+                               xfs_btree_del_cursor(tcur, XFS_BTREE_NOERROR);
                                pag->pagl_leftrec = trec.ir_startino;
                                pag->pagl_rightrec = rec.ir_startino;
                                pag->pagl_pagino = pagino;
index c1dc7ef..b92a4fa 100644 (file)
@@ -3068,9 +3068,9 @@ xfs_iflush_int(
        SYNCHRONIZE();
 
        /*
-        * Make sure to get the latest atime from the Linux inode.
+        * Make sure to get the latest timestamps from the Linux inode.
         */
-       xfs_synchronize_atime(ip);
+       xfs_synchronize_times(ip);
 
        if (XFS_TEST_ERROR(be16_to_cpu(dip->di_magic) != XFS_DINODE_MAGIC,
                               mp, XFS_ERRTAG_IFLUSH_1, XFS_RANDOM_IFLUSH_1)) {
index 0b38b9a..41555de 100644 (file)
@@ -504,7 +504,7 @@ void                xfs_ichgtime(xfs_inode_t *, int);
 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_synchronize_times(xfs_inode_t *);
 void           xfs_mark_inode_dirty_sync(xfs_inode_t *);
 
 #if defined(XFS_INODE_TRACE)
index 47d5b66..9794b87 100644 (file)
@@ -232,6 +232,15 @@ xfs_inode_item_format(
        nvecs        = 1;
 
        /*
+        * Make sure the linux inode is dirty. We do this before
+        * clearing i_update_core as the VFS will call back into
+        * XFS here and set i_update_core, so we need to dirty the
+        * inode first so that the ordering of i_update_core and
+        * unlogged modifications still works as described below.
+        */
+       xfs_mark_inode_dirty_sync(ip);
+
+       /*
         * Clear i_update_core if the timestamps (or any other
         * non-transactional modification) need flushing/logging
         * and we're about to log them with the rest of the core.
@@ -263,14 +272,9 @@ xfs_inode_item_format(
        }
 
        /*
-        * Make sure to get the latest atime from the Linux inode.
+        * Make sure to get the latest timestamps from the Linux inode.
         */
-       xfs_synchronize_atime(ip);
-
-       /*
-        * make sure the linux inode is dirty
-        */
-       xfs_mark_inode_dirty_sync(ip);
+       xfs_synchronize_times(ip);
 
        vecp->i_addr = (xfs_caddr_t)&ip->i_d;
        vecp->i_len  = sizeof(struct xfs_icdinode);
index b68f910..62efab2 100644 (file)
@@ -59,6 +59,7 @@ xfs_bulkstat_one_iget(
 {
        xfs_icdinode_t  *dic;   /* dinode core info pointer */
        xfs_inode_t     *ip;            /* incore inode pointer */
+       struct inode    *inode;
        int             error;
 
        error = xfs_iget(mp, NULL, ino,
@@ -72,6 +73,7 @@ xfs_bulkstat_one_iget(
        ASSERT(ip->i_imap.im_blkno != 0);
 
        dic = &ip->i_d;
+       inode = VFS_I(ip);
 
        /* xfs_iget returns the following without needing
         * further change.
@@ -83,16 +85,19 @@ xfs_bulkstat_one_iget(
        buf->bs_uid = dic->di_uid;
        buf->bs_gid = dic->di_gid;
        buf->bs_size = dic->di_size;
+
        /*
-        * We are reading the atime from the Linux inode because the
-        * dinode might not be uptodate.
+        * We need to read the timestamps from the Linux inode because
+        * the VFS keeps writing directly into the inode structure instead
+        * of telling us about the updates.
         */
-       buf->bs_atime.tv_sec = VFS_I(ip)->i_atime.tv_sec;
-       buf->bs_atime.tv_nsec = VFS_I(ip)->i_atime.tv_nsec;
-       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;
-       buf->bs_ctime.tv_nsec = dic->di_ctime.t_nsec;
+       buf->bs_atime.tv_sec = inode->i_atime.tv_sec;
+       buf->bs_atime.tv_nsec = inode->i_atime.tv_nsec;
+       buf->bs_mtime.tv_sec = inode->i_mtime.tv_sec;
+       buf->bs_mtime.tv_nsec = inode->i_mtime.tv_nsec;
+       buf->bs_ctime.tv_sec = inode->i_ctime.tv_sec;
+       buf->bs_ctime.tv_nsec = inode->i_ctime.tv_nsec;
+
        buf->bs_xflags = xfs_ip2xflags(ip);
        buf->bs_extsize = dic->di_extsize << mp->m_sb.sb_blocklog;
        buf->bs_extents = dic->di_nextents;
index a434f28..b572f7e 100644 (file)
@@ -2476,12 +2476,6 @@ xfs_reclaim(
        ASSERT(XFS_FORCED_SHUTDOWN(ip->i_mount) || ip->i_delayed_blks == 0);
 
        /*
-        * Make sure the atime in the XFS inode is correct before freeing the
-        * Linux inode.
-        */
-       xfs_synchronize_atime(ip);
-
-       /*
         * If we have nothing to flush with this inode then complete the
         * teardown now, otherwise break the link between the xfs inode and the
         * linux inode and clean up the xfs inode later. This avoids flushing
index 23bb4da..62f5908 100644 (file)
@@ -6,7 +6,7 @@
 #include <linux/irq.h>
 
 typedef struct {
-       unsigned long __softirq_pending;
+       unsigned int __softirq_pending;
 } ____cacheline_aligned irq_cpustat_t;
 
 #include <linux/irq_cpustat.h> /* Standard mappings for irq_cpustat_t above */
index ef47dfd..b29e201 100644 (file)
@@ -61,6 +61,9 @@ struct drm_crtc_helper_funcs {
        /* Move the crtc on the current fb to the given position *optional* */
        int (*mode_set_base)(struct drm_crtc *crtc, int x, int y,
                             struct drm_framebuffer *old_fb);
+
+       /* reload the current crtc LUT */
+       void (*load_lut)(struct drm_crtc *crtc);
 };
 
 struct drm_encoder_helper_funcs {
index 4aa5740..58c892a 100644 (file)
@@ -39,6 +39,8 @@ struct drm_fb_helper_crtc {
 struct drm_fb_helper_funcs {
        void (*gamma_set)(struct drm_crtc *crtc, u16 red, u16 green,
                          u16 blue, int regno);
+       void (*gamma_get)(struct drm_crtc *crtc, u16 *red, u16 *green,
+                         u16 *blue, int regno);
 };
 
 /* mode specified on the command line */
@@ -71,6 +73,7 @@ struct drm_fb_helper {
 };
 
 int drm_fb_helper_single_fb_probe(struct drm_device *dev,
+                                 int preferred_bpp,
                                  int (*fb_create)(struct drm_device *dev,
                                                   uint32_t fb_width,
                                                   uint32_t fb_height,
@@ -98,9 +101,11 @@ int drm_fb_helper_setcolreg(unsigned regno,
 void drm_fb_helper_restore(void);
 void drm_fb_helper_fill_var(struct fb_info *info, struct drm_framebuffer *fb,
                            uint32_t fb_width, uint32_t fb_height);
-void drm_fb_helper_fill_fix(struct fb_info *info, uint32_t pitch);
+void drm_fb_helper_fill_fix(struct fb_info *info, uint32_t pitch,
+                           uint32_t depth);
 
 int drm_fb_helper_add_connector(struct drm_connector *connector);
 int drm_fb_helper_parse_command_line(struct drm_device *dev);
+int drm_fb_helper_setcmap(struct fb_cmap *cmap, struct fb_info *info);
 
 #endif
index 3f6e545..e6f3b12 100644 (file)
@@ -80,7 +80,7 @@
        {0x1002, 0x5158, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV200}, \
        {0x1002, 0x5159, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV100}, \
        {0x1002, 0x515A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV100}, \
-       {0x1002, 0x515E, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV100}, \
+       {0x1002, 0x515E, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV100|RADEON_SINGLE_CRTC}, \
        {0x1002, 0x5460, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|RADEON_IS_MOBILITY}, \
        {0x1002, 0x5462, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|RADEON_IS_MOBILITY}, \
        {0x1002, 0x5464, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|RADEON_IS_MOBILITY}, \
        {0x1002, 0x5962, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280}, \
        {0x1002, 0x5964, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280}, \
        {0x1002, 0x5965, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280}, \
-       {0x1002, 0x5969, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV100}, \
+       {0x1002, 0x5969, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV100|RADEON_SINGLE_CRTC}, \
        {0x1002, 0x5a41, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS400|RADEON_IS_IGP|RADEON_IS_IGPGART}, \
        {0x1002, 0x5a42, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS400|RADEON_IS_IGP|RADEON_IS_MOBILITY|RADEON_IS_IGPGART}, \
        {0x1002, 0x5a61, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS400|RADEON_IS_IGP|RADEON_IS_IGPGART}, \
index cff4a10..1feed71 100644 (file)
@@ -126,6 +126,7 @@ header-y += nfs_mount.h
 header-y += nl80211.h
 header-y += param.h
 header-y += pci_regs.h
+header-y += perf_event.h
 header-y += pfkeyv2.h
 header-y += pg.h
 header-y += phantom.h
@@ -363,6 +364,7 @@ unifdef-y += utsname.h
 unifdef-y += videodev2.h
 unifdef-y += videodev.h
 unifdef-y += virtio_config.h
+unifdef-y += virtio_ids.h
 unifdef-y += virtio_blk.h
 unifdef-y += virtio_net.h
 unifdef-y += virtio_9p.h
index 6299a25..4fb3573 100644 (file)
@@ -334,9 +334,12 @@ enum {
        SETFEATURES_SATA_DISABLE = 0x90, /* Disable use of SATA feature */
 
        /* SETFEATURE Sector counts for SATA features */
-       SATA_AN                 = 0x05,  /* Asynchronous Notification */
-       SATA_DIPM               = 0x03,  /* Device Initiated Power Management */
-       SATA_FPDMA_AA           = 0x02,  /* DMA Setup FIS Auto-Activate */
+       SATA_FPDMA_OFFSET       = 0x01, /* FPDMA non-zero buffer offsets */
+       SATA_FPDMA_AA           = 0x02, /* FPDMA Setup FIS Auto-Activate */
+       SATA_DIPM               = 0x03, /* Device Initiated Power Management */
+       SATA_FPDMA_IN_ORDER     = 0x04, /* FPDMA in-order data delivery */
+       SATA_AN                 = 0x05, /* Asynchronous Notification */
+       SATA_SSP                = 0x06, /* Software Settings Preservation */
 
        /* feature values for SET_MAX */
        ATA_SET_MAX_ADDR        = 0x00,
index 2511904..221cecd 100644 (file)
@@ -1172,11 +1172,7 @@ static inline void put_dev_sector(Sector p)
 }
 
 struct work_struct;
-struct delayed_work;
 int kblockd_schedule_work(struct request_queue *q, struct work_struct *work);
-int kblockd_schedule_delayed_work(struct request_queue *q,
-                                       struct delayed_work *work,
-                                       unsigned long delay);
 
 #define MODULE_ALIAS_BLOCKDEV(major,minor) \
        MODULE_ALIAS("block-major-" __stringify(major) "-" __stringify(minor))
index 44717eb..79a2340 100644 (file)
@@ -291,8 +291,15 @@ struct global_attr {
 int cpufreq_get_policy(struct cpufreq_policy *policy, unsigned int cpu);
 int cpufreq_update_policy(unsigned int cpu);
 
+#ifdef CONFIG_CPU_FREQ
 /* query the current CPU frequency (in kHz). If zero, cpufreq couldn't detect it */
 unsigned int cpufreq_get(unsigned int cpu);
+#else
+static inline unsigned int cpufreq_get(unsigned int cpu)
+{
+       return 0;
+}
+#endif
 
 /* query the last known CPU freq (in kHz). If zero, cpufreq couldn't detect it */
 #ifdef CONFIG_CPU_FREQ
index aca31bf..2ea3e49 100644 (file)
@@ -124,7 +124,9 @@ struct device_driver {
        struct bus_type         *bus;
 
        struct module           *owner;
-       const char              *mod_name;      /* used for built-in modules */
+       const char              *mod_name;      /* used for built-in modules */
+
+       bool suppress_bind_attrs;       /* disables bind/unbind via sysfs */
 
        int (*probe) (struct device *dev);
        int (*remove) (struct device *dev);
index 45a937b..90a4ed0 100644 (file)
@@ -361,6 +361,7 @@ typedef struct elf64_shdr {
 #define NT_PPC_VSX     0x102           /* PowerPC VSX registers */
 #define NT_386_TLS     0x200           /* i386 TLS slots (struct user_desc) */
 #define NT_386_IOPERM  0x201           /* x86 io permission bitmap (1=deny) */
+#define NT_PRXSTATUS   0x300           /* s390 upper register halves */
 
 
 /* Note header in a PT_NOTE section */
index cd3d2ab..0b4f97d 100644 (file)
@@ -241,7 +241,7 @@ extern void ftrace_enable_daemon(void);
 # define ftrace_set_filter(buf, len, reset)    do { } while (0)
 # define ftrace_disable_daemon()               do { } while (0)
 # define ftrace_enable_daemon()                        do { } while (0)
-static inline void ftrace_release(void *start, unsigned long size) { }
+static inline void ftrace_release_mod(struct module *mod) {}
 static inline int register_ftrace_command(struct ftrace_func_command *cmd)
 {
        return -EINVAL;
index 8ec1799..1e5a26d 100644 (file)
@@ -33,8 +33,8 @@
 #define FUTEX_LOCK_PI_PRIVATE  (FUTEX_LOCK_PI | FUTEX_PRIVATE_FLAG)
 #define FUTEX_UNLOCK_PI_PRIVATE        (FUTEX_UNLOCK_PI | FUTEX_PRIVATE_FLAG)
 #define FUTEX_TRYLOCK_PI_PRIVATE (FUTEX_TRYLOCK_PI | FUTEX_PRIVATE_FLAG)
-#define FUTEX_WAIT_BITSET_PRIVATE      (FUTEX_WAIT_BITS | FUTEX_PRIVATE_FLAG)
-#define FUTEX_WAKE_BITSET_PRIVATE      (FUTEX_WAKE_BITS | FUTEX_PRIVATE_FLAG)
+#define FUTEX_WAIT_BITSET_PRIVATE      (FUTEX_WAIT_BITSET | FUTEX_PRIVATE_FLAG)
+#define FUTEX_WAKE_BITSET_PRIVATE      (FUTEX_WAKE_BITSET | FUTEX_PRIVATE_FLAG)
 #define FUTEX_WAIT_REQUEUE_PI_PRIVATE  (FUTEX_WAIT_REQUEUE_PI | \
                                         FUTEX_PRIVATE_FLAG)
 #define FUTEX_CMP_REQUEUE_PI_PRIVATE   (FUTEX_CMP_REQUEUE_PI | \
index 7beaa21..297df45 100644 (file)
@@ -98,7 +98,7 @@ struct hd_struct {
        int make_it_fail;
 #endif
        unsigned long stamp;
-       int in_flight;
+       int in_flight[2];
 #ifdef CONFIG_SMP
        struct disk_stats *dkstats;
 #else
@@ -322,18 +322,23 @@ static inline void free_part_stats(struct hd_struct *part)
 #define part_stat_sub(cpu, gendiskp, field, subnd)                     \
        part_stat_add(cpu, gendiskp, field, -subnd)
 
-static inline void part_inc_in_flight(struct hd_struct *part)
+static inline void part_inc_in_flight(struct hd_struct *part, int rw)
 {
-       part->in_flight++;
+       part->in_flight[rw]++;
        if (part->partno)
-               part_to_disk(part)->part0.in_flight++;
+               part_to_disk(part)->part0.in_flight[rw]++;
 }
 
-static inline void part_dec_in_flight(struct hd_struct *part)
+static inline void part_dec_in_flight(struct hd_struct *part, int rw)
 {
-       part->in_flight--;
+       part->in_flight[rw]--;
        if (part->partno)
-               part_to_disk(part)->part0.in_flight--;
+               part_to_disk(part)->part0.in_flight[rw]--;
+}
+
+static inline int part_in_flight(struct hd_struct *part)
+{
+       return part->in_flight[0] + part->in_flight[1];
 }
 
 /* block/blk-core.c */
@@ -546,6 +551,8 @@ extern ssize_t part_size_show(struct device *dev,
                              struct device_attribute *attr, char *buf);
 extern ssize_t part_stat_show(struct device *dev,
                              struct device_attribute *attr, char *buf);
+extern ssize_t part_inflight_show(struct device *dev,
+                             struct device_attribute *attr, char *buf);
 #ifdef CONFIG_FAIL_MAKE_REQUEST
 extern ssize_t part_fail_show(struct device *dev,
                              struct device_attribute *attr, char *buf);
index 2d02dfd..508824e 100644 (file)
@@ -349,11 +349,11 @@ struct twl4030_madc_platform_data {
        int             irq_line;
 };
 
-/* Boards have uniqe mappings of {col, row} --> keycode.
- * Column and row are 4 bits, but range only from 0..7.
+/* Boards have uniqe mappings of {row, col} --> keycode.
+ * Column and row are 8 bits each, but range only from 0..7.
  * a PERSISTENT_KEY is "always on" and never reported.
  */
-#define PERSISTENT_KEY(c, r)   KEY((c), (r), KEY_RESERVED)
+#define PERSISTENT_KEY(r, c)   KEY((r), (c), KEY_RESERVED)
 
 struct twl4030_keypad_data {
        const struct matrix_keymap_data *keymap_data;
index 400adbb..ff8bde5 100644 (file)
@@ -271,6 +271,7 @@ void __init parse_early_options(char *cmdline);
 #else /* MODULE */
 
 /* Don't use these in modules, but some people do... */
+#define early_initcall(fn)             module_init(fn)
 #define core_initcall(fn)              module_init(fn)
 #define postcore_initcall(fn)          module_init(fn)
 #define arch_initcall(fn)              module_init(fn)
index b78cf81..7ca72b7 100644 (file)
@@ -10,7 +10,6 @@
 #include <linux/irqreturn.h>
 #include <linux/irqnr.h>
 #include <linux/hardirq.h>
-#include <linux/sched.h>
 #include <linux/irqflags.h>
 #include <linux/smp.h>
 #include <linux/percpu.h>
@@ -610,6 +609,7 @@ extern void debug_poll_all_shared_irqs(void);
 static inline void debug_poll_all_shared_irqs(void) { }
 #endif
 
+struct seq_file;
 int show_interrupts(struct seq_file *p, void *v);
 
 struct irq_desc;
index d3cd23f..f4e3184 100644 (file)
@@ -659,6 +659,12 @@ extern int do_sysinfo(struct sysinfo *info);
 
 #endif /* __KERNEL__ */
 
+#ifndef __EXPORTED_HEADERS__
+#ifndef __KERNEL__
+#warning Attempt to use kernel headers from user space, see http://kernelnewbies.org/KernelHeaders
+#endif /* __KERNEL__ */
+#endif /* __EXPORTED_HEADERS__ */
+
 #define SI_LOAD_SHIFT  16
 struct sysinfo {
        long uptime;                    /* Seconds since boot */
index 76319bf..8769864 100644 (file)
@@ -418,6 +418,17 @@ enum {
                                  ATA_TIMING_ACTIVE | ATA_TIMING_RECOVER |
                                  ATA_TIMING_DMACK_HOLD | ATA_TIMING_CYCLE |
                                  ATA_TIMING_UDMA,
+
+       /* ACPI constants */
+       ATA_ACPI_FILTER_SETXFER = 1 << 0,
+       ATA_ACPI_FILTER_LOCK    = 1 << 1,
+       ATA_ACPI_FILTER_DIPM    = 1 << 2,
+       ATA_ACPI_FILTER_FPDMA_OFFSET = 1 << 3,  /* FPDMA non-zero offset */
+       ATA_ACPI_FILTER_FPDMA_AA = 1 << 4,      /* FPDMA auto activate */
+
+       ATA_ACPI_FILTER_DEFAULT = ATA_ACPI_FILTER_SETXFER |
+                                 ATA_ACPI_FILTER_LOCK |
+                                 ATA_ACPI_FILTER_DIPM,
 };
 
 enum ata_xfer_mask {
@@ -587,6 +598,7 @@ struct ata_device {
 #ifdef CONFIG_ATA_ACPI
        acpi_handle             acpi_handle;
        union acpi_object       *gtf_cache;
+       unsigned int            gtf_filter;
 #endif
        /* n_sector is CLEAR_BEGIN, read comment above CLEAR_BEGIN */
        u64                     n_sectors;      /* size of device, if ATA */
index 81bb423..eaf3636 100644 (file)
@@ -11,6 +11,7 @@
 #define LINUX_MMC_HOST_H
 
 #include <linux/leds.h>
+#include <linux/sched.h>
 
 #include <linux/mmc/core.h>
 
index 6547c3c..82a9124 100644 (file)
@@ -37,7 +37,6 @@ typedef int (*param_set_fn)(const char *val, struct kernel_param *kp);
 typedef int (*param_get_fn)(char *buffer, struct kernel_param *kp);
 
 /* Flag bits for kernel_param.flags */
-#define KPARAM_KMALLOCED       1
 #define KPARAM_ISBOOL          2
 
 struct kernel_param {
index 94958c1..812a5f3 100644 (file)
@@ -557,7 +557,7 @@ struct netdev_queue {
  *     Callback uses when the transmitter has not made any progress
  *     for dev->watchdog ticks.
  *
- * struct net_device_stats* (*get_stats)(struct net_device *dev);
+ * struct net_device_stats* (*ndo_get_stats)(struct net_device *dev);
  *     Called when a user wants to get the network device usage
  *     statistics. If not defined, the counters in dev->stats will
  *     be used.
index da1fda8..b0f0f38 100644 (file)
 #define PCI_DEVICE_ID_ATI_IXP600_IDE   0x438c
 #define PCI_DEVICE_ID_ATI_IXP700_SATA  0x4390
 #define PCI_DEVICE_ID_ATI_IXP700_IDE   0x439c
-/* AMD SB Chipset */
-#define PCI_DEVICE_ID_AMD_SB900_IDE     0x780c
-#define PCI_DEVICE_ID_AMD_SB900_SATA_IDE 0x7800
 
 #define PCI_VENDOR_ID_VLSI             0x1004
 #define PCI_DEVICE_ID_VLSI_82C592      0x0005
 #define PCI_DEVICE_ID_IBM_ICOM_V2_ONE_PORT_RVX_ONE_PORT_MDM_PCIE 0x0361
 #define PCI_DEVICE_ID_IBM_ICOM_FOUR_PORT_MODEL 0x252
 
+#define PCI_SUBVENDOR_ID_IBM           0x1014
+#define PCI_SUBDEVICE_ID_IBM_SATURN_SERIAL_ONE_PORT    0x03d4
+
 #define PCI_VENDOR_ID_UNISYS           0x1018
 #define PCI_DEVICE_ID_UNISYS_DMA_DIRECTOR 0x001C
 
 #define PCI_DEVICE_ID_AMD_CS5536_UDC    0x2096
 #define PCI_DEVICE_ID_AMD_CS5536_UOC    0x2097
 #define PCI_DEVICE_ID_AMD_CS5536_IDE    0x209A
-
 #define PCI_DEVICE_ID_AMD_LX_VIDEO  0x2081
 #define PCI_DEVICE_ID_AMD_LX_AES    0x2082
+#define PCI_DEVICE_ID_AMD_HUDSON2_IDE          0x780c
+#define PCI_DEVICE_ID_AMD_HUDSON2_SATA_IDE     0x7800
 
 #define PCI_VENDOR_ID_TRIDENT          0x1023
 #define PCI_DEVICE_ID_TRIDENT_4DWAVE_DX        0x2000
 #define PCI_DEVICE_ID_TI_X515          0x8036
 #define PCI_DEVICE_ID_TI_XX12          0x8039
 #define PCI_DEVICE_ID_TI_XX12_FM       0x803b
+#define PCI_DEVICE_ID_TI_XIO2000A      0x8231
 #define PCI_DEVICE_ID_TI_1130          0xac12
 #define PCI_DEVICE_ID_TI_1031          0xac13
 #define PCI_DEVICE_ID_TI_1131          0xac15
 #define PCI_DEVICE_ID_ADDIDATA_APCI7420_3      0x700D
 #define PCI_DEVICE_ID_ADDIDATA_APCI7300_3      0x700E
 #define PCI_DEVICE_ID_ADDIDATA_APCI7800_3      0x700F
+#define PCI_DEVICE_ID_ADDIDATA_APCIe7300       0x7010
+#define PCI_DEVICE_ID_ADDIDATA_APCIe7420       0x7011
+#define PCI_DEVICE_ID_ADDIDATA_APCIe7500       0x7012
+#define PCI_DEVICE_ID_ADDIDATA_APCIe7800       0x7013
 
 #define PCI_VENDOR_ID_PDC              0x15e9
 
index 3a9d36d..9e70126 100644 (file)
@@ -442,6 +442,7 @@ enum perf_callchain_context {
 #include <linux/hrtimer.h>
 #include <linux/fs.h>
 #include <linux/pid_namespace.h>
+#include <linux/workqueue.h>
 #include <asm/atomic.h>
 
 #define PERF_MAX_STACK_DEPTH           255
@@ -470,8 +471,8 @@ struct hw_perf_event {
                        unsigned long   event_base;
                        int             idx;
                };
-               union { /* software */
-                       atomic64_t      count;
+               struct { /* software */
+                       s64             remaining;
                        struct hrtimer  hrtimer;
                };
        };
@@ -513,6 +514,10 @@ struct file;
 
 struct perf_mmap_data {
        struct rcu_head                 rcu_head;
+#ifdef CONFIG_PERF_USE_VMALLOC
+       struct work_struct              work;
+#endif
+       int                             data_order;
        int                             nr_pages;       /* nr of data pages  */
        int                             writable;       /* are we writable   */
        int                             nr_locked;      /* nr pages mlocked  */
index 9311505..a3baeb2 100644 (file)
 #define PR_TASK_PERF_EVENTS_DISABLE            31
 #define PR_TASK_PERF_EVENTS_ENABLE             32
 
+/*
+ * Set early/late kill mode for hwpoison memory corruption.
+ * This influences when the process gets killed on a memory corruption.
+ */
 #define PR_MCE_KILL    33
+# define PR_MCE_KILL_CLEAR   0
+# define PR_MCE_KILL_SET     1
+
+# define PR_MCE_KILL_LATE    0
+# define PR_MCE_KILL_EARLY   1
+# define PR_MCE_KILL_DEFAULT 2
+
+#define PR_MCE_KILL_GET 34
 
 #endif /* _LINUX_PRCTL_H */
index 6fe0363..3ebd0b7 100644 (file)
@@ -77,7 +77,7 @@ extern int rcu_scheduler_active;
 #error "Unknown RCU implementation specified to kernel configuration"
 #endif
 
-#define RCU_HEAD_INIT  { .next = NULL, .func = NULL }
+#define RCU_HEAD_INIT  { .next = NULL, .func = NULL }
 #define RCU_HEAD(head) struct rcu_head head = RCU_HEAD_INIT
 #define INIT_RCU_HEAD(ptr) do { \
        (ptr)->next = NULL; (ptr)->func = NULL; \
@@ -129,12 +129,6 @@ static inline void rcu_read_lock(void)
        rcu_read_acquire();
 }
 
-/**
- * rcu_read_unlock - marks the end of an RCU read-side critical section.
- *
- * See rcu_read_lock() for more information.
- */
-
 /*
  * So where is rcu_write_lock()?  It does not exist, as there is no
  * way for writers to lock out RCU readers.  This is a feature, not
@@ -144,6 +138,12 @@ static inline void rcu_read_lock(void)
  * used as well.  RCU does not care how the writers keep out of each
  * others' way, as long as they do so.
  */
+
+/**
+ * rcu_read_unlock - marks the end of an RCU read-side critical section.
+ *
+ * See rcu_read_lock() for more information.
+ */
 static inline void rcu_read_unlock(void)
 {
        rcu_read_release();
@@ -196,6 +196,8 @@ static inline void rcu_read_lock_sched(void)
        __acquire(RCU_SCHED);
        rcu_read_acquire();
 }
+
+/* Used by lockdep and tracing: cannot be traced, cannot call lockdep. */
 static inline notrace void rcu_read_lock_sched_notrace(void)
 {
        preempt_disable_notrace();
@@ -213,6 +215,8 @@ static inline void rcu_read_unlock_sched(void)
        __release(RCU_SCHED);
        preempt_enable();
 }
+
+/* Used by lockdep and tracing: cannot be traced, cannot call lockdep. */
 static inline notrace void rcu_read_unlock_sched_notrace(void)
 {
        __release(RCU_SCHED);
index 3768277..9642c6b 100644 (file)
 #ifndef __LINUX_RCUTREE_H
 #define __LINUX_RCUTREE_H
 
+struct notifier_block;
+
 extern void rcu_sched_qs(int cpu);
 extern void rcu_bh_qs(int cpu);
-
+extern int rcu_cpu_notify(struct notifier_block *self,
+                         unsigned long action, void *hcpu);
 extern int rcu_needs_cpu(int cpu);
+extern int rcu_expedited_torture_stats(char *page);
 
 #ifdef CONFIG_TREE_PREEMPT_RCU
 
@@ -72,11 +76,7 @@ static inline void __rcu_read_unlock_bh(void)
 
 extern void call_rcu_sched(struct rcu_head *head,
                           void (*func)(struct rcu_head *rcu));
-
-static inline void synchronize_rcu_expedited(void)
-{
-       synchronize_sched_expedited();
-}
+extern void synchronize_rcu_expedited(void);
 
 static inline void synchronize_rcu_bh_expedited(void)
 {
@@ -85,16 +85,11 @@ static inline void synchronize_rcu_bh_expedited(void)
 
 extern void __rcu_init(void);
 extern void rcu_check_callbacks(int cpu, int user);
-extern void rcu_restart_cpu(int cpu);
 
 extern long rcu_batches_completed(void);
 extern long rcu_batches_completed_bh(void);
 extern long rcu_batches_completed_sched(void);
 
-static inline void rcu_init_sched(void)
-{
-}
-
 #ifdef CONFIG_NO_HZ
 void rcu_enter_nohz(void);
 void rcu_exit_nohz(void);
@@ -107,7 +102,7 @@ static inline void rcu_exit_nohz(void)
 }
 #endif /* CONFIG_NO_HZ */
 
-/* A context switch is a grace period for rcutree. */
+/* A context switch is a grace period for RCU-sched and RCU-bh. */
 static inline int rcu_blocking_is_gp(void)
 {
        return num_online_cpus() == 1;
index df7b23a..bcdd660 100644 (file)
@@ -354,8 +354,8 @@ struct sk_buff {
                                ipvs_property:1,
                                peeked:1,
                                nf_trace:1;
+       __be16                  protocol:16;
        kmemcheck_bitfield_end(flags1);
-       __be16                  protocol;
 
        void                    (*destructor)(struct sk_buff *skb);
 #if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
@@ -367,7 +367,6 @@ struct sk_buff {
 #endif
 
        int                     iif;
-       __u16                   queue_mapping;
 #ifdef CONFIG_NET_SCHED
        __u16                   tc_index;       /* traffic control index */
 #ifdef CONFIG_NET_CLS_ACT
@@ -376,6 +375,7 @@ struct sk_buff {
 #endif
 
        kmemcheck_bitfield_begin(flags2);
+       __u16                   queue_mapping:16;
 #ifdef CONFIG_IPV6_NDISC_NODETYPE
        __u8                    ndisc_nodetype:2;
 #endif
@@ -1757,6 +1757,8 @@ extern int               skb_copy_datagram_const_iovec(const struct sk_buff *from,
                                                     int to_offset,
                                                     int size);
 extern void           skb_free_datagram(struct sock *sk, struct sk_buff *skb);
+extern void           skb_free_datagram_locked(struct sock *sk,
+                                               struct sk_buff *skb);
 extern int            skb_kill_datagram(struct sock *sk, struct sk_buff *skb,
                                         unsigned int flags);
 extern __wsum         skb_checksum(const struct sk_buff *skb, int offset,
index 3b461df..3273a0c 100644 (file)
@@ -16,7 +16,7 @@ struct __kernel_sockaddr_storage {
                                /* _SS_MAXSIZE value minus size of ss_family */
 } __attribute__ ((aligned(_K_SS_ALIGNSIZE)));  /* force desired alignment */
 
-#if defined(__KERNEL__) || !defined(__GLIBC__) || (__GLIBC__ < 2)
+#ifdef __KERNEL__
 
 #include <asm/socket.h>                        /* arch-dependent defines       */
 #include <linux/sockios.h>             /* the SIOCxxx I/O controls     */
@@ -101,21 +101,6 @@ struct cmsghdr {
                              ((char *)(cmsg) - (char *)(mhdr)->msg_control)))
 
 /*
- *     This mess will go away with glibc
- */
-#ifdef __KERNEL__
-#define __KINLINE static inline
-#elif  defined(__GNUC__) 
-#define __KINLINE static __inline__
-#elif defined(__cplusplus)
-#define __KINLINE static inline
-#else
-#define __KINLINE static
-#endif
-
-
-/*
  *     Get the next cmsg header
  *
  *     PLEASE, do not touch this function. If you think, that it is
@@ -128,7 +113,7 @@ struct cmsghdr {
  *     ancillary object DATA.                          --ANK (980731)
  */
  
-__KINLINE struct cmsghdr * __cmsg_nxthdr(void *__ctl, __kernel_size_t __size,
+static inline struct cmsghdr * __cmsg_nxthdr(void *__ctl, __kernel_size_t __size,
                                               struct cmsghdr *__cmsg)
 {
        struct cmsghdr * __ptr;
@@ -140,7 +125,7 @@ __KINLINE struct cmsghdr * __cmsg_nxthdr(void *__ctl, __kernel_size_t __size,
        return __ptr;
 }
 
-__KINLINE struct cmsghdr * cmsg_nxthdr (struct msghdr *__msg, struct cmsghdr *__cmsg)
+static inline struct cmsghdr * cmsg_nxthdr (struct msghdr *__msg, struct cmsghdr *__cmsg)
 {
        return __cmsg_nxthdr(__msg->msg_control, __msg->msg_controllen, __cmsg);
 }
index 489019e..b850886 100644 (file)
@@ -62,7 +62,7 @@ extern char * strnchr(const char *, size_t, int);
 #ifndef __HAVE_ARCH_STRRCHR
 extern char * strrchr(const char *,int);
 #endif
-extern char * strstrip(char *);
+extern char * __must_check strstrip(char *);
 #ifndef __HAVE_ARCH_STRSTR
 extern char * strstr(const char *,const char *);
 #endif
index fc0bf3e..57e6357 100644 (file)
@@ -129,7 +129,7 @@ int arch_update_cpu_topology(void);
                                | 1*SD_BALANCE_FORK                     \
                                | 0*SD_BALANCE_WAKE                     \
                                | 1*SD_WAKE_AFFINE                      \
-                               | 1*SD_PREFER_LOCAL                     \
+                               | 0*SD_PREFER_LOCAL                     \
                                | 0*SD_SHARE_CPUPOWER                   \
                                | 1*SD_SHARE_PKG_RESOURCES              \
                                | 0*SD_SERIALIZE                        \
@@ -162,7 +162,7 @@ int arch_update_cpu_topology(void);
                                | 1*SD_BALANCE_FORK                     \
                                | 0*SD_BALANCE_WAKE                     \
                                | 1*SD_WAKE_AFFINE                      \
-                               | 1*SD_PREFER_LOCAL                     \
+                               | 0*SD_PREFER_LOCAL                     \
                                | 0*SD_SHARE_CPUPOWER                   \
                                | 0*SD_SHARE_PKG_RESOURCES              \
                                | 0*SD_SERIALIZE                        \
index c134dd1..09077f6 100644 (file)
@@ -7,7 +7,7 @@
 
 /*
  * Trace sequences are used to allow a function to call several other functions
- * to create a string of data to use (up to a max of PAGE_SIZE.
+ * to create a string of data to use (up to a max of PAGE_SIZE).
  */
 
 struct trace_seq {
index c17eb64..ce911eb 100644 (file)
@@ -150,6 +150,7 @@ struct usb_serial {
        struct usb_interface            *interface;
        unsigned char                   disconnected:1;
        unsigned char                   suspending:1;
+       unsigned char                   attached:1;
        unsigned char                   minor;
        unsigned char                   num_ports;
        unsigned char                   num_port_pointers;
index ea7226a..095e10d 100644 (file)
@@ -2,6 +2,7 @@
 #define _LINUX_VIRTIO_9P_H
 /* This header is BSD licensed so anyone can use the definitions to implement
  * compatible drivers/servers. */
+#include <linux/virtio_ids.h>
 #include <linux/virtio_config.h>
 
 /* Maximum number of virtio channels per partition (1 for now) */
index 09d7300..1418f04 100644 (file)
@@ -2,6 +2,7 @@
 #define _LINUX_VIRTIO_BALLOON_H
 /* This header is BSD licensed so anyone can use the definitions to implement
  * compatible drivers/servers. */
+#include <linux/virtio_ids.h>
 #include <linux/virtio_config.h>
 
 /* The feature bitmap for virtio balloon */
index 15cb666..fd294c5 100644 (file)
@@ -3,6 +3,7 @@
 /* This header is BSD licensed so anyone can use the definitions to implement
  * compatible drivers/servers. */
 #include <linux/types.h>
+#include <linux/virtio_ids.h>
 #include <linux/virtio_config.h>
 
 /* Feature bits */
 #define VIRTIO_BLK_F_RO                5       /* Disk is read-only */
 #define VIRTIO_BLK_F_BLK_SIZE  6       /* Block size of disk is available*/
 #define VIRTIO_BLK_F_SCSI      7       /* Supports scsi command passthru */
-#define VIRTIO_BLK_F_IDENTIFY  8       /* ATA IDENTIFY supported */
 #define VIRTIO_BLK_F_FLUSH     9       /* Cache flush command support */
 
-#define VIRTIO_BLK_ID_BYTES    (sizeof(__u16[256]))    /* IDENTIFY DATA */
-
 struct virtio_blk_config {
        /* The capacity (in 512-byte sectors). */
        __u64 capacity;
@@ -33,7 +31,6 @@ struct virtio_blk_config {
        } geometry;
        /* block size of device (if VIRTIO_BLK_F_BLK_SIZE) */
        __u32 blk_size;
-       __u8 identify[VIRTIO_BLK_ID_BYTES];
 } __attribute__((packed));
 
 /*
index b5f5198..fe88517 100644 (file)
@@ -1,6 +1,7 @@
 #ifndef _LINUX_VIRTIO_CONSOLE_H
 #define _LINUX_VIRTIO_CONSOLE_H
 #include <linux/types.h>
+#include <linux/virtio_ids.h>
 #include <linux/virtio_config.h>
 /* This header, excluding the #ifdef __KERNEL__ part, is BSD licensed so
  * anyone can use the definitions to implement compatible drivers/servers. */
index 1f41734..085e422 100644 (file)
@@ -3,6 +3,7 @@
 /* This header is BSD licensed so anyone can use the definitions to implement
  * compatible drivers/servers. */
 #include <linux/types.h>
+#include <linux/virtio_ids.h>
 #include <linux/virtio_config.h>
 #include <linux/if_ether.h>
 
index 48121c3..c4d5de8 100644 (file)
@@ -2,6 +2,7 @@
 #define _LINUX_VIRTIO_RNG_H
 /* This header is BSD licensed so anyone can use the definitions to implement
  * compatible drivers/servers. */
+#include <linux/virtio_ids.h>
 #include <linux/virtio_config.h>
 
 #endif /* _LINUX_VIRTIO_RNG_H */
index 7ef0c7b..cf24c20 100644 (file)
@@ -207,6 +207,7 @@ extern int queue_delayed_work_on(int cpu, struct workqueue_struct *wq,
 
 extern void flush_workqueue(struct workqueue_struct *wq);
 extern void flush_scheduled_work(void);
+extern void flush_delayed_work(struct delayed_work *work);
 
 extern int schedule_work(struct work_struct *work);
 extern int schedule_work_on(int cpu, struct work_struct *work);
index e268122..fb00b32 100644 (file)
@@ -159,8 +159,7 @@ struct p9_client {
  * @qid: the &p9_qid server identifier this handle points to
  * @iounit: the server reported maximum transaction size for this file
  * @uid: the numeric uid of the local user who owns this handle
- * @aux: transport specific information (unused?)
- * @rdir_fpos: tracks offset of file position when reading directory contents
+ * @rdir: readdir accounting structure (allocated on demand)
  * @flist: per-client-instance fid tracking
  * @dlist: per-dentry fid tracking
  *
@@ -174,9 +173,9 @@ struct p9_fid {
        struct p9_qid qid;
        u32 iounit;
        uid_t uid;
-       void *aux;
 
-       int rdir_fpos;
+       void *rdir;
+
        struct list_head flist;
        struct list_head dlist; /* list of all fids attached to a dentry */
 };
index b63b80f..f93ad90 100644 (file)
@@ -130,11 +130,11 @@ struct inet_timewait_sock {
        __u16                   tw_num;
        kmemcheck_bitfield_begin(flags);
        /* And these are ours. */
-       __u8                    tw_ipv6only:1,
-                               tw_transparent:1;
-       /* 14 bits hole, try to pack */
+       unsigned int            tw_ipv6only     : 1,
+                               tw_transparent  : 1,
+                               tw_pad          : 14,   /* 14 bits hole */
+                               tw_ipv6_offset  : 16;
        kmemcheck_bitfield_end(flags);
-       __u16                   tw_ipv6_offset;
        unsigned long           tw_ttd;
        struct inet_bind_bucket *tw_tb;
        struct hlist_node       tw_death_node;
index ef91fe9..4d22fab 100644 (file)
@@ -210,7 +210,8 @@ extern struct fib_table *fib_get_table(struct net *net, u32 id);
 extern const struct nla_policy rtm_ipv4_policy[];
 extern void            ip_fib_init(void);
 extern int fib_validate_source(__be32 src, __be32 dst, u8 tos, int oif,
-                              struct net_device *dev, __be32 *spec_dst, u32 *itag);
+                              struct net_device *dev, __be32 *spec_dst,
+                              u32 *itag, u32 mark);
 extern void fib_select_default(struct net *net, const struct flowi *flp,
                               struct fib_result *res);
 
index 466859b..c75b960 100644 (file)
@@ -1669,6 +1669,8 @@ void ieee80211_restart_hw(struct ieee80211_hw *hw);
  * to this function and ieee80211_rx_irqsafe() may not be mixed for a
  * single hardware.
  *
+ * Note that right now, this function must be called with softirqs disabled.
+ *
  * @hw: the hardware this frame came in on
  * @skb: the buffer to receive, owned by mac80211 after this call
  */
index 1621935..9f96394 100644 (file)
@@ -226,12 +226,12 @@ struct sock {
 #define sk_prot                        __sk_common.skc_prot
 #define sk_net                 __sk_common.skc_net
        kmemcheck_bitfield_begin(flags);
-       unsigned char           sk_shutdown : 2,
-                               sk_no_check : 2,
-                               sk_userlocks : 4;
+       unsigned int            sk_shutdown  : 2,
+                               sk_no_check  : 2,
+                               sk_userlocks : 4,
+                               sk_protocol  : 8,
+                               sk_type      : 16;
        kmemcheck_bitfield_end(flags);
-       unsigned char           sk_protocol;
-       unsigned short          sk_type;
        int                     sk_rcvbuf;
        socket_lock_t           sk_lock;
        /*
index d696a69..e0f6feb 100644 (file)
@@ -262,6 +262,8 @@ struct pcmcia_socket {
        struct device                   dev;
        /* data internal to the socket driver */
        void                            *driver_data;
+       /* status of the card during resume from a system sleep state */
+       int                             resume_status;
 };
 
 
@@ -280,6 +282,8 @@ extern struct pccard_resource_ops pccard_nonstatic_ops;
 
 /* socket drivers are expected to use these callbacks in their .drv struct */
 extern int pcmcia_socket_dev_suspend(struct device *dev);
+extern void pcmcia_socket_dev_early_resume(struct device *dev);
+extern void pcmcia_socket_dev_late_resume(struct device *dev);
 extern int pcmcia_socket_dev_resume(struct device *dev);
 
 /* socket drivers use this callback in their IRQ handler */
index 887e57e..a72edd4 100644 (file)
@@ -303,6 +303,7 @@ struct iscsi_session {
        int                     cmds_max;       /* size of cmds array */
        struct iscsi_task       **cmds;         /* Original Cmds arr */
        struct iscsi_pool       cmdpool;        /* PDU's pool */
+       void                    *dd_data;       /* LLD private data */
 };
 
 enum {
@@ -363,7 +364,7 @@ extern int iscsi_target_alloc(struct scsi_target *starget);
  */
 extern struct iscsi_cls_session *
 iscsi_session_setup(struct iscsi_transport *, struct Scsi_Host *shost,
-                   uint16_t, int, uint32_t, unsigned int);
+                   uint16_t, int, int, uint32_t, unsigned int);
 extern void iscsi_session_teardown(struct iscsi_cls_session *);
 extern void iscsi_session_recovery_timedout(struct iscsi_cls_session *);
 extern int iscsi_set_param(struct iscsi_cls_conn *cls_conn,
index 084478e..34c46ab 100644 (file)
@@ -129,6 +129,9 @@ struct scsi_cmnd;
 #define MI_REPORT_TARGET_PGS  0x0a
 /* values for maintenance out */
 #define MO_SET_TARGET_PGS     0x0a
+/* values for variable length command */
+#define READ_32                      0x09
+#define WRITE_32             0x0b
 
 /* Values for T10/04-262r7 */
 #define        ATA_16                0x85      /* 16-byte pass-thru */
index 3878d1d..a5e885a 100644 (file)
@@ -229,10 +229,6 @@ enum scsi_prot_operations {
        /* OS-HBA: Protected, HBA-Target: Protected */
        SCSI_PROT_READ_PASS,
        SCSI_PROT_WRITE_PASS,
-
-       /* OS-HBA: Protected, HBA-Target: Protected, checksum conversion */
-       SCSI_PROT_READ_CONVERT,
-       SCSI_PROT_WRITE_CONVERT,
 };
 
 static inline void scsi_set_prot_op(struct scsi_cmnd *scmd, unsigned char op)
index b62a097..6e728b1 100644 (file)
@@ -798,9 +798,15 @@ static inline unsigned int scsi_host_get_prot(struct Scsi_Host *shost)
 static inline unsigned int scsi_host_dif_capable(struct Scsi_Host *shost, unsigned int target_type)
 {
        switch (target_type) {
-       case 1: return shost->prot_capabilities & SHOST_DIF_TYPE1_PROTECTION;
-       case 2: return shost->prot_capabilities & SHOST_DIF_TYPE2_PROTECTION;
-       case 3: return shost->prot_capabilities & SHOST_DIF_TYPE3_PROTECTION;
+       case 1:
+               if (shost->prot_capabilities & SHOST_DIF_TYPE1_PROTECTION)
+                       return target_type;
+       case 2:
+               if (shost->prot_capabilities & SHOST_DIF_TYPE2_PROTECTION)
+                       return target_type;
+       case 3:
+               if (shost->prot_capabilities & SHOST_DIF_TYPE3_PROTECTION)
+                       return target_type;
        }
 
        return 0;
@@ -808,13 +814,14 @@ static inline unsigned int scsi_host_dif_capable(struct Scsi_Host *shost, unsign
 
 static inline unsigned int scsi_host_dix_capable(struct Scsi_Host *shost, unsigned int target_type)
 {
+#if defined(CONFIG_BLK_DEV_INTEGRITY)
        switch (target_type) {
        case 0: return shost->prot_capabilities & SHOST_DIX_TYPE0_PROTECTION;
        case 1: return shost->prot_capabilities & SHOST_DIX_TYPE1_PROTECTION;
        case 2: return shost->prot_capabilities & SHOST_DIX_TYPE2_PROTECTION;
        case 3: return shost->prot_capabilities & SHOST_DIX_TYPE3_PROTECTION;
        }
-
+#endif
        return 0;
 }
 
index c7bac39..f515864 100644 (file)
@@ -297,7 +297,7 @@ config AUDIT
 
 config AUDITSYSCALL
        bool "Enable system-call auditing support"
-       depends on AUDIT && (X86 || PPC || PPC64 || S390 || IA64 || UML || SPARC64|| SUPERH)
+       depends on AUDIT && (X86 || PPC || S390 || IA64 || UML || SPARC64 || SUPERH)
        default y if SECURITY_SELINUX
        help
          Enable low-overhead system-call auditing infrastructure that
@@ -921,6 +921,11 @@ config HAVE_PERF_EVENTS
        help
          See tools/perf/design.txt for details.
 
+config PERF_USE_VMALLOC
+       bool
+       help
+         See tools/perf/design.txt for details
+
 menu "Kernel Performance Events And Counters"
 
 config PERF_EVENTS
@@ -976,6 +981,19 @@ config PERF_COUNTERS
 
          Say N if unsure.
 
+config DEBUG_PERF_USE_VMALLOC
+       default n
+       bool "Debug: use vmalloc to back perf mmap() buffers"
+       depends on PERF_EVENTS && DEBUG_KERNEL
+       select PERF_USE_VMALLOC
+       help
+        Use vmalloc memory to back perf mmap() buffers.
+
+        Mostly useful for debugging the vmalloc code on platforms
+        that don't require it.
+
+        Say N if unsure.
+
 endmenu
 
 config VM_EVENT_COUNTERS
index 7449819..5988deb 100644 (file)
@@ -778,7 +778,6 @@ static void __init do_initcalls(void)
  */
 static void __init do_basic_setup(void)
 {
-       rcu_init_sched(); /* needed by module_init stage. */
        init_workqueues();
        cpuset_init_smp();
        usermodehelper_init();
index ca83b73..0249f4b 100644 (file)
@@ -1710,14 +1710,13 @@ static ssize_t cgroup_write_X64(struct cgroup *cgrp, struct cftype *cft,
                return -EFAULT;
 
        buffer[nbytes] = 0;     /* nul-terminate */
-       strstrip(buffer);
        if (cft->write_u64) {
-               u64 val = simple_strtoull(buffer, &end, 0);
+               u64 val = simple_strtoull(strstrip(buffer), &end, 0);
                if (*end)
                        return -EINVAL;
                retval = cft->write_u64(cgrp, cft, val);
        } else {
-               s64 val = simple_strtoll(buffer, &end, 0);
+               s64 val = simple_strtoll(strstrip(buffer), &end, 0);
                if (*end)
                        return -EINVAL;
                retval = cft->write_s64(cgrp, cft, val);
@@ -1753,8 +1752,7 @@ static ssize_t cgroup_write_string(struct cgroup *cgrp, struct cftype *cft,
        }
 
        buffer[nbytes] = 0;     /* nul-terminate */
-       strstrip(buffer);
-       retval = cft->write_string(cgrp, cft, buffer);
+       retval = cft->write_string(cgrp, cft, strstrip(buffer));
        if (!retval)
                retval = nbytes;
 out:
index 5859f59..f7864ac 100644 (file)
@@ -359,10 +359,8 @@ void __set_special_pids(struct pid *pid)
 {
        struct task_struct *curr = current->group_leader;
 
-       if (task_session(curr) != pid) {
+       if (task_session(curr) != pid)
                change_pid(curr, PIDTYPE_SID, pid);
-               proc_sid_connector(curr);
-       }
 
        if (task_pgrp(curr) != pid)
                change_pid(curr, PIDTYPE_PGID, pid);
@@ -991,8 +989,6 @@ NORET_TYPE void do_exit(long code)
        tsk->mempolicy = NULL;
 #endif
 #ifdef CONFIG_FUTEX
-       if (unlikely(!list_empty(&tsk->pi_state_list)))
-               exit_pi_state_list(tsk);
        if (unlikely(current->pi_state_cache))
                kfree(current->pi_state_cache);
 #endif
index 266c6af..166b8c4 100644 (file)
@@ -91,7 +91,7 @@ int nr_processes(void)
        int cpu;
        int total = 0;
 
-       for_each_online_cpu(cpu)
+       for_each_possible_cpu(cpu)
                total += per_cpu(process_counts, cpu);
 
        return total;
@@ -570,12 +570,18 @@ void mm_release(struct task_struct *tsk, struct mm_struct *mm)
 
        /* Get rid of any futexes when releasing the mm */
 #ifdef CONFIG_FUTEX
-       if (unlikely(tsk->robust_list))
+       if (unlikely(tsk->robust_list)) {
                exit_robust_list(tsk);
+               tsk->robust_list = NULL;
+       }
 #ifdef CONFIG_COMPAT
-       if (unlikely(tsk->compat_robust_list))
+       if (unlikely(tsk->compat_robust_list)) {
                compat_exit_robust_list(tsk);
+               tsk->compat_robust_list = NULL;
+       }
 #endif
+       if (unlikely(!list_empty(&tsk->pi_state_list)))
+               exit_pi_state_list(tsk);
 #endif
 
        /* Get rid of any cached register state */
index b911adc..fb65e82 100644 (file)
@@ -150,7 +150,8 @@ static struct futex_hash_bucket *hash_futex(union futex_key *key)
  */
 static inline int match_futex(union futex_key *key1, union futex_key *key2)
 {
-       return (key1->both.word == key2->both.word
+       return (key1 && key2
+               && key1->both.word == key2->both.word
                && key1->both.ptr == key2->both.ptr
                && key1->both.offset == key2->both.offset);
 }
@@ -916,8 +917,8 @@ retry:
        hb1 = hash_futex(&key1);
        hb2 = hash_futex(&key2);
 
-       double_lock_hb(hb1, hb2);
 retry_private:
+       double_lock_hb(hb1, hb2);
        op_ret = futex_atomic_op_inuser(op, uaddr2);
        if (unlikely(op_ret < 0)) {
 
@@ -1028,7 +1029,6 @@ static inline
 void requeue_pi_wake_futex(struct futex_q *q, union futex_key *key,
                           struct futex_hash_bucket *hb)
 {
-       drop_futex_key_refs(&q->key);
        get_futex_key_refs(key);
        q->key = *key;
 
@@ -1226,6 +1226,7 @@ retry_private:
                 */
                if (ret == 1) {
                        WARN_ON(pi_state);
+                       drop_count++;
                        task_count++;
                        ret = get_futex_value_locked(&curval2, uaddr2);
                        if (!ret)
@@ -1304,6 +1305,7 @@ retry_private:
                        if (ret == 1) {
                                /* We got the lock. */
                                requeue_pi_wake_futex(this, &key2, hb2);
+                               drop_count++;
                                continue;
                        } else if (ret) {
                                /* -EDEADLK */
@@ -1791,6 +1793,7 @@ static int futex_wait(u32 __user *uaddr, int fshared,
                                             current->timer_slack_ns);
        }
 
+retry:
        /* Prepare to wait on uaddr. */
        ret = futex_wait_setup(uaddr, val, fshared, &q, &hb);
        if (ret)
@@ -1808,9 +1811,14 @@ static int futex_wait(u32 __user *uaddr, int fshared,
                goto out_put_key;
 
        /*
-        * We expect signal_pending(current), but another thread may
-        * have handled it for us already.
+        * We expect signal_pending(current), but we might be the
+        * victim of a spurious wakeup as well.
         */
+       if (!signal_pending(current)) {
+               put_futex_key(fshared, &q.key);
+               goto retry;
+       }
+
        ret = -ERESTARTSYS;
        if (!abs_time)
                goto out_put_key;
@@ -2117,11 +2125,12 @@ int handle_early_requeue_pi_wakeup(struct futex_hash_bucket *hb,
                 * Unqueue the futex_q and determine which it was.
                 */
                plist_del(&q->list, &q->list.plist);
-               drop_futex_key_refs(&q->key);
 
+               /* Handle spurious wakeups gracefully */
+               ret = -EWOULDBLOCK;
                if (timeout && !timeout->task)
                        ret = -ETIMEDOUT;
-               else
+               else if (signal_pending(current))
                        ret = -ERESTARTNOINTR;
        }
        return ret;
index 6d70204..3e1c36e 100644 (file)
@@ -726,8 +726,6 @@ static int hrtimer_switch_to_hres(void)
        /* "Retrigger" the interrupt to get things going */
        retrigger_next_event(NULL);
        local_irq_restore(flags);
-       printk(KERN_DEBUG "Switched to high resolution mode on CPU %d\n",
-              smp_processor_id());
        return 1;
 }
 
index a81cf80..17c71bb 100644 (file)
@@ -11,6 +11,7 @@
  */
 
 #include <linux/irq.h>
+#include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/module.h>
 #include <linux/random.h>
index 3815ac1..9af5672 100644 (file)
@@ -142,6 +142,11 @@ static inline struct lock_class *hlock_class(struct held_lock *hlock)
 #ifdef CONFIG_LOCK_STAT
 static DEFINE_PER_CPU(struct lock_class_stats[MAX_LOCKDEP_KEYS], lock_stats);
 
+static inline u64 lockstat_clock(void)
+{
+       return cpu_clock(smp_processor_id());
+}
+
 static int lock_point(unsigned long points[], unsigned long ip)
 {
        int i;
@@ -158,7 +163,7 @@ static int lock_point(unsigned long points[], unsigned long ip)
        return i;
 }
 
-static void lock_time_inc(struct lock_time *lt, s64 time)
+static void lock_time_inc(struct lock_time *lt, u64 time)
 {
        if (time > lt->max)
                lt->max = time;
@@ -234,12 +239,12 @@ static void put_lock_stats(struct lock_class_stats *stats)
 static void lock_release_holdtime(struct held_lock *hlock)
 {
        struct lock_class_stats *stats;
-       s64 holdtime;
+       u64 holdtime;
 
        if (!lock_stat)
                return;
 
-       holdtime = sched_clock() - hlock->holdtime_stamp;
+       holdtime = lockstat_clock() - hlock->holdtime_stamp;
 
        stats = get_lock_stats(hlock_class(hlock));
        if (hlock->read)
@@ -2792,7 +2797,7 @@ static int __lock_acquire(struct lockdep_map *lock, unsigned int subclass,
        hlock->references = references;
 #ifdef CONFIG_LOCK_STAT
        hlock->waittime_stamp = 0;
-       hlock->holdtime_stamp = sched_clock();
+       hlock->holdtime_stamp = lockstat_clock();
 #endif
 
        if (check == 2 && !mark_irqflags(curr, hlock))
@@ -3322,7 +3327,7 @@ found_it:
        if (hlock->instance != lock)
                return;
 
-       hlock->waittime_stamp = sched_clock();
+       hlock->waittime_stamp = lockstat_clock();
 
        contention_point = lock_point(hlock_class(hlock)->contention_point, ip);
        contending_point = lock_point(hlock_class(hlock)->contending_point,
@@ -3345,8 +3350,7 @@ __lock_acquired(struct lockdep_map *lock, unsigned long ip)
        struct held_lock *hlock, *prev_hlock;
        struct lock_class_stats *stats;
        unsigned int depth;
-       u64 now;
-       s64 waittime = 0;
+       u64 now, waittime = 0;
        int i, cpu;
 
        depth = curr->lockdep_depth;
@@ -3374,7 +3378,7 @@ found_it:
 
        cpu = smp_processor_id();
        if (hlock->waittime_stamp) {
-               now = sched_clock();
+               now = lockstat_clock();
                waittime = now - hlock->waittime_stamp;
                hlock->holdtime_stamp = now;
        }
index 50d022e..ec815a9 100644 (file)
@@ -16,6 +16,7 @@
 #include <linux/delay.h>
 #include <linux/module.h>
 #include <linux/poison.h>
+#include <linux/sched.h>
 #include <linux/spinlock.h>
 #include <linux/kallsyms.h>
 #include <linux/interrupt.h>
index bcdef26..96b45d0 100644 (file)
@@ -90,6 +90,8 @@ NORET_TYPE void panic(const char * fmt, ...)
 
        atomic_notifier_call_chain(&panic_notifier_list, 0, buf);
 
+       bust_spinlocks(0);
+
        if (!panic_blink)
                panic_blink = no_blink;
 
@@ -136,7 +138,6 @@ NORET_TYPE void panic(const char * fmt, ...)
                mdelay(1);
                i++;
        }
-       bust_spinlocks(0);
 }
 
 EXPORT_SYMBOL(panic);
index 9da58ea..d656c27 100644 (file)
@@ -218,15 +218,11 @@ int param_set_charp(const char *val, struct kernel_param *kp)
                return -ENOSPC;
        }
 
-       if (kp->flags & KPARAM_KMALLOCED)
-               kfree(*(char **)kp->arg);
-
        /* This is a hack.  We can't need to strdup in early boot, and we
         * don't need to; this mangled commandline is preserved. */
        if (slab_is_available()) {
-               kp->flags |= KPARAM_KMALLOCED;
                *(char **)kp->arg = kstrdup(val, GFP_KERNEL);
-               if (!kp->arg)
+               if (!*(char **)kp->arg)
                        return -ENOMEM;
        } else
                *(const char **)kp->arg = val;
@@ -304,6 +300,7 @@ static int param_array(const char *name,
                       unsigned int min, unsigned int max,
                       void *elem, int elemsize,
                       int (*set)(const char *, struct kernel_param *kp),
+                      u16 flags,
                       unsigned int *num)
 {
        int ret;
@@ -313,6 +310,7 @@ static int param_array(const char *name,
        /* Get the name right for errors. */
        kp.name = name;
        kp.arg = elem;
+       kp.flags = flags;
 
        /* No equals sign? */
        if (!val) {
@@ -358,7 +356,8 @@ int param_array_set(const char *val, struct kernel_param *kp)
        unsigned int temp_num;
 
        return param_array(kp->name, val, 1, arr->max, arr->elem,
-                          arr->elemsize, arr->set, arr->num ?: &temp_num);
+                          arr->elemsize, arr->set, kp->flags,
+                          arr->num ?: &temp_num);
 }
 
 int param_array_get(char *buffer, struct kernel_param *kp)
@@ -605,11 +604,7 @@ void module_param_sysfs_remove(struct module *mod)
 
 void destroy_params(const struct kernel_param *params, unsigned num)
 {
-       unsigned int i;
-
-       for (i = 0; i < num; i++)
-               if (params[i].flags & KPARAM_KMALLOCED)
-                       kfree(*(char **)params[i].arg);
+       /* FIXME: This should free kmalloced charp parameters.  It doesn't. */
 }
 
 static void __init kernel_add_sysfs_param(const char *name,
index 0f86feb..7f29643 100644 (file)
@@ -20,6 +20,7 @@
 #include <linux/percpu.h>
 #include <linux/ptrace.h>
 #include <linux/vmstat.h>
+#include <linux/vmalloc.h>
 #include <linux/hardirq.h>
 #include <linux/rculist.h>
 #include <linux/uaccess.h>
@@ -1030,14 +1031,10 @@ void __perf_event_sched_out(struct perf_event_context *ctx,
        update_context_time(ctx);
 
        perf_disable();
-       if (ctx->nr_active) {
-               list_for_each_entry(event, &ctx->group_list, group_entry) {
-                       if (event != event->group_leader)
-                               event_sched_out(event, cpuctx, ctx);
-                       else
-                               group_sched_out(event, cpuctx, ctx);
-               }
-       }
+       if (ctx->nr_active)
+               list_for_each_entry(event, &ctx->group_list, group_entry)
+                       group_sched_out(event, cpuctx, ctx);
+
        perf_enable();
  out:
        spin_unlock(&ctx->lock);
@@ -1258,12 +1255,8 @@ __perf_event_sched_in(struct perf_event_context *ctx,
                if (event->cpu != -1 && event->cpu != cpu)
                        continue;
 
-               if (event != event->group_leader)
-                       event_sched_in(event, cpuctx, ctx, cpu);
-               else {
-                       if (group_can_go_on(event, cpuctx, 1))
-                               group_sched_in(event, cpuctx, ctx, cpu);
-               }
+               if (group_can_go_on(event, cpuctx, 1))
+                       group_sched_in(event, cpuctx, ctx, cpu);
 
                /*
                 * If this pinned group hasn't been scheduled,
@@ -1291,15 +1284,9 @@ __perf_event_sched_in(struct perf_event_context *ctx,
                if (event->cpu != -1 && event->cpu != cpu)
                        continue;
 
-               if (event != event->group_leader) {
-                       if (event_sched_in(event, cpuctx, ctx, cpu))
+               if (group_can_go_on(event, cpuctx, can_add_hw))
+                       if (group_sched_in(event, cpuctx, ctx, cpu))
                                can_add_hw = 0;
-               } else {
-                       if (group_can_go_on(event, cpuctx, can_add_hw)) {
-                               if (group_sched_in(event, cpuctx, ctx, cpu))
-                                       can_add_hw = 0;
-                       }
-               }
        }
        perf_enable();
  out:
@@ -1368,7 +1355,7 @@ static void perf_ctx_adjust_freq(struct perf_event_context *ctx)
        u64 interrupts, freq;
 
        spin_lock(&ctx->lock);
-       list_for_each_entry(event, &ctx->group_list, group_entry) {
+       list_for_each_entry_rcu(event, &ctx->event_list, event_entry) {
                if (event->state != PERF_EVENT_STATE_ACTIVE)
                        continue;
 
@@ -2105,49 +2092,31 @@ unlock:
        rcu_read_unlock();
 }
 
-static int perf_mmap_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
+static unsigned long perf_data_size(struct perf_mmap_data *data)
 {
-       struct perf_event *event = vma->vm_file->private_data;
-       struct perf_mmap_data *data;
-       int ret = VM_FAULT_SIGBUS;
-
-       if (vmf->flags & FAULT_FLAG_MKWRITE) {
-               if (vmf->pgoff == 0)
-                       ret = 0;
-               return ret;
-       }
-
-       rcu_read_lock();
-       data = rcu_dereference(event->data);
-       if (!data)
-               goto unlock;
-
-       if (vmf->pgoff == 0) {
-               vmf->page = virt_to_page(data->user_page);
-       } else {
-               int nr = vmf->pgoff - 1;
-
-               if ((unsigned)nr > data->nr_pages)
-                       goto unlock;
+       return data->nr_pages << (PAGE_SHIFT + data->data_order);
+}
 
-               if (vmf->flags & FAULT_FLAG_WRITE)
-                       goto unlock;
+#ifndef CONFIG_PERF_USE_VMALLOC
 
-               vmf->page = virt_to_page(data->data_pages[nr]);
-       }
+/*
+ * Back perf_mmap() with regular GFP_KERNEL-0 pages.
+ */
 
-       get_page(vmf->page);
-       vmf->page->mapping = vma->vm_file->f_mapping;
-       vmf->page->index   = vmf->pgoff;
+static struct page *
+perf_mmap_to_page(struct perf_mmap_data *data, unsigned long pgoff)
+{
+       if (pgoff > data->nr_pages)
+               return NULL;
 
-       ret = 0;
-unlock:
-       rcu_read_unlock();
+       if (pgoff == 0)
+               return virt_to_page(data->user_page);
 
-       return ret;
+       return virt_to_page(data->data_pages[pgoff - 1]);
 }
 
-static int perf_mmap_data_alloc(struct perf_event *event, int nr_pages)
+static struct perf_mmap_data *
+perf_mmap_data_alloc(struct perf_event *event, int nr_pages)
 {
        struct perf_mmap_data *data;
        unsigned long size;
@@ -2172,19 +2141,10 @@ static int perf_mmap_data_alloc(struct perf_event *event, int nr_pages)
                        goto fail_data_pages;
        }
 
+       data->data_order = 0;
        data->nr_pages = nr_pages;
-       atomic_set(&data->lock, -1);
-
-       if (event->attr.watermark) {
-               data->watermark = min_t(long, PAGE_SIZE * nr_pages,
-                                     event->attr.wakeup_watermark);
-       }
-       if (!data->watermark)
-               data->watermark = max(PAGE_SIZE, PAGE_SIZE * nr_pages / 4);
-
-       rcu_assign_pointer(event->data, data);
 
-       return 0;
+       return data;
 
 fail_data_pages:
        for (i--; i >= 0; i--)
@@ -2196,7 +2156,7 @@ fail_user_page:
        kfree(data);
 
 fail:
-       return -ENOMEM;
+       return NULL;
 }
 
 static void perf_mmap_free_page(unsigned long addr)
@@ -2207,28 +2167,169 @@ static void perf_mmap_free_page(unsigned long addr)
        __free_page(page);
 }
 
-static void __perf_mmap_data_free(struct rcu_head *rcu_head)
+static void perf_mmap_data_free(struct perf_mmap_data *data)
 {
-       struct perf_mmap_data *data;
        int i;
 
-       data = container_of(rcu_head, struct perf_mmap_data, rcu_head);
-
        perf_mmap_free_page((unsigned long)data->user_page);
        for (i = 0; i < data->nr_pages; i++)
                perf_mmap_free_page((unsigned long)data->data_pages[i]);
+}
+
+#else
+
+/*
+ * Back perf_mmap() with vmalloc memory.
+ *
+ * Required for architectures that have d-cache aliasing issues.
+ */
+
+static struct page *
+perf_mmap_to_page(struct perf_mmap_data *data, unsigned long pgoff)
+{
+       if (pgoff > (1UL << data->data_order))
+               return NULL;
+
+       return vmalloc_to_page((void *)data->user_page + pgoff * PAGE_SIZE);
+}
+
+static void perf_mmap_unmark_page(void *addr)
+{
+       struct page *page = vmalloc_to_page(addr);
+
+       page->mapping = NULL;
+}
+
+static void perf_mmap_data_free_work(struct work_struct *work)
+{
+       struct perf_mmap_data *data;
+       void *base;
+       int i, nr;
+
+       data = container_of(work, struct perf_mmap_data, work);
+       nr = 1 << data->data_order;
 
+       base = data->user_page;
+       for (i = 0; i < nr + 1; i++)
+               perf_mmap_unmark_page(base + (i * PAGE_SIZE));
+
+       vfree(base);
+}
+
+static void perf_mmap_data_free(struct perf_mmap_data *data)
+{
+       schedule_work(&data->work);
+}
+
+static struct perf_mmap_data *
+perf_mmap_data_alloc(struct perf_event *event, int nr_pages)
+{
+       struct perf_mmap_data *data;
+       unsigned long size;
+       void *all_buf;
+
+       WARN_ON(atomic_read(&event->mmap_count));
+
+       size = sizeof(struct perf_mmap_data);
+       size += sizeof(void *);
+
+       data = kzalloc(size, GFP_KERNEL);
+       if (!data)
+               goto fail;
+
+       INIT_WORK(&data->work, perf_mmap_data_free_work);
+
+       all_buf = vmalloc_user((nr_pages + 1) * PAGE_SIZE);
+       if (!all_buf)
+               goto fail_all_buf;
+
+       data->user_page = all_buf;
+       data->data_pages[0] = all_buf + PAGE_SIZE;
+       data->data_order = ilog2(nr_pages);
+       data->nr_pages = 1;
+
+       return data;
+
+fail_all_buf:
        kfree(data);
+
+fail:
+       return NULL;
 }
 
-static void perf_mmap_data_free(struct perf_event *event)
+#endif
+
+static int perf_mmap_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
+{
+       struct perf_event *event = vma->vm_file->private_data;
+       struct perf_mmap_data *data;
+       int ret = VM_FAULT_SIGBUS;
+
+       if (vmf->flags & FAULT_FLAG_MKWRITE) {
+               if (vmf->pgoff == 0)
+                       ret = 0;
+               return ret;
+       }
+
+       rcu_read_lock();
+       data = rcu_dereference(event->data);
+       if (!data)
+               goto unlock;
+
+       if (vmf->pgoff && (vmf->flags & FAULT_FLAG_WRITE))
+               goto unlock;
+
+       vmf->page = perf_mmap_to_page(data, vmf->pgoff);
+       if (!vmf->page)
+               goto unlock;
+
+       get_page(vmf->page);
+       vmf->page->mapping = vma->vm_file->f_mapping;
+       vmf->page->index   = vmf->pgoff;
+
+       ret = 0;
+unlock:
+       rcu_read_unlock();
+
+       return ret;
+}
+
+static void
+perf_mmap_data_init(struct perf_event *event, struct perf_mmap_data *data)
+{
+       long max_size = perf_data_size(data);
+
+       atomic_set(&data->lock, -1);
+
+       if (event->attr.watermark) {
+               data->watermark = min_t(long, max_size,
+                                       event->attr.wakeup_watermark);
+       }
+
+       if (!data->watermark)
+               data->watermark = max_t(long, PAGE_SIZE, max_size / 2);
+
+
+       rcu_assign_pointer(event->data, data);
+}
+
+static void perf_mmap_data_free_rcu(struct rcu_head *rcu_head)
+{
+       struct perf_mmap_data *data;
+
+       data = container_of(rcu_head, struct perf_mmap_data, rcu_head);
+       perf_mmap_data_free(data);
+       kfree(data);
+}
+
+static void perf_mmap_data_release(struct perf_event *event)
 {
        struct perf_mmap_data *data = event->data;
 
        WARN_ON(atomic_read(&event->mmap_count));
 
        rcu_assign_pointer(event->data, NULL);
-       call_rcu(&data->rcu_head, __perf_mmap_data_free);
+       call_rcu(&data->rcu_head, perf_mmap_data_free_rcu);
 }
 
 static void perf_mmap_open(struct vm_area_struct *vma)
@@ -2244,11 +2345,12 @@ static void perf_mmap_close(struct vm_area_struct *vma)
 
        WARN_ON_ONCE(event->ctx->parent_ctx);
        if (atomic_dec_and_mutex_lock(&event->mmap_count, &event->mmap_mutex)) {
+               unsigned long size = perf_data_size(event->data);
                struct user_struct *user = current_user();
 
-               atomic_long_sub(event->data->nr_pages + 1, &user->locked_vm);
+               atomic_long_sub((size >> PAGE_SHIFT) + 1, &user->locked_vm);
                vma->vm_mm->locked_vm -= event->data->nr_locked;
-               perf_mmap_data_free(event);
+               perf_mmap_data_release(event);
                mutex_unlock(&event->mmap_mutex);
        }
 }
@@ -2266,6 +2368,7 @@ static int perf_mmap(struct file *file, struct vm_area_struct *vma)
        unsigned long user_locked, user_lock_limit;
        struct user_struct *user = current_user();
        unsigned long locked, lock_limit;
+       struct perf_mmap_data *data;
        unsigned long vma_size;
        unsigned long nr_pages;
        long user_extra, extra;
@@ -2328,10 +2431,15 @@ static int perf_mmap(struct file *file, struct vm_area_struct *vma)
        }
 
        WARN_ON(event->data);
-       ret = perf_mmap_data_alloc(event, nr_pages);
-       if (ret)
+
+       data = perf_mmap_data_alloc(event, nr_pages);
+       ret = -ENOMEM;
+       if (!data)
                goto unlock;
 
+       ret = 0;
+       perf_mmap_data_init(event, data);
+
        atomic_set(&event->mmap_count, 1);
        atomic_long_add(user_extra, &user->locked_vm);
        vma->vm_mm->locked_vm += extra;
@@ -2519,7 +2627,7 @@ static bool perf_output_space(struct perf_mmap_data *data, unsigned long tail,
        if (!data->writable)
                return true;
 
-       mask = (data->nr_pages << PAGE_SHIFT) - 1;
+       mask = perf_data_size(data) - 1;
 
        offset = (offset - tail) & mask;
        head   = (head   - tail) & mask;
@@ -2624,7 +2732,7 @@ void perf_output_copy(struct perf_output_handle *handle,
                      const void *buf, unsigned int len)
 {
        unsigned int pages_mask;
-       unsigned int offset;
+       unsigned long offset;
        unsigned int size;
        void **pages;
 
@@ -2633,12 +2741,14 @@ void perf_output_copy(struct perf_output_handle *handle,
        pages           = handle->data->data_pages;
 
        do {
-               unsigned int page_offset;
+               unsigned long page_offset;
+               unsigned long page_size;
                int nr;
 
                nr          = (offset >> PAGE_SHIFT) & pages_mask;
-               page_offset = offset & (PAGE_SIZE - 1);
-               size        = min_t(unsigned int, PAGE_SIZE - page_offset, len);
+               page_size   = 1UL << (handle->data->data_order + PAGE_SHIFT);
+               page_offset = offset & (page_size - 1);
+               size        = min_t(unsigned int, page_size - page_offset, len);
 
                memcpy(pages[nr] + page_offset, buf, size);
 
@@ -3849,8 +3959,9 @@ static enum hrtimer_restart perf_swevent_hrtimer(struct hrtimer *hrtimer)
                regs = task_pt_regs(current);
 
        if (regs) {
-               if (perf_event_overflow(event, 0, &data, regs))
-                       ret = HRTIMER_NORESTART;
+               if (!(event->attr.exclude_idle && current->pid == 0))
+                       if (perf_event_overflow(event, 0, &data, regs))
+                               ret = HRTIMER_NORESTART;
        }
 
        period = max_t(u64, 10000, event->hw.sample_period);
@@ -3859,6 +3970,42 @@ static enum hrtimer_restart perf_swevent_hrtimer(struct hrtimer *hrtimer)
        return ret;
 }
 
+static void perf_swevent_start_hrtimer(struct perf_event *event)
+{
+       struct hw_perf_event *hwc = &event->hw;
+
+       hrtimer_init(&hwc->hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
+       hwc->hrtimer.function = perf_swevent_hrtimer;
+       if (hwc->sample_period) {
+               u64 period;
+
+               if (hwc->remaining) {
+                       if (hwc->remaining < 0)
+                               period = 10000;
+                       else
+                               period = hwc->remaining;
+                       hwc->remaining = 0;
+               } else {
+                       period = max_t(u64, 10000, hwc->sample_period);
+               }
+               __hrtimer_start_range_ns(&hwc->hrtimer,
+                               ns_to_ktime(period), 0,
+                               HRTIMER_MODE_REL, 0);
+       }
+}
+
+static void perf_swevent_cancel_hrtimer(struct perf_event *event)
+{
+       struct hw_perf_event *hwc = &event->hw;
+
+       if (hwc->sample_period) {
+               ktime_t remaining = hrtimer_get_remaining(&hwc->hrtimer);
+               hwc->remaining = ktime_to_ns(remaining);
+
+               hrtimer_cancel(&hwc->hrtimer);
+       }
+}
+
 /*
  * Software event: cpu wall time clock
  */
@@ -3881,22 +4028,14 @@ static int cpu_clock_perf_event_enable(struct perf_event *event)
        int cpu = raw_smp_processor_id();
 
        atomic64_set(&hwc->prev_count, cpu_clock(cpu));
-       hrtimer_init(&hwc->hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
-       hwc->hrtimer.function = perf_swevent_hrtimer;
-       if (hwc->sample_period) {
-               u64 period = max_t(u64, 10000, hwc->sample_period);
-               __hrtimer_start_range_ns(&hwc->hrtimer,
-                               ns_to_ktime(period), 0,
-                               HRTIMER_MODE_REL, 0);
-       }
+       perf_swevent_start_hrtimer(event);
 
        return 0;
 }
 
 static void cpu_clock_perf_event_disable(struct perf_event *event)
 {
-       if (event->hw.sample_period)
-               hrtimer_cancel(&event->hw.hrtimer);
+       perf_swevent_cancel_hrtimer(event);
        cpu_clock_perf_event_update(event);
 }
 
@@ -3933,22 +4072,15 @@ static int task_clock_perf_event_enable(struct perf_event *event)
        now = event->ctx->time;
 
        atomic64_set(&hwc->prev_count, now);
-       hrtimer_init(&hwc->hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
-       hwc->hrtimer.function = perf_swevent_hrtimer;
-       if (hwc->sample_period) {
-               u64 period = max_t(u64, 10000, hwc->sample_period);
-               __hrtimer_start_range_ns(&hwc->hrtimer,
-                               ns_to_ktime(period), 0,
-                               HRTIMER_MODE_REL, 0);
-       }
+
+       perf_swevent_start_hrtimer(event);
 
        return 0;
 }
 
 static void task_clock_perf_event_disable(struct perf_event *event)
 {
-       if (event->hw.sample_period)
-               hrtimer_cancel(&event->hw.hrtimer);
+       perf_swevent_cancel_hrtimer(event);
        task_clock_perf_event_update(event, event->ctx->time);
 
 }
@@ -4781,9 +4913,7 @@ int perf_event_init_task(struct task_struct *child)
         * We dont have to disable NMIs - we are only looking at
         * the list, not manipulating it:
         */
-       list_for_each_entry_rcu(event, &parent_ctx->event_list, event_entry) {
-               if (event != event->group_leader)
-                       continue;
+       list_for_each_entry(event, &parent_ctx->group_list, group_entry) {
 
                if (!event->attr.inherit) {
                        inherited_all = 0;
index 04b3a83..04a9e90 100644 (file)
@@ -693,21 +693,22 @@ static int software_resume(void)
        /* The snapshot device should not be opened while we're running */
        if (!atomic_add_unless(&snapshot_device_available, -1, 0)) {
                error = -EBUSY;
+               swsusp_close(FMODE_READ);
                goto Unlock;
        }
 
        pm_prepare_console();
        error = pm_notifier_call_chain(PM_RESTORE_PREPARE);
        if (error)
-               goto Finish;
+               goto close_finish;
 
        error = usermodehelper_disable();
        if (error)
-               goto Finish;
+               goto close_finish;
 
        error = create_basic_memory_bitmaps();
        if (error)
-               goto Finish;
+               goto close_finish;
 
        pr_debug("PM: Preparing processes for restore.\n");
        error = prepare_processes();
@@ -719,6 +720,7 @@ static int software_resume(void)
        pr_debug("PM: Reading hibernation image.\n");
 
        error = swsusp_read(&flags);
+       swsusp_close(FMODE_READ);
        if (!error)
                hibernation_restore(flags & SF_PLATFORM_MODE);
 
@@ -737,6 +739,9 @@ static int software_resume(void)
        mutex_unlock(&pm_mutex);
        pr_debug("PM: Resume from disk failed.\n");
        return error;
+close_finish:
+       swsusp_close(FMODE_READ);
+       goto Finish;
 }
 
 late_initcall(software_resume);
index 17d8bb1..25596e4 100644 (file)
@@ -19,7 +19,7 @@
  * The time it takes is system-specific though, so when we test this
  * during system bootup we allow a LOT of time.
  */
-#define TEST_SUSPEND_SECONDS   5
+#define TEST_SUSPEND_SECONDS   10
 
 static unsigned long suspend_test_start_time;
 
@@ -49,7 +49,8 @@ void suspend_test_finish(const char *label)
         * has some performance issues.  The stack dump of a WARN_ON
         * is more likely to get the right attention than a printk...
         */
-       WARN(msec > (TEST_SUSPEND_SECONDS * 1000), "Component: %s\n", label);
+       WARN(msec > (TEST_SUSPEND_SECONDS * 1000),
+            "Component: %s, time: %u\n", label, msec);
 }
 
 /*
index b101cdc..890f6b1 100644 (file)
@@ -314,7 +314,6 @@ static int save_image(struct swap_map_handle *handle,
 {
        unsigned int m;
        int ret;
-       int error = 0;
        int nr_pages;
        int err2;
        struct bio *bio;
@@ -329,26 +328,27 @@ static int save_image(struct swap_map_handle *handle,
        nr_pages = 0;
        bio = NULL;
        do_gettimeofday(&start);
-       do {
+       while (1) {
                ret = snapshot_read_next(snapshot, PAGE_SIZE);
-               if (ret > 0) {
-                       error = swap_write_page(handle, data_of(*snapshot),
-                                               &bio);
-                       if (error)
-                               break;
-                       if (!(nr_pages % m))
-                               printk("\b\b\b\b%3d%%", nr_pages / m);
-                       nr_pages++;
-               }
-       } while (ret > 0);
+               if (ret <= 0)
+                       break;
+               ret = swap_write_page(handle, data_of(*snapshot), &bio);
+               if (ret)
+                       break;
+               if (!(nr_pages % m))
+                       printk("\b\b\b\b%3d%%", nr_pages / m);
+               nr_pages++;
+       }
        err2 = wait_on_bio_chain(&bio);
        do_gettimeofday(&stop);
-       if (!error)
-               error = err2;
-       if (!error)
+       if (!ret)
+               ret = err2;
+       if (!ret)
                printk("\b\b\b\bdone\n");
+       else
+               printk("\n");
        swsusp_show_speed(&start, &stop, nr_to_write, "Wrote");
-       return error;
+       return ret;
 }
 
 /**
@@ -536,7 +536,8 @@ static int load_image(struct swap_map_handle *handle,
                snapshot_write_finalize(snapshot);
                if (!snapshot_image_loaded(snapshot))
                        error = -ENODATA;
-       }
+       } else
+               printk("\n");
        swsusp_show_speed(&start, &stop, nr_to_read, "Read");
        return error;
 }
@@ -572,8 +573,6 @@ int swsusp_read(unsigned int *flags_p)
                error = load_image(&handle, &snapshot, header->pages - 1);
        release_swap_reader(&handle);
 
-       blkdev_put(resume_bdev, FMODE_READ);
-
        if (!error)
                pr_debug("PM: Image successfully loaded\n");
        else
@@ -596,7 +595,7 @@ int swsusp_check(void)
                error = bio_read_page(swsusp_resume_block,
                                        swsusp_header, NULL);
                if (error)
-                       return error;
+                       goto put;
 
                if (!memcmp(SWSUSP_SIG, swsusp_header->sig, 10)) {
                        memcpy(swsusp_header->sig, swsusp_header->orig_sig, 10);
@@ -604,8 +603,10 @@ int swsusp_check(void)
                        error = bio_write_page(swsusp_resume_block,
                                                swsusp_header, NULL);
                } else {
-                       return -EINVAL;
+                       error = -EINVAL;
                }
+
+put:
                if (error)
                        blkdev_put(resume_bdev, FMODE_READ);
                else
index 37ac454..4001833 100644 (file)
 #include <linux/module.h>
 #include <linux/kernel_stat.h>
 
-enum rcu_barrier {
-       RCU_BARRIER_STD,
-       RCU_BARRIER_BH,
-       RCU_BARRIER_SCHED,
-};
+#ifdef CONFIG_DEBUG_LOCK_ALLOC
+static struct lock_class_key rcu_lock_key;
+struct lockdep_map rcu_lock_map =
+       STATIC_LOCKDEP_MAP_INIT("rcu_read_lock", &rcu_lock_key);
+EXPORT_SYMBOL_GPL(rcu_lock_map);
+#endif
 
-static DEFINE_PER_CPU(struct rcu_head, rcu_barrier_head) = {NULL};
-static atomic_t rcu_barrier_cpu_count;
-static DEFINE_MUTEX(rcu_barrier_mutex);
-static struct completion rcu_barrier_completion;
 int rcu_scheduler_active __read_mostly;
 
-static atomic_t rcu_migrate_type_count = ATOMIC_INIT(0);
-static struct rcu_head rcu_migrate_head[3];
-static DECLARE_WAIT_QUEUE_HEAD(rcu_migrate_wq);
-
 /*
  * Awaken the corresponding synchronize_rcu() instance now that a
  * grace period has elapsed.
@@ -164,129 +157,10 @@ void synchronize_rcu_bh(void)
 }
 EXPORT_SYMBOL_GPL(synchronize_rcu_bh);
 
-static void rcu_barrier_callback(struct rcu_head *notused)
-{
-       if (atomic_dec_and_test(&rcu_barrier_cpu_count))
-               complete(&rcu_barrier_completion);
-}
-
-/*
- * Called with preemption disabled, and from cross-cpu IRQ context.
- */
-static void rcu_barrier_func(void *type)
-{
-       int cpu = smp_processor_id();
-       struct rcu_head *head = &per_cpu(rcu_barrier_head, cpu);
-
-       atomic_inc(&rcu_barrier_cpu_count);
-       switch ((enum rcu_barrier)type) {
-       case RCU_BARRIER_STD:
-               call_rcu(head, rcu_barrier_callback);
-               break;
-       case RCU_BARRIER_BH:
-               call_rcu_bh(head, rcu_barrier_callback);
-               break;
-       case RCU_BARRIER_SCHED:
-               call_rcu_sched(head, rcu_barrier_callback);
-               break;
-       }
-}
-
-static inline void wait_migrated_callbacks(void)
-{
-       wait_event(rcu_migrate_wq, !atomic_read(&rcu_migrate_type_count));
-       smp_mb(); /* In case we didn't sleep. */
-}
-
-/*
- * Orchestrate the specified type of RCU barrier, waiting for all
- * RCU callbacks of the specified type to complete.
- */
-static void _rcu_barrier(enum rcu_barrier type)
-{
-       BUG_ON(in_interrupt());
-       /* Take cpucontrol mutex to protect against CPU hotplug */
-       mutex_lock(&rcu_barrier_mutex);
-       init_completion(&rcu_barrier_completion);
-       /*
-        * Initialize rcu_barrier_cpu_count to 1, then invoke
-        * rcu_barrier_func() on each CPU, so that each CPU also has
-        * incremented rcu_barrier_cpu_count.  Only then is it safe to
-        * decrement rcu_barrier_cpu_count -- otherwise the first CPU
-        * might complete its grace period before all of the other CPUs
-        * did their increment, causing this function to return too
-        * early.
-        */
-       atomic_set(&rcu_barrier_cpu_count, 1);
-       on_each_cpu(rcu_barrier_func, (void *)type, 1);
-       if (atomic_dec_and_test(&rcu_barrier_cpu_count))
-               complete(&rcu_barrier_completion);
-       wait_for_completion(&rcu_barrier_completion);
-       mutex_unlock(&rcu_barrier_mutex);
-       wait_migrated_callbacks();
-}
-
-/**
- * rcu_barrier - Wait until all in-flight call_rcu() callbacks complete.
- */
-void rcu_barrier(void)
-{
-       _rcu_barrier(RCU_BARRIER_STD);
-}
-EXPORT_SYMBOL_GPL(rcu_barrier);
-
-/**
- * rcu_barrier_bh - Wait until all in-flight call_rcu_bh() callbacks complete.
- */
-void rcu_barrier_bh(void)
-{
-       _rcu_barrier(RCU_BARRIER_BH);
-}
-EXPORT_SYMBOL_GPL(rcu_barrier_bh);
-
-/**
- * rcu_barrier_sched - Wait for in-flight call_rcu_sched() callbacks.
- */
-void rcu_barrier_sched(void)
-{
-       _rcu_barrier(RCU_BARRIER_SCHED);
-}
-EXPORT_SYMBOL_GPL(rcu_barrier_sched);
-
-static void rcu_migrate_callback(struct rcu_head *notused)
-{
-       if (atomic_dec_and_test(&rcu_migrate_type_count))
-               wake_up(&rcu_migrate_wq);
-}
-
-extern int rcu_cpu_notify(struct notifier_block *self,
-                         unsigned long action, void *hcpu);
-
 static int __cpuinit rcu_barrier_cpu_hotplug(struct notifier_block *self,
                unsigned long action, void *hcpu)
 {
-       rcu_cpu_notify(self, action, hcpu);
-       if (action == CPU_DYING) {
-               /*
-                * preempt_disable() in on_each_cpu() prevents stop_machine(),
-                * so when "on_each_cpu(rcu_barrier_func, (void *)type, 1);"
-                * returns, all online cpus have queued rcu_barrier_func(),
-                * and the dead cpu(if it exist) queues rcu_migrate_callback()s.
-                *
-                * These callbacks ensure _rcu_barrier() waits for all
-                * RCU callbacks of the specified type to complete.
-                */
-               atomic_set(&rcu_migrate_type_count, 3);
-               call_rcu_bh(rcu_migrate_head, rcu_migrate_callback);
-               call_rcu_sched(rcu_migrate_head + 1, rcu_migrate_callback);
-               call_rcu(rcu_migrate_head + 2, rcu_migrate_callback);
-       } else if (action == CPU_DOWN_PREPARE) {
-               /* Don't need to wait until next removal operation. */
-               /* rcu_migrate_head is protected by cpu_add_remove_lock */
-               wait_migrated_callbacks();
-       }
-
-       return NOTIFY_OK;
+       return rcu_cpu_notify(self, action, hcpu);
 }
 
 void __init rcu_init(void)
index 233768f..697c0a0 100644 (file)
@@ -606,8 +606,6 @@ static struct rcu_torture_ops sched_ops_sync = {
        .name           = "sched_sync"
 };
 
-extern int rcu_expedited_torture_stats(char *page);
-
 static struct rcu_torture_ops sched_expedited_ops = {
        .init           = rcu_sync_torture_init,
        .cleanup        = NULL,
@@ -650,7 +648,7 @@ rcu_torture_writer(void *arg)
                old_rp = rcu_torture_current;
                rp->rtort_mbtest = 1;
                rcu_assign_pointer(rcu_torture_current, rp);
-               smp_wmb();
+               smp_wmb(); /* Mods to old_rp must follow rcu_assign_pointer() */
                if (old_rp) {
                        i = old_rp->rtort_pipe_count;
                        if (i > RCU_TORTURE_PIPE_LEN)
index 52b06f6..0536125 100644 (file)
 
 #include "rcutree.h"
 
-#ifdef CONFIG_DEBUG_LOCK_ALLOC
-static struct lock_class_key rcu_lock_key;
-struct lockdep_map rcu_lock_map =
-       STATIC_LOCKDEP_MAP_INIT("rcu_read_lock", &rcu_lock_key);
-EXPORT_SYMBOL_GPL(rcu_lock_map);
-#endif
-
 /* Data structures. */
 
 #define RCU_STATE_INITIALIZER(name) { \
@@ -70,6 +63,9 @@ EXPORT_SYMBOL_GPL(rcu_lock_map);
        .gpnum = -300, \
        .completed = -300, \
        .onofflock = __SPIN_LOCK_UNLOCKED(&name.onofflock), \
+       .orphan_cbs_list = NULL, \
+       .orphan_cbs_tail = &name.orphan_cbs_list, \
+       .orphan_qlen = 0, \
        .fqslock = __SPIN_LOCK_UNLOCKED(&name.fqslock), \
        .n_force_qs = 0, \
        .n_force_qs_ngp = 0, \
@@ -81,24 +77,16 @@ DEFINE_PER_CPU(struct rcu_data, rcu_sched_data);
 struct rcu_state rcu_bh_state = RCU_STATE_INITIALIZER(rcu_bh_state);
 DEFINE_PER_CPU(struct rcu_data, rcu_bh_data);
 
-extern long rcu_batches_completed_sched(void);
-static struct rcu_node *rcu_get_root(struct rcu_state *rsp);
-static void cpu_quiet_msk(unsigned long mask, struct rcu_state *rsp,
-                         struct rcu_node *rnp, unsigned long flags);
-static void cpu_quiet_msk_finish(struct rcu_state *rsp, unsigned long flags);
-#ifdef CONFIG_HOTPLUG_CPU
-static void __rcu_offline_cpu(int cpu, struct rcu_state *rsp);
-#endif /* #ifdef CONFIG_HOTPLUG_CPU */
-static void __rcu_process_callbacks(struct rcu_state *rsp,
-                                   struct rcu_data *rdp);
-static void __call_rcu(struct rcu_head *head,
-                      void (*func)(struct rcu_head *rcu),
-                      struct rcu_state *rsp);
-static int __rcu_pending(struct rcu_state *rsp, struct rcu_data *rdp);
-static void __cpuinit rcu_init_percpu_data(int cpu, struct rcu_state *rsp,
-                                          int preemptable);
 
-#include "rcutree_plugin.h"
+/*
+ * Return true if an RCU grace period is in progress.  The ACCESS_ONCE()s
+ * permit this function to be invoked without holding the root rcu_node
+ * structure's ->lock, but of course results can be subject to change.
+ */
+static int rcu_gp_in_progress(struct rcu_state *rsp)
+{
+       return ACCESS_ONCE(rsp->completed) != ACCESS_ONCE(rsp->gpnum);
+}
 
 /*
  * Note a quiescent state.  Because we do not need to know
@@ -137,6 +125,10 @@ static int blimit = 10;            /* Maximum callbacks per softirq. */
 static int qhimark = 10000;    /* If this many pending, ignore blimit. */
 static int qlowmark = 100;     /* Once only this many pending, use blimit. */
 
+module_param(blimit, int, 0);
+module_param(qhimark, int, 0);
+module_param(qlowmark, int, 0);
+
 static void force_quiescent_state(struct rcu_state *rsp, int relaxed);
 static int rcu_pending(int cpu);
 
@@ -173,9 +165,7 @@ cpu_has_callbacks_ready_to_invoke(struct rcu_data *rdp)
 static int
 cpu_needs_another_gp(struct rcu_state *rsp, struct rcu_data *rdp)
 {
-       /* ACCESS_ONCE() because we are accessing outside of lock. */
-       return *rdp->nxttail[RCU_DONE_TAIL] &&
-              ACCESS_ONCE(rsp->completed) == ACCESS_ONCE(rsp->gpnum);
+       return *rdp->nxttail[RCU_DONE_TAIL] && !rcu_gp_in_progress(rsp);
 }
 
 /*
@@ -369,7 +359,7 @@ static long dyntick_recall_completed(struct rcu_state *rsp)
 /*
  * Snapshot the specified CPU's dynticks counter so that we can later
  * credit them with an implicit quiescent state.  Return 1 if this CPU
- * is already in a quiescent state courtesy of dynticks idle mode.
+ * is in dynticks idle mode, which is an extended quiescent state.
  */
 static int dyntick_save_progress_counter(struct rcu_data *rdp)
 {
@@ -475,30 +465,34 @@ static void print_other_cpu_stall(struct rcu_state *rsp)
        long delta;
        unsigned long flags;
        struct rcu_node *rnp = rcu_get_root(rsp);
-       struct rcu_node *rnp_cur = rsp->level[NUM_RCU_LVLS - 1];
-       struct rcu_node *rnp_end = &rsp->node[NUM_RCU_NODES];
 
        /* Only let one CPU complain about others per time interval. */
 
        spin_lock_irqsave(&rnp->lock, flags);
        delta = jiffies - rsp->jiffies_stall;
-       if (delta < RCU_STALL_RAT_DELAY || rsp->gpnum == rsp->completed) {
+       if (delta < RCU_STALL_RAT_DELAY || !rcu_gp_in_progress(rsp)) {
                spin_unlock_irqrestore(&rnp->lock, flags);
                return;
        }
        rsp->jiffies_stall = jiffies + RCU_SECONDS_TILL_STALL_RECHECK;
+
+       /*
+        * Now rat on any tasks that got kicked up to the root rcu_node
+        * due to CPU offlining.
+        */
+       rcu_print_task_stall(rnp);
        spin_unlock_irqrestore(&rnp->lock, flags);
 
        /* OK, time to rat on our buddy... */
 
        printk(KERN_ERR "INFO: RCU detected CPU stalls:");
-       for (; rnp_cur < rnp_end; rnp_cur++) {
+       rcu_for_each_leaf_node(rsp, rnp) {
                rcu_print_task_stall(rnp);
-               if (rnp_cur->qsmask == 0)
+               if (rnp->qsmask == 0)
                        continue;
-               for (cpu = 0; cpu <= rnp_cur->grphi - rnp_cur->grplo; cpu++)
-                       if (rnp_cur->qsmask & (1UL << cpu))
-                               printk(" %d", rnp_cur->grplo + cpu);
+               for (cpu = 0; cpu <= rnp->grphi - rnp->grplo; cpu++)
+                       if (rnp->qsmask & (1UL << cpu))
+                               printk(" %d", rnp->grplo + cpu);
        }
        printk(" (detected by %d, t=%ld jiffies)\n",
               smp_processor_id(), (long)(jiffies - rsp->gp_start));
@@ -537,8 +531,7 @@ static void check_cpu_stall(struct rcu_state *rsp, struct rcu_data *rdp)
                /* We haven't checked in, so go dump stack. */
                print_cpu_stall(rsp);
 
-       } else if (rsp->gpnum != rsp->completed &&
-                  delta >= RCU_STALL_RAT_DELAY) {
+       } else if (rcu_gp_in_progress(rsp) && delta >= RCU_STALL_RAT_DELAY) {
 
                /* They had two time units to dump stack, so complain. */
                print_other_cpu_stall(rsp);
@@ -617,9 +610,15 @@ rcu_start_gp(struct rcu_state *rsp, unsigned long flags)
        note_new_gpnum(rsp, rdp);
 
        /*
-        * Because we are first, we know that all our callbacks will
-        * be covered by this upcoming grace period, even the ones
-        * that were registered arbitrarily recently.
+        * Because this CPU just now started the new grace period, we know
+        * that all of its callbacks will be covered by this upcoming grace
+        * period, even the ones that were registered arbitrarily recently.
+        * Therefore, advance all outstanding callbacks to RCU_WAIT_TAIL.
+        *
+        * Other CPUs cannot be sure exactly when the grace period started.
+        * Therefore, their recently registered callbacks must pass through
+        * an additional RCU_NEXT_READY stage, so that they will be handled
+        * by the next RCU grace period.
         */
        rdp->nxttail[RCU_NEXT_READY_TAIL] = rdp->nxttail[RCU_NEXT_TAIL];
        rdp->nxttail[RCU_WAIT_TAIL] = rdp->nxttail[RCU_NEXT_TAIL];
@@ -657,7 +656,7 @@ rcu_start_gp(struct rcu_state *rsp, unsigned long flags)
         * one corresponding to this CPU, due to the fact that we have
         * irqs disabled.
         */
-       for (rnp = &rsp->node[0]; rnp < &rsp->node[NUM_RCU_NODES]; rnp++) {
+       rcu_for_each_node_breadth_first(rsp, rnp) {
                spin_lock(&rnp->lock);  /* irqs already disabled. */
                rcu_preempt_check_blocked_tasks(rnp);
                rnp->qsmask = rnp->qsmaskinit;
@@ -703,9 +702,9 @@ rcu_process_gp_end(struct rcu_state *rsp, struct rcu_data *rdp)
  * hold rnp->lock, as required by rcu_start_gp(), which will release it.
  */
 static void cpu_quiet_msk_finish(struct rcu_state *rsp, unsigned long flags)
-       __releases(rnp->lock)
+       __releases(rcu_get_root(rsp)->lock)
 {
-       WARN_ON_ONCE(rsp->completed == rsp->gpnum);
+       WARN_ON_ONCE(!rcu_gp_in_progress(rsp));
        rsp->completed = rsp->gpnum;
        rcu_process_gp_end(rsp, rsp->rda[smp_processor_id()]);
        rcu_start_gp(rsp, flags);  /* releases root node's rnp->lock. */
@@ -842,17 +841,63 @@ rcu_check_quiescent_state(struct rcu_state *rsp, struct rcu_data *rdp)
 #ifdef CONFIG_HOTPLUG_CPU
 
 /*
+ * Move a dying CPU's RCU callbacks to the ->orphan_cbs_list for the
+ * specified flavor of RCU.  The callbacks will be adopted by the next
+ * _rcu_barrier() invocation or by the CPU_DEAD notifier, whichever
+ * comes first.  Because this is invoked from the CPU_DYING notifier,
+ * irqs are already disabled.
+ */
+static void rcu_send_cbs_to_orphanage(struct rcu_state *rsp)
+{
+       int i;
+       struct rcu_data *rdp = rsp->rda[smp_processor_id()];
+
+       if (rdp->nxtlist == NULL)
+               return;  /* irqs disabled, so comparison is stable. */
+       spin_lock(&rsp->onofflock);  /* irqs already disabled. */
+       *rsp->orphan_cbs_tail = rdp->nxtlist;
+       rsp->orphan_cbs_tail = rdp->nxttail[RCU_NEXT_TAIL];
+       rdp->nxtlist = NULL;
+       for (i = 0; i < RCU_NEXT_SIZE; i++)
+               rdp->nxttail[i] = &rdp->nxtlist;
+       rsp->orphan_qlen += rdp->qlen;
+       rdp->qlen = 0;
+       spin_unlock(&rsp->onofflock);  /* irqs remain disabled. */
+}
+
+/*
+ * Adopt previously orphaned RCU callbacks.
+ */
+static void rcu_adopt_orphan_cbs(struct rcu_state *rsp)
+{
+       unsigned long flags;
+       struct rcu_data *rdp;
+
+       spin_lock_irqsave(&rsp->onofflock, flags);
+       rdp = rsp->rda[smp_processor_id()];
+       if (rsp->orphan_cbs_list == NULL) {
+               spin_unlock_irqrestore(&rsp->onofflock, flags);
+               return;
+       }
+       *rdp->nxttail[RCU_NEXT_TAIL] = rsp->orphan_cbs_list;
+       rdp->nxttail[RCU_NEXT_TAIL] = rsp->orphan_cbs_tail;
+       rdp->qlen += rsp->orphan_qlen;
+       rsp->orphan_cbs_list = NULL;
+       rsp->orphan_cbs_tail = &rsp->orphan_cbs_list;
+       rsp->orphan_qlen = 0;
+       spin_unlock_irqrestore(&rsp->onofflock, flags);
+}
+
+/*
  * Remove the outgoing CPU from the bitmasks in the rcu_node hierarchy
  * and move all callbacks from the outgoing CPU to the current one.
  */
 static void __rcu_offline_cpu(int cpu, struct rcu_state *rsp)
 {
-       int i;
        unsigned long flags;
        long lastcomp;
        unsigned long mask;
        struct rcu_data *rdp = rsp->rda[cpu];
-       struct rcu_data *rdp_me;
        struct rcu_node *rnp;
 
        /* Exclude any attempts to start a new grace period. */
@@ -868,39 +913,29 @@ static void __rcu_offline_cpu(int cpu, struct rcu_state *rsp)
                        spin_unlock(&rnp->lock); /* irqs remain disabled. */
                        break;
                }
-               rcu_preempt_offline_tasks(rsp, rnp, rdp);
+
+               /*
+                * If there was a task blocking the current grace period,
+                * and if all CPUs have checked in, we need to propagate
+                * the quiescent state up the rcu_node hierarchy.  But that
+                * is inconvenient at the moment due to deadlock issues if
+                * this should end the current grace period.  So set the
+                * offlined CPU's bit in ->qsmask in order to force the
+                * next force_quiescent_state() invocation to clean up this
+                * mess in a deadlock-free manner.
+                */
+               if (rcu_preempt_offline_tasks(rsp, rnp, rdp) && !rnp->qsmask)
+                       rnp->qsmask |= mask;
+
                mask = rnp->grpmask;
                spin_unlock(&rnp->lock);        /* irqs remain disabled. */
                rnp = rnp->parent;
        } while (rnp != NULL);
        lastcomp = rsp->completed;
 
-       spin_unlock(&rsp->onofflock);           /* irqs remain disabled. */
+       spin_unlock_irqrestore(&rsp->onofflock, flags);
 
-       /*
-        * Move callbacks from the outgoing CPU to the running CPU.
-        * Note that the outgoing CPU is now quiscent, so it is now
-        * (uncharacteristically) safe to access its rcu_data structure.
-        * Note also that we must carefully retain the order of the
-        * outgoing CPU's callbacks in order for rcu_barrier() to work
-        * correctly.  Finally, note that we start all the callbacks
-        * afresh, even those that have passed through a grace period
-        * and are therefore ready to invoke.  The theory is that hotplug
-        * events are rare, and that if they are frequent enough to
-        * indefinitely delay callbacks, you have far worse things to
-        * be worrying about.
-        */
-       rdp_me = rsp->rda[smp_processor_id()];
-       if (rdp->nxtlist != NULL) {
-               *rdp_me->nxttail[RCU_NEXT_TAIL] = rdp->nxtlist;
-               rdp_me->nxttail[RCU_NEXT_TAIL] = rdp->nxttail[RCU_NEXT_TAIL];
-               rdp->nxtlist = NULL;
-               for (i = 0; i < RCU_NEXT_SIZE; i++)
-                       rdp->nxttail[i] = &rdp->nxtlist;
-               rdp_me->qlen += rdp->qlen;
-               rdp->qlen = 0;
-       }
-       local_irq_restore(flags);
+       rcu_adopt_orphan_cbs(rsp);
 }
 
 /*
@@ -918,6 +953,14 @@ static void rcu_offline_cpu(int cpu)
 
 #else /* #ifdef CONFIG_HOTPLUG_CPU */
 
+static void rcu_send_cbs_to_orphanage(struct rcu_state *rsp)
+{
+}
+
+static void rcu_adopt_orphan_cbs(struct rcu_state *rsp)
+{
+}
+
 static void rcu_offline_cpu(int cpu)
 {
 }
@@ -928,7 +971,7 @@ static void rcu_offline_cpu(int cpu)
  * Invoke any RCU callbacks that have made it to the end of their grace
  * period.  Thottle as specified by rdp->blimit.
  */
-static void rcu_do_batch(struct rcu_data *rdp)
+static void rcu_do_batch(struct rcu_state *rsp, struct rcu_data *rdp)
 {
        unsigned long flags;
        struct rcu_head *next, *list, **tail;
@@ -981,6 +1024,13 @@ static void rcu_do_batch(struct rcu_data *rdp)
        if (rdp->blimit == LONG_MAX && rdp->qlen <= qlowmark)
                rdp->blimit = blimit;
 
+       /* Reset ->qlen_last_fqs_check trigger if enough CBs have drained. */
+       if (rdp->qlen == 0 && rdp->qlen_last_fqs_check != 0) {
+               rdp->qlen_last_fqs_check = 0;
+               rdp->n_force_qs_snap = rsp->n_force_qs;
+       } else if (rdp->qlen < rdp->qlen_last_fqs_check - qhimark)
+               rdp->qlen_last_fqs_check = rdp->qlen;
+
        local_irq_restore(flags);
 
        /* Re-raise the RCU softirq if there are callbacks remaining. */
@@ -1050,33 +1100,32 @@ static int rcu_process_dyntick(struct rcu_state *rsp, long lastcomp,
        int cpu;
        unsigned long flags;
        unsigned long mask;
-       struct rcu_node *rnp_cur = rsp->level[NUM_RCU_LVLS - 1];
-       struct rcu_node *rnp_end = &rsp->node[NUM_RCU_NODES];
+       struct rcu_node *rnp;
 
-       for (; rnp_cur < rnp_end; rnp_cur++) {
+       rcu_for_each_leaf_node(rsp, rnp) {
                mask = 0;
-               spin_lock_irqsave(&rnp_cur->lock, flags);
+               spin_lock_irqsave(&rnp->lock, flags);
                if (rsp->completed != lastcomp) {
-                       spin_unlock_irqrestore(&rnp_cur->lock, flags);
+                       spin_unlock_irqrestore(&rnp->lock, flags);
                        return 1;
                }
-               if (rnp_cur->qsmask == 0) {
-                       spin_unlock_irqrestore(&rnp_cur->lock, flags);
+               if (rnp->qsmask == 0) {
+                       spin_unlock_irqrestore(&rnp->lock, flags);
                        continue;
                }
-               cpu = rnp_cur->grplo;
+               cpu = rnp->grplo;
                bit = 1;
-               for (; cpu <= rnp_cur->grphi; cpu++, bit <<= 1) {
-                       if ((rnp_cur->qsmask & bit) != 0 && f(rsp->rda[cpu]))
+               for (; cpu <= rnp->grphi; cpu++, bit <<= 1) {
+                       if ((rnp->qsmask & bit) != 0 && f(rsp->rda[cpu]))
                                mask |= bit;
                }
                if (mask != 0 && rsp->completed == lastcomp) {
 
-                       /* cpu_quiet_msk() releases rnp_cur->lock. */
-                       cpu_quiet_msk(mask, rsp, rnp_cur, flags);
+                       /* cpu_quiet_msk() releases rnp->lock. */
+                       cpu_quiet_msk(mask, rsp, rnp, flags);
                        continue;
                }
-               spin_unlock_irqrestore(&rnp_cur->lock, flags);
+               spin_unlock_irqrestore(&rnp->lock, flags);
        }
        return 0;
 }
@@ -1092,7 +1141,7 @@ static void force_quiescent_state(struct rcu_state *rsp, int relaxed)
        struct rcu_node *rnp = rcu_get_root(rsp);
        u8 signaled;
 
-       if (ACCESS_ONCE(rsp->completed) == ACCESS_ONCE(rsp->gpnum))
+       if (!rcu_gp_in_progress(rsp))
                return;  /* No grace period in progress, nothing to force. */
        if (!spin_trylock_irqsave(&rsp->fqslock, flags)) {
                rsp->n_force_qs_lh++; /* Inexact, can lose counts.  Tough! */
@@ -1195,7 +1244,7 @@ __rcu_process_callbacks(struct rcu_state *rsp, struct rcu_data *rdp)
        }
 
        /* If there are callbacks ready, invoke them. */
-       rcu_do_batch(rdp);
+       rcu_do_batch(rsp, rdp);
 }
 
 /*
@@ -1251,7 +1300,7 @@ __call_rcu(struct rcu_head *head, void (*func)(struct rcu_head *rcu),
        rdp->nxttail[RCU_NEXT_TAIL] = &head->next;
 
        /* Start a new grace period if one not already started. */
-       if (ACCESS_ONCE(rsp->completed) == ACCESS_ONCE(rsp->gpnum)) {
+       if (!rcu_gp_in_progress(rsp)) {
                unsigned long nestflag;
                struct rcu_node *rnp_root = rcu_get_root(rsp);
 
@@ -1259,10 +1308,20 @@ __call_rcu(struct rcu_head *head, void (*func)(struct rcu_head *rcu),
                rcu_start_gp(rsp, nestflag);  /* releases rnp_root->lock. */
        }
 
-       /* Force the grace period if too many callbacks or too long waiting. */
-       if (unlikely(++rdp->qlen > qhimark)) {
+       /*
+        * Force the grace period if too many callbacks or too long waiting.
+        * Enforce hysteresis, and don't invoke force_quiescent_state()
+        * if some other CPU has recently done so.  Also, don't bother
+        * invoking force_quiescent_state() if the newly enqueued callback
+        * is the only one waiting for a grace period to complete.
+        */
+       if (unlikely(++rdp->qlen > rdp->qlen_last_fqs_check + qhimark)) {
                rdp->blimit = LONG_MAX;
-               force_quiescent_state(rsp, 0);
+               if (rsp->n_force_qs == rdp->n_force_qs_snap &&
+                   *rdp->nxttail[RCU_DONE_TAIL] != head)
+                       force_quiescent_state(rsp, 0);
+               rdp->n_force_qs_snap = rsp->n_force_qs;
+               rdp->qlen_last_fqs_check = rdp->qlen;
        } else if ((long)(ACCESS_ONCE(rsp->jiffies_force_qs) - jiffies) < 0)
                force_quiescent_state(rsp, 1);
        local_irq_restore(flags);
@@ -1331,7 +1390,7 @@ static int __rcu_pending(struct rcu_state *rsp, struct rcu_data *rdp)
        }
 
        /* Has an RCU GP gone long enough to send resched IPIs &c? */
-       if (ACCESS_ONCE(rsp->completed) != ACCESS_ONCE(rsp->gpnum) &&
+       if (rcu_gp_in_progress(rsp) &&
            ((long)(ACCESS_ONCE(rsp->jiffies_force_qs) - jiffies) < 0)) {
                rdp->n_rp_need_fqs++;
                return 1;
@@ -1368,6 +1427,82 @@ int rcu_needs_cpu(int cpu)
               rcu_preempt_needs_cpu(cpu);
 }
 
+static DEFINE_PER_CPU(struct rcu_head, rcu_barrier_head) = {NULL};
+static atomic_t rcu_barrier_cpu_count;
+static DEFINE_MUTEX(rcu_barrier_mutex);
+static struct completion rcu_barrier_completion;
+
+static void rcu_barrier_callback(struct rcu_head *notused)
+{
+       if (atomic_dec_and_test(&rcu_barrier_cpu_count))
+               complete(&rcu_barrier_completion);
+}
+
+/*
+ * Called with preemption disabled, and from cross-cpu IRQ context.
+ */
+static void rcu_barrier_func(void *type)
+{
+       int cpu = smp_processor_id();
+       struct rcu_head *head = &per_cpu(rcu_barrier_head, cpu);
+       void (*call_rcu_func)(struct rcu_head *head,
+                             void (*func)(struct rcu_head *head));
+
+       atomic_inc(&rcu_barrier_cpu_count);
+       call_rcu_func = type;
+       call_rcu_func(head, rcu_barrier_callback);
+}
+
+/*
+ * Orchestrate the specified type of RCU barrier, waiting for all
+ * RCU callbacks of the specified type to complete.
+ */
+static void _rcu_barrier(struct rcu_state *rsp,
+                        void (*call_rcu_func)(struct rcu_head *head,
+                                              void (*func)(struct rcu_head *head)))
+{
+       BUG_ON(in_interrupt());
+       /* Take mutex to serialize concurrent rcu_barrier() requests. */
+       mutex_lock(&rcu_barrier_mutex);
+       init_completion(&rcu_barrier_completion);
+       /*
+        * Initialize rcu_barrier_cpu_count to 1, then invoke
+        * rcu_barrier_func() on each CPU, so that each CPU also has
+        * incremented rcu_barrier_cpu_count.  Only then is it safe to
+        * decrement rcu_barrier_cpu_count -- otherwise the first CPU
+        * might complete its grace period before all of the other CPUs
+        * did their increment, causing this function to return too
+        * early.
+        */
+       atomic_set(&rcu_barrier_cpu_count, 1);
+       preempt_disable(); /* stop CPU_DYING from filling orphan_cbs_list */
+       rcu_adopt_orphan_cbs(rsp);
+       on_each_cpu(rcu_barrier_func, (void *)call_rcu_func, 1);
+       preempt_enable(); /* CPU_DYING can again fill orphan_cbs_list */
+       if (atomic_dec_and_test(&rcu_barrier_cpu_count))
+               complete(&rcu_barrier_completion);
+       wait_for_completion(&rcu_barrier_completion);
+       mutex_unlock(&rcu_barrier_mutex);
+}
+
+/**
+ * rcu_barrier_bh - Wait until all in-flight call_rcu_bh() callbacks complete.
+ */
+void rcu_barrier_bh(void)
+{
+       _rcu_barrier(&rcu_bh_state, call_rcu_bh);
+}
+EXPORT_SYMBOL_GPL(rcu_barrier_bh);
+
+/**
+ * rcu_barrier_sched - Wait for in-flight call_rcu_sched() callbacks.
+ */
+void rcu_barrier_sched(void)
+{
+       _rcu_barrier(&rcu_sched_state, call_rcu_sched);
+}
+EXPORT_SYMBOL_GPL(rcu_barrier_sched);
+
 /*
  * Do boot-time initialization of a CPU's per-CPU RCU data.
  */
@@ -1418,6 +1553,8 @@ rcu_init_percpu_data(int cpu, struct rcu_state *rsp, int preemptable)
        rdp->beenonline = 1;     /* We have now been online. */
        rdp->preemptable = preemptable;
        rdp->passed_quiesc_completed = lastcomp - 1;
+       rdp->qlen_last_fqs_check = 0;
+       rdp->n_force_qs_snap = rsp->n_force_qs;
        rdp->blimit = blimit;
        spin_unlock(&rnp->lock);                /* irqs remain disabled. */
 
@@ -1464,6 +1601,22 @@ int __cpuinit rcu_cpu_notify(struct notifier_block *self,
        case CPU_UP_PREPARE_FROZEN:
                rcu_online_cpu(cpu);
                break;
+       case CPU_DYING:
+       case CPU_DYING_FROZEN:
+               /*
+                * preempt_disable() in _rcu_barrier() prevents stop_machine(),
+                * so when "on_each_cpu(rcu_barrier_func, (void *)type, 1);"
+                * returns, all online cpus have queued rcu_barrier_func().
+                * The dying CPU clears its cpu_online_mask bit and
+                * moves all of its RCU callbacks to ->orphan_cbs_list
+                * in the context of stop_machine(), so subsequent calls
+                * to _rcu_barrier() will adopt these callbacks and only
+                * then queue rcu_barrier_func() on all remaining CPUs.
+                */
+               rcu_send_cbs_to_orphanage(&rcu_bh_state);
+               rcu_send_cbs_to_orphanage(&rcu_sched_state);
+               rcu_preempt_send_cbs_to_orphanage();
+               break;
        case CPU_DEAD:
        case CPU_DEAD_FROZEN:
        case CPU_UP_CANCELED:
@@ -1526,7 +1679,8 @@ static void __init rcu_init_one(struct rcu_state *rsp)
                cpustride *= rsp->levelspread[i];
                rnp = rsp->level[i];
                for (j = 0; j < rsp->levelcnt[i]; j++, rnp++) {
-                       spin_lock_init(&rnp->lock);
+                       if (rnp != rcu_get_root(rsp))
+                               spin_lock_init(&rnp->lock);
                        rnp->gpnum = 0;
                        rnp->qsmask = 0;
                        rnp->qsmaskinit = 0;
@@ -1549,6 +1703,7 @@ static void __init rcu_init_one(struct rcu_state *rsp)
                        INIT_LIST_HEAD(&rnp->blocked_tasks[1]);
                }
        }
+       spin_lock_init(&rcu_get_root(rsp)->lock);
 }
 
 /*
@@ -1558,6 +1713,10 @@ static void __init rcu_init_one(struct rcu_state *rsp)
  */
 #define RCU_INIT_FLAVOR(rsp, rcu_data) \
 do { \
+       int i; \
+       int j; \
+       struct rcu_node *rnp; \
+       \
        rcu_init_one(rsp); \
        rnp = (rsp)->level[NUM_RCU_LVLS - 1]; \
        j = 0; \
@@ -1570,31 +1729,8 @@ do { \
        } \
 } while (0)
 
-#ifdef CONFIG_TREE_PREEMPT_RCU
-
-void __init __rcu_init_preempt(void)
-{
-       int i;                  /* All used by RCU_INIT_FLAVOR(). */
-       int j;
-       struct rcu_node *rnp;
-
-       RCU_INIT_FLAVOR(&rcu_preempt_state, rcu_preempt_data);
-}
-
-#else /* #ifdef CONFIG_TREE_PREEMPT_RCU */
-
-void __init __rcu_init_preempt(void)
-{
-}
-
-#endif /* #else #ifdef CONFIG_TREE_PREEMPT_RCU */
-
 void __init __rcu_init(void)
 {
-       int i;                  /* All used by RCU_INIT_FLAVOR(). */
-       int j;
-       struct rcu_node *rnp;
-
        rcu_bootup_announce();
 #ifdef CONFIG_RCU_CPU_STALL_DETECTOR
        printk(KERN_INFO "RCU-based detection of stalled CPUs is enabled.\n");
@@ -1605,6 +1741,4 @@ void __init __rcu_init(void)
        open_softirq(RCU_SOFTIRQ, rcu_process_callbacks);
 }
 
-module_param(blimit, int, 0);
-module_param(qhimark, int, 0);
-module_param(qlowmark, int, 0);
+#include "rcutree_plugin.h"
index 8e8287a..1823c6e 100644 (file)
 #elif NR_CPUS <= RCU_FANOUT_SQ
 #  define NUM_RCU_LVLS       2
 #  define NUM_RCU_LVL_0              1
-#  define NUM_RCU_LVL_1              (((NR_CPUS) + RCU_FANOUT - 1) / RCU_FANOUT)
+#  define NUM_RCU_LVL_1              DIV_ROUND_UP(NR_CPUS, RCU_FANOUT)
 #  define NUM_RCU_LVL_2              (NR_CPUS)
 #  define NUM_RCU_LVL_3              0
 #elif NR_CPUS <= RCU_FANOUT_CUBE
 #  define NUM_RCU_LVLS       3
 #  define NUM_RCU_LVL_0              1
-#  define NUM_RCU_LVL_1              (((NR_CPUS) + RCU_FANOUT_SQ - 1) / RCU_FANOUT_SQ)
-#  define NUM_RCU_LVL_2              (((NR_CPUS) + (RCU_FANOUT) - 1) / (RCU_FANOUT))
+#  define NUM_RCU_LVL_1              DIV_ROUND_UP(NR_CPUS, RCU_FANOUT_SQ)
+#  define NUM_RCU_LVL_2              DIV_ROUND_UP(NR_CPUS, RCU_FANOUT)
 #  define NUM_RCU_LVL_3              NR_CPUS
 #else
 # error "CONFIG_RCU_FANOUT insufficient for NR_CPUS"
@@ -79,15 +79,21 @@ struct rcu_dynticks {
  * Definition for node within the RCU grace-period-detection hierarchy.
  */
 struct rcu_node {
-       spinlock_t lock;
+       spinlock_t lock;        /* Root rcu_node's lock protects some */
+                               /*  rcu_state fields as well as following. */
        long    gpnum;          /* Current grace period for this node. */
                                /*  This will either be equal to or one */
                                /*  behind the root rcu_node's gpnum. */
        unsigned long qsmask;   /* CPUs or groups that need to switch in */
                                /*  order for current grace period to proceed.*/
+                               /*  In leaf rcu_node, each bit corresponds to */
+                               /*  an rcu_data structure, otherwise, each */
+                               /*  bit corresponds to a child rcu_node */
+                               /*  structure. */
        unsigned long qsmaskinit;
                                /* Per-GP initialization for qsmask. */
        unsigned long grpmask;  /* Mask to apply to parent qsmask. */
+                               /*  Only one bit will be set in this mask. */
        int     grplo;          /* lowest-numbered CPU or group here. */
        int     grphi;          /* highest-numbered CPU or group here. */
        u8      grpnum;         /* CPU/group number for next level up. */
@@ -95,8 +101,23 @@ struct rcu_node {
        struct rcu_node *parent;
        struct list_head blocked_tasks[2];
                                /* Tasks blocked in RCU read-side critsect. */
+                               /*  Grace period number (->gpnum) x blocked */
+                               /*  by tasks on the (x & 0x1) element of the */
+                               /*  blocked_tasks[] array. */
 } ____cacheline_internodealigned_in_smp;
 
+/*
+ * Do a full breadth-first scan of the rcu_node structures for the
+ * specified rcu_state structure.
+ */
+#define rcu_for_each_node_breadth_first(rsp, rnp) \
+       for ((rnp) = &(rsp)->node[0]; \
+            (rnp) < &(rsp)->node[NUM_RCU_NODES]; (rnp)++)
+
+#define rcu_for_each_leaf_node(rsp, rnp) \
+       for ((rnp) = (rsp)->level[NUM_RCU_LVLS - 1]; \
+            (rnp) < &(rsp)->node[NUM_RCU_NODES]; (rnp)++)
+
 /* Index values for nxttail array in struct rcu_data. */
 #define RCU_DONE_TAIL          0       /* Also RCU_WAIT head. */
 #define RCU_WAIT_TAIL          1       /* Also RCU_NEXT_READY head. */
@@ -126,23 +147,30 @@ struct rcu_data {
         * Any of the partitions might be empty, in which case the
         * pointer to that partition will be equal to the pointer for
         * the following partition.  When the list is empty, all of
-        * the nxttail elements point to nxtlist, which is NULL.
+        * the nxttail elements point to the ->nxtlist pointer itself,
+        * which in that case is NULL.
         *
-        * [*nxttail[RCU_NEXT_READY_TAIL], NULL = *nxttail[RCU_NEXT_TAIL]):
-        *      Entries that might have arrived after current GP ended
-        * [*nxttail[RCU_WAIT_TAIL], *nxttail[RCU_NEXT_READY_TAIL]):
-        *      Entries known to have arrived before current GP ended
-        * [*nxttail[RCU_DONE_TAIL], *nxttail[RCU_WAIT_TAIL]):
-        *      Entries that batch # <= ->completed - 1: waiting for current GP
         * [nxtlist, *nxttail[RCU_DONE_TAIL]):
         *      Entries that batch # <= ->completed
         *      The grace period for these entries has completed, and
         *      the other grace-period-completed entries may be moved
         *      here temporarily in rcu_process_callbacks().
+        * [*nxttail[RCU_DONE_TAIL], *nxttail[RCU_WAIT_TAIL]):
+        *      Entries that batch # <= ->completed - 1: waiting for current GP
+        * [*nxttail[RCU_WAIT_TAIL], *nxttail[RCU_NEXT_READY_TAIL]):
+        *      Entries known to have arrived before current GP ended
+        * [*nxttail[RCU_NEXT_READY_TAIL], *nxttail[RCU_NEXT_TAIL]):
+        *      Entries that might have arrived after current GP ended
+        *      Note that the value of *nxttail[RCU_NEXT_TAIL] will
+        *      always be NULL, as this is the end of the list.
         */
        struct rcu_head *nxtlist;
        struct rcu_head **nxttail[RCU_NEXT_SIZE];
        long            qlen;           /* # of queued callbacks */
+       long            qlen_last_fqs_check;
+                                       /* qlen at last check for QS forcing */
+       unsigned long   n_force_qs_snap;
+                                       /* did other CPU force QS recently? */
        long            blimit;         /* Upper limit on a processed batch */
 
 #ifdef CONFIG_NO_HZ
@@ -216,8 +244,19 @@ struct rcu_state {
                                                /* Force QS state. */
        long    gpnum;                          /* Current gp number. */
        long    completed;                      /* # of last completed gp. */
+
+       /* End  of fields guarded by root rcu_node's lock. */
+
        spinlock_t onofflock;                   /* exclude on/offline and */
-                                               /*  starting new GP. */
+                                               /*  starting new GP.  Also */
+                                               /*  protects the following */
+                                               /*  orphan_cbs fields. */
+       struct rcu_head *orphan_cbs_list;       /* list of rcu_head structs */
+                                               /*  orphaned by all CPUs in */
+                                               /*  a given leaf rcu_node */
+                                               /*  going offline. */
+       struct rcu_head **orphan_cbs_tail;      /* And tail pointer. */
+       long orphan_qlen;                       /* Number of orphaned cbs. */
        spinlock_t fqslock;                     /* Only one task forcing */
                                                /*  quiescent states. */
        unsigned long jiffies_force_qs;         /* Time at which to invoke */
@@ -255,5 +294,30 @@ extern struct rcu_state rcu_preempt_state;
 DECLARE_PER_CPU(struct rcu_data, rcu_preempt_data);
 #endif /* #ifdef CONFIG_TREE_PREEMPT_RCU */
 
-#endif /* #ifdef RCU_TREE_NONCORE */
+#else /* #ifdef RCU_TREE_NONCORE */
+
+/* Forward declarations for rcutree_plugin.h */
+static inline void rcu_bootup_announce(void);
+long rcu_batches_completed(void);
+static void rcu_preempt_note_context_switch(int cpu);
+static int rcu_preempted_readers(struct rcu_node *rnp);
+#ifdef CONFIG_RCU_CPU_STALL_DETECTOR
+static void rcu_print_task_stall(struct rcu_node *rnp);
+#endif /* #ifdef CONFIG_RCU_CPU_STALL_DETECTOR */
+static void rcu_preempt_check_blocked_tasks(struct rcu_node *rnp);
+#ifdef CONFIG_HOTPLUG_CPU
+static int rcu_preempt_offline_tasks(struct rcu_state *rsp,
+                                    struct rcu_node *rnp,
+                                    struct rcu_data *rdp);
+static void rcu_preempt_offline_cpu(int cpu);
+#endif /* #ifdef CONFIG_HOTPLUG_CPU */
+static void rcu_preempt_check_callbacks(int cpu);
+static void rcu_preempt_process_callbacks(void);
+void call_rcu(struct rcu_head *head, void (*func)(struct rcu_head *rcu));
+static int rcu_preempt_pending(int cpu);
+static int rcu_preempt_needs_cpu(int cpu);
+static void __cpuinit rcu_preempt_init_percpu_data(int cpu);
+static void rcu_preempt_send_cbs_to_orphanage(void);
+static void __init __rcu_init_preempt(void);
 
+#endif /* #else #ifdef RCU_TREE_NONCORE */
index 1cee04f..ef2a58c 100644 (file)
@@ -150,6 +150,16 @@ void __rcu_read_lock(void)
 }
 EXPORT_SYMBOL_GPL(__rcu_read_lock);
 
+/*
+ * Check for preempted RCU readers blocking the current grace period
+ * for the specified rcu_node structure.  If the caller needs a reliable
+ * answer, it must hold the rcu_node's ->lock.
+ */
+static int rcu_preempted_readers(struct rcu_node *rnp)
+{
+       return !list_empty(&rnp->blocked_tasks[rnp->gpnum & 0x1]);
+}
+
 static void rcu_read_unlock_special(struct task_struct *t)
 {
        int empty;
@@ -196,7 +206,7 @@ static void rcu_read_unlock_special(struct task_struct *t)
                                break;
                        spin_unlock(&rnp->lock);  /* irqs remain disabled. */
                }
-               empty = list_empty(&rnp->blocked_tasks[rnp->gpnum & 0x1]);
+               empty = !rcu_preempted_readers(rnp);
                list_del_init(&t->rcu_node_entry);
                t->rcu_blocked_node = NULL;
 
@@ -207,7 +217,7 @@ static void rcu_read_unlock_special(struct task_struct *t)
                 * drop rnp->lock and restore irq.
                 */
                if (!empty && rnp->qsmask == 0 &&
-                   list_empty(&rnp->blocked_tasks[rnp->gpnum & 0x1])) {
+                   !rcu_preempted_readers(rnp)) {
                        struct rcu_node *rnp_p;
 
                        if (rnp->parent == NULL) {
@@ -257,12 +267,12 @@ static void rcu_print_task_stall(struct rcu_node *rnp)
 {
        unsigned long flags;
        struct list_head *lp;
-       int phase = rnp->gpnum & 0x1;
+       int phase;
        struct task_struct *t;
 
-       if (!list_empty(&rnp->blocked_tasks[phase])) {
+       if (rcu_preempted_readers(rnp)) {
                spin_lock_irqsave(&rnp->lock, flags);
-               phase = rnp->gpnum & 0x1; /* re-read under lock. */
+               phase = rnp->gpnum & 0x1;
                lp = &rnp->blocked_tasks[phase];
                list_for_each_entry(t, lp, rcu_node_entry)
                        printk(" P%d", t->pid);
@@ -281,20 +291,10 @@ static void rcu_print_task_stall(struct rcu_node *rnp)
  */
 static void rcu_preempt_check_blocked_tasks(struct rcu_node *rnp)
 {
-       WARN_ON_ONCE(!list_empty(&rnp->blocked_tasks[rnp->gpnum & 0x1]));
+       WARN_ON_ONCE(rcu_preempted_readers(rnp));
        WARN_ON_ONCE(rnp->qsmask);
 }
 
-/*
- * Check for preempted RCU readers for the specified rcu_node structure.
- * If the caller needs a reliable answer, it must hold the rcu_node's
- * >lock.
- */
-static int rcu_preempted_readers(struct rcu_node *rnp)
-{
-       return !list_empty(&rnp->blocked_tasks[rnp->gpnum & 0x1]);
-}
-
 #ifdef CONFIG_HOTPLUG_CPU
 
 /*
@@ -304,21 +304,25 @@ static int rcu_preempted_readers(struct rcu_node *rnp)
  * parent is to remove the need for rcu_read_unlock_special() to
  * make more than two attempts to acquire the target rcu_node's lock.
  *
+ * Returns 1 if there was previously a task blocking the current grace
+ * period on the specified rcu_node structure.
+ *
  * The caller must hold rnp->lock with irqs disabled.
  */
-static void rcu_preempt_offline_tasks(struct rcu_state *rsp,
-                                     struct rcu_node *rnp,
-                                     struct rcu_data *rdp)
+static int rcu_preempt_offline_tasks(struct rcu_state *rsp,
+                                    struct rcu_node *rnp,
+                                    struct rcu_data *rdp)
 {
        int i;
        struct list_head *lp;
        struct list_head *lp_root;
+       int retval = rcu_preempted_readers(rnp);
        struct rcu_node *rnp_root = rcu_get_root(rsp);
        struct task_struct *tp;
 
        if (rnp == rnp_root) {
                WARN_ONCE(1, "Last CPU thought to be offlined?");
-               return;  /* Shouldn't happen: at least one CPU online. */
+               return 0;  /* Shouldn't happen: at least one CPU online. */
        }
        WARN_ON_ONCE(rnp != rdp->mynode &&
                     (!list_empty(&rnp->blocked_tasks[0]) ||
@@ -342,6 +346,8 @@ static void rcu_preempt_offline_tasks(struct rcu_state *rsp,
                        spin_unlock(&rnp_root->lock); /* irqs remain disabled */
                }
        }
+
+       return retval;
 }
 
 /*
@@ -393,6 +399,17 @@ void call_rcu(struct rcu_head *head, void (*func)(struct rcu_head *rcu))
 EXPORT_SYMBOL_GPL(call_rcu);
 
 /*
+ * Wait for an rcu-preempt grace period.  We are supposed to expedite the
+ * grace period, but this is the crude slow compatability hack, so just
+ * invoke synchronize_rcu().
+ */
+void synchronize_rcu_expedited(void)
+{
+       synchronize_rcu();
+}
+EXPORT_SYMBOL_GPL(synchronize_rcu_expedited);
+
+/*
  * Check to see if there is any immediate preemptable-RCU-related work
  * to be done.
  */
@@ -410,6 +427,15 @@ static int rcu_preempt_needs_cpu(int cpu)
        return !!per_cpu(rcu_preempt_data, cpu).nxtlist;
 }
 
+/**
+ * rcu_barrier - Wait until all in-flight call_rcu() callbacks complete.
+ */
+void rcu_barrier(void)
+{
+       _rcu_barrier(&rcu_preempt_state, call_rcu);
+}
+EXPORT_SYMBOL_GPL(rcu_barrier);
+
 /*
  * Initialize preemptable RCU's per-CPU data.
  */
@@ -419,6 +445,22 @@ static void __cpuinit rcu_preempt_init_percpu_data(int cpu)
 }
 
 /*
+ * Move preemptable RCU's callbacks to ->orphan_cbs_list.
+ */
+static void rcu_preempt_send_cbs_to_orphanage(void)
+{
+       rcu_send_cbs_to_orphanage(&rcu_preempt_state);
+}
+
+/*
+ * Initialize preemptable RCU's state structures.
+ */
+static void __init __rcu_init_preempt(void)
+{
+       RCU_INIT_FLAVOR(&rcu_preempt_state, rcu_preempt_data);
+}
+
+/*
  * Check for a task exiting while in a preemptable-RCU read-side
  * critical section, clean up if so.  No need to issue warnings,
  * as debug_check_no_locks_held() already does this if lockdep
@@ -461,6 +503,15 @@ static void rcu_preempt_note_context_switch(int cpu)
 {
 }
 
+/*
+ * Because preemptable RCU does not exist, there are never any preempted
+ * RCU readers.
+ */
+static int rcu_preempted_readers(struct rcu_node *rnp)
+{
+       return 0;
+}
+
 #ifdef CONFIG_RCU_CPU_STALL_DETECTOR
 
 /*
@@ -483,25 +534,19 @@ static void rcu_preempt_check_blocked_tasks(struct rcu_node *rnp)
        WARN_ON_ONCE(rnp->qsmask);
 }
 
-/*
- * Because preemptable RCU does not exist, there are never any preempted
- * RCU readers.
- */
-static int rcu_preempted_readers(struct rcu_node *rnp)
-{
-       return 0;
-}
-
 #ifdef CONFIG_HOTPLUG_CPU
 
 /*
  * Because preemptable RCU does not exist, it never needs to migrate
- * tasks that were blocked within RCU read-side critical sections.
+ * tasks that were blocked within RCU read-side critical sections, and
+ * such non-existent tasks cannot possibly have been blocking the current
+ * grace period.
  */
-static void rcu_preempt_offline_tasks(struct rcu_state *rsp,
-                                     struct rcu_node *rnp,
-                                     struct rcu_data *rdp)
+static int rcu_preempt_offline_tasks(struct rcu_state *rsp,
+                                    struct rcu_node *rnp,
+                                    struct rcu_data *rdp)
 {
+       return 0;
 }
 
 /*
@@ -518,7 +563,7 @@ static void rcu_preempt_offline_cpu(int cpu)
  * Because preemptable RCU does not exist, it never has any callbacks
  * to check.
  */
-void rcu_preempt_check_callbacks(int cpu)
+static void rcu_preempt_check_callbacks(int cpu)
 {
 }
 
@@ -526,7 +571,7 @@ void rcu_preempt_check_callbacks(int cpu)
  * Because preemptable RCU does not exist, it never has any callbacks
  * to process.
  */
-void rcu_preempt_process_callbacks(void)
+static void rcu_preempt_process_callbacks(void)
 {
 }
 
@@ -540,6 +585,16 @@ void call_rcu(struct rcu_head *head, void (*func)(struct rcu_head *rcu))
 EXPORT_SYMBOL_GPL(call_rcu);
 
 /*
+ * Wait for an rcu-preempt grace period, but make it happen quickly.
+ * But because preemptable RCU does not exist, map to rcu-sched.
+ */
+void synchronize_rcu_expedited(void)
+{
+       synchronize_sched_expedited();
+}
+EXPORT_SYMBOL_GPL(synchronize_rcu_expedited);
+
+/*
  * Because preemptable RCU does not exist, it never has any work to do.
  */
 static int rcu_preempt_pending(int cpu)
@@ -556,6 +611,16 @@ static int rcu_preempt_needs_cpu(int cpu)
 }
 
 /*
+ * Because preemptable RCU does not exist, rcu_barrier() is just
+ * another name for rcu_barrier_sched().
+ */
+void rcu_barrier(void)
+{
+       rcu_barrier_sched();
+}
+EXPORT_SYMBOL_GPL(rcu_barrier);
+
+/*
  * Because preemptable RCU does not exist, there is no per-CPU
  * data to initialize.
  */
@@ -563,4 +628,18 @@ static void __cpuinit rcu_preempt_init_percpu_data(int cpu)
 {
 }
 
+/*
+ * Because there is no preemptable RCU, there are no callbacks to move.
+ */
+static void rcu_preempt_send_cbs_to_orphanage(void)
+{
+}
+
+/*
+ * Because preemptable RCU does not exist, it need not be initialized.
+ */
+static void __init __rcu_init_preempt(void)
+{
+}
+
 #endif /* #else #ifdef CONFIG_TREE_PREEMPT_RCU */
index 179e6ad..4b31c77 100644 (file)
@@ -159,13 +159,13 @@ static void print_one_rcu_state(struct seq_file *m, struct rcu_state *rsp)
        struct rcu_node *rnp;
 
        seq_printf(m, "c=%ld g=%ld s=%d jfq=%ld j=%x "
-                     "nfqs=%lu/nfqsng=%lu(%lu) fqlh=%lu\n",
+                     "nfqs=%lu/nfqsng=%lu(%lu) fqlh=%lu oqlen=%ld\n",
                   rsp->completed, rsp->gpnum, rsp->signaled,
                   (long)(rsp->jiffies_force_qs - jiffies),
                   (int)(jiffies & 0xffff),
                   rsp->n_force_qs, rsp->n_force_qs_ngp,
                   rsp->n_force_qs - rsp->n_force_qs_ngp,
-                  rsp->n_force_qs_lh);
+                  rsp->n_force_qs_lh, rsp->orphan_qlen);
        for (rnp = &rsp->node[0]; rnp - &rsp->node[0] < NUM_RCU_NODES; rnp++) {
                if (rnp->level != level) {
                        seq_puts(m, "\n");
index 1535f38..a455dca 100644 (file)
@@ -676,6 +676,7 @@ inline void update_rq_clock(struct rq *rq)
 
 /**
  * runqueue_is_locked
+ * @cpu: the processor in question.
  *
  * Returns true if the current cpu runqueue is locked.
  * This interface allows printk to be called with the runqueue lock
@@ -1563,11 +1564,7 @@ static unsigned long cpu_avg_load_per_task(int cpu)
 
 #ifdef CONFIG_FAIR_GROUP_SCHED
 
-struct update_shares_data {
-       unsigned long rq_weight[NR_CPUS];
-};
-
-static DEFINE_PER_CPU(struct update_shares_data, update_shares_data);
+static __read_mostly unsigned long *update_shares_data;
 
 static void __set_se_shares(struct sched_entity *se, unsigned long shares);
 
@@ -1577,12 +1574,12 @@ static void __set_se_shares(struct sched_entity *se, unsigned long shares);
 static void update_group_shares_cpu(struct task_group *tg, int cpu,
                                    unsigned long sd_shares,
                                    unsigned long sd_rq_weight,
-                                   struct update_shares_data *usd)
+                                   unsigned long *usd_rq_weight)
 {
        unsigned long shares, rq_weight;
        int boost = 0;
 
-       rq_weight = usd->rq_weight[cpu];
+       rq_weight = usd_rq_weight[cpu];
        if (!rq_weight) {
                boost = 1;
                rq_weight = NICE_0_LOAD;
@@ -1617,7 +1614,7 @@ static void update_group_shares_cpu(struct task_group *tg, int cpu,
 static int tg_shares_up(struct task_group *tg, void *data)
 {
        unsigned long weight, rq_weight = 0, shares = 0;
-       struct update_shares_data *usd;
+       unsigned long *usd_rq_weight;
        struct sched_domain *sd = data;
        unsigned long flags;
        int i;
@@ -1626,11 +1623,11 @@ static int tg_shares_up(struct task_group *tg, void *data)
                return 0;
 
        local_irq_save(flags);
-       usd = &__get_cpu_var(update_shares_data);
+       usd_rq_weight = per_cpu_ptr(update_shares_data, smp_processor_id());
 
        for_each_cpu(i, sched_domain_span(sd)) {
                weight = tg->cfs_rq[i]->load.weight;
-               usd->rq_weight[i] = weight;
+               usd_rq_weight[i] = weight;
 
                /*
                 * If there are currently no tasks on the cpu pretend there
@@ -1651,7 +1648,7 @@ static int tg_shares_up(struct task_group *tg, void *data)
                shares = tg->shares;
 
        for_each_cpu(i, sched_domain_span(sd))
-               update_group_shares_cpu(tg, i, shares, rq_weight, usd);
+               update_group_shares_cpu(tg, i, shares, rq_weight, usd_rq_weight);
 
        local_irq_restore(flags);
 
@@ -2311,7 +2308,7 @@ static int try_to_wake_up(struct task_struct *p, unsigned int state,
 {
        int cpu, orig_cpu, this_cpu, success = 0;
        unsigned long flags;
-       struct rq *rq;
+       struct rq *rq, *orig_rq;
 
        if (!sched_feat(SYNC_WAKEUPS))
                wake_flags &= ~WF_SYNC;
@@ -2319,7 +2316,7 @@ static int try_to_wake_up(struct task_struct *p, unsigned int state,
        this_cpu = get_cpu();
 
        smp_wmb();
-       rq = task_rq_lock(p, &flags);
+       rq = orig_rq = task_rq_lock(p, &flags);
        update_rq_clock(rq);
        if (!(p->state & state))
                goto out;
@@ -2350,6 +2347,10 @@ static int try_to_wake_up(struct task_struct *p, unsigned int state,
                set_task_cpu(p, cpu);
 
        rq = task_rq_lock(p, &flags);
+
+       if (rq != orig_rq)
+               update_rq_clock(rq);
+
        WARN_ON(p->state != TASK_WAKING);
        cpu = task_cpu(p);
 
@@ -2515,22 +2516,17 @@ void sched_fork(struct task_struct *p, int clone_flags)
        __sched_fork(p);
 
        /*
-        * Make sure we do not leak PI boosting priority to the child.
-        */
-       p->prio = current->normal_prio;
-
-       /*
         * Revert to default priority/policy on fork if requested.
         */
        if (unlikely(p->sched_reset_on_fork)) {
-               if (p->policy == SCHED_FIFO || p->policy == SCHED_RR)
+               if (p->policy == SCHED_FIFO || p->policy == SCHED_RR) {
                        p->policy = SCHED_NORMAL;
-
-               if (p->normal_prio < DEFAULT_PRIO)
-                       p->prio = DEFAULT_PRIO;
+                       p->normal_prio = p->static_prio;
+               }
 
                if (PRIO_TO_NICE(p->static_prio) < 0) {
                        p->static_prio = NICE_TO_PRIO(0);
+                       p->normal_prio = p->static_prio;
                        set_load_weight(p);
                }
 
@@ -2541,6 +2537,11 @@ void sched_fork(struct task_struct *p, int clone_flags)
                p->sched_reset_on_fork = 0;
        }
 
+       /*
+        * Make sure we do not leak PI boosting priority to the child.
+        */
+       p->prio = current->normal_prio;
+
        if (!rt_prio(p->prio))
                p->sched_class = &fair_sched_class;
 
@@ -2581,8 +2582,6 @@ void wake_up_new_task(struct task_struct *p, unsigned long clone_flags)
        BUG_ON(p->state != TASK_RUNNING);
        update_rq_clock(rq);
 
-       p->prio = effective_prio(p);
-
        if (!p->sched_class->task_new || !current->se.on_rq) {
                activate_task(rq, p, 0);
        } else {
@@ -3658,6 +3657,7 @@ static void update_group_power(struct sched_domain *sd, int cpu)
 
 /**
  * update_sg_lb_stats - Update sched_group's statistics for load balancing.
+ * @sd: The sched_domain whose statistics are to be updated.
  * @group: sched_group whose statistics are to be updated.
  * @this_cpu: Cpu for which load balance is currently performed.
  * @idle: Idle status of this_cpu
@@ -6720,9 +6720,6 @@ EXPORT_SYMBOL(yield);
 /*
  * This task is about to go to sleep on IO. Increment rq->nr_iowait so
  * that process accounting knows that this is a task in IO wait state.
- *
- * But don't do that if it is a deliberate, throttling IO wait (this task
- * has set its backing_dev_info: the queue against which it should throttle)
  */
 void __sched io_schedule(void)
 {
@@ -9406,6 +9403,10 @@ void __init sched_init(void)
 #endif /* CONFIG_USER_SCHED */
 #endif /* CONFIG_GROUP_SCHED */
 
+#if defined CONFIG_FAIR_GROUP_SCHED && defined CONFIG_SMP
+       update_shares_data = __alloc_percpu(nr_cpu_ids * sizeof(unsigned long),
+                                           __alignof__(unsigned long));
+#endif
        for_each_possible_cpu(i) {
                struct rq *rq;
 
index 4e777b4..c32c3e6 100644 (file)
@@ -861,12 +861,21 @@ wakeup_preempt_entity(struct sched_entity *curr, struct sched_entity *se);
 static struct sched_entity *pick_next_entity(struct cfs_rq *cfs_rq)
 {
        struct sched_entity *se = __pick_next_entity(cfs_rq);
+       struct sched_entity *buddy;
 
-       if (cfs_rq->next && wakeup_preempt_entity(cfs_rq->next, se) < 1)
-               return cfs_rq->next;
+       if (cfs_rq->next) {
+               buddy = cfs_rq->next;
+               cfs_rq->next = NULL;
+               if (wakeup_preempt_entity(buddy, se) < 1)
+                       return buddy;
+       }
 
-       if (cfs_rq->last && wakeup_preempt_entity(cfs_rq->last, se) < 1)
-               return cfs_rq->last;
+       if (cfs_rq->last) {
+               buddy = cfs_rq->last;
+               cfs_rq->last = NULL;
+               if (wakeup_preempt_entity(buddy, se) < 1)
+                       return buddy;
+       }
 
        return se;
 }
@@ -1654,16 +1663,6 @@ static struct task_struct *pick_next_task_fair(struct rq *rq)
 
        do {
                se = pick_next_entity(cfs_rq);
-               /*
-                * If se was a buddy, clear it so that it will have to earn
-                * the favour again.
-                *
-                * If se was not a buddy, clear the buddies because neither
-                * was elegible to run, let them earn it again.
-                *
-                * IOW. unconditionally clear buddies.
-                */
-               __clear_buddies(cfs_rq, NULL);
                set_next_entity(cfs_rq, se);
                cfs_rq = group_cfs_rq(se);
        } while (cfs_rq);
index 255475d..ce17760 100644 (file)
@@ -1110,6 +1110,8 @@ SYSCALL_DEFINE0(setsid)
        err = session;
 out:
        write_unlock_irq(&tasklist_lock);
+       if (err > 0)
+               proc_sid_connector(group_leader);
        return err;
 }
 
@@ -1546,24 +1548,37 @@ SYSCALL_DEFINE5(prctl, int, option, unsigned long, arg2, unsigned long, arg3,
                        if (arg4 | arg5)
                                return -EINVAL;
                        switch (arg2) {
-                       case 0:
+                       case PR_MCE_KILL_CLEAR:
                                if (arg3 != 0)
                                        return -EINVAL;
                                current->flags &= ~PF_MCE_PROCESS;
                                break;
-                       case 1:
+                       case PR_MCE_KILL_SET:
                                current->flags |= PF_MCE_PROCESS;
-                               if (arg3 != 0)
+                               if (arg3 == PR_MCE_KILL_EARLY)
                                        current->flags |= PF_MCE_EARLY;
-                               else
+                               else if (arg3 == PR_MCE_KILL_LATE)
                                        current->flags &= ~PF_MCE_EARLY;
+                               else if (arg3 == PR_MCE_KILL_DEFAULT)
+                                       current->flags &=
+                                               ~(PF_MCE_EARLY|PF_MCE_PROCESS);
+                               else
+                                       return -EINVAL;
                                break;
                        default:
                                return -EINVAL;
                        }
                        error = 0;
                        break;
-
+               case PR_MCE_KILL_GET:
+                       if (arg2 | arg3 | arg4 | arg5)
+                               return -EINVAL;
+                       if (current->flags & PF_MCE_PROCESS)
+                               error = (current->flags & PF_MCE_EARLY) ?
+                                       PR_MCE_KILL_EARLY : PR_MCE_KILL_LATE;
+                       else
+                               error = PR_MCE_KILL_DEFAULT;
+                       break;
                default:
                        error = -EINVAL;
                        break;
index b38423c..b6e7aae 100644 (file)
@@ -1521,7 +1521,7 @@ int sysctl_check_table(struct nsproxy *namespaces, struct ctl_table *table)
                        if (!table->ctl_name && table->strategy)
                                set_fail(&fail, table, "Strategy without ctl_name");
 #endif
-#ifdef CONFIG_PROC_FS
+#ifdef CONFIG_PROC_SYSCTL
                        if (table->procname && !table->proc_handler)
                                set_fail(&fail, table, "No proc_handler");
 #endif
index e0f59a2..89aed59 100644 (file)
@@ -231,6 +231,13 @@ void tick_nohz_stop_sched_tick(int inidle)
        if (!inidle && !ts->inidle)
                goto end;
 
+       /*
+        * Set ts->inidle unconditionally. Even if the system did not
+        * switch to NOHZ mode the cpu frequency governers rely on the
+        * update of the idle time accounting in tick_nohz_start_idle().
+        */
+       ts->inidle = 1;
+
        now = tick_nohz_start_idle(ts);
 
        /*
@@ -248,8 +255,6 @@ void tick_nohz_stop_sched_tick(int inidle)
        if (unlikely(ts->nohz_mode == NOHZ_MODE_INACTIVE))
                goto end;
 
-       ts->inidle = 1;
-
        if (need_resched())
                goto end;
 
index fb0f46f..c3a4e29 100644 (file)
@@ -13,6 +13,7 @@
 #include <linux/percpu.h>
 #include <linux/init.h>
 #include <linux/mm.h>
+#include <linux/sched.h>
 #include <linux/sysdev.h>
 #include <linux/clocksource.h>
 #include <linux/jiffies.h>
index 46592fe..9c451a1 100644 (file)
@@ -225,7 +225,11 @@ static void ftrace_update_pid_func(void)
        if (ftrace_trace_function == ftrace_stub)
                return;
 
+#ifdef CONFIG_HAVE_FUNCTION_TRACE_MCOUNT_TEST
        func = ftrace_trace_function;
+#else
+       func = __ftrace_trace_function;
+#endif
 
        if (ftrace_pid_trace) {
                set_ftrace_pid_function(func);
@@ -736,7 +740,7 @@ ftrace_profile_write(struct file *filp, const char __user *ubuf,
  out:
        mutex_unlock(&ftrace_profile_lock);
 
-       filp->f_pos += cnt;
+       *ppos += cnt;
 
        return cnt;
 }
@@ -1074,14 +1078,9 @@ static void ftrace_replace_code(int enable)
                failed = __ftrace_replace_code(rec, enable);
                if (failed) {
                        rec->flags |= FTRACE_FL_FAILED;
-                       if ((system_state == SYSTEM_BOOTING) ||
-                           !core_kernel_text(rec->ip)) {
-                               ftrace_free_rec(rec);
-                               } else {
-                               ftrace_bug(failed, rec->ip);
-                                       /* Stop processing */
-                                       return;
-                               }
+                       ftrace_bug(failed, rec->ip);
+                       /* Stop processing */
+                       return;
                }
        } while_for_each_ftrace_rec();
 }
@@ -2658,19 +2657,17 @@ static int ftrace_convert_nops(struct module *mod,
 }
 
 #ifdef CONFIG_MODULES
-void ftrace_release(void *start, void *end)
+void ftrace_release_mod(struct module *mod)
 {
        struct dyn_ftrace *rec;
        struct ftrace_page *pg;
-       unsigned long s = (unsigned long)start;
-       unsigned long e = (unsigned long)end;
 
-       if (ftrace_disabled || !start || start == end)
+       if (ftrace_disabled)
                return;
 
        mutex_lock(&ftrace_lock);
        do_for_each_ftrace_rec(pg, rec) {
-               if ((rec->ip >= s) && (rec->ip < e)) {
+               if (within_module_core(rec->ip, mod)) {
                        /*
                         * rec->ip is changed in ftrace_free_rec()
                         * It should not between s and e if record was freed.
@@ -2702,9 +2699,7 @@ static int ftrace_module_notify(struct notifier_block *self,
                                   mod->num_ftrace_callsites);
                break;
        case MODULE_STATE_GOING:
-               ftrace_release(mod->ftrace_callsites,
-                              mod->ftrace_callsites +
-                              mod->num_ftrace_callsites);
+               ftrace_release_mod(mod);
                break;
        }
 
index 81b1645..a91da69 100644 (file)
@@ -501,7 +501,7 @@ static int __init init_kmem_tracer(void)
                return 1;
        }
 
-       if (!register_tracer(&kmem_tracer)) {
+       if (register_tracer(&kmem_tracer) != 0) {
                pr_warning("Warning: could not register the kmem tracer\n");
                return 1;
        }
index d4ff019..3ffa502 100644 (file)
@@ -483,7 +483,7 @@ struct ring_buffer_iter {
 /* Up this if you want to test the TIME_EXTENTS and normalization */
 #define DEBUG_SHIFT 0
 
-static inline u64 rb_time_stamp(struct ring_buffer *buffer, int cpu)
+static inline u64 rb_time_stamp(struct ring_buffer *buffer)
 {
        /* shift to debug/test normalization and TIME_EXTENTS */
        return buffer->clock() << DEBUG_SHIFT;
@@ -494,7 +494,7 @@ u64 ring_buffer_time_stamp(struct ring_buffer *buffer, int cpu)
        u64 time;
 
        preempt_disable_notrace();
-       time = rb_time_stamp(buffer, cpu);
+       time = rb_time_stamp(buffer);
        preempt_enable_no_resched_notrace();
 
        return time;
@@ -599,7 +599,7 @@ static struct list_head *rb_list_head(struct list_head *list)
 }
 
 /*
- * rb_is_head_page - test if the give page is the head page
+ * rb_is_head_page - test if the given page is the head page
  *
  * Because the reader may move the head_page pointer, we can
  * not trust what the head page is (it may be pointing to
@@ -1868,7 +1868,7 @@ rb_move_tail(struct ring_buffer_per_cpu *cpu_buffer,
                 * Nested commits always have zero deltas, so
                 * just reread the time stamp
                 */
-               *ts = rb_time_stamp(buffer, cpu_buffer->cpu);
+               *ts = rb_time_stamp(buffer);
                next_page->page->time_stamp = *ts;
        }
 
@@ -2111,7 +2111,7 @@ rb_reserve_next_event(struct ring_buffer *buffer,
        if (RB_WARN_ON(cpu_buffer, ++nr_loops > 1000))
                goto out_fail;
 
-       ts = rb_time_stamp(cpu_buffer->buffer, cpu_buffer->cpu);
+       ts = rb_time_stamp(cpu_buffer->buffer);
 
        /*
         * Only the first commit can update the timestamp.
@@ -2681,7 +2681,7 @@ unsigned long ring_buffer_entries(struct ring_buffer *buffer)
 EXPORT_SYMBOL_GPL(ring_buffer_entries);
 
 /**
- * ring_buffer_overrun_cpu - get the number of overruns in buffer
+ * ring_buffer_overruns - get the number of overruns in buffer
  * @buffer: The ring buffer
  *
  * Returns the total number of overruns in the ring buffer
index 4506826..b20d3ec 100644 (file)
@@ -1393,7 +1393,7 @@ int trace_array_vprintk(struct trace_array *tr,
 
 int trace_vprintk(unsigned long ip, const char *fmt, va_list args)
 {
-       return trace_array_printk(&global_trace, ip, fmt, args);
+       return trace_array_vprintk(&global_trace, ip, fmt, args);
 }
 EXPORT_SYMBOL_GPL(trace_vprintk);
 
@@ -2440,7 +2440,7 @@ tracing_trace_options_write(struct file *filp, const char __user *ubuf,
                        return ret;
        }
 
-       filp->f_pos += cnt;
+       *ppos += cnt;
 
        return cnt;
 }
@@ -2582,7 +2582,7 @@ tracing_ctrl_write(struct file *filp, const char __user *ubuf,
        }
        mutex_unlock(&trace_types_lock);
 
-       filp->f_pos += cnt;
+       *ppos += cnt;
 
        return cnt;
 }
@@ -2764,7 +2764,7 @@ tracing_set_trace_write(struct file *filp, const char __user *ubuf,
        if (err)
                return err;
 
-       filp->f_pos += ret;
+       *ppos += ret;
 
        return ret;
 }
@@ -3299,7 +3299,7 @@ tracing_entries_write(struct file *filp, const char __user *ubuf,
                }
        }
 
-       filp->f_pos += cnt;
+       *ppos += cnt;
 
        /* If check pages failed, return ENOMEM */
        if (tracing_disabled)
index 7a7a9fd..4a194f0 100644 (file)
@@ -34,6 +34,7 @@ probe_likely_condition(struct ftrace_branch_data *f, int val, int expect)
        struct trace_array *tr = branch_tracer;
        struct ring_buffer_event *event;
        struct trace_branch *entry;
+       struct ring_buffer *buffer;
        unsigned long flags;
        int cpu, pc;
        const char *p;
@@ -54,7 +55,8 @@ probe_likely_condition(struct ftrace_branch_data *f, int val, int expect)
                goto out;
 
        pc = preempt_count();
-       event = trace_buffer_lock_reserve(tr, TRACE_BRANCH,
+       buffer = tr->buffer;
+       event = trace_buffer_lock_reserve(buffer, TRACE_BRANCH,
                                          sizeof(*entry), flags, pc);
        if (!event)
                goto out;
@@ -74,8 +76,8 @@ probe_likely_condition(struct ftrace_branch_data *f, int val, int expect)
        entry->line = f->line;
        entry->correct = val == expect;
 
-       if (!filter_check_discard(call, entry, tr->buffer, event))
-               ring_buffer_unlock_commit(tr->buffer, event);
+       if (!filter_check_discard(call, entry, buffer, event))
+               ring_buffer_unlock_commit(buffer, event);
 
  out:
        atomic_dec(&tr->data[cpu]->disabled);
index dd44b87..8d5c171 100644 (file)
@@ -31,7 +31,7 @@ static int ftrace_profile_enable_event(struct ftrace_event_call *event)
        if (atomic_inc_return(&event->profile_count))
                return 0;
 
-       if (!total_profile_count++) {
+       if (!total_profile_count) {
                buf = (char *)alloc_percpu(profile_buf_t);
                if (!buf)
                        goto fail_buf;
@@ -46,14 +46,19 @@ static int ftrace_profile_enable_event(struct ftrace_event_call *event)
        }
 
        ret = event->profile_enable();
-       if (!ret)
+       if (!ret) {
+               total_profile_count++;
                return 0;
+       }
 
-       kfree(trace_profile_buf_nmi);
 fail_buf_nmi:
-       kfree(trace_profile_buf);
+       if (!total_profile_count) {
+               free_percpu(trace_profile_buf_nmi);
+               free_percpu(trace_profile_buf);
+               trace_profile_buf_nmi = NULL;
+               trace_profile_buf = NULL;
+       }
 fail_buf:
-       total_profile_count--;
        atomic_dec(&event->profile_count);
 
        return ret;
index 2324578..98a6cc5 100644 (file)
@@ -933,8 +933,9 @@ static void postfix_clear(struct filter_parse_state *ps)
 
        while (!list_empty(&ps->postfix)) {
                elt = list_first_entry(&ps->postfix, struct postfix_elt, list);
-               kfree(elt->operand);
                list_del(&elt->list);
+               kfree(elt->operand);
+               kfree(elt);
        }
 }
 
index 23b6385..69543a9 100644 (file)
@@ -165,6 +165,7 @@ void trace_hw_branch(u64 from, u64 to)
        struct ftrace_event_call *call = &event_hw_branch;
        struct trace_array *tr = hw_branch_trace;
        struct ring_buffer_event *event;
+       struct ring_buffer *buf;
        struct hw_branch_entry *entry;
        unsigned long irq1;
        int cpu;
@@ -180,7 +181,8 @@ void trace_hw_branch(u64 from, u64 to)
        if (atomic_inc_return(&tr->data[cpu]->disabled) != 1)
                goto out;
 
-       event = trace_buffer_lock_reserve(tr, TRACE_HW_BRANCHES,
+       buf = tr->buffer;
+       event = trace_buffer_lock_reserve(buf, TRACE_HW_BRANCHES,
                                          sizeof(*entry), 0, 0);
        if (!event)
                goto out;
@@ -189,8 +191,8 @@ void trace_hw_branch(u64 from, u64 to)
        entry->ent.type = TRACE_HW_BRANCHES;
        entry->from = from;
        entry->to   = to;
-       if (!filter_check_discard(call, entry, tr->buffer, event))
-               trace_buffer_unlock_commit(tr, event, 0, 0);
+       if (!filter_check_discard(call, entry, buf, event))
+               trace_buffer_unlock_commit(buf, event, 0, 0);
 
  out:
        atomic_dec(&tr->data[cpu]->disabled);
index f572f44..b6c12c6 100644 (file)
@@ -69,6 +69,9 @@ enum print_line_t trace_print_printk_msg_only(struct trace_iterator *iter)
  * @s: trace sequence descriptor
  * @fmt: printf format string
  *
+ * It returns 0 if the trace oversizes the buffer's free
+ * space, 1 otherwise.
+ *
  * The tracer may use either sequence operations or its own
  * copy to user routines. To simplify formating of a trace
  * trace_seq_printf is used to store strings into a special
@@ -95,7 +98,7 @@ trace_seq_printf(struct trace_seq *s, const char *fmt, ...)
 
        s->len += ret;
 
-       return len;
+       return 1;
 }
 EXPORT_SYMBOL_GPL(trace_seq_printf);
 
@@ -486,16 +489,18 @@ int trace_print_lat_fmt(struct trace_seq *s, struct trace_entry *entry)
                                hardirq ? 'h' : softirq ? 's' : '.'))
                return 0;
 
-       if (entry->lock_depth < 0)
-               ret = trace_seq_putc(s, '.');
+       if (entry->preempt_count)
+               ret = trace_seq_printf(s, "%x", entry->preempt_count);
        else
-               ret = trace_seq_printf(s, "%d", entry->lock_depth);
+               ret = trace_seq_putc(s, '.');
+
        if (!ret)
                return 0;
 
-       if (entry->preempt_count)
-               return trace_seq_printf(s, "%x", entry->preempt_count);
-       return trace_seq_putc(s, '.');
+       if (entry->lock_depth < 0)
+               return trace_seq_putc(s, '.');
+
+       return trace_seq_printf(s, "%d", entry->lock_depth);
 }
 
 static int
@@ -883,7 +888,7 @@ static int trace_ctxwake_raw(struct trace_iterator *iter, char S)
        trace_assign_type(field, iter->ent);
 
        if (!S)
-               task_state_char(field->prev_state);
+               S = task_state_char(field->prev_state);
        T = task_state_char(field->next_state);
        if (!trace_seq_printf(&iter->seq, "%d %d %c %d %d %d %c\n",
                              field->prev_pid,
@@ -918,7 +923,7 @@ static int trace_ctxwake_hex(struct trace_iterator *iter, char S)
        trace_assign_type(field, iter->ent);
 
        if (!S)
-               task_state_char(field->prev_state);
+               S = task_state_char(field->prev_state);
        T = task_state_char(field->next_state);
 
        SEQ_PUT_HEX_FIELD_RET(s, field->prev_pid);
index 9fbce6c..527e17e 100644 (file)
@@ -166,7 +166,7 @@ int syscall_exit_format(struct ftrace_event_call *call, struct trace_seq *s)
                               "\tfield:%s %s;\toffset:%zu;\tsize:%zu;\n"
                               "\tfield:%s %s;\toffset:%zu;\tsize:%zu;\n",
                               SYSCALL_FIELD(int, nr),
-                              SYSCALL_FIELD(unsigned long, ret));
+                              SYSCALL_FIELD(long, ret));
        if (!ret)
                return 0;
 
@@ -212,7 +212,7 @@ int syscall_exit_define_fields(struct ftrace_event_call *call)
        if (ret)
                return ret;
 
-       ret = trace_define_field(call, SYSCALL_FIELD(unsigned long, ret), 0,
+       ret = trace_define_field(call, SYSCALL_FIELD(long, ret), 0,
                                 FILTER_OTHER);
 
        return ret;
index addfe2d..1232814 100644 (file)
@@ -640,6 +640,24 @@ int schedule_delayed_work(struct delayed_work *dwork,
 EXPORT_SYMBOL(schedule_delayed_work);
 
 /**
+ * flush_delayed_work - block until a dwork_struct's callback has terminated
+ * @dwork: the delayed work which is to be flushed
+ *
+ * Any timeout is cancelled, and any pending work is run immediately.
+ */
+void flush_delayed_work(struct delayed_work *dwork)
+{
+       if (del_timer_sync(&dwork->timer)) {
+               struct cpu_workqueue_struct *cwq;
+               cwq = wq_per_cpu(keventd_wq, get_cpu());
+               __queue_work(cwq, &dwork->work);
+               put_cpu();
+       }
+       flush_work(&dwork->work);
+}
+EXPORT_SYMBOL(flush_delayed_work);
+
+/**
  * schedule_delayed_work_on - queue work in global workqueue on CPU after delay
  * @cpu: cpu to use
  * @dwork: job to be done
@@ -667,21 +685,38 @@ EXPORT_SYMBOL(schedule_delayed_work_on);
 int schedule_on_each_cpu(work_func_t func)
 {
        int cpu;
+       int orig = -1;
        struct work_struct *works;
 
        works = alloc_percpu(struct work_struct);
        if (!works)
                return -ENOMEM;
 
+       /*
+        * when running in keventd don't schedule a work item on itself.
+        * Can just call directly because the work queue is already bound.
+        * This also is faster.
+        * Make this a generic parameter for other workqueues?
+        */
+       if (current_is_keventd()) {
+               orig = raw_smp_processor_id();
+               INIT_WORK(per_cpu_ptr(works, orig), func);
+               func(per_cpu_ptr(works, orig));
+       }
+
        get_online_cpus();
        for_each_online_cpu(cpu) {
                struct work_struct *work = per_cpu_ptr(works, cpu);
 
+               if (cpu == orig)
+                       continue;
                INIT_WORK(work, func);
                schedule_work_on(cpu, work);
        }
-       for_each_online_cpu(cpu)
-               flush_work(per_cpu_ptr(works, cpu));
+       for_each_online_cpu(cpu) {
+               if (cpu != orig)
+                       flush_work(per_cpu_ptr(works, cpu));
+       }
        put_online_cpus();
        free_percpu(works);
        return 0;
index 8911558..234ceb1 100644 (file)
@@ -346,8 +346,9 @@ config SLUB_STATS
 
 config DEBUG_KMEMLEAK
        bool "Kernel memory leak detector"
-       depends on DEBUG_KERNEL && EXPERIMENTAL && (X86 || ARM || PPC) && \
-               !MEMORY_HOTPLUG
+       depends on DEBUG_KERNEL && EXPERIMENTAL && !MEMORY_HOTPLUG && \
+               (X86 || ARM || PPC || S390)
+
        select DEBUG_FS if SYSFS
        select STACKTRACE if STACKTRACE_SUPPORT
        select KALLSYMS
@@ -370,7 +371,7 @@ config DEBUG_KMEMLEAK
 config DEBUG_KMEMLEAK_EARLY_LOG_SIZE
        int "Maximum kmemleak early log entries"
        depends on DEBUG_KMEMLEAK
-       range 200 2000
+       range 200 40000
        default 400
        help
          Kmemleak must track all the memory allocations to avoid
@@ -391,7 +392,7 @@ config DEBUG_KMEMLEAK_TEST
 
 config DEBUG_PREEMPT
        bool "Debug preemptible kernel"
-       depends on DEBUG_KERNEL && PREEMPT && (TRACE_IRQFLAGS_SUPPORT || PPC64)
+       depends on DEBUG_KERNEL && PREEMPT && TRACE_IRQFLAGS_SUPPORT
        default y
        help
          If you say Y here then the kernel will use a debug variant of the
index 2755a3b..eae56fd 100644 (file)
@@ -9,6 +9,7 @@
  */
 #include <linux/debugobjects.h>
 #include <linux/interrupt.h>
+#include <linux/sched.h>
 #include <linux/seq_file.h>
 #include <linux/debugfs.h>
 #include <linux/hash.h>
index f97af55..7e65af7 100644 (file)
@@ -1,6 +1,7 @@
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/random.h>
+#include <linux/sched.h>
 #include <linux/stat.h>
 #include <linux/types.h>
 #include <linux/fs.h>
index edd300a..fd33862 100644 (file)
@@ -67,7 +67,7 @@ config DISCONTIGMEM
 
 config SPARSEMEM
        def_bool y
-       depends on SPARSEMEM_MANUAL
+       depends on (!SELECT_MEMORY_MODEL && ARCH_SPARSEMEM_ENABLE) || SPARSEMEM_MANUAL
 
 config FLATMEM
        def_bool y
@@ -129,7 +129,7 @@ config MEMORY_HOTPLUG
        bool "Allow for memory hot-add"
        depends on SPARSEMEM || X86_64_ACPI_NUMA
        depends on HOTPLUG && !(HIBERNATION && !S390) && ARCH_ENABLE_MEMORY_HOTPLUG
-       depends on (IA64 || X86 || PPC64 || SUPERH || S390)
+       depends on (IA64 || X86 || PPC_BOOK3S_64 || SUPERH || S390)
 
 comment "Memory hotplug is currently incompatible with Software Suspend"
        depends on SPARSEMEM && HOTPLUG && HIBERNATION && !S390
@@ -224,7 +224,9 @@ config KSM
          the many instances by a single resident page with that content, so
          saving memory until one or another app needs to modify the content.
          Recommended for use with KVM, or with other duplicative applications.
-         See Documentation/vm/ksm.txt for more information.
+         See Documentation/vm/ksm.txt for more information: KSM is inactive
+         until a program has madvised that an area is MADV_MERGEABLE, and
+         root has set /sys/kernel/mm/ksm/run to 1 (if CONFIG_SYSFS is set).
 
 config DEFAULT_MMAP_MIN_ADDR
         int "Low address space to protect from user allocation"
index 3d3accb..1065b71 100644 (file)
@@ -92,7 +92,7 @@ static int bdi_debug_stats_show(struct seq_file *m, void *v)
                   "BdiDirtyThresh:   %8lu kB\n"
                   "DirtyThresh:      %8lu kB\n"
                   "BackgroundThresh: %8lu kB\n"
-                  "WriteBack threads:%8lu\n"
+                  "WritebackThreads: %8lu\n"
                   "b_dirty:          %8lu\n"
                   "b_io:             %8lu\n"
                   "b_more_io:        %8lu\n"
@@ -610,6 +610,21 @@ static void bdi_wb_shutdown(struct backing_dev_info *bdi)
                kthread_stop(wb->task);
 }
 
+/*
+ * This bdi is going away now, make sure that no super_blocks point to it
+ */
+static void bdi_prune_sb(struct backing_dev_info *bdi)
+{
+       struct super_block *sb;
+
+       spin_lock(&sb_lock);
+       list_for_each_entry(sb, &super_blocks, s_list) {
+               if (sb->s_bdi == bdi)
+                       sb->s_bdi = NULL;
+       }
+       spin_unlock(&sb_lock);
+}
+
 void bdi_unregister(struct backing_dev_info *bdi)
 {
        if (bdi->dev) {
@@ -682,6 +697,7 @@ void bdi_destroy(struct backing_dev_info *bdi)
                spin_unlock(&inode_lock);
        }
 
+       bdi_prune_sb(bdi);
        bdi_unregister(bdi);
 
        for (i = 0; i < NR_BDI_STAT_ITEMS; i++)
index 4ea4510..8bf765c 100644 (file)
@@ -833,12 +833,15 @@ static void early_alloc(struct early_log *log)
         */
        rcu_read_lock();
        object = create_object((unsigned long)log->ptr, log->size,
-                              log->min_count, GFP_KERNEL);
+                              log->min_count, GFP_ATOMIC);
+       if (!object)
+               goto out;
        spin_lock_irqsave(&object->lock, flags);
        for (i = 0; i < log->trace_len; i++)
                object->trace[i] = log->trace[i];
        object->trace_len = log->trace_len;
        spin_unlock_irqrestore(&object->lock, flags);
+out:
        rcu_read_unlock();
 }
 
index f7edac3..bef1af4 100644 (file)
--- a/mm/ksm.c
+++ b/mm/ksm.c
@@ -184,11 +184,6 @@ static DEFINE_SPINLOCK(ksm_mmlist_lock);
                sizeof(struct __struct), __alignof__(struct __struct),\
                (__flags), NULL)
 
-static void __init ksm_init_max_kernel_pages(void)
-{
-       ksm_max_kernel_pages = nr_free_buffer_pages() / 4;
-}
-
 static int __init ksm_slab_init(void)
 {
        rmap_item_cache = KSM_KMEM_CACHE(rmap_item, 0);
@@ -1673,7 +1668,7 @@ static int __init ksm_init(void)
        struct task_struct *ksm_thread;
        int err;
 
-       ksm_init_max_kernel_pages();
+       ksm_max_kernel_pages = totalram_pages / 4;
 
        err = ksm_slab_init();
        if (err)
@@ -1697,6 +1692,9 @@ static int __init ksm_init(void)
                kthread_stop(ksm_thread);
                goto out_free2;
        }
+#else
+       ksm_run = KSM_RUN_MERGE;        /* no way for user to start it */
+
 #endif /* CONFIG_SYSFS */
 
        return 0;
index 729d4b1..dacc641 100644 (file)
@@ -35,6 +35,7 @@
 #include <linux/mm.h>
 #include <linux/page-flags.h>
 #include <linux/sched.h>
+#include <linux/ksm.h>
 #include <linux/rmap.h>
 #include <linux/pagemap.h>
 #include <linux/swap.h>
@@ -370,9 +371,6 @@ static int me_pagecache_clean(struct page *p, unsigned long pfn)
        int ret = FAILED;
        struct address_space *mapping;
 
-       if (!isolate_lru_page(p))
-               page_cache_release(p);
-
        /*
         * For anonymous pages we're done the only reference left
         * should be the one m_f() holds.
@@ -498,30 +496,18 @@ static int me_pagecache_dirty(struct page *p, unsigned long pfn)
  */
 static int me_swapcache_dirty(struct page *p, unsigned long pfn)
 {
-       int ret = FAILED;
-
        ClearPageDirty(p);
        /* Trigger EIO in shmem: */
        ClearPageUptodate(p);
 
-       if (!isolate_lru_page(p)) {
-               page_cache_release(p);
-               ret = DELAYED;
-       }
-
-       return ret;
+       return DELAYED;
 }
 
 static int me_swapcache_clean(struct page *p, unsigned long pfn)
 {
-       int ret = FAILED;
-
-       if (!isolate_lru_page(p)) {
-               page_cache_release(p);
-               ret = RECOVERED;
-       }
        delete_from_swap_cache(p);
-       return ret;
+
+       return RECOVERED;
 }
 
 /*
@@ -611,8 +597,6 @@ static struct page_state {
        { 0,            0,              "unknown page state",   me_unknown },
 };
 
-#undef lru
-
 static void action_result(unsigned long pfn, char *msg, int result)
 {
        struct page *page = NULL;
@@ -629,13 +613,16 @@ static int page_action(struct page_state *ps, struct page *p,
                        unsigned long pfn, int ref)
 {
        int result;
+       int count;
 
        result = ps->action(p, pfn);
        action_result(pfn, ps->msg, result);
-       if (page_count(p) != 1 + ref)
+
+       count = page_count(p) - 1 - ref;
+       if (count != 0)
                printk(KERN_ERR
                       "MCE %#lx: %s page still referenced by %d users\n",
-                      pfn, ps->msg, page_count(p) - 1);
+                      pfn, ps->msg, count);
 
        /* Could do more checks here if page looks ok */
        /*
@@ -661,12 +648,9 @@ static void hwpoison_user_mappings(struct page *p, unsigned long pfn,
        int i;
        int kill = 1;
 
-       if (PageReserved(p) || PageCompound(p) || PageSlab(p))
+       if (PageReserved(p) || PageCompound(p) || PageSlab(p) || PageKsm(p))
                return;
 
-       if (!PageLRU(p))
-               lru_add_drain_all();
-
        /*
         * This check implies we don't kill processes if their pages
         * are in the swap cache early. Those are always late kills.
@@ -738,6 +722,7 @@ static void hwpoison_user_mappings(struct page *p, unsigned long pfn,
 
 int __memory_failure(unsigned long pfn, int trapno, int ref)
 {
+       unsigned long lru_flag;
        struct page_state *ps;
        struct page *p;
        int res;
@@ -775,6 +760,24 @@ int __memory_failure(unsigned long pfn, int trapno, int ref)
        }
 
        /*
+        * We ignore non-LRU pages for good reasons.
+        * - PG_locked is only well defined for LRU pages and a few others
+        * - to avoid races with __set_page_locked()
+        * - to avoid races with __SetPageSlab*() (and more non-atomic ops)
+        * The check (unnecessarily) ignores LRU pages being isolated and
+        * walked by the page reclaim code, however that's not a big loss.
+        */
+       if (!PageLRU(p))
+               lru_add_drain_all();
+       lru_flag = p->flags & lru;
+       if (isolate_lru_page(p)) {
+               action_result(pfn, "non LRU", IGNORED);
+               put_page(p);
+               return -EBUSY;
+       }
+       page_cache_release(p);
+
+       /*
         * Lock the page and wait for writeback to finish.
         * It's very difficult to mess with pages currently under IO
         * and in many cases impossible, so we just avoid it here.
@@ -790,7 +793,7 @@ int __memory_failure(unsigned long pfn, int trapno, int ref)
        /*
         * Torn down by someone else?
         */
-       if (PageLRU(p) && !PageSwapCache(p) && p->mapping == NULL) {
+       if ((lru_flag & lru) && !PageSwapCache(p) && p->mapping == NULL) {
                action_result(pfn, "already truncated LRU", IGNORED);
                res = 0;
                goto out;
@@ -798,7 +801,7 @@ int __memory_failure(unsigned long pfn, int trapno, int ref)
 
        res = -EBUSY;
        for (ps = error_states;; ps++) {
-               if ((p->flags & ps->mask) == ps->res) {
+               if (((p->flags | lru_flag)& ps->mask) == ps->res) {
                        res = page_action(ps, p, pfn, ref);
                        break;
                }
index 7e91b5f..6ab19dd 100644 (file)
@@ -641,6 +641,7 @@ static int copy_pte_range(struct mm_struct *dst_mm, struct mm_struct *src_mm,
                pmd_t *dst_pmd, pmd_t *src_pmd, struct vm_area_struct *vma,
                unsigned long addr, unsigned long end)
 {
+       pte_t *orig_src_pte, *orig_dst_pte;
        pte_t *src_pte, *dst_pte;
        spinlock_t *src_ptl, *dst_ptl;
        int progress = 0;
@@ -654,6 +655,8 @@ again:
        src_pte = pte_offset_map_nested(src_pmd, addr);
        src_ptl = pte_lockptr(src_mm, src_pmd);
        spin_lock_nested(src_ptl, SINGLE_DEPTH_NESTING);
+       orig_src_pte = src_pte;
+       orig_dst_pte = dst_pte;
        arch_enter_lazy_mmu_mode();
 
        do {
@@ -677,9 +680,9 @@ again:
 
        arch_leave_lazy_mmu_mode();
        spin_unlock(src_ptl);
-       pte_unmap_nested(src_pte - 1);
+       pte_unmap_nested(orig_src_pte);
        add_mm_rss(dst_mm, rss[0], rss[1]);
-       pte_unmap_unlock(dst_pte - 1, dst_ptl);
+       pte_unmap_unlock(orig_dst_pte, dst_ptl);
        cond_resched();
        if (addr != end)
                goto again;
@@ -1820,10 +1823,10 @@ static int apply_to_pte_range(struct mm_struct *mm, pmd_t *pmd,
        token = pmd_pgtable(*pmd);
 
        do {
-               err = fn(pte, token, addr, data);
+               err = fn(pte++, token, addr, data);
                if (err)
                        break;
-       } while (pte++, addr += PAGE_SIZE, addr != end);
+       } while (addr += PAGE_SIZE, addr != end);
 
        arch_leave_lazy_mmu_mode();
 
@@ -2539,7 +2542,7 @@ static int do_swap_page(struct mm_struct *mm, struct vm_area_struct *vma,
        } else if (PageHWPoison(page)) {
                ret = VM_FAULT_HWPOISON;
                delayacct_clear_flag(DELAYACCT_PF_SWAPIN);
-               goto out;
+               goto out_release;
        }
 
        lock_page(page);
@@ -2611,6 +2614,7 @@ out_nomap:
        pte_unmap_unlock(page_table, ptl);
 out_page:
        unlock_page(page);
+out_release:
        page_cache_release(page);
        return ret;
 }
index 7dd9d9f..4545d59 100644 (file)
@@ -1024,7 +1024,7 @@ static long do_mbind(unsigned long start, unsigned long len,
 
                err = migrate_prep();
                if (err)
-                       return err;
+                       goto mpol_out;
        }
        {
                NODEMASK_SCRATCH(scratch);
@@ -1039,10 +1039,9 @@ static long do_mbind(unsigned long start, unsigned long len,
                        err = -ENOMEM;
                NODEMASK_SCRATCH_FREE(scratch);
        }
-       if (err) {
-               mpol_put(new);
-               return err;
-       }
+       if (err)
+               goto mpol_out;
+
        vma = check_range(mm, start, end, nmask,
                          flags | MPOL_MF_INVERT, &pagelist);
 
@@ -1058,9 +1057,11 @@ static long do_mbind(unsigned long start, unsigned long len,
 
                if (!err && nr_failed && (flags & MPOL_MF_STRICT))
                        err = -EIO;
-       }
+       } else
+               putback_lru_pages(&pagelist);
 
        up_write(&mm->mmap_sem);
+ mpol_out:
        mpol_put(new);
        return err;
 }
index 5189b5a..9876fa0 100644 (file)
@@ -1362,9 +1362,11 @@ share:
 error_just_free:
        up_write(&nommu_region_sem);
 error:
-       fput(region->vm_file);
+       if (region->vm_file)
+               fput(region->vm_file);
        kmem_cache_free(vm_region_jar, region);
-       fput(vma->vm_file);
+       if (vma->vm_file)
+               fput(vma->vm_file);
        if (vma->vm_flags & VM_EXECUTABLE)
                removed_exe_file_vma(vma->vm_mm);
        kmem_cache_free(vm_area_cachep, vma);
index a3b1409..2c5d792 100644 (file)
@@ -566,7 +566,8 @@ static void balance_dirty_pages(struct address_space *mapping,
                if (pages_written >= write_chunk)
                        break;          /* We've done our duty */
 
-               schedule_timeout_interruptible(pause);
+               __set_current_state(TASK_INTERRUPTIBLE);
+               io_schedule_timeout(pause);
 
                /*
                 * Increase the delay for each loop, up to our previous
index bf72055..cdcedf6 100644 (file)
@@ -2183,7 +2183,7 @@ void show_free_areas(void)
        printk("active_anon:%lu inactive_anon:%lu isolated_anon:%lu\n"
                " active_file:%lu inactive_file:%lu isolated_file:%lu\n"
                " unevictable:%lu"
-               " dirty:%lu writeback:%lu unstable:%lu buffer:%lu\n"
+               " dirty:%lu writeback:%lu unstable:%lu\n"
                " free:%lu slab_reclaimable:%lu slab_unreclaimable:%lu\n"
                " mapped:%lu shmem:%lu pagetables:%lu bounce:%lu\n",
                global_page_state(NR_ACTIVE_ANON),
@@ -2196,7 +2196,6 @@ void show_free_areas(void)
                global_page_state(NR_FILE_DIRTY),
                global_page_state(NR_WRITEBACK),
                global_page_state(NR_UNSTABLE_NFS),
-               nr_blockdev_pages(),
                global_page_state(NR_FREE_PAGES),
                global_page_state(NR_SLAB_RECLAIMABLE),
                global_page_state(NR_SLAB_UNRECLAIMABLE),
index 4a048ab..d907971 100644 (file)
@@ -153,7 +153,10 @@ static int pcpu_reserved_chunk_limit;
  *
  * During allocation, pcpu_alloc_mutex is kept locked all the time and
  * pcpu_lock is grabbed and released as necessary.  All actual memory
- * allocations are done using GFP_KERNEL with pcpu_lock released.
+ * allocations are done using GFP_KERNEL with pcpu_lock released.  In
+ * general, percpu memory can't be allocated with irq off but
+ * irqsave/restore are still used in alloc path so that it can be used
+ * from early init path - sched_init() specifically.
  *
  * Free path accesses and alters only the index data structures, so it
  * can be safely called from atomic context.  When memory needs to be
@@ -366,7 +369,7 @@ static struct pcpu_chunk *pcpu_chunk_addr_search(void *addr)
  * RETURNS:
  * 0 if noop, 1 if successfully extended, -errno on failure.
  */
-static int pcpu_extend_area_map(struct pcpu_chunk *chunk)
+static int pcpu_extend_area_map(struct pcpu_chunk *chunk, unsigned long *flags)
 {
        int new_alloc;
        int *new;
@@ -376,7 +379,7 @@ static int pcpu_extend_area_map(struct pcpu_chunk *chunk)
        if (chunk->map_alloc >= chunk->map_used + 2)
                return 0;
 
-       spin_unlock_irq(&pcpu_lock);
+       spin_unlock_irqrestore(&pcpu_lock, *flags);
 
        new_alloc = PCPU_DFL_MAP_ALLOC;
        while (new_alloc < chunk->map_used + 2)
@@ -384,7 +387,7 @@ static int pcpu_extend_area_map(struct pcpu_chunk *chunk)
 
        new = pcpu_mem_alloc(new_alloc * sizeof(new[0]));
        if (!new) {
-               spin_lock_irq(&pcpu_lock);
+               spin_lock_irqsave(&pcpu_lock, *flags);
                return -ENOMEM;
        }
 
@@ -393,7 +396,7 @@ static int pcpu_extend_area_map(struct pcpu_chunk *chunk)
         * could have happened inbetween, so map_used couldn't have
         * grown.
         */
-       spin_lock_irq(&pcpu_lock);
+       spin_lock_irqsave(&pcpu_lock, *flags);
        BUG_ON(new_alloc < chunk->map_used + 2);
 
        size = chunk->map_alloc * sizeof(chunk->map[0]);
@@ -1047,6 +1050,7 @@ static void *pcpu_alloc(size_t size, size_t align, bool reserved)
        struct pcpu_chunk *chunk;
        const char *err;
        int slot, off;
+       unsigned long flags;
 
        if (unlikely(!size || size > PCPU_MIN_UNIT_SIZE || align > PAGE_SIZE)) {
                WARN(true, "illegal size (%zu) or align (%zu) for "
@@ -1055,13 +1059,13 @@ static void *pcpu_alloc(size_t size, size_t align, bool reserved)
        }
 
        mutex_lock(&pcpu_alloc_mutex);
-       spin_lock_irq(&pcpu_lock);
+       spin_lock_irqsave(&pcpu_lock, flags);
 
        /* serve reserved allocations from the reserved chunk if available */
        if (reserved && pcpu_reserved_chunk) {
                chunk = pcpu_reserved_chunk;
                if (size > chunk->contig_hint ||
-                   pcpu_extend_area_map(chunk) < 0) {
+                   pcpu_extend_area_map(chunk, &flags) < 0) {
                        err = "failed to extend area map of reserved chunk";
                        goto fail_unlock;
                }
@@ -1079,7 +1083,7 @@ restart:
                        if (size > chunk->contig_hint)
                                continue;
 
-                       switch (pcpu_extend_area_map(chunk)) {
+                       switch (pcpu_extend_area_map(chunk, &flags)) {
                        case 0:
                                break;
                        case 1:
@@ -1096,7 +1100,7 @@ restart:
        }
 
        /* hmmm... no space left, create a new chunk */
-       spin_unlock_irq(&pcpu_lock);
+       spin_unlock_irqrestore(&pcpu_lock, flags);
 
        chunk = alloc_pcpu_chunk();
        if (!chunk) {
@@ -1104,16 +1108,16 @@ restart:
                goto fail_unlock_mutex;
        }
 
-       spin_lock_irq(&pcpu_lock);
+       spin_lock_irqsave(&pcpu_lock, flags);
        pcpu_chunk_relocate(chunk, -1);
        goto restart;
 
 area_found:
-       spin_unlock_irq(&pcpu_lock);
+       spin_unlock_irqrestore(&pcpu_lock, flags);
 
        /* populate, map and clear the area */
        if (pcpu_populate_chunk(chunk, off, size)) {
-               spin_lock_irq(&pcpu_lock);
+               spin_lock_irqsave(&pcpu_lock, flags);
                pcpu_free_area(chunk, off);
                err = "failed to populate";
                goto fail_unlock;
@@ -1125,7 +1129,7 @@ area_found:
        return __addr_to_pcpu_ptr(chunk->base_addr + off);
 
 fail_unlock:
-       spin_unlock_irq(&pcpu_lock);
+       spin_unlock_irqrestore(&pcpu_lock, flags);
 fail_unlock_mutex:
        mutex_unlock(&pcpu_alloc_mutex);
        if (warn_limit) {
@@ -1870,13 +1874,14 @@ int __init pcpu_embed_first_chunk(size_t reserved_size, ssize_t dyn_size,
        max_distance = 0;
        for (group = 0; group < ai->nr_groups; group++) {
                ai->groups[group].base_offset = areas[group] - base;
-               max_distance = max(max_distance, ai->groups[group].base_offset);
+               max_distance = max_t(size_t, max_distance,
+                                    ai->groups[group].base_offset);
        }
        max_distance += ai->unit_size;
 
        /* warn if maximum distance is further than 75% of vmalloc space */
        if (max_distance > (VMALLOC_END - VMALLOC_START) * 3 / 4) {
-               pr_warning("PERCPU: max_distance=0x%lx too large for vmalloc "
+               pr_warning("PERCPU: max_distance=0x%zx too large for vmalloc "
                           "space 0x%lx\n",
                           max_distance, VMALLOC_END - VMALLOC_START);
 #ifdef CONFIG_NEED_PER_CPU_PAGE_FIRST_CHUNK
index a1bc6b9..9c590ee 100644 (file)
@@ -1151,8 +1151,7 @@ static int try_to_unuse(unsigned int type)
                                } else
                                        retval = unuse_mm(mm, entry, page);
 
-                               if (set_start_mm &&
-                                   swap_count(*swap_map) < swcount) {
+                               if (set_start_mm && *swap_map < swcount) {
                                        mmput(new_start_mm);
                                        atomic_inc(&mm->mm_users);
                                        new_start_mm = mm;
index 69511e6..0f551a4 100644 (file)
@@ -12,6 +12,7 @@
 #include <linux/mm.h>
 #include <linux/module.h>
 #include <linux/highmem.h>
+#include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/spinlock.h>
 #include <linux/interrupt.h>
 #include <linux/rcupdate.h>
 #include <linux/pfn.h>
 #include <linux/kmemleak.h>
-#include <linux/highmem.h>
 #include <asm/atomic.h>
 #include <asm/uaccess.h>
 #include <asm/tlbflush.h>
+#include <asm/shmparam.h>
 
 
 /*** Page table manipulation functions ***/
@@ -1156,12 +1157,11 @@ static void insert_vmalloc_vm(struct vm_struct *vm, struct vmap_area *va,
 }
 
 static struct vm_struct *__get_vm_area_node(unsigned long size,
-               unsigned long flags, unsigned long start, unsigned long end,
-               int node, gfp_t gfp_mask, void *caller)
+               unsigned long align, unsigned long flags, unsigned long start,
+               unsigned long end, int node, gfp_t gfp_mask, void *caller)
 {
        static struct vmap_area *va;
        struct vm_struct *area;
-       unsigned long align = 1;
 
        BUG_ON(in_interrupt());
        if (flags & VM_IOREMAP) {
@@ -1201,7 +1201,7 @@ static struct vm_struct *__get_vm_area_node(unsigned long size,
 struct vm_struct *__get_vm_area(unsigned long size, unsigned long flags,
                                unsigned long start, unsigned long end)
 {
-       return __get_vm_area_node(size, flags, start, end, -1, GFP_KERNEL,
+       return __get_vm_area_node(size, 1, flags, start, end, -1, GFP_KERNEL,
                                                __builtin_return_address(0));
 }
 EXPORT_SYMBOL_GPL(__get_vm_area);
@@ -1210,7 +1210,7 @@ struct vm_struct *__get_vm_area_caller(unsigned long size, unsigned long flags,
                                       unsigned long start, unsigned long end,
                                       void *caller)
 {
-       return __get_vm_area_node(size, flags, start, end, -1, GFP_KERNEL,
+       return __get_vm_area_node(size, 1, flags, start, end, -1, GFP_KERNEL,
                                  caller);
 }
 
@@ -1225,22 +1225,22 @@ struct vm_struct *__get_vm_area_caller(unsigned long size, unsigned long flags,
  */
 struct vm_struct *get_vm_area(unsigned long size, unsigned long flags)
 {
-       return __get_vm_area_node(size, flags, VMALLOC_START, VMALLOC_END,
+       return __get_vm_area_node(size, 1, flags, VMALLOC_START, VMALLOC_END,
                                -1, GFP_KERNEL, __builtin_return_address(0));
 }
 
 struct vm_struct *get_vm_area_caller(unsigned long size, unsigned long flags,
                                void *caller)
 {
-       return __get_vm_area_node(size, flags, VMALLOC_START, VMALLOC_END,
+       return __get_vm_area_node(size, 1, flags, VMALLOC_START, VMALLOC_END,
                                                -1, GFP_KERNEL, caller);
 }
 
 struct vm_struct *get_vm_area_node(unsigned long size, unsigned long flags,
                                   int node, gfp_t gfp_mask)
 {
-       return __get_vm_area_node(size, flags, VMALLOC_START, VMALLOC_END, node,
-                                 gfp_mask, __builtin_return_address(0));
+       return __get_vm_area_node(size, 1, flags, VMALLOC_START, VMALLOC_END,
+                                 node, gfp_mask, __builtin_return_address(0));
 }
 
 static struct vm_struct *find_vm_area(const void *addr)
@@ -1403,7 +1403,8 @@ void *vmap(struct page **pages, unsigned int count,
 }
 EXPORT_SYMBOL(vmap);
 
-static void *__vmalloc_node(unsigned long size, gfp_t gfp_mask, pgprot_t prot,
+static void *__vmalloc_node(unsigned long size, unsigned long align,
+                           gfp_t gfp_mask, pgprot_t prot,
                            int node, void *caller);
 static void *__vmalloc_area_node(struct vm_struct *area, gfp_t gfp_mask,
                                 pgprot_t prot, int node, void *caller)
@@ -1417,7 +1418,7 @@ static void *__vmalloc_area_node(struct vm_struct *area, gfp_t gfp_mask,
        area->nr_pages = nr_pages;
        /* Please note that the recursion is strictly bounded. */
        if (array_size > PAGE_SIZE) {
-               pages = __vmalloc_node(array_size, gfp_mask | __GFP_ZERO,
+               pages = __vmalloc_node(array_size, 1, gfp_mask | __GFP_ZERO,
                                PAGE_KERNEL, node, caller);
                area->flags |= VM_VPAGES;
        } else {
@@ -1476,6 +1477,7 @@ void *__vmalloc_area(struct vm_struct *area, gfp_t gfp_mask, pgprot_t prot)
 /**
  *     __vmalloc_node  -  allocate virtually contiguous memory
  *     @size:          allocation size
+ *     @align:         desired alignment
  *     @gfp_mask:      flags for the page level allocator
  *     @prot:          protection mask for the allocated pages
  *     @node:          node to use for allocation or -1
@@ -1485,8 +1487,9 @@ void *__vmalloc_area(struct vm_struct *area, gfp_t gfp_mask, pgprot_t prot)
  *     allocator with @gfp_mask flags.  Map them into contiguous
  *     kernel virtual space, using a pagetable protection of @prot.
  */
-static void *__vmalloc_node(unsigned long size, gfp_t gfp_mask, pgprot_t prot,
-                                               int node, void *caller)
+static void *__vmalloc_node(unsigned long size, unsigned long align,
+                           gfp_t gfp_mask, pgprot_t prot,
+                           int node, void *caller)
 {
        struct vm_struct *area;
        void *addr;
@@ -1496,8 +1499,8 @@ static void *__vmalloc_node(unsigned long size, gfp_t gfp_mask, pgprot_t prot,
        if (!size || (size >> PAGE_SHIFT) > totalram_pages)
                return NULL;
 
-       area = __get_vm_area_node(size, VM_ALLOC, VMALLOC_START, VMALLOC_END,
-                                               node, gfp_mask, caller);
+       area = __get_vm_area_node(size, align, VM_ALLOC, VMALLOC_START,
+                                 VMALLOC_END, node, gfp_mask, caller);
 
        if (!area)
                return NULL;
@@ -1516,7 +1519,7 @@ static void *__vmalloc_node(unsigned long size, gfp_t gfp_mask, pgprot_t prot,
 
 void *__vmalloc(unsigned long size, gfp_t gfp_mask, pgprot_t prot)
 {
-       return __vmalloc_node(size, gfp_mask, prot, -1,
+       return __vmalloc_node(size, 1, gfp_mask, prot, -1,
                                __builtin_return_address(0));
 }
 EXPORT_SYMBOL(__vmalloc);
@@ -1532,7 +1535,7 @@ EXPORT_SYMBOL(__vmalloc);
  */
 void *vmalloc(unsigned long size)
 {
-       return __vmalloc_node(size, GFP_KERNEL | __GFP_HIGHMEM, PAGE_KERNEL,
+       return __vmalloc_node(size, 1, GFP_KERNEL | __GFP_HIGHMEM, PAGE_KERNEL,
                                        -1, __builtin_return_address(0));
 }
 EXPORT_SYMBOL(vmalloc);
@@ -1549,7 +1552,8 @@ void *vmalloc_user(unsigned long size)
        struct vm_struct *area;
        void *ret;
 
-       ret = __vmalloc_node(size, GFP_KERNEL | __GFP_HIGHMEM | __GFP_ZERO,
+       ret = __vmalloc_node(size, SHMLBA,
+                            GFP_KERNEL | __GFP_HIGHMEM | __GFP_ZERO,
                             PAGE_KERNEL, -1, __builtin_return_address(0));
        if (ret) {
                area = find_vm_area(ret);
@@ -1572,7 +1576,7 @@ EXPORT_SYMBOL(vmalloc_user);
  */
 void *vmalloc_node(unsigned long size, int node)
 {
-       return __vmalloc_node(size, GFP_KERNEL | __GFP_HIGHMEM, PAGE_KERNEL,
+       return __vmalloc_node(size, 1, GFP_KERNEL | __GFP_HIGHMEM, PAGE_KERNEL,
                                        node, __builtin_return_address(0));
 }
 EXPORT_SYMBOL(vmalloc_node);
@@ -1595,7 +1599,7 @@ EXPORT_SYMBOL(vmalloc_node);
 
 void *vmalloc_exec(unsigned long size)
 {
-       return __vmalloc_node(size, GFP_KERNEL | __GFP_HIGHMEM, PAGE_KERNEL_EXEC,
+       return __vmalloc_node(size, 1, GFP_KERNEL | __GFP_HIGHMEM, PAGE_KERNEL_EXEC,
                              -1, __builtin_return_address(0));
 }
 
@@ -1616,7 +1620,7 @@ void *vmalloc_exec(unsigned long size)
  */
 void *vmalloc_32(unsigned long size)
 {
-       return __vmalloc_node(size, GFP_VMALLOC32, PAGE_KERNEL,
+       return __vmalloc_node(size, 1, GFP_VMALLOC32, PAGE_KERNEL,
                              -1, __builtin_return_address(0));
 }
 EXPORT_SYMBOL(vmalloc_32);
@@ -1633,7 +1637,7 @@ void *vmalloc_32_user(unsigned long size)
        struct vm_struct *area;
        void *ret;
 
-       ret = __vmalloc_node(size, GFP_VMALLOC32 | __GFP_ZERO, PAGE_KERNEL,
+       ret = __vmalloc_node(size, 1, GFP_VMALLOC32 | __GFP_ZERO, PAGE_KERNEL,
                             -1, __builtin_return_address(0));
        if (ret) {
                area = find_vm_area(ret);
index 64e4388..777af57 100644 (file)
@@ -544,6 +544,16 @@ redo:
                 */
                lru = LRU_UNEVICTABLE;
                add_page_to_unevictable_list(page);
+               /*
+                * When racing with an mlock clearing (page is
+                * unlocked), make sure that if the other thread does
+                * not observe our setting of PG_lru and fails
+                * isolation, we see PG_mlocked cleared below and move
+                * the page back to the evictable list.
+                *
+                * The other side is TestClearPageMlocked().
+                */
+               smp_mb();
        }
 
        /*
@@ -1088,7 +1098,7 @@ static unsigned long shrink_inactive_list(unsigned long max_scan,
        int lumpy_reclaim = 0;
 
        while (unlikely(too_many_isolated(zone, file, sc))) {
-               congestion_wait(WRITE, HZ/10);
+               congestion_wait(BLK_RW_ASYNC, HZ/10);
 
                /* We are about to die and free our memory. Return now. */
                if (fatal_signal_pending(current))
@@ -1356,7 +1366,7 @@ static void shrink_active_list(unsigned long nr_pages, struct zone *zone,
                         * IO, plus JVM can create lots of anon VM_EXEC pages,
                         * so we ignore them here.
                         */
-                       if ((vm_flags & VM_EXEC) && !PageAnon(page)) {
+                       if ((vm_flags & VM_EXEC) && page_is_file_cache(page)) {
                                list_add(&page->lru, &l_active);
                                continue;
                        }
index 5bf5f22..8af95b2 100644 (file)
@@ -582,11 +582,9 @@ static struct p9_fid *p9_fid_create(struct p9_client *clnt)
 
        memset(&fid->qid, 0, sizeof(struct p9_qid));
        fid->mode = -1;
-       fid->rdir_fpos = 0;
        fid->uid = current_fsuid();
        fid->clnt = clnt;
-       fid->aux = NULL;
-
+       fid->rdir = NULL;
        spin_lock_irqsave(&clnt->lock, flags);
        list_add(&fid->flist, &clnt->fidlist);
        spin_unlock_irqrestore(&clnt->lock, flags);
@@ -609,6 +607,7 @@ static void p9_fid_destroy(struct p9_fid *fid)
        spin_lock_irqsave(&clnt->lock, flags);
        list_del(&fid->flist);
        spin_unlock_irqrestore(&clnt->lock, flags);
+       kfree(fid->rdir);
        kfree(fid);
 }
 
index b2e07f0..ea1e3da 100644 (file)
@@ -43,7 +43,6 @@
 #include <net/9p/transport.h>
 #include <linux/scatterlist.h>
 #include <linux/virtio.h>
-#include <linux/virtio_ids.h>
 #include <linux/virtio_9p.h>
 
 #define VIRTQUEUE_NUM  128
index 7f939ce..2bc6f6a 100644 (file)
@@ -92,6 +92,8 @@ static void add_conn(struct work_struct *work)
 
        dev_set_name(&conn->dev, "%s:%d", hdev->name, conn->handle);
 
+       dev_set_drvdata(&conn->dev, conn);
+
        if (device_add(&conn->dev) < 0) {
                BT_ERR("Failed to register connection device");
                return;
@@ -144,8 +146,6 @@ void hci_conn_init_sysfs(struct hci_conn *conn)
        conn->dev.class = bt_class;
        conn->dev.parent = &hdev->dev;
 
-       dev_set_drvdata(&conn->dev, conn);
-
        device_initialize(&conn->dev);
 
        INIT_WORK(&conn->work_add, add_conn);
index 555d9da..77e9fb1 100644 (file)
@@ -555,12 +555,12 @@ static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon, u8 status)
 
        conn->feat_mask = 0;
 
-       setup_timer(&conn->info_timer, l2cap_info_timeout,
-                                               (unsigned long) conn);
-
        spin_lock_init(&conn->lock);
        rwlock_init(&conn->chan_list.lock);
 
+       setup_timer(&conn->info_timer, l2cap_info_timeout,
+                                               (unsigned long) conn);
+
        conn->disc_reason = 0x13;
 
        return conn;
@@ -783,6 +783,9 @@ static void l2cap_sock_init(struct sock *sk, struct sock *parent)
        /* Default config options */
        pi->conf_len = 0;
        pi->flush_to = L2CAP_DEFAULT_FLUSH_TO;
+       skb_queue_head_init(TX_QUEUE(sk));
+       skb_queue_head_init(SREJ_QUEUE(sk));
+       INIT_LIST_HEAD(SREJ_LIST(sk));
 }
 
 static struct proto l2cap_proto = {
index 1c6cf3a..4ade301 100644 (file)
@@ -224,6 +224,15 @@ void skb_free_datagram(struct sock *sk, struct sk_buff *skb)
        consume_skb(skb);
        sk_mem_reclaim_partial(sk);
 }
+EXPORT_SYMBOL(skb_free_datagram);
+
+void skb_free_datagram_locked(struct sock *sk, struct sk_buff *skb)
+{
+       lock_sock(sk);
+       skb_free_datagram(sk, skb);
+       release_sock(sk);
+}
+EXPORT_SYMBOL(skb_free_datagram_locked);
 
 /**
  *     skb_kill_datagram - Free a datagram skbuff forcibly
@@ -752,5 +761,4 @@ unsigned int datagram_poll(struct file *file, struct socket *sock,
 EXPORT_SYMBOL(datagram_poll);
 EXPORT_SYMBOL(skb_copy_and_csum_datagram_iovec);
 EXPORT_SYMBOL(skb_copy_datagram_iovec);
-EXPORT_SYMBOL(skb_free_datagram);
 EXPORT_SYMBOL(skb_recv_datagram);
index 821d309..427ded8 100644 (file)
@@ -366,13 +366,13 @@ static ssize_t wireless_show(struct device *d, char *buf,
        const struct iw_statistics *iw;
        ssize_t ret = -EINVAL;
 
-       read_lock(&dev_base_lock);
+       rtnl_lock();
        if (dev_isalive(dev)) {
                iw = get_wireless_stats(dev);
                if (iw)
                        ret = (*format)(iw, buf);
        }
-       read_unlock(&dev_base_lock);
+       rtnl_unlock();
 
        return ret;
 }
index b694552..6eb8d47 100644 (file)
@@ -335,6 +335,7 @@ struct pktgen_dev {
        __u32 cur_src_mac_offset;
        __be32 cur_saddr;
        __be32 cur_daddr;
+       __u16 ip_id;
        __u16 cur_udp_dst;
        __u16 cur_udp_src;
        __u16 cur_queue_map;
@@ -964,7 +965,7 @@ static ssize_t pktgen_if_write(struct file *file,
                if (value == 0x7FFFFFFF)
                        pkt_dev->delay = ULLONG_MAX;
                else
-                       pkt_dev->delay = (u64)value * NSEC_PER_USEC;
+                       pkt_dev->delay = (u64)value;
 
                sprintf(pg_result, "OK: delay=%llu",
                        (unsigned long long) pkt_dev->delay);
@@ -2212,7 +2213,7 @@ static void set_cur_queue_map(struct pktgen_dev *pkt_dev)
        if (pkt_dev->flags & F_QUEUE_MAP_CPU)
                pkt_dev->cur_queue_map = smp_processor_id();
 
-       else if (pkt_dev->queue_map_min < pkt_dev->queue_map_max) {
+       else if (pkt_dev->queue_map_min <= pkt_dev->queue_map_max) {
                __u16 t;
                if (pkt_dev->flags & F_QUEUE_MAP_RND) {
                        t = random32() %
@@ -2630,6 +2631,8 @@ static struct sk_buff *fill_packet_ipv4(struct net_device *odev,
        iph->protocol = IPPROTO_UDP;    /* UDP */
        iph->saddr = pkt_dev->cur_saddr;
        iph->daddr = pkt_dev->cur_daddr;
+       iph->id = htons(pkt_dev->ip_id);
+       pkt_dev->ip_id++;
        iph->frag_off = 0;
        iplen = 20 + 8 + datalen;
        iph->tot_len = htons(iplen);
@@ -2641,24 +2644,26 @@ static struct sk_buff *fill_packet_ipv4(struct net_device *odev,
        skb->dev = odev;
        skb->pkt_type = PACKET_HOST;
 
-       if (pkt_dev->nfrags <= 0)
+       if (pkt_dev->nfrags <= 0) {
                pgh = (struct pktgen_hdr *)skb_put(skb, datalen);
-       else {
+               memset(pgh + 1, 0, datalen - sizeof(struct pktgen_hdr));
+       } else {
                int frags = pkt_dev->nfrags;
-               int i;
+               int i, len;
 
                pgh = (struct pktgen_hdr *)(((char *)(udph)) + 8);
 
                if (frags > MAX_SKB_FRAGS)
                        frags = MAX_SKB_FRAGS;
                if (datalen > frags * PAGE_SIZE) {
-                       skb_put(skb, datalen - frags * PAGE_SIZE);
+                       len = datalen - frags * PAGE_SIZE;
+                       memset(skb_put(skb, len), 0, len);
                        datalen = frags * PAGE_SIZE;
                }
 
                i = 0;
                while (datalen > 0) {
-                       struct page *page = alloc_pages(GFP_KERNEL, 0);
+                       struct page *page = alloc_pages(GFP_KERNEL | __GFP_ZERO, 0);
                        skb_shinfo(skb)->frags[i].page = page;
                        skb_shinfo(skb)->frags[i].page_offset = 0;
                        skb_shinfo(skb)->frags[i].size =
index e92f1fd..5df2f6a 100644 (file)
@@ -1077,12 +1077,16 @@ static int inetdev_event(struct notifier_block *this, unsigned long event,
                ip_mc_up(in_dev);
                /* fall through */
        case NETDEV_CHANGEADDR:
-               if (IN_DEV_ARP_NOTIFY(in_dev))
-                       arp_send(ARPOP_REQUEST, ETH_P_ARP,
-                                in_dev->ifa_list->ifa_address,
-                                dev,
-                                in_dev->ifa_list->ifa_address,
-                                NULL, dev->dev_addr, NULL);
+               /* Send gratuitous ARP to notify of link change */
+               if (IN_DEV_ARP_NOTIFY(in_dev)) {
+                       struct in_ifaddr *ifa = in_dev->ifa_list;
+
+                       if (ifa)
+                               arp_send(ARPOP_REQUEST, ETH_P_ARP,
+                                        ifa->ifa_address, dev,
+                                        ifa->ifa_address, NULL,
+                                        dev->dev_addr, NULL);
+               }
                break;
        case NETDEV_DOWN:
                ip_mc_down(in_dev);
index e2f9505..aa00398 100644 (file)
@@ -229,14 +229,17 @@ unsigned int inet_dev_addr_type(struct net *net, const struct net_device *dev,
  */
 
 int fib_validate_source(__be32 src, __be32 dst, u8 tos, int oif,
-                       struct net_device *dev, __be32 *spec_dst, u32 *itag)
+                       struct net_device *dev, __be32 *spec_dst,
+                       u32 *itag, u32 mark)
 {
        struct in_device *in_dev;
        struct flowi fl = { .nl_u = { .ip4_u =
                                      { .daddr = src,
                                        .saddr = dst,
                                        .tos = tos } },
+                           .mark = mark,
                            .iif = oif };
+
        struct fib_result res;
        int no_addr, rpf;
        int ret;
index 4351ca2..537731b 100644 (file)
@@ -446,6 +446,28 @@ extern int sysctl_tcp_synack_retries;
 
 EXPORT_SYMBOL_GPL(inet_csk_reqsk_queue_hash_add);
 
+/* Decide when to expire the request and when to resend SYN-ACK */
+static inline void syn_ack_recalc(struct request_sock *req, const int thresh,
+                                 const int max_retries,
+                                 const u8 rskq_defer_accept,
+                                 int *expire, int *resend)
+{
+       if (!rskq_defer_accept) {
+               *expire = req->retrans >= thresh;
+               *resend = 1;
+               return;
+       }
+       *expire = req->retrans >= thresh &&
+                 (!inet_rsk(req)->acked || req->retrans >= max_retries);
+       /*
+        * Do not resend while waiting for data after ACK,
+        * start to resend on end of deferring period to give
+        * last chance for data or ACK to create established socket.
+        */
+       *resend = !inet_rsk(req)->acked ||
+                 req->retrans >= rskq_defer_accept - 1;
+}
+
 void inet_csk_reqsk_queue_prune(struct sock *parent,
                                const unsigned long interval,
                                const unsigned long timeout,
@@ -501,9 +523,15 @@ void inet_csk_reqsk_queue_prune(struct sock *parent,
                reqp=&lopt->syn_table[i];
                while ((req = *reqp) != NULL) {
                        if (time_after_eq(now, req->expires)) {
-                               if ((req->retrans < thresh ||
-                                    (inet_rsk(req)->acked && req->retrans < max_retries))
-                                   && !req->rsk_ops->rtx_syn_ack(parent, req)) {
+                               int expire = 0, resend = 0;
+
+                               syn_ack_recalc(req, thresh, max_retries,
+                                              queue->rskq_defer_accept,
+                                              &expire, &resend);
+                               if (!expire &&
+                                   (!resend ||
+                                    !req->rsk_ops->rtx_syn_ack(parent, req) ||
+                                    inet_rsk(req)->acked)) {
                                        unsigned long timeo;
 
                                        if (req->retrans++ == 0)
index 41ada99..1433338 100644 (file)
@@ -1464,7 +1464,7 @@ static void ipgre_tap_setup(struct net_device *dev)
 
        ether_setup(dev);
 
-       dev->netdev_ops         = &ipgre_netdev_ops;
+       dev->netdev_ops         = &ipgre_tap_netdev_ops;
        dev->destructor         = free_netdev;
 
        dev->iflink             = 0;
@@ -1525,25 +1525,29 @@ static int ipgre_changelink(struct net_device *dev, struct nlattr *tb[],
                if (t->dev != dev)
                        return -EEXIST;
        } else {
-               unsigned nflags = 0;
-
                t = nt;
 
-               if (ipv4_is_multicast(p.iph.daddr))
-                       nflags = IFF_BROADCAST;
-               else if (p.iph.daddr)
-                       nflags = IFF_POINTOPOINT;
+               if (dev->type != ARPHRD_ETHER) {
+                       unsigned nflags = 0;
 
-               if ((dev->flags ^ nflags) &
-                   (IFF_POINTOPOINT | IFF_BROADCAST))
-                       return -EINVAL;
+                       if (ipv4_is_multicast(p.iph.daddr))
+                               nflags = IFF_BROADCAST;
+                       else if (p.iph.daddr)
+                               nflags = IFF_POINTOPOINT;
+
+                       if ((dev->flags ^ nflags) &
+                           (IFF_POINTOPOINT | IFF_BROADCAST))
+                               return -EINVAL;
+               }
 
                ipgre_tunnel_unlink(ign, t);
                t->parms.iph.saddr = p.iph.saddr;
                t->parms.iph.daddr = p.iph.daddr;
                t->parms.i_key = p.i_key;
-               memcpy(dev->dev_addr, &p.iph.saddr, 4);
-               memcpy(dev->broadcast, &p.iph.daddr, 4);
+               if (dev->type != ARPHRD_ETHER) {
+                       memcpy(dev->dev_addr, &p.iph.saddr, 4);
+                       memcpy(dev->broadcast, &p.iph.daddr, 4);
+               }
                ipgre_tunnel_link(ign, t);
                netdev_state_change(dev);
        }
index 0c0b6e3..e982b5c 100644 (file)
@@ -634,17 +634,16 @@ static int do_ip_setsockopt(struct sock *sk, int level,
                                break;
                        }
                        dev = ip_dev_find(sock_net(sk), mreq.imr_address.s_addr);
-                       if (dev) {
+                       if (dev)
                                mreq.imr_ifindex = dev->ifindex;
-                               dev_put(dev);
-                       }
                } else
-                       dev = __dev_get_by_index(sock_net(sk), mreq.imr_ifindex);
+                       dev = dev_get_by_index(sock_net(sk), mreq.imr_ifindex);
 
 
                err = -EADDRNOTAVAIL;
                if (!dev)
                        break;
+               dev_put(dev);
 
                err = -EINVAL;
                if (sk->sk_bound_dev_if &&
index 757c917..ab996f9 100644 (file)
@@ -352,13 +352,24 @@ static int raw_send_hdrinc(struct sock *sk, void *from, size_t length,
        skb->ip_summed = CHECKSUM_NONE;
 
        skb->transport_header = skb->network_header;
-       err = memcpy_fromiovecend((void *)iph, from, 0, length);
-       if (err)
-               goto error_fault;
+       err = -EFAULT;
+       if (memcpy_fromiovecend((void *)iph, from, 0, length))
+               goto error_free;
 
-       /* We don't modify invalid header */
        iphlen = iph->ihl * 4;
-       if (iphlen >= sizeof(*iph) && iphlen <= length) {
+
+       /*
+        * We don't want to modify the ip header, but we do need to
+        * be sure that it won't cause problems later along the network
+        * stack.  Specifically we want to make sure that iph->ihl is a
+        * sane value.  If ihl points beyond the length of the buffer passed
+        * in, reject the frame as invalid
+        */
+       err = -EINVAL;
+       if (iphlen > length)
+               goto error_free;
+
+       if (iphlen >= sizeof(*iph)) {
                if (!iph->saddr)
                        iph->saddr = rt->rt_src;
                iph->check   = 0;
@@ -381,8 +392,7 @@ static int raw_send_hdrinc(struct sock *sk, void *from, size_t length,
 out:
        return 0;
 
-error_fault:
-       err = -EFAULT;
+error_free:
        kfree_skb(skb);
 error:
        IP_INC_STATS(net, IPSTATS_MIB_OUTDISCARDS);
index bb41992..5b1050a 100644 (file)
@@ -1854,7 +1854,7 @@ static int ip_route_input_mc(struct sk_buff *skb, __be32 daddr, __be32 saddr,
                        goto e_inval;
                spec_dst = inet_select_addr(dev, 0, RT_SCOPE_LINK);
        } else if (fib_validate_source(saddr, 0, tos, 0,
-                                       dev, &spec_dst, &itag) < 0)
+                                       dev, &spec_dst, &itag, 0) < 0)
                goto e_inval;
 
        rth = dst_alloc(&ipv4_dst_ops);
@@ -1967,7 +1967,7 @@ static int __mkroute_input(struct sk_buff *skb,
 
 
        err = fib_validate_source(saddr, daddr, tos, FIB_RES_OIF(*res),
-                                 in_dev->dev, &spec_dst, &itag);
+                                 in_dev->dev, &spec_dst, &itag, skb->mark);
        if (err < 0) {
                ip_handle_martian_source(in_dev->dev, in_dev, skb, daddr,
                                         saddr);
@@ -2141,7 +2141,7 @@ static int ip_route_input_slow(struct sk_buff *skb, __be32 daddr, __be32 saddr,
                int result;
                result = fib_validate_source(saddr, daddr, tos,
                                             net->loopback_dev->ifindex,
-                                            dev, &spec_dst, &itag);
+                                            dev, &spec_dst, &itag, skb->mark);
                if (result < 0)
                        goto martian_source;
                if (result)
@@ -2170,7 +2170,7 @@ brd_input:
                spec_dst = inet_select_addr(dev, 0, RT_SCOPE_LINK);
        else {
                err = fib_validate_source(saddr, 0, tos, 0, dev, &spec_dst,
-                                         &itag);
+                                         &itag, skb->mark);
                if (err < 0)
                        goto martian_source;
                if (err)
index 64d0af6..98440ad 100644 (file)
@@ -326,6 +326,43 @@ void tcp_enter_memory_pressure(struct sock *sk)
 
 EXPORT_SYMBOL(tcp_enter_memory_pressure);
 
+/* Convert seconds to retransmits based on initial and max timeout */
+static u8 secs_to_retrans(int seconds, int timeout, int rto_max)
+{
+       u8 res = 0;
+
+       if (seconds > 0) {
+               int period = timeout;
+
+               res = 1;
+               while (seconds > period && res < 255) {
+                       res++;
+                       timeout <<= 1;
+                       if (timeout > rto_max)
+                               timeout = rto_max;
+                       period += timeout;
+               }
+       }
+       return res;
+}
+
+/* Convert retransmits to seconds based on initial and max timeout */
+static int retrans_to_secs(u8 retrans, int timeout, int rto_max)
+{
+       int period = 0;
+
+       if (retrans > 0) {
+               period = timeout;
+               while (--retrans) {
+                       timeout <<= 1;
+                       if (timeout > rto_max)
+                               timeout = rto_max;
+                       period += timeout;
+               }
+       }
+       return period;
+}
+
 /*
  *     Wait for a TCP event.
  *
@@ -1405,7 +1442,9 @@ int tcp_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
                                goto found_ok_skb;
                        if (tcp_hdr(skb)->fin)
                                goto found_fin_ok;
-                       WARN_ON(!(flags & MSG_PEEK));
+                       WARN(!(flags & MSG_PEEK), KERN_INFO "recvmsg bug 2: "
+                                       "copied %X seq %X\n", *seq,
+                                       TCP_SKB_CB(skb)->seq);
                }
 
                /* Well, if we have backlog, try to process it now yet. */
@@ -2163,16 +2202,10 @@ static int do_tcp_setsockopt(struct sock *sk, int level,
                break;
 
        case TCP_DEFER_ACCEPT:
-               icsk->icsk_accept_queue.rskq_defer_accept = 0;
-               if (val > 0) {
-                       /* Translate value in seconds to number of
-                        * retransmits */
-                       while (icsk->icsk_accept_queue.rskq_defer_accept < 32 &&
-                              val > ((TCP_TIMEOUT_INIT / HZ) <<
-                                      icsk->icsk_accept_queue.rskq_defer_accept))
-                               icsk->icsk_accept_queue.rskq_defer_accept++;
-                       icsk->icsk_accept_queue.rskq_defer_accept++;
-               }
+               /* Translate value in seconds to number of retransmits */
+               icsk->icsk_accept_queue.rskq_defer_accept =
+                       secs_to_retrans(val, TCP_TIMEOUT_INIT / HZ,
+                                       TCP_RTO_MAX / HZ);
                break;
 
        case TCP_WINDOW_CLAMP:
@@ -2353,8 +2386,8 @@ static int do_tcp_getsockopt(struct sock *sk, int level,
                        val = (val ? : sysctl_tcp_fin_timeout) / HZ;
                break;
        case TCP_DEFER_ACCEPT:
-               val = !icsk->icsk_accept_queue.rskq_defer_accept ? 0 :
-                       ((TCP_TIMEOUT_INIT / HZ) << (icsk->icsk_accept_queue.rskq_defer_accept - 1));
+               val = retrans_to_secs(icsk->icsk_accept_queue.rskq_defer_accept,
+                                     TCP_TIMEOUT_INIT / HZ, TCP_RTO_MAX / HZ);
                break;
        case TCP_WINDOW_CLAMP:
                val = tp->window_clamp;
index 624c3c9..4c03598 100644 (file)
@@ -641,8 +641,8 @@ struct sock *tcp_check_req(struct sock *sk, struct sk_buff *skb,
        if (!(flg & TCP_FLAG_ACK))
                return NULL;
 
-       /* If TCP_DEFER_ACCEPT is set, drop bare ACK. */
-       if (inet_csk(sk)->icsk_accept_queue.rskq_defer_accept &&
+       /* While TCP_DEFER_ACCEPT is active, drop bare ACK. */
+       if (req->retrans < inet_csk(sk)->icsk_accept_queue.rskq_defer_accept &&
            TCP_SKB_CB(skb)->end_seq == tcp_rsk(req)->rcv_isn + 1) {
                inet_rsk(req)->acked = 1;
                return NULL;
index 6ec6a8a..0fa9f70 100644 (file)
@@ -841,6 +841,42 @@ out:
        return ret;
 }
 
+
+/**
+ *     first_packet_length     - return length of first packet in receive queue
+ *     @sk: socket
+ *
+ *     Drops all bad checksum frames, until a valid one is found.
+ *     Returns the length of found skb, or 0 if none is found.
+ */
+static unsigned int first_packet_length(struct sock *sk)
+{
+       struct sk_buff_head list_kill, *rcvq = &sk->sk_receive_queue;
+       struct sk_buff *skb;
+       unsigned int res;
+
+       __skb_queue_head_init(&list_kill);
+
+       spin_lock_bh(&rcvq->lock);
+       while ((skb = skb_peek(rcvq)) != NULL &&
+               udp_lib_checksum_complete(skb)) {
+               UDP_INC_STATS_BH(sock_net(sk), UDP_MIB_INERRORS,
+                                IS_UDPLITE(sk));
+               __skb_unlink(skb, rcvq);
+               __skb_queue_tail(&list_kill, skb);
+       }
+       res = skb ? skb->len : 0;
+       spin_unlock_bh(&rcvq->lock);
+
+       if (!skb_queue_empty(&list_kill)) {
+               lock_sock(sk);
+               __skb_queue_purge(&list_kill);
+               sk_mem_reclaim_partial(sk);
+               release_sock(sk);
+       }
+       return res;
+}
+
 /*
  *     IOCTL requests applicable to the UDP protocol
  */
@@ -857,21 +893,16 @@ int udp_ioctl(struct sock *sk, int cmd, unsigned long arg)
 
        case SIOCINQ:
        {
-               struct sk_buff *skb;
-               unsigned long amount;
+               unsigned int amount = first_packet_length(sk);
 
-               amount = 0;
-               spin_lock_bh(&sk->sk_receive_queue.lock);
-               skb = skb_peek(&sk->sk_receive_queue);
-               if (skb != NULL) {
+               if (amount)
                        /*
                         * We will only return the amount
                         * of this packet since that is all
                         * that will be read.
                         */
-                       amount = skb->len - sizeof(struct udphdr);
-               }
-               spin_unlock_bh(&sk->sk_receive_queue.lock);
+                       amount -= sizeof(struct udphdr);
+
                return put_user(amount, (int __user *)arg);
        }
 
@@ -968,9 +999,7 @@ try_again:
                err = ulen;
 
 out_free:
-       lock_sock(sk);
-       skb_free_datagram(sk, skb);
-       release_sock(sk);
+       skb_free_datagram_locked(sk, skb);
 out:
        return err;
 
@@ -1540,29 +1569,11 @@ unsigned int udp_poll(struct file *file, struct socket *sock, poll_table *wait)
 {
        unsigned int mask = datagram_poll(file, sock, wait);
        struct sock *sk = sock->sk;
-       int     is_lite = IS_UDPLITE(sk);
 
        /* Check for false positives due to checksum errors */
-       if ((mask & POLLRDNORM) &&
-           !(file->f_flags & O_NONBLOCK) &&
-           !(sk->sk_shutdown & RCV_SHUTDOWN)) {
-               struct sk_buff_head *rcvq = &sk->sk_receive_queue;
-               struct sk_buff *skb;
-
-               spin_lock_bh(&rcvq->lock);
-               while ((skb = skb_peek(rcvq)) != NULL &&
-                      udp_lib_checksum_complete(skb)) {
-                       UDP_INC_STATS_BH(sock_net(sk),
-                                       UDP_MIB_INERRORS, is_lite);
-                       __skb_unlink(skb, rcvq);
-                       kfree_skb(skb);
-               }
-               spin_unlock_bh(&rcvq->lock);
-
-               /* nothing to see, move along */
-               if (skb == NULL)
-                       mask &= ~(POLLIN | POLLRDNORM);
-       }
+       if ((mask & POLLRDNORM) && !(file->f_flags & O_NONBLOCK) &&
+           !(sk->sk_shutdown & RCV_SHUTDOWN) && !first_packet_length(sk))
+               mask &= ~(POLLIN | POLLRDNORM);
 
        return mask;
 
index 14f54eb..4f7aaf6 100644 (file)
@@ -496,13 +496,17 @@ done:
                        goto e_inval;
 
                if (val) {
+                       struct net_device *dev;
+
                        if (sk->sk_bound_dev_if && sk->sk_bound_dev_if != val)
                                goto e_inval;
 
-                       if (__dev_get_by_index(net, val) == NULL) {
+                       dev = dev_get_by_index(net, val);
+                       if (!dev) {
                                retv = -ENODEV;
                                break;
                        }
+                       dev_put(dev);
                }
                np->mcast_oif = val;
                retv = 0;
index 3a60f12..cf538ed 100644 (file)
@@ -288,9 +288,7 @@ try_again:
                err = ulen;
 
 out_free:
-       lock_sock(sk);
-       skb_free_datagram(sk, skb);
-       release_sock(sk);
+       skb_free_datagram_locked(sk, skb);
 out:
        return err;
 
index eafc010..3c17540 100644 (file)
@@ -30,6 +30,7 @@
  ********************************************************************/
 
 #include <linux/init.h>
+#include <linux/sched.h>
 
 #include <net/irda/irda.h>
 #include <net/irda/irlmp.h>
index 6211682..315ead3 100644 (file)
@@ -30,6 +30,7 @@
 #include <linux/init.h>
 #include <linux/errno.h>
 #include <linux/proc_fs.h>
+#include <linux/sched.h>
 #include <linux/seq_file.h>
 #include <linux/random.h>
 #include <linux/netdevice.h>
index 7b6b631..d340110 100644 (file)
@@ -30,6 +30,7 @@
 #include <linux/inetdevice.h>
 #include <linux/if_arp.h>
 #include <linux/module.h>
+#include <linux/sched.h>
 #include <net/arp.h>
 
 #include <net/irda/irda.h>
index cf9a4b5..cccc2e9 100644 (file)
@@ -9,6 +9,7 @@
  */
 
 #include "irnet_irda.h"                /* Private header */
+#include <linux/sched.h>
 #include <linux/seq_file.h>
 #include <asm/unaligned.h>
 
index 68cbcb1..7dea882 100644 (file)
@@ -13,6 +13,7 @@
  *     2) as a control channel (write commands, read events)
  */
 
+#include <linux/sched.h>
 #include <linux/smp_lock.h>
 #include "irnet_ppp.h"         /* Private header */
 /* Please put other headers in irnet.h - Thanks */
index bd765f3..b09948c 100644 (file)
@@ -666,26 +666,25 @@ void ieee80211_process_addba_resp(struct ieee80211_local *local,
 
        state = &sta->ampdu_mlme.tid_state_tx[tid];
 
+       del_timer_sync(&sta->ampdu_mlme.tid_tx[tid]->addba_resp_timer);
+
        spin_lock_bh(&sta->lock);
 
-       if (!(*state & HT_ADDBA_REQUESTED_MSK)) {
-               spin_unlock_bh(&sta->lock);
-               return;
-       }
+       if (!(*state & HT_ADDBA_REQUESTED_MSK))
+               goto timer_still_needed;
 
        if (mgmt->u.action.u.addba_resp.dialog_token !=
                sta->ampdu_mlme.tid_tx[tid]->dialog_token) {
-               spin_unlock_bh(&sta->lock);
 #ifdef CONFIG_MAC80211_HT_DEBUG
                printk(KERN_DEBUG "wrong addBA response token, tid %d\n", tid);
 #endif /* CONFIG_MAC80211_HT_DEBUG */
-               return;
+               goto timer_still_needed;
        }
 
-       del_timer_sync(&sta->ampdu_mlme.tid_tx[tid]->addba_resp_timer);
 #ifdef CONFIG_MAC80211_HT_DEBUG
        printk(KERN_DEBUG "switched off addBA timer for tid %d \n", tid);
 #endif /* CONFIG_MAC80211_HT_DEBUG */
+
        if (le16_to_cpu(mgmt->u.action.u.addba_resp.status)
                        == WLAN_STATUS_SUCCESS) {
                u8 curstate = *state;
@@ -699,5 +698,11 @@ void ieee80211_process_addba_resp(struct ieee80211_local *local,
        } else {
                ___ieee80211_stop_tx_ba_session(sta, tid, WLAN_BACK_INITIATOR);
        }
+
+       goto out;
+
+ timer_still_needed:
+       add_timer(&sta->ampdu_mlme.tid_tx[tid]->addba_resp_timer);
+ out:
        spin_unlock_bh(&sta->lock);
 }
index 5608f6c..7b5131b 100644 (file)
@@ -72,6 +72,9 @@ static int ieee80211_change_iface(struct wiphy *wiphy,
        struct ieee80211_sub_if_data *sdata;
        int ret;
 
+       if (netif_running(dev))
+               return -EBUSY;
+
        if (!nl80211_type_check(type))
                return -EINVAL;
 
@@ -81,9 +84,6 @@ static int ieee80211_change_iface(struct wiphy *wiphy,
        if (ret)
                return ret;
 
-       if (netif_running(sdata->dev))
-               return -EBUSY;
-
        if (ieee80211_vif_is_mesh(&sdata->vif) && params->mesh_id_len)
                ieee80211_sdata_set_mesh_id(sdata,
                                            params->mesh_id_len,
index 0891bfb..48ef1a2 100644 (file)
@@ -153,7 +153,7 @@ void ieee80211_process_delba(struct ieee80211_sub_if_data *sdata,
        if (net_ratelimit())
                printk(KERN_DEBUG "delba from %pM (%s) tid %d reason code %d\n",
                        mgmt->sa, initiator ? "initiator" : "recipient", tid,
-                       mgmt->u.action.u.delba.reason_code);
+                       le16_to_cpu(mgmt->u.action.u.delba.reason_code));
 #endif /* CONFIG_MAC80211_HT_DEBUG */
 
        if (initiator == WLAN_BACK_INITIATOR)
index 920ec87..f1362f3 100644 (file)
@@ -73,6 +73,7 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
        struct ieee80211_mgmt *mgmt;
        u8 *pos;
        struct ieee80211_supported_band *sband;
+       struct cfg80211_bss *bss;
        u32 bss_change;
        u8 supp_rates[IEEE80211_MAX_SUPP_RATES];
 
@@ -177,8 +178,9 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
        mod_timer(&ifibss->timer,
                  round_jiffies(jiffies + IEEE80211_IBSS_MERGE_INTERVAL));
 
-       cfg80211_inform_bss_frame(local->hw.wiphy, local->hw.conf.channel,
-                                 mgmt, skb->len, 0, GFP_KERNEL);
+       bss = cfg80211_inform_bss_frame(local->hw.wiphy, local->hw.conf.channel,
+                                       mgmt, skb->len, 0, GFP_KERNEL);
+       cfg80211_put_bss(bss);
        cfg80211_ibss_joined(sdata->dev, ifibss->bssid, GFP_KERNEL);
 }
 
@@ -538,13 +540,12 @@ static void ieee80211_sta_find_ibss(struct ieee80211_sub_if_data *sdata)
                                       WLAN_CAPABILITY_PRIVACY,
                                       capability);
 
+       if (bss) {
 #ifdef CONFIG_MAC80211_IBSS_DEBUG
-       if (bss)
                printk(KERN_DEBUG "   sta_find_ibss: selected %pM current "
                       "%pM\n", bss->cbss.bssid, ifibss->bssid);
 #endif /* CONFIG_MAC80211_IBSS_DEBUG */
 
-       if (bss && memcmp(ifibss->bssid, bss->cbss.bssid, ETH_ALEN)) {
                printk(KERN_DEBUG "%s: Selected IBSS BSSID %pM"
                       " based on configured SSID\n",
                       sdata->dev->name, bss->cbss.bssid);
@@ -552,8 +553,7 @@ static void ieee80211_sta_find_ibss(struct ieee80211_sub_if_data *sdata)
                ieee80211_sta_join_ibss(sdata, bss);
                ieee80211_rx_bss_put(local, bss);
                return;
-       } else if (bss)
-               ieee80211_rx_bss_put(local, bss);
+       }
 
 #ifdef CONFIG_MAC80211_IBSS_DEBUG
        printk(KERN_DEBUG "   did not try to join ibss\n");
@@ -829,7 +829,7 @@ void ieee80211_ibss_notify_scan_completed(struct ieee80211_local *local)
                if (!sdata->u.ibss.ssid_len)
                        continue;
                sdata->u.ibss.last_scan_completed = jiffies;
-               ieee80211_sta_find_ibss(sdata);
+               mod_timer(&sdata->u.ibss.timer, 0);
        }
        mutex_unlock(&local->iflist_mtx);
 }
index e12a786..29b82e9 100644 (file)
@@ -259,7 +259,7 @@ static u32 airtime_link_metric_get(struct ieee80211_local *local,
  * @hwmp_ie: hwmp information element (PREP or PREQ)
  *
  * This function updates the path routing information to the originator and the
- * transmitter of a HWMP PREQ or PREP fram.
+ * transmitter of a HWMP PREQ or PREP frame.
  *
  * Returns: metric to frame originator or 0 if the frame should not be further
  * processed
index 8d26e9b..dc5049d 100644 (file)
@@ -1457,8 +1457,7 @@ ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata,
        if (status_code != WLAN_STATUS_SUCCESS) {
                printk(KERN_DEBUG "%s: AP denied association (code=%d)\n",
                       sdata->dev->name, status_code);
-               list_del(&wk->list);
-               kfree(wk);
+               wk->state = IEEE80211_MGD_STATE_IDLE;
                return RX_MGMT_CFG80211_ASSOC;
        }
 
index a59043f..4566705 100644 (file)
@@ -6,6 +6,7 @@
  * published by the Free Software Foundation.
  */
 
+#include <linux/sched.h>
 #include <linux/spinlock.h>
 #include <linux/poll.h>
 #include <linux/netdevice.h>
index c01588f..7170bf4 100644 (file)
@@ -2164,11 +2164,17 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw,
 
        skb = rx.skb;
 
-       list_for_each_entry_rcu(sdata, &local->interfaces, list) {
+       if (rx.sdata && ieee80211_is_data(hdr->frame_control)) {
+               rx.flags |= IEEE80211_RX_RA_MATCH;
+               prepares = prepare_for_handlers(rx.sdata, &rx, hdr);
+               if (prepares)
+                       prev = rx.sdata;
+       } else list_for_each_entry_rcu(sdata, &local->interfaces, list) {
                if (!netif_running(sdata->dev))
                        continue;
 
-               if (sdata->vif.type == NL80211_IFTYPE_MONITOR)
+               if (sdata->vif.type == NL80211_IFTYPE_MONITOR ||
+                   sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
                        continue;
 
                rx.flags |= IEEE80211_RX_RA_MATCH;
@@ -2447,6 +2453,8 @@ void ieee80211_rx(struct ieee80211_hw *hw, struct sk_buff *skb)
        struct ieee80211_supported_band *sband;
        struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
 
+       WARN_ON_ONCE(softirq_count() == 0);
+
        if (WARN_ON(status->band < 0 ||
                    status->band >= IEEE80211_NUM_BANDS))
                goto drop;
index eec0014..594f231 100644 (file)
@@ -361,6 +361,7 @@ int sta_info_insert(struct sta_info *sta)
                                             u.ap);
 
                drv_sta_notify(local, &sdata->vif, STA_NOTIFY_ADD, &sta->sta);
+               sdata = sta->sdata;
        }
 
 #ifdef CONFIG_MAC80211_VERBOSE_DEBUG
@@ -496,6 +497,7 @@ static void __sta_info_unlink(struct sta_info **sta)
 
                drv_sta_notify(local, &sdata->vif, STA_NOTIFY_REMOVE,
                               &(*sta)->sta);
+               sdata = (*sta)->sdata;
        }
 
        if (ieee80211_vif_is_mesh(&sdata->vif)) {
index fd40282..eaa4118 100644 (file)
@@ -1445,7 +1445,7 @@ static void ieee80211_xmit(struct ieee80211_sub_if_data *sdata,
                                if (tmp_sdata->vif.type != NL80211_IFTYPE_AP)
                                        continue;
                                if (compare_ether_addr(tmp_sdata->dev->dev_addr,
-                                                      hdr->addr2)) {
+                                                      hdr->addr2) == 0) {
                                        dev_hold(tmp_sdata->dev);
                                        dev_put(sdata->dev);
                                        sdata = tmp_sdata;
@@ -1704,7 +1704,8 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb,
        if (!is_multicast_ether_addr(hdr.addr1)) {
                rcu_read_lock();
                sta = sta_info_get(local, hdr.addr1);
-               if (sta)
+               /* XXX: in the future, use sdata to look up the sta */
+               if (sta && sta->sdata == sdata)
                        sta_flags = get_sta_flags(sta);
                rcu_read_unlock();
        }
index dd65643..aeb65b3 100644 (file)
@@ -339,7 +339,7 @@ void ieee80211_add_pending_skb(struct ieee80211_local *local,
        struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
 
        if (WARN_ON(!info->control.vif)) {
-               kfree(skb);
+               kfree_skb(skb);
                return;
        }
 
@@ -367,7 +367,7 @@ int ieee80211_add_pending_skbs(struct ieee80211_local *local,
                struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
 
                if (WARN_ON(!info->control.vif)) {
-                       kfree(skb);
+                       kfree_skb(skb);
                        continue;
                }
 
index 7c9ec3d..ca6e68d 100644 (file)
@@ -14,6 +14,7 @@
 #include <linux/types.h>
 #include <linux/netfilter.h>
 #include <linux/module.h>
+#include <linux/sched.h>
 #include <linux/skbuff.h>
 #include <linux/proc_fs.h>
 #include <linux/vmalloc.h>
index d7ecca0..f2d116a 100644 (file)
@@ -982,10 +982,7 @@ static int tpacket_snd(struct packet_sock *po, struct msghdr *msg)
                goto out_put;
 
        size_max = po->tx_ring.frame_size
-               - sizeof(struct skb_shared_info)
-               - po->tp_hdrlen
-               - LL_ALLOCATED_SPACE(dev)
-               - sizeof(struct sockaddr_ll);
+               - (po->tp_hdrlen - sizeof(struct sockaddr_ll));
 
        if (size_max > dev->mtu + reserve)
                size_max = dev->mtu + reserve;
index 96c0ed1..6b0359a 100644 (file)
@@ -34,7 +34,7 @@ static struct tcf_hashinfo pedit_hash_info = {
 };
 
 static const struct nla_policy pedit_policy[TCA_PEDIT_MAX + 1] = {
-       [TCA_PEDIT_PARMS]       = { .len = sizeof(struct tcf_pedit) },
+       [TCA_PEDIT_PARMS]       = { .len = sizeof(struct tc_pedit) },
 };
 
 static int tcf_pedit_init(struct nlattr *nla, struct nlattr *est,
index 6a53694..7cf6c0f 100644 (file)
@@ -350,7 +350,7 @@ static int tcf_fill_node(struct sk_buff *skb, struct tcf_proto *tp,
        tcm = NLMSG_DATA(nlh);
        tcm->tcm_family = AF_UNSPEC;
        tcm->tcm__pad1 = 0;
-       tcm->tcm__pad1 = 0;
+       tcm->tcm__pad2 = 0;
        tcm->tcm_ifindex = qdisc_dev(tp->q)->ifindex;
        tcm->tcm_parent = tp->classid;
        tcm->tcm_info = TC_H_MAKE(tp->prio, tp->protocol);
index ccc5e83..1c246a4 100644 (file)
@@ -111,7 +111,7 @@ static void svc_release_skb(struct svc_rqst *rqstp)
                rqstp->rq_xprt_ctxt = NULL;
 
                dprintk("svc: service %p, releasing skb %p\n", rqstp, skb);
-               skb_free_datagram(svsk->sk_sk, skb);
+               skb_free_datagram_locked(svsk->sk_sk, skb);
        }
 }
 
@@ -578,7 +578,7 @@ static int svc_udp_recvfrom(struct svc_rqst *rqstp)
                                "svc: received unknown control message %d/%d; "
                                "dropping RPC reply datagram\n",
                                        cmh->cmsg_level, cmh->cmsg_type);
-               skb_free_datagram(svsk->sk_sk, skb);
+               skb_free_datagram_locked(svsk->sk_sk, skb);
                return 0;
        }
 
@@ -588,18 +588,18 @@ static int svc_udp_recvfrom(struct svc_rqst *rqstp)
                if (csum_partial_copy_to_xdr(&rqstp->rq_arg, skb)) {
                        local_bh_enable();
                        /* checksum error */
-                       skb_free_datagram(svsk->sk_sk, skb);
+                       skb_free_datagram_locked(svsk->sk_sk, skb);
                        return 0;
                }
                local_bh_enable();
-               skb_free_datagram(svsk->sk_sk, skb);
+               skb_free_datagram_locked(svsk->sk_sk, skb);
        } else {
                /* we can use it in-place */
                rqstp->rq_arg.head[0].iov_base = skb->data +
                        sizeof(struct udphdr);
                rqstp->rq_arg.head[0].iov_len = len;
                if (skb_checksum_complete(skb)) {
-                       skb_free_datagram(svsk->sk_sk, skb);
+                       skb_free_datagram_locked(svsk->sk_sk, skb);
                        return 0;
                }
                rqstp->rq_xprt_ctxt = skb;
index 0cf5e8c..3fa5751 100644 (file)
@@ -42,6 +42,7 @@
 #include <linux/sunrpc/svc_xprt.h>
 #include <linux/sunrpc/debug.h>
 #include <linux/sunrpc/rpc_rdma.h>
+#include <linux/sched.h>
 #include <linux/spinlock.h>
 #include <rdma/ib_verbs.h>
 #include <rdma/rdma_cm.h>
index 51ab497..fc820cd 100644 (file)
@@ -1074,6 +1074,8 @@ restart:
        err = -ECONNREFUSED;
        if (other->sk_state != TCP_LISTEN)
                goto out_unlock;
+       if (other->sk_shutdown & RCV_SHUTDOWN)
+               goto out_unlock;
 
        if (unix_recvq_full(other)) {
                err = -EAGAIN;
index 45b2be3..a595f71 100644 (file)
@@ -14,6 +14,7 @@
 #include <linux/device.h>
 #include <linux/etherdevice.h>
 #include <linux/rtnetlink.h>
+#include <linux/sched.h>
 #include <net/genetlink.h>
 #include <net/cfg80211.h>
 #include "nl80211.h"
index 2a33d8b..68b3219 100644 (file)
@@ -358,6 +358,7 @@ int cfg80211_mgd_wext_connect(struct cfg80211_registered_device *rdev,
                              struct wireless_dev *wdev);
 
 void cfg80211_conn_work(struct work_struct *work);
+void cfg80211_sme_failed_assoc(struct wireless_dev *wdev);
 bool cfg80211_sme_failed_reassoc(struct wireless_dev *wdev);
 
 /* internal helpers */
index 79d2eec..0a6b7a0 100644 (file)
@@ -62,6 +62,7 @@ void cfg80211_send_rx_assoc(struct net_device *dev, const u8 *buf, size_t len)
        u8 *ie = mgmt->u.assoc_resp.variable;
        int i, ieoffs = offsetof(struct ieee80211_mgmt, u.assoc_resp.variable);
        struct cfg80211_internal_bss *bss = NULL;
+       bool need_connect_result = true;
 
        wdev_lock(wdev);
 
@@ -94,6 +95,14 @@ void cfg80211_send_rx_assoc(struct net_device *dev, const u8 *buf, size_t len)
                }
 
                WARN_ON(!bss);
+       } else if (wdev->conn) {
+               cfg80211_sme_failed_assoc(wdev);
+               need_connect_result = false;
+               /*
+                * do not call connect_result() now because the
+                * sme will schedule work that does it later.
+                */
+               goto out;
        }
 
        if (!wdev->conn && wdev->sme_state == CFG80211_SME_IDLE) {
index eddab09..ca3c92a 100644 (file)
@@ -4029,7 +4029,7 @@ static int nl80211_wiphy_netns(struct sk_buff *skb, struct genl_info *info)
        rdev = cfg80211_get_dev_from_info(info);
        if (IS_ERR(rdev)) {
                err = PTR_ERR(rdev);
-               goto out;
+               goto out_rtnl;
        }
 
        net = get_net_ns_by_pid(pid);
@@ -4049,6 +4049,7 @@ static int nl80211_wiphy_netns(struct sk_buff *skb, struct genl_info *info)
        put_net(net);
  out:
        cfg80211_unlock_rdev(rdev);
+ out_rtnl:
        rtnl_unlock();
        return err;
 }
index 93c3ed3..9f0b280 100644 (file)
@@ -26,6 +26,7 @@ struct cfg80211_conn {
                CFG80211_CONN_AUTHENTICATING,
                CFG80211_CONN_ASSOCIATE_NEXT,
                CFG80211_CONN_ASSOCIATING,
+               CFG80211_CONN_DEAUTH_ASSOC_FAIL,
        } state;
        u8 bssid[ETH_ALEN], prev_bssid[ETH_ALEN];
        u8 *ie;
@@ -148,6 +149,12 @@ static int cfg80211_conn_do_work(struct wireless_dev *wdev)
                                               NULL, 0,
                                               WLAN_REASON_DEAUTH_LEAVING);
                return err;
+       case CFG80211_CONN_DEAUTH_ASSOC_FAIL:
+               __cfg80211_mlme_deauth(rdev, wdev->netdev, params->bssid,
+                                      NULL, 0,
+                                      WLAN_REASON_DEAUTH_LEAVING);
+               /* return an error so that we call __cfg80211_connect_result() */
+               return -EINVAL;
        default:
                return 0;
        }
@@ -158,6 +165,7 @@ void cfg80211_conn_work(struct work_struct *work)
        struct cfg80211_registered_device *rdev =
                container_of(work, struct cfg80211_registered_device, conn_work);
        struct wireless_dev *wdev;
+       u8 bssid_buf[ETH_ALEN], *bssid = NULL;
 
        rtnl_lock();
        cfg80211_lock_rdev(rdev);
@@ -173,10 +181,13 @@ void cfg80211_conn_work(struct work_struct *work)
                        wdev_unlock(wdev);
                        continue;
                }
+               if (wdev->conn->params.bssid) {
+                       memcpy(bssid_buf, wdev->conn->params.bssid, ETH_ALEN);
+                       bssid = bssid_buf;
+               }
                if (cfg80211_conn_do_work(wdev))
                        __cfg80211_connect_result(
-                                       wdev->netdev,
-                                       wdev->conn->params.bssid,
+                                       wdev->netdev, bssid,
                                        NULL, 0, NULL, 0,
                                        WLAN_STATUS_UNSPECIFIED_FAILURE,
                                        false, NULL);
@@ -337,6 +348,15 @@ bool cfg80211_sme_failed_reassoc(struct wireless_dev *wdev)
        return true;
 }
 
+void cfg80211_sme_failed_assoc(struct wireless_dev *wdev)
+{
+       struct wiphy *wiphy = wdev->wiphy;
+       struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
+
+       wdev->conn->state = CFG80211_CONN_DEAUTH_ASSOC_FAIL;
+       schedule_work(&rdev->conn_work);
+}
+
 void __cfg80211_connect_result(struct net_device *dev, const u8 *bssid,
                               const u8 *req_ie, size_t req_ie_len,
                               const u8 *resp_ie, size_t resp_ie_len,
index 4f9c190..c67e73e 100644 (file)
@@ -100,7 +100,7 @@ as-option = $(call try-run,\
 # Usage: cflags-y += $(call as-instr,instr,option1,option2)
 
 as-instr = $(call try-run,\
-       echo -e "$(1)" | $(CC) $(KBUILD_AFLAGS) -c -xassembler -o "$$TMP" -,$(2),$(3))
+       /bin/echo -e "$(1)" | $(CC) $(KBUILD_AFLAGS) -c -xassembler -o "$$TMP" -,$(2),$(3))
 
 # cc-option
 # Usage: cflags-y += $(call cc-option,-march=winchip-c6,-march=i586)
index 7a77787..ffdafb2 100644 (file)
@@ -208,7 +208,7 @@ cmd_gzip = (cat $(filter-out FORCE,$^) | gzip -f -9 > $@) || \
 
 # Bzip2 and LZMA do not include size in file... so we have to fake that;
 # append the size as a 32-bit littleendian number as gzip does.
-size_append = echo -ne $(shell                                         \
+size_append = /bin/echo -ne $(shell                                    \
 dec_size=0;                                                            \
 for F in $1; do                                                                \
        fsize=$$(stat -c "%s" $$F);                                     \
index 39677c8..46be3c5 100755 (executable)
@@ -9,7 +9,7 @@ paths="$@"
 # Doing this once at the beginning saves a lot of time, on a cache-hot tree.
 Kconfigs="`find . -name 'Kconfig' -o -name 'Kconfig*[^~]'`"
 
-echo -e "File list \tundefined symbol used"
+/bin/echo -e "File list \tundefined symbol used"
 find $paths -name '*.[chS]' -o -name 'Makefile' -o -name 'Makefile*[^~]'| while read i
 do
        # Output the bare Kconfig variable and the filename; the _MODULE part at
@@ -54,6 +54,6 @@ while read symb files; do
        # beyond the purpose of this script.
        symb_bare=`echo $symb | sed -e 's/_MODULE//'`
        if ! grep -q "\<$symb_bare\>" $Kconfigs; then
-               echo -e "$files: \t$symb"
+               /bin/echo -e "$files: \t$symb"
        fi
 done|sort
index 87bbb8b..bc4114f 100755 (executable)
@@ -2,7 +2,7 @@
 # (c) 2001, Dave Jones. <davej@redhat.com> (the file handling bit)
 # (c) 2005, Joel Schopp <jschopp@austin.ibm.com> (the ugly bit)
 # (c) 2007,2008, Andy Whitcroft <apw@uk.ibm.com> (new conditions, test suite)
-# (c) 2008, Andy Whitcroft <apw@canonical.com>
+# (c) 2008,2009, Andy Whitcroft <apw@canonical.com>
 # Licensed under the terms of the GNU GPL License version 2
 
 use strict;
@@ -10,7 +10,7 @@ use strict;
 my $P = $0;
 $P =~ s@.*/@@g;
 
-my $V = '0.29';
+my $V = '0.30';
 
 use Getopt::Long qw(:config no_auto_abbrev);
 
@@ -130,7 +130,10 @@ if ($tree) {
 
 my $emitted_corrupt = 0;
 
-our $Ident       = qr{[A-Za-z_][A-Za-z\d_]*};
+our $Ident     = qr{
+                       [A-Za-z_][A-Za-z\d_]*
+                       (?:\s*\#\#\s*[A-Za-z_][A-Za-z\d_]*)*
+               }x;
 our $Storage   = qr{extern|static|asmlinkage};
 our $Sparse    = qr{
                        __user|
@@ -997,23 +1000,25 @@ sub annotate_values {
 
 sub possible {
        my ($possible, $line) = @_;
-
-       print "CHECK<$possible> ($line)\n" if ($dbg_possible > 2);
-       if ($possible !~ /(?:
+       my $notPermitted = qr{(?:
                ^(?:
                        $Modifier|
                        $Storage|
                        $Type|
-                       DEFINE_\S+|
+                       DEFINE_\S+
+               )$|
+               ^(?:
                        goto|
                        return|
                        case|
                        else|
                        asm|__asm__|
                        do
-               )$|
+               )(?:\s|$)|
                ^(?:typedef|struct|enum)\b
-           )/x) {
+           )}x;
+       warn "CHECK<$possible> ($line)\n" if ($dbg_possible > 2);
+       if ($possible !~ $notPermitted) {
                # Check for modifiers.
                $possible =~ s/\s*$Storage\s*//g;
                $possible =~ s/\s*$Sparse\s*//g;
@@ -1022,8 +1027,10 @@ sub possible {
                } elsif ($possible =~ /\s/) {
                        $possible =~ s/\s*$Type\s*//g;
                        for my $modifier (split(' ', $possible)) {
-                               warn "MODIFIER: $modifier ($possible) ($line)\n" if ($dbg_possible);
-                               push(@modifierList, $modifier);
+                               if ($modifier !~ $notPermitted) {
+                                       warn "MODIFIER: $modifier ($possible) ($line)\n" if ($dbg_possible);
+                                       push(@modifierList, $modifier);
+                               }
                        }
 
                } else {
@@ -1138,6 +1145,7 @@ sub process {
        # suppression flags
        my %suppress_ifbraces;
        my %suppress_whiletrailers;
+       my %suppress_export;
 
        # Pre-scan the patch sanitizing the lines.
        # Pre-scan the patch looking for any __setup documentation.
@@ -1230,7 +1238,6 @@ sub process {
                $linenr++;
 
                my $rawline = $rawlines[$linenr - 1];
-               my $hunk_line = ($realcnt != 0);
 
 #extract the line range in the file after the patch is applied
                if ($line=~/^\@\@ -\d+(?:,\d+)? \+(\d+)(,(\d+))? \@\@/) {
@@ -1247,6 +1254,7 @@ sub process {
 
                        %suppress_ifbraces = ();
                        %suppress_whiletrailers = ();
+                       %suppress_export = ();
                        next;
 
 # track the line number as we move through the hunk, note that
@@ -1270,6 +1278,8 @@ sub process {
                        $realcnt--;
                }
 
+               my $hunk_line = ($realcnt != 0);
+
 #make up the handle for any error we report on this line
                $prefix = "$filename:$realline: " if ($emacs && $file);
                $prefix = "$filename:$linenr: " if ($emacs && !$file);
@@ -1420,13 +1430,22 @@ sub process {
                }
 
 # Check for potential 'bare' types
-               my ($stat, $cond, $line_nr_next, $remain_next, $off_next);
+               my ($stat, $cond, $line_nr_next, $remain_next, $off_next,
+                   $realline_next);
                if ($realcnt && $line =~ /.\s*\S/) {
                        ($stat, $cond, $line_nr_next, $remain_next, $off_next) =
                                ctx_statement_block($linenr, $realcnt, 0);
                        $stat =~ s/\n./\n /g;
                        $cond =~ s/\n./\n /g;
 
+                       # Find the real next line.
+                       $realline_next = $line_nr_next;
+                       if (defined $realline_next &&
+                           (!defined $lines[$realline_next - 1] ||
+                            substr($lines[$realline_next - 1], $off_next) =~ /^\s*$/)) {
+                               $realline_next++;
+                       }
+
                        my $s = $stat;
                        $s =~ s/{.*$//s;
 
@@ -1661,8 +1680,8 @@ sub process {
                }
 
 # check for initialisation to aggregates open brace on the next line
-               if ($prevline =~ /$Declare\s*$Ident\s*=\s*$/ &&
-                   $line =~ /^.\s*{/) {
+               if ($line =~ /^.\s*{/ &&
+                   $prevline =~ /(?:^|[^=])=\s*$/) {
                        ERROR("that open brace { should be on the previous line\n" . $hereprev);
                }
 
@@ -1687,21 +1706,40 @@ sub process {
                $line =~ s@//.*@@;
                $opline =~ s@//.*@@;
 
-#EXPORT_SYMBOL should immediately follow its function closing }.
-               if (($line =~ /EXPORT_SYMBOL.*\((.*)\)/) ||
-                   ($line =~ /EXPORT_UNUSED_SYMBOL.*\((.*)\)/)) {
+# EXPORT_SYMBOL should immediately follow the thing it is exporting, consider
+# the whole statement.
+#print "APW <$lines[$realline_next - 1]>\n";
+               if (defined $realline_next &&
+                   exists $lines[$realline_next - 1] &&
+                   !defined $suppress_export{$realline_next} &&
+                   ($lines[$realline_next - 1] =~ /EXPORT_SYMBOL.*\((.*)\)/ ||
+                    $lines[$realline_next - 1] =~ /EXPORT_UNUSED_SYMBOL.*\((.*)\)/)) {
                        my $name = $1;
-                       if ($prevline !~ /(?:
-                               ^.}|
+                       if ($stat !~ /(?:
+                               \n.}\s*$|
                                ^.DEFINE_$Ident\(\Q$name\E\)|
                                ^.DECLARE_$Ident\(\Q$name\E\)|
                                ^.LIST_HEAD\(\Q$name\E\)|
-                               ^.$Type\s*\(\s*\*\s*\Q$name\E\s*\)\s*\(|
-                               \b\Q$name\E(?:\s+$Attribute)?\s*(?:;|=|\[)
+                               ^.(?:$Storage\s+)?$Type\s*\(\s*\*\s*\Q$name\E\s*\)\s*\(|
+                               \b\Q$name\E(?:\s+$Attribute)*\s*(?:;|=|\[|\()
                            )/x) {
-                               WARN("EXPORT_SYMBOL(foo); should immediately follow its function/variable\n" . $herecurr);
+#print "FOO A<$lines[$realline_next - 1]> stat<$stat> name<$name>\n";
+                               $suppress_export{$realline_next} = 2;
+                       } else {
+                               $suppress_export{$realline_next} = 1;
                        }
                }
+               if (!defined $suppress_export{$linenr} &&
+                   $prevline =~ /^.\s*$/ &&
+                   ($line =~ /EXPORT_SYMBOL.*\((.*)\)/ ||
+                    $line =~ /EXPORT_UNUSED_SYMBOL.*\((.*)\)/)) {
+#print "FOO B <$lines[$linenr - 1]>\n";
+                       $suppress_export{$linenr} = 2;
+               }
+               if (defined $suppress_export{$linenr} &&
+                   $suppress_export{$linenr} == 2) {
+                       WARN("EXPORT_SYMBOL(foo); should immediately follow its function/variable\n" . $herecurr);
+               }
 
 # check for external initialisers.
                if ($line =~ /^.$Type\s*$Ident\s*(?:\s+$Modifier)*\s*=\s*(0|NULL|false)\s*;/) {
index cdb44b6..102b766 100755 (executable)
@@ -13,7 +13,7 @@
 use strict;
 
 my $P = $0;
-my $V = '0.20';
+my $V = '0.21';
 
 use Getopt::Long qw(:config no_auto_abbrev);
 
@@ -37,6 +37,7 @@ my $scm = 0;
 my $web = 0;
 my $subsystem = 0;
 my $status = 0;
+my $keywords = 1;
 my $from_filename = 0;
 my $pattern_depth = 0;
 my $version = 0;
@@ -84,6 +85,7 @@ if (!GetOptions(
                'scm!' => \$scm,
                'web!' => \$web,
                'pattern-depth=i' => \$pattern_depth,
+               'k|keywords!' => \$keywords,
                'f|file' => \$from_filename,
                'v|version' => \$version,
                'h|help' => \$help,
@@ -132,6 +134,8 @@ if (!top_of_kernel_tree($lk_path)) {
 ## Read MAINTAINERS for type/value pairs
 
 my @typevalue = ();
+my %keyword_hash;
+
 open(MAINT, "<${lk_path}MAINTAINERS") || die "$P: Can't open MAINTAINERS\n";
 while (<MAINT>) {
     my $line = $_;
@@ -149,6 +153,8 @@ while (<MAINT>) {
            if ((-d $value)) {
                $value =~ s@([^/])$@$1/@;
            }
+       } elsif ($type eq "K") {
+           $keyword_hash{@typevalue} = $value;
        }
        push(@typevalue, "$type:$value");
     } elsif (!/^(\s)*$/) {
@@ -188,6 +194,7 @@ if ($email_remove_duplicates) {
 
 my @files = ();
 my @range = ();
+my @keyword_tvi = ();
 
 foreach my $file (@ARGV) {
     ##if $file is a directory and it lacks a trailing slash, add one
@@ -198,11 +205,24 @@ foreach my $file (@ARGV) {
     }
     if ($from_filename) {
        push(@files, $file);
+       if (-f $file && $keywords) {
+           open(FILE, "<$file") or die "$P: Can't open ${file}\n";
+           while (<FILE>) {
+               my $patch_line = $_;
+               foreach my $line (keys %keyword_hash) {
+                   if ($patch_line =~ m/^.*$keyword_hash{$line}/x) {
+                       push(@keyword_tvi, $line);
+                   }
+               }
+           }
+           close(FILE);
+       }
     } else {
        my $file_cnt = @files;
        my $lastfile;
        open(PATCH, "<$file") or die "$P: Can't open ${file}\n";
        while (<PATCH>) {
+           my $patch_line = $_;
            if (m/^\+\+\+\s+(\S+)/) {
                my $filename = $1;
                $filename =~ s@^[^/]*/@@;
@@ -213,6 +233,12 @@ foreach my $file (@ARGV) {
                if ($email_git_blame) {
                    push(@range, "$lastfile:$1:$2");
                }
+           } elsif ($keywords) {
+               foreach my $line (keys %keyword_hash) {
+                   if ($patch_line =~ m/^[+-].*$keyword_hash{$line}/x) {
+                       push(@keyword_tvi, $line);
+                   }
+               }
            }
        }
        close(PATCH);
@@ -286,6 +312,13 @@ foreach my $file (@files) {
     }
 }
 
+if ($keywords) {
+    @keyword_tvi = sort_and_uniq(@keyword_tvi);
+    foreach my $line (@keyword_tvi) {
+       add_categories($line);
+    }
+}
+
 if ($email) {
     foreach my $chief (@penguin_chief) {
        if ($chief =~ m/^(.*):(.*)/) {
@@ -384,6 +417,7 @@ Output type options:
 
 Other options:
   --pattern-depth => Number of pattern directory traversals (default: 0 (all))
+  --keywords => scan patch for keywords (default: 1 (on))
   --version => show version
   --help => show this help information
 
@@ -486,7 +520,6 @@ sub format_email {
 }
 
 sub find_starting_index {
-
     my ($index) = @_;
 
     while ($index > 0) {
index c6ae405..b89ca2c 100644 (file)
@@ -20,7 +20,7 @@ use strict;
 
 my ($readdir, $installdir, $arch, @files) = @ARGV;
 
-my $unifdef = "scripts/unifdef -U__KERNEL__";
+my $unifdef = "scripts/unifdef -U__KERNEL__ -D__EXPORTED_HEADERS__";
 
 foreach my $file (@files) {
        local *INFILE;
index 6a12dd9..bce3d0f 100755 (executable)
@@ -1,3 +1,5 @@
+#!/bin/sh
+
 TARGET=$1
 ARCH=$2
 SMP=$3
@@ -50,7 +52,7 @@ UTS_VERSION="$UTS_VERSION $CONFIG_FLAGS $TIMESTAMP"
 # Truncate to maximum length
 
 UTS_LEN=64
-UTS_TRUNCATE="sed -e s/\(.\{1,$UTS_LEN\}\).*/\1/"
+UTS_TRUNCATE="cut -b -$UTS_LEN"
 
 # Generate a temporary compile.h
 
@@ -66,9 +68,13 @@ UTS_TRUNCATE="sed -e s/\(.\{1,$UTS_LEN\}\).*/\1/"
   echo \#define LINUX_COMPILE_HOST \"`hostname | $UTS_TRUNCATE`\"
 
   if [ -x /bin/dnsdomainname ]; then
-    echo \#define LINUX_COMPILE_DOMAIN \"`dnsdomainname | $UTS_TRUNCATE`\"
+    domain=`dnsdomainname 2> /dev/null`
   elif [ -x /bin/domainname ]; then
-    echo \#define LINUX_COMPILE_DOMAIN \"`domainname | $UTS_TRUNCATE`\"
+    domain=`domainname 2> /dev/null`
+  fi
+
+  if [ -n "$domain" ]; then
+    echo \#define LINUX_COMPILE_DOMAIN \"`echo $domain | $UTS_TRUNCATE`\"
   else
     echo \#define LINUX_COMPILE_DOMAIN
   fi
index fa4a0a1..f67cc88 100644 (file)
@@ -18,6 +18,9 @@
 # e) generate the rpm files, based on kernel.spec
 # - Use /. to avoid tar packing just the symlink
 
+# Note that the rpm-pkg target cannot be used with KBUILD_OUTPUT,
+# but the binrpm-pkg target can; for some reason O= gets ignored.
+
 # Do we have rpmbuild, otherwise fall back to the older rpm
 RPM := $(shell if [ -x "/usr/bin/rpmbuild" ]; then echo rpmbuild; \
                   else echo rpm; fi)
@@ -33,6 +36,12 @@ $(objtree)/kernel.spec: $(MKSPEC) $(srctree)/Makefile
        $(CONFIG_SHELL) $(MKSPEC) > $@
 
 rpm-pkg rpm: $(objtree)/kernel.spec FORCE
+       @if test -n "$(KBUILD_OUTPUT)"; then \
+               echo "Building source + binary RPM is not possible outside the"; \
+               echo "kernel source tree. Don't set KBUILD_OUTPUT, or use the"; \
+               echo "binrpm-pkg target instead."; \
+               false; \
+       fi
        $(MAKE) clean
        $(PREV) ln -sf $(srctree) $(KERNELPATH)
        $(CONFIG_SHELL) $(srctree)/scripts/setlocalversion > $(objtree)/.scmversion
@@ -61,7 +70,7 @@ binrpm-pkg: $(objtree)/binkernel.spec FORCE
        set -e; \
        mv -f $(objtree)/.tmp_version $(objtree)/.version
 
-       $(RPM) $(RPMOPTS) --define "_builddir $(srctree)" --target \
+       $(RPM) $(RPMOPTS) --define "_builddir $(objtree)" --target \
                $(UTS_MACHINE) -bb $<
 
 clean-files += $(objtree)/binkernel.spec
index 3d93f8c..47bdd2f 100755 (executable)
@@ -70,7 +70,7 @@ echo 'mkdir -p $RPM_BUILD_ROOT/boot $RPM_BUILD_ROOT/lib/modules'
 echo 'mkdir -p $RPM_BUILD_ROOT/lib/firmware'
 echo "%endif"
 
-echo 'INSTALL_MOD_PATH=$RPM_BUILD_ROOT make %{_smp_mflags} modules_install'
+echo 'INSTALL_MOD_PATH=$RPM_BUILD_ROOT make %{_smp_mflags} KBUILD_SRC= modules_install'
 echo "%ifarch ia64"
 echo 'cp $KBUILD_IMAGE $RPM_BUILD_ROOT'"/boot/efi/vmlinuz-$KERNELRELEASE"
 echo 'ln -s '"efi/vmlinuz-$KERNELRELEASE" '$RPM_BUILD_ROOT'"/boot/"
index 2fb28ef..06ec722 100644 (file)
@@ -873,7 +873,7 @@ static long get_instantiation_keyring(key_serial_t ringid,
        /* otherwise specify the destination keyring recorded in the
         * authorisation key (any KEY_SPEC_*_KEYRING) */
        if (ringid >= KEY_SPEC_REQUESTOR_KEYRING) {
-               *_dest_keyring = rka->dest_keyring;
+               *_dest_keyring = key_get(rka->dest_keyring);
                return 0;
        }
 
index c9ad182..e340792 100644 (file)
@@ -2674,6 +2674,7 @@ static struct pci_device_id azx_ids[] = {
        { PCI_DEVICE(0x10de, 0x044b), .driver_data = AZX_DRIVER_NVIDIA },
        { PCI_DEVICE(0x10de, 0x055c), .driver_data = AZX_DRIVER_NVIDIA },
        { PCI_DEVICE(0x10de, 0x055d), .driver_data = AZX_DRIVER_NVIDIA },
+       { PCI_DEVICE(0x10de, 0x0590), .driver_data = AZX_DRIVER_NVIDIA },
        { PCI_DEVICE(0x10de, 0x0774), .driver_data = AZX_DRIVER_NVIDIA },
        { PCI_DEVICE(0x10de, 0x0775), .driver_data = AZX_DRIVER_NVIDIA },
        { PCI_DEVICE(0x10de, 0x0776), .driver_data = AZX_DRIVER_NVIDIA },
index c08ca66..ff20048 100644 (file)
@@ -965,6 +965,8 @@ static void alc_automute_pin(struct hda_codec *codec)
        unsigned int nid = spec->autocfg.hp_pins[0];
        int i;
 
+       if (!nid)
+               return;
        pincap = snd_hda_query_pin_caps(codec, nid);
        if (pincap & AC_PINCAP_TRIG_REQ) /* need trigger? */
                snd_hda_codec_read(codec, nid, 0, AC_VERB_SET_PIN_SENSE, 0);
@@ -12602,7 +12604,8 @@ static struct snd_pci_quirk alc268_cfg_tbl[] = {
        SND_PCI_QUIRK(0x1025, 0x015b, "Acer Aspire One",
                                                ALC268_ACER_ASPIRE_ONE),
        SND_PCI_QUIRK(0x1028, 0x0253, "Dell OEM", ALC268_DELL),
-       SND_PCI_QUIRK(0x1028, 0x02b0, "Dell Inspiron Mini9", ALC268_DELL),
+       SND_PCI_QUIRK_MASK(0x1028, 0xfff0, 0x02b0,
+                       "Dell Inspiron Mini9/Vostro A90", ALC268_DELL),
        /* almost compatible with toshiba but with optional digital outs;
         * auto-probing seems working fine
         */
@@ -17374,7 +17377,7 @@ static int alc662_auto_create_extra_out(struct hda_codec *codec, hda_nid_t pin,
 
 /* create playback/capture controls for input pins */
 #define alc662_auto_create_input_ctls \
-       alc880_auto_create_input_ctls
+       alc882_auto_create_input_ctls
 
 static void alc662_auto_set_output_and_unmute(struct hda_codec *codec,
                                              hda_nid_t nid, int pin_type,
index bd2338a..0519c60 100644 (file)
@@ -2,7 +2,7 @@
 
 menuconfig SND_PPC
        bool "PowerPC sound devices"
-       depends on PPC64 || PPC32
+       depends on PPC
        default y
        help
          Support for sound devices specific to PowerPC architectures.
index 2dee983..653a362 100644 (file)
@@ -21,7 +21,18 @@ config SND_OMAP_SOC_AMS_DELTA
        select SND_OMAP_SOC_MCBSP
        select SND_SOC_CX20442
        help
-         Say Y if you want to add support for SoC audio on Amstrad Delta.
+         Say Y  if you want to add support  for SoC audio device  connected to
+         a handset and a speakerphone found on Amstrad E3 (Delta) videophone.
+
+         Note that in order to get those devices fully supported,  you have to
+         build  the kernel  with  standard  serial port  driver  included  and
+         configured for at least 4 ports.  Then, from userspace, you must load
+         a line discipline #19 on the modem (ttyS3) serial line.  The simplest
+         way to achieve this is to install util-linux-ng  and use the included
+         ldattach  utility.  This  can be  started  automatically  from  udev,
+         a simple rule like this one should do the trick (it does for me):
+               ACTION=="add", KERNEL=="controlC0", \
+                               RUN+="/usr/sbin/ldattach 19 /dev/ttyS3"
 
 config SND_OMAP_SOC_OSK5912
        tristate "SoC Audio support for omap osk5912"
index 5735945..6a829ee 100644 (file)
@@ -195,8 +195,12 @@ static int omap_pcm_prepare(struct snd_pcm_substream *substream)
        else
                omap_enable_dma_irq(prtd->dma_ch, OMAP_DMA_FRAME_IRQ);
 
-       omap_set_dma_src_burst_mode(prtd->dma_ch, OMAP_DMA_DATA_BURST_16);
-       omap_set_dma_dest_burst_mode(prtd->dma_ch, OMAP_DMA_DATA_BURST_16);
+       if (!(cpu_class_is_omap1())) {
+               omap_set_dma_src_burst_mode(prtd->dma_ch,
+                                               OMAP_DMA_DATA_BURST_16);
+               omap_set_dma_dest_burst_mode(prtd->dma_ch,
+                                               OMAP_DMA_DATA_BURST_16);
+       }
 
        return 0;
 }
index 5cbbdc8..1f35c6f 100644 (file)
@@ -75,11 +75,19 @@ static void s3c24xx_pcm_enqueue(struct snd_pcm_substream *substream)
 {
        struct s3c24xx_runtime_data *prtd = substream->runtime->private_data;
        dma_addr_t pos = prtd->dma_pos;
+       unsigned int limit;
        int ret;
 
        pr_debug("Entered %s\n", __func__);
 
-       while (prtd->dma_loaded < prtd->dma_limit) {
+       if (s3c_dma_has_circular()) {
+               limit = (prtd->dma_end - prtd->dma_start) / prtd->dma_period;
+       } else
+               limit = prtd->dma_limit;
+
+       pr_debug("%s: loaded %d, limit %d\n", __func__, prtd->dma_loaded, limit);
+
+       while (prtd->dma_loaded < limit) {
                unsigned long len = prtd->dma_period;
 
                pr_debug("dma_loaded: %d\n", prtd->dma_loaded);
@@ -123,7 +131,7 @@ static void s3c24xx_audio_buffdone(struct s3c2410_dma_chan *channel,
                snd_pcm_period_elapsed(substream);
 
        spin_lock(&prtd->lock);
-       if (prtd->state & ST_RUNNING) {
+       if (prtd->state & ST_RUNNING && !s3c_dma_has_circular()) {
                prtd->dma_loaded--;
                s3c24xx_pcm_enqueue(substream);
        }
@@ -164,6 +172,11 @@ static int s3c24xx_pcm_hw_params(struct snd_pcm_substream *substream,
                        printk(KERN_ERR "failed to get dma channel\n");
                        return ret;
                }
+
+               /* use the circular buffering if we have it available. */
+               if (s3c_dma_has_circular())
+                       s3c2410_dma_setflags(prtd->params->channel,
+                                            S3C2410_DMAF_CIRCULAR);
        }
 
        s3c2410_dma_set_buffdone_fn(prtd->params->channel,
index 3c06c40..105a77e 100644 (file)
@@ -220,6 +220,8 @@ static __devinit int s3c64xx_iis_dev_probe(struct platform_device *pdev)
                goto err;
        }
 
+       clk_enable(i2s->iis_cclk);
+
        ret = s3c_i2sv2_probe(pdev, dai, i2s, 0);
        if (ret)
                goto err_clk;
index 7ff04ad..0a1b2f6 100644 (file)
@@ -834,6 +834,9 @@ EXPORT_SYMBOL_GPL(snd_soc_resume_device);
 #define soc_resume     NULL
 #endif
 
+static struct snd_soc_dai_ops null_dai_ops = {
+};
+
 static void snd_soc_instantiate_card(struct snd_soc_card *card)
 {
        struct platform_device *pdev = container_of(card->dev,
@@ -877,6 +880,11 @@ static void snd_soc_instantiate_card(struct snd_soc_card *card)
                        ac97 = 1;
        }
 
+       for (i = 0; i < card->num_links; i++) {
+               if (!card->dai_link[i].codec_dai->ops)
+                       card->dai_link[i].codec_dai->ops = &null_dai_ops;
+       }
+
        /* If we have AC97 in the system then don't wait for the
         * codec.  This will need revisiting if we have to handle
         * systems with mixed AC97 and non-AC97 parts.  Only check for
@@ -2329,9 +2337,6 @@ static int snd_soc_unregister_card(struct snd_soc_card *card)
        return 0;
 }
 
-static struct snd_soc_dai_ops null_dai_ops = {
-};
-
 /**
  * snd_soc_register_dai - Register a DAI with the ASoC core
  *
index 8de6f9d..d89f6dc 100644 (file)
@@ -2072,9 +2072,9 @@ int snd_soc_dapm_stream_event(struct snd_soc_codec *codec,
                        }
                }
        }
-       mutex_unlock(&codec->mutex);
 
        dapm_power_widgets(codec, event);
+       mutex_unlock(&codec->mutex);
        dump_dapm(codec, __func__);
        return 0;
 }
index 1c2ed30..a791009 100644 (file)
@@ -31,6 +31,9 @@ OPTIONS
 -w::
 --width=::
         Select the width of the SVG file (default: 1000)
+-p::
+--power-only::
+        Only output the CPU power section of the diagram
 
 
 SEE ALSO
index b5f1953..7e190d5 100644 (file)
@@ -157,11 +157,18 @@ uname_R := $(shell sh -c 'uname -r 2>/dev/null || echo not')
 uname_P := $(shell sh -c 'uname -p 2>/dev/null || echo not')
 uname_V := $(shell sh -c 'uname -v 2>/dev/null || echo not')
 
-# If we're on a 64-bit kernel, use -m64
-ifndef NO_64BIT
-       ifneq ($(patsubst %64,%,$(uname_M)),$(uname_M))
-         M64 := -m64
-       endif
+#
+# Add -m32 for cross-builds:
+#
+ifdef NO_64BIT
+  MBITS := -m32
+else
+  #
+  # If we're on a 64-bit kernel, use -m64:
+  #
+  ifneq ($(patsubst %64,%,$(uname_M)),$(uname_M))
+    MBITS := -m64
+  endif
 endif
 
 # CFLAGS and LDFLAGS are for the users to override from the command line.
@@ -170,8 +177,7 @@ endif
 # Include saner warnings here, which can catch bugs:
 #
 
-EXTRA_WARNINGS := -Wcast-align
-EXTRA_WARNINGS := $(EXTRA_WARNINGS) -Wformat
+EXTRA_WARNINGS := -Wformat
 EXTRA_WARNINGS := $(EXTRA_WARNINGS) -Wformat-security
 EXTRA_WARNINGS := $(EXTRA_WARNINGS) -Wformat-y2k
 EXTRA_WARNINGS := $(EXTRA_WARNINGS) -Wshadow
@@ -194,7 +200,7 @@ EXTRA_WARNINGS := $(EXTRA_WARNINGS) -Wold-style-definition
 EXTRA_WARNINGS := $(EXTRA_WARNINGS) -Wstrict-prototypes
 EXTRA_WARNINGS := $(EXTRA_WARNINGS) -Wdeclaration-after-statement
 
-CFLAGS = $(M64) -ggdb3 -Wall -Wextra -std=gnu99 -Werror -O6 -fstack-protector-all -D_FORTIFY_SOURCE=2 $(EXTRA_WARNINGS)
+CFLAGS = $(MBITS) -ggdb3 -Wall -Wextra -std=gnu99 -Werror -O6 -fstack-protector-all -D_FORTIFY_SOURCE=2 $(EXTRA_WARNINGS)
 LDFLAGS = -lpthread -lrt -lelf -lm
 ALL_CFLAGS = $(CFLAGS)
 ALL_LDFLAGS = $(LDFLAGS)
@@ -415,8 +421,12 @@ ifeq ($(uname_S),Darwin)
        PTHREAD_LIBS =
 endif
 
-ifneq ($(shell sh -c "(echo '\#include <libelf.h>'; echo 'int main(void) { Elf * elf = elf_begin(0, ELF_C_READ_MMAP, 0); return (long)elf; }') | $(CC) -x c - $(ALL_CFLAGS) -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -o /dev/null $(ALL_LDFLAGS) > /dev/null 2>&1 && echo y"), y)
-       msg := $(error No libelf.h/libelf found, please install libelf-dev/elfutils-libelf-devel);
+ifeq ($(shell sh -c "(echo '\#include <libelf.h>'; echo 'int main(void) { Elf * elf = elf_begin(0, ELF_C_READ, 0); return (long)elf; }') | $(CC) -x c - $(ALL_CFLAGS) -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -o /dev/null $(ALL_LDFLAGS) > /dev/null 2>&1 && echo y"), y)
+       ifneq ($(shell sh -c "(echo '\#include <libelf.h>'; echo 'int main(void) { Elf * elf = elf_begin(0, ELF_C_READ_MMAP, 0); return (long)elf; }') | $(CC) -x c - $(ALL_CFLAGS) -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -o /dev/null $(ALL_LDFLAGS) > /dev/null 2>&1 && echo y"), y)
+               BASIC_CFLAGS += -DLIBELF_NO_MMAP
+       endif
+else
+       msg := $(error No libelf.h/libelf found, please install libelf-dev/elfutils-libelf-devel and glibc-dev[el]);
 endif
 
 ifdef NO_DEMANGLE
@@ -728,7 +738,7 @@ $(BUILT_INS): perf$X
 common-cmds.h: util/generate-cmdlist.sh command-list.txt
 
 common-cmds.h: $(wildcard Documentation/perf-*.txt)
-       $(QUIET_GEN)util/generate-cmdlist.sh > $@+ && mv $@+ $@
+       $(QUIET_GEN)util/generate-cmdlist.sh > $@+ && mv $@+ $@
 
 $(patsubst %.sh,%,$(SCRIPT_SH)) : % : %.sh
        $(QUIET_GEN)$(RM) $@ $@+ && \
index a5a050a..3eeef33 100644 (file)
@@ -41,6 +41,7 @@ static int                    raw_samples                     = 0;
 static int                     system_wide                     = 0;
 static int                     profile_cpu                     = -1;
 static pid_t                   target_pid                      = -1;
+static pid_t                   child_pid                       = -1;
 static int                     inherit                         = 1;
 static int                     force                           = 0;
 static int                     append_file                     = 0;
@@ -184,6 +185,9 @@ static void sig_handler(int sig)
 
 static void sig_atexit(void)
 {
+       if (child_pid != -1)
+               kill(child_pid, SIGTERM);
+
        if (signr == -1)
                return;
 
@@ -610,6 +614,8 @@ static int __cmd_record(int argc, const char **argv)
                                exit(-1);
                        }
                }
+
+               child_pid = pid;
        }
 
        if (realtime_prio) {
index ea9c15c..ce2d5be 100644 (file)
@@ -1287,7 +1287,7 @@ static struct sort_dimension *available_sorts[] = {
 
 static LIST_HEAD(sort_list);
 
-static int sort_dimension__add(char *tok, struct list_head *list)
+static int sort_dimension__add(const char *tok, struct list_head *list)
 {
        int i;
 
@@ -1917,7 +1917,7 @@ static void setup_sorting(void)
 
        free(str);
 
-       sort_dimension__add((char *)"pid", &cmp_pid);
+       sort_dimension__add("pid", &cmp_pid);
 }
 
 static const char *record_args[] = {
index e5f6ece..3db31e7 100644 (file)
@@ -69,7 +69,8 @@ static int                    run_idx                         =  0;
 static int                     run_count                       =  1;
 static int                     inherit                         =  1;
 static int                     scale                           =  1;
-static int                     target_pid                      = -1;
+static pid_t                   target_pid                      = -1;
+static pid_t                   child_pid                       = -1;
 static int                     null_run                        =  0;
 
 static int                     fd[MAX_NR_CPUS][MAX_COUNTERS];
@@ -285,6 +286,8 @@ static int run_perf_stat(int argc __used, const char **argv)
                exit(-1);
        }
 
+       child_pid = pid;
+
        /*
         * Wait for the child to be ready to exec.
         */
@@ -433,6 +436,9 @@ static void skip_signal(int signo)
 
 static void sig_atexit(void)
 {
+       if (child_pid != -1)
+               kill(child_pid, SIGTERM);
+
        if (signr == -1)
                return;
 
index 4405681..e8a510d 100644 (file)
@@ -46,6 +46,8 @@ static u64            turbo_frequency;
 
 static u64             first_time, last_time;
 
+static int             power_only;
+
 
 static struct perf_header      *header;
 
@@ -547,7 +549,7 @@ static void end_sample_processing(void)
        u64 cpu;
        struct power_event *pwr;
 
-       for (cpu = 0; cpu < numcpus; cpu++) {
+       for (cpu = 0; cpu <= numcpus; cpu++) {
                pwr = malloc(sizeof(struct power_event));
                if (!pwr)
                        return;
@@ -763,19 +765,40 @@ static void draw_wakeups(void)
                                        if (c->Y && c->start_time <= we->time && c->end_time >= we->time) {
                                                if (p->pid == we->waker) {
                                                        from = c->Y;
-                                                       task_from = c->comm;
+                                                       task_from = strdup(c->comm);
                                                }
                                                if (p->pid == we->wakee) {
                                                        to = c->Y;
-                                                       task_to = c->comm;
+                                                       task_to = strdup(c->comm);
                                                }
                                        }
                                        c = c->next;
                                }
+                               c = p->all;
+                               while (c) {
+                                       if (p->pid == we->waker && !from) {
+                                               from = c->Y;
+                                               task_from = strdup(c->comm);
+                                       }
+                                       if (p->pid == we->wakee && !to) {
+                                               to = c->Y;
+                                               task_to = strdup(c->comm);
+                                       }
+                                       c = c->next;
+                               }
                        }
                        p = p->next;
                }
 
+               if (!task_from) {
+                       task_from = malloc(40);
+                       sprintf(task_from, "[%i]", we->waker);
+               }
+               if (!task_to) {
+                       task_to = malloc(40);
+                       sprintf(task_to, "[%i]", we->wakee);
+               }
+
                if (we->waker == -1)
                        svg_interrupt(we->time, to);
                else if (from && to && abs(from - to) == 1)
@@ -783,6 +806,9 @@ static void draw_wakeups(void)
                else
                        svg_partial_wakeline(we->time, from, task_from, to, task_to);
                we = we->next;
+
+               free(task_from);
+               free(task_to);
        }
 }
 
@@ -871,7 +897,7 @@ static int determine_display_tasks(u64 threshold)
                /* no exit marker, task kept running to the end */
                if (p->end_time == 0)
                        p->end_time = last_time;
-               if (p->total_time >= threshold)
+               if (p->total_time >= threshold && !power_only)
                        p->display = 1;
 
                c = p->all;
@@ -882,7 +908,7 @@ static int determine_display_tasks(u64 threshold)
                        if (c->start_time == 1)
                                c->start_time = first_time;
 
-                       if (c->total_time >= threshold) {
+                       if (c->total_time >= threshold && !power_only) {
                                c->display = 1;
                                count++;
                        }
@@ -1134,6 +1160,8 @@ static const struct option options[] = {
                    "output file name"),
        OPT_INTEGER('w', "width", &svg_page_width,
                    "page width"),
+       OPT_BOOLEAN('p', "power-only", &power_only,
+                   "output power data only"),
        OPT_END()
 };
 
index 1ca8889..a1b1d10 100644 (file)
@@ -686,6 +686,8 @@ static void handle_keypress(int c)
        switch (c) {
                case 'd':
                        prompt_integer(&delay_secs, "Enter display delay");
+                       if (delay_secs < 1)
+                               delay_secs = 1;
                        break;
                case 'e':
                        prompt_integer(&print_entries, "Enter display entries (lines)");
@@ -782,6 +784,7 @@ static const char *skip_symbols[] = {
        "exit_idle",
        "mwait_idle",
        "mwait_idle_with_hints",
+       "poll_idle",
        "ppc64_runlatch_off",
        "pseries_dedicated_idle_sleep",
        NULL
index e9d256e..0c5e4f7 100644 (file)
@@ -219,10 +219,6 @@ remap:
 more:
        event = (event_t *)(buf + head);
 
-       size = event->header.size;
-       if (!size)
-               size = 8;
-
        if (head + event->header.size >= page_size * mmap_window) {
                unsigned long shift = page_size * (head / page_size);
                int res;
@@ -237,7 +233,6 @@ more:
 
        size = event->header.size;
 
-
        if (!size || process_event(event, offset, head) < 0) {
 
                /*
@@ -290,7 +285,6 @@ int cmd_trace(int argc, const char **argv, const char *prefix __used)
                        usage_with_options(annotate_usage, options);
        }
 
-
        setup_pager();
 
        return __cmd_trace();
index f1946d1..fdd42a8 100644 (file)
@@ -455,3 +455,6 @@ will need at least this:
 
 If your architecture does have hardware capabilities, you can override the
 weak stub hw_perf_event_init() to register hardware counters.
+
+Architectures that have d-cache aliassing issues, such as Sparc and ARM,
+should select PERF_USE_VMALLOC in order to avoid these for perf mmap().
index c561d15..54552a0 100755 (executable)
@@ -1,7 +1,7 @@
 #!/bin/sh
 
 GVF=PERF-VERSION-FILE
-DEF_VER=v0.0.1.PERF
+DEF_VER=v0.0.2.PERF
 
 LF='
 '
index 87c424d..8cfb48c 100644 (file)
@@ -691,7 +691,10 @@ static void store_event_type(const char *orgname)
        FILE *file;
        int id;
 
-       sprintf(filename, "/sys/kernel/debug/tracing/events/%s/id", orgname);
+       sprintf(filename, "%s/", debugfs_path);
+       strncat(filename, orgname, strlen(orgname));
+       strcat(filename, "/id");
+
        c = strchr(filename, ':');
        if (c)
                *c = '/';
index a778fd0..b3637db 100644 (file)
@@ -28,7 +28,7 @@ static u64 turbo_frequency, max_freq;
 
 int svg_page_width = 1000;
 
-#define MIN_TEXT_SIZE 0.001
+#define MIN_TEXT_SIZE 0.01
 
 static u64 total_height;
 static FILE *svgfile;
@@ -103,7 +103,7 @@ void open_svg(const char *filename, int cpus, int rows, u64 start, u64 end)
        fprintf(svgfile, "      rect.process2 { fill:rgb(180,180,180); fill-opacity:0.9; stroke-width:0;   stroke:rgb(  0,  0,  0); } \n");
        fprintf(svgfile, "      rect.sample   { fill:rgb(  0,  0,255); fill-opacity:0.8; stroke-width:0;   stroke:rgb(  0,  0,  0); } \n");
        fprintf(svgfile, "      rect.blocked  { fill:rgb(255,  0,  0); fill-opacity:0.5; stroke-width:0;   stroke:rgb(  0,  0,  0); } \n");
-       fprintf(svgfile, "      rect.waiting  { fill:rgb(214,214,  0); fill-opacity:0.3; stroke-width:0;   stroke:rgb(  0,  0,  0); } \n");
+       fprintf(svgfile, "      rect.waiting  { fill:rgb(224,214,  0); fill-opacity:0.8; stroke-width:0;   stroke:rgb(  0,  0,  0); } \n");
        fprintf(svgfile, "      rect.WAITING  { fill:rgb(255,214, 48); fill-opacity:0.6; stroke-width:0;   stroke:rgb(  0,  0,  0); } \n");
        fprintf(svgfile, "      rect.cpu      { fill:rgb(192,192,192); fill-opacity:0.2; stroke-width:0.5; stroke:rgb(128,128,128); } \n");
        fprintf(svgfile, "      rect.pstate   { fill:rgb(128,128,128); fill-opacity:0.8; stroke-width:0; } \n");
@@ -217,6 +217,18 @@ static char *cpu_model(void)
                }
                fclose(file);
        }
+
+       /* CPU type */
+       file = fopen("/sys/devices/system/cpu/cpu0/cpufreq/scaling_available_frequencies", "r");
+       if (file) {
+               while (fgets(buf, 255, file)) {
+                       unsigned int freq;
+                       freq = strtoull(buf, NULL, 10);
+                       if (freq > max_freq)
+                               max_freq = freq;
+               }
+               fclose(file);
+       }
        return cpu_m;
 }
 
index 559fb06..226f44a 100644 (file)
@@ -324,8 +324,7 @@ static inline int elf_sym__is_function(const GElf_Sym *sym)
 {
        return elf_sym__type(sym) == STT_FUNC &&
               sym->st_name != 0 &&
-              sym->st_shndx != SHN_UNDEF &&
-              sym->st_size != 0;
+              sym->st_shndx != SHN_UNDEF;
 }
 
 static inline int elf_sym__is_label(const GElf_Sym *sym)
@@ -414,7 +413,7 @@ static int dso__synthesize_plt_symbols(struct  dso *self, int v)
        if (fd < 0)
                goto out;
 
-       elf = elf_begin(fd, ELF_C_READ_MMAP, NULL);
+       elf = elf_begin(fd, PERF_ELF_C_READ_MMAP, NULL);
        if (elf == NULL)
                goto out_close;
 
@@ -534,7 +533,7 @@ static int dso__load_sym(struct dso *self, int fd, const char *name,
        Elf *elf;
        int nr = 0, kernel = !strcmp("[kernel]", self->name);
 
-       elf = elf_begin(fd, ELF_C_READ_MMAP, NULL);
+       elf = elf_begin(fd, PERF_ELF_C_READ_MMAP, NULL);
        if (elf == NULL) {
                if (v)
                        fprintf(stderr, "%s: cannot read %s ELF file.\n",
@@ -676,7 +675,7 @@ static char *dso__read_build_id(struct dso *self, int v)
        if (fd < 0)
                goto out;
 
-       elf = elf_begin(fd, ELF_C_READ_MMAP, NULL);
+       elf = elf_begin(fd, PERF_ELF_C_READ_MMAP, NULL);
        if (elf == NULL) {
                if (v)
                        fprintf(stderr, "%s: cannot read %s ELF file.\n",
index 6e84907..829da9e 100644 (file)
@@ -27,6 +27,16 @@ static inline char *bfd_demangle(void __used *v, const char __used *c,
 #endif
 #endif
 
+/*
+ * libelf 0.8.x and earlier do not support ELF_C_READ_MMAP;
+ * for newer versions we can use mmap to reduce memory usage:
+ */
+#ifdef LIBELF_NO_MMAP
+# define PERF_ELF_C_READ_MMAP ELF_C_READ
+#else
+# define PERF_ELF_C_READ_MMAP ELF_C_READ_MMAP
+#endif
+
 #ifndef DMGL_PARAMS
 #define DMGL_PARAMS      (1 << 0)       /* Include function args */
 #define DMGL_ANSI        (1 << 1)       /* Include const, volatile, etc */
index f6a8437..55c9659 100644 (file)
@@ -618,7 +618,7 @@ static int test_type(enum event_type type, enum event_type expect)
 }
 
 static int test_type_token(enum event_type type, char *token,
-                   enum event_type expect, char *expect_tok)
+                   enum event_type expect, const char *expect_tok)
 {
        if (type != expect) {
                die("Error: expected type %d but read %d",
@@ -650,7 +650,7 @@ static int read_expect_type(enum event_type expect, char **tok)
        return __read_expect_type(expect, tok, 1);
 }
 
-static int __read_expected(enum event_type expect, char *str, int newline_ok)
+static int __read_expected(enum event_type expect, const char *str, int newline_ok)
 {
        enum event_type type;
        char *token;
@@ -668,12 +668,12 @@ static int __read_expected(enum event_type expect, char *str, int newline_ok)
        return 0;
 }
 
-static int read_expected(enum event_type expect, char *str)
+static int read_expected(enum event_type expect, const char *str)
 {
        return __read_expected(expect, str, 1);
 }
 
-static int read_expected_item(enum event_type expect, char *str)
+static int read_expected_item(enum event_type expect, const char *str)
 {
        return __read_expected(expect, str, 0);
 }
@@ -1968,10 +1968,11 @@ static const struct flag flags[] = {
        { "NET_TX_SOFTIRQ", 2 },
        { "NET_RX_SOFTIRQ", 3 },
        { "BLOCK_SOFTIRQ", 4 },
-       { "TASKLET_SOFTIRQ", 5 },
-       { "SCHED_SOFTIRQ", 6 },
-       { "HRTIMER_SOFTIRQ", 7 },
-       { "RCU_SOFTIRQ", 8 },
+       { "BLOCK_IOPOLL_SOFTIRQ", 5 },
+       { "TASKLET_SOFTIRQ", 6 },
+       { "SCHED_SOFTIRQ", 7 },
+       { "HRTIMER_SOFTIRQ", 8 },
+       { "RCU_SOFTIRQ", 9 },
 
        { "HRTIMER_NORESTART", 0 },
        { "HRTIMER_RESTART", 1 },
index e79c540..7495ce3 100644 (file)
@@ -850,6 +850,19 @@ static void kvm_mmu_notifier_invalidate_page(struct mmu_notifier *mn,
 
 }
 
+static void kvm_mmu_notifier_change_pte(struct mmu_notifier *mn,
+                                       struct mm_struct *mm,
+                                       unsigned long address,
+                                       pte_t pte)
+{
+       struct kvm *kvm = mmu_notifier_to_kvm(mn);
+
+       spin_lock(&kvm->mmu_lock);
+       kvm->mmu_notifier_seq++;
+       kvm_set_spte_hva(kvm, address, pte);
+       spin_unlock(&kvm->mmu_lock);
+}
+
 static void kvm_mmu_notifier_invalidate_range_start(struct mmu_notifier *mn,
                                                    struct mm_struct *mm,
                                                    unsigned long start,
@@ -929,6 +942,7 @@ static const struct mmu_notifier_ops kvm_mmu_notifier_ops = {
        .invalidate_range_start = kvm_mmu_notifier_invalidate_range_start,
        .invalidate_range_end   = kvm_mmu_notifier_invalidate_range_end,
        .clear_flush_young      = kvm_mmu_notifier_clear_flush_young,
+       .change_pte             = kvm_mmu_notifier_change_pte,
        .release                = kvm_mmu_notifier_release,
 };
 #endif /* CONFIG_MMU_NOTIFIER && KVM_ARCH_WANT_MMU_NOTIFIER */
@@ -2703,8 +2717,6 @@ int kvm_init(void *opaque, unsigned int vcpu_size,
        int r;
        int cpu;
 
-       kvm_init_debug();
-
        r = kvm_arch_init(opaque);
        if (r)
                goto out_fail;
@@ -2771,6 +2783,8 @@ int kvm_init(void *opaque, unsigned int vcpu_size,
        kvm_preempt_ops.sched_in = kvm_sched_in;
        kvm_preempt_ops.sched_out = kvm_sched_out;
 
+       kvm_init_debug();
+
        return 0;
 
 out_free:
@@ -2793,7 +2807,6 @@ out_free_0:
 out:
        kvm_arch_exit();
 out_fail:
-       kvm_exit_debug();
        return r;
 }
 EXPORT_SYMBOL_GPL(kvm_init);
@@ -2801,6 +2814,7 @@ EXPORT_SYMBOL_GPL(kvm_init);
 void kvm_exit(void)
 {
        tracepoint_synchronize_unregister();
+       kvm_exit_debug();
        misc_deregister(&kvm_dev);
        kmem_cache_destroy(kvm_vcpu_cache);
        sysdev_unregister(&kvm_sysdev);
@@ -2810,7 +2824,6 @@ void kvm_exit(void)
        on_each_cpu(hardware_disable, NULL, 1);
        kvm_arch_hardware_unsetup();
        kvm_arch_exit();
-       kvm_exit_debug();
        free_cpumask_var(cpus_hardware_enabled);
        __free_page(bad_page);
 }