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)
1759 files changed:
Documentation/ABI/testing/sysfs-class-usb_host [deleted file]
Documentation/ABI/testing/sysfs-class-uwb_rc-wusbhc [new file with mode: 0644]
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

diff --git a/Documentation/ABI/testing/sysfs-class-usb_host b/Documentation/ABI/testing/sysfs-class-usb_host
deleted file mode 100644 (file)
index 46b66ad..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-What:           /sys/class/usb_host/usb_hostN/wusb_chid
-Date:           July 2008
-KernelVersion:  2.6.27
-Contact:        David Vrabel <david.vrabel@csr.com>
-Description:
-                Write the CHID (16 space-separated hex octets) for this host controller.
-                This starts the host controller, allowing it to accept connection from
-                WUSB devices.
-
-                Set an all zero CHID to stop the host controller.
-
-What:           /sys/class/usb_host/usb_hostN/wusb_trust_timeout
-Date:           July 2008
-KernelVersion:  2.6.27
-Contact:        David Vrabel <david.vrabel@csr.com>
-Description:
-                Devices that haven't sent a WUSB packet to the host
-                within 'wusb_trust_timeout' ms are considered to have
-                disconnected and are removed.  The default value of
-                4000 ms is the value required by the WUSB
-                specification.
-
-                Since this relates to security (specifically, the
-                lifetime of PTKs and GTKs) it should not be changed
-                from the default.
diff --git a/Documentation/ABI/testing/sysfs-class-uwb_rc-wusbhc b/Documentation/ABI/testing/sysfs-class-uwb_rc-wusbhc
new file mode 100644 (file)
index 0000000..4e8106f
--- /dev/null
@@ -0,0 +1,25 @@
+What:           /sys/class/uwb_rc/uwbN/wusbhc/wusb_chid
+Date:           July 2008
+KernelVersion:  2.6.27
+Contact:        David Vrabel <david.vrabel@csr.com>
+Description:
+                Write the CHID (16 space-separated hex octets) for this host controller.
+                This starts the host controller, allowing it to accept connection from
+                WUSB devices.
+
+                Set an all zero CHID to stop the host controller.
+
+What:           /sys/class/uwb_rc/uwbN/wusbhc/wusb_trust_timeout
+Date:           July 2008
+KernelVersion:  2.6.27
+Contact:        David Vrabel <david.vrabel@csr.com>
+Description:
+                Devices that haven't sent a WUSB packet to the host
+                within 'wusb_trust_timeout' ms are considered to have
+                disconnected and are removed.  The default value of
+                4000 ms is the value required by the WUSB
+                specification.
+
+                Since this relates to security (specifically, the
+                lifetime of PTKs and GTKs) it should not be changed
+                from the default.
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 455d4e6d346d839eb0bd8b811efed40afd3642fa..0b33bfe7dde99ecc98df6d0fa4466b3e79eb8f2b 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 b41f3e58aefa8581eda3fa35286791b4ae0117c7..f1c5c4bccd3e8ed6674903eedbc59db3cf76ff9e 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 59a91e5c690968f756397f989e18423c144830a6..611f5a5499b153c9594ad37e7237f7a35489b3bd 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 89a47b5aff07f11f04d504d2e91aab9aa4bfadfe..bc693fffabe08d1fcd06ba14747b2017556e14ed 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 570f9bd9be2becb3fee1c7869d9c911226690dc4..05d5cf1d743f1318ef97e2f47cf06a607ebc0f2c 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 bf4f4b7e11b38298c67d4eac41fec30e63d70c16..6d94e0696f8c313ee5a439f5ed2f140b356500f6 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 84eb26808dee9265edb9fb90eeb259bc989aeb19..cb8a3a00cc92694947cb72840ddbcb340407ce08 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 dcbd502c8792b4e786507bc2023860c716d8fd8b..82def883361b1a1d30ca2e5af6f1e0a5b56c9b27 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 744687dd195bb04e4af3cf8f549769824fa02087..8a366959f5cc2e01a190692593b6962e830bf8bd 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 f847501e50b5e0811885b66842b3b80e165113ec..afe3f8da9018e842d582eee546508b732451208d 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 686e107923ec16f36a4f6a32fd49b791e36b30b9..5fe8de5cc7275f768b3c1106c5276f56ab35e256 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 6fa7292947e5c8d100d6e426013aa31aa421f115..9107b387e91fce095ee320dbeed53d5dfe5cb332 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 ba9373f82ab5fa9fe62276cc27333447a22475ba..098de5bce00a795126301b870c7b19359fe164a0 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 c6cf4a3c16e029258e3c6790ee3b5da441259eff..61bb645d50e061d7450f3f75d8805d2ca9308501 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 a6eb4add1be6d2b7dc1b553853fd04d3d2189b5b..9605179711f4db78f5f99c0d75296860c9c3e0e3 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 957b22fde2dfddac0bcf061d7af84259384f32f2..8179692fbb903a3ccb92de0422e7c370137e9d9d 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 72a22f65960ed942c24c43feb9c0be4b8adab233..262d8e6793a3e008c36bb39905f49634f9e570ae 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 fa1a30d9e9d540a27324affbfe8aae579661c877..3ec4f2a2258537a80b77f1ca341b1df03ded6ae8 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 600a304a828cb2865e63a85e031fb881f27cbbc7..df09b9650a811045ee99708682b2172c0c8fee83 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 09a2028bab7f78786266c10fe1d2f99b0e1e263c..a1a2aceca5bd5e911f78745b44201a0da0beb0f9 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 e50569ab5fe8b656396afd38193fc9b847fe30b4..b4c04f734e56b0e546824e7956f29fef4590001a 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 8da75dede52eb403f4d5c0cb1bb4bf281d30e73c..264f52b5c52dddfe454e514c6903d3ea3291cc84 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 357d4021e2d0f50602c0545b8a63ee74e40257ca..b3c8cce0f8fb02a31f81ea76ea9a6b7dd3211a25 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 7d61ae6e75daf7e9da06b214818ee0ad2ff22efa..953ba0297fc4f8e50c49f4c7168854b2b8b7ac34 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 63a481fbbed43ed12ecc9802ffc729a06e8d23c6..338ff19ae4473252f769d6984f72e260200a947b 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 fd03fb63a33222ca6ff67a25469414371d68431d..3d0cdd21b882d1d39cade901827b17509c63e06e 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 c3b911ee9151af1501adefc7362dc7738e7d204b..6aac3f5bb2f3ee1975f53578d2742a5e5d1295b9 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 a45ab5dd82559cc7d21e887f24135193bc2fea6b..c2f1605de35902df4378b1e77898cc796441b4db 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 322410be573ca027bd8e03da67e134492423974d..0022b4d57f8b8c9e736df3e896ce1a06b4835aba 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 ac34c0d9384b000c39eec3f63763756f086ee8a7..7e9ed1eea40a63d3a72e898b46278ef38911c741 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 790fbee92ec5acd7f98eb48c69448c152c15fbb8..0d96d0171c05601bf59a5e44c579cd7f59e9af23 100644 (file)
@@ -327,6 +327,15 @@ copy_thread(unsigned long clone_flags, unsigned long stack_start,
        return 0;
 }
 
+/*
+ * 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...
  */
index 1423a3419789c0d2ddaacbb7ae763da8c17e55c9..2a573d4fea24a7ab12873282ad5c805a4c0e8de1 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.
@@ -48,6 +49,18 @@ const unsigned long sigreturn_codes[7] = {
        MOV_R7_NR_RT_SIGRETURN, SWI_SYS_RT_SIGRETURN, SWI_THUMB_RT_SIGRETURN,
 };
 
+/*
+ * 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.
  */
@@ -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 27beece1550263e3555e140f06b115aae034fb2b..6fcfe8398aa473051fbf72396986a84dc700978f 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 4cdc4a0bd02d6ebe94038e5f5fcd80da2b945324..d38cdf2c8276e6e23c769b9cf494dad5ff803d1f 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 467b69ed1021b39fb87848b4009edfef9fb9f1d2..95718a6b50a6bde2a2e059e906b59398a1d08428 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 39baf1128bfa16c82a805ce668cc797e9d82e44e..786ac2b6914ae4bc96cb3cb78dc6daa05127eee5 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 d581cff80c4c673468e4d6dec2608d847f176c1b..332b784050b272592d402afddf077b0ec591d00b 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 34a9502c48bce9ab05dae962c89cf3ac68ae6162..c22df30ed5e5d5784a6d7f09350ea17cd6b53706 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 4b4f69251b313a07676a6dcef5b19418c9c3c379..e590bbe0a7b46acb51e42baba1c5344239a29753 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 cdbf93c694a64ae9ef7fddac96e06359af65b71a..38b37060d42683a9f09d9340ad001914410b4e25 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 d7291c682a64622f45e5a243aebfab1384538017..9167c3d2a5edaf02ef6b74df0a00cab5572341ba 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 27a085a8f12a8020e237517809f3f65cabeccf21..0ad33f15c622644449eacc1bbf329c05f4741930 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 dda19cd76194fd4334785dea7af869713d6db467..1d0f9d8aff2e93583ba5ff0793f80d0f991f4786 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 f7ebed942f662fda227c002a4998091f02616de4..b4357c388d2e5e87b37e344fbdaa965083fac4e6 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 73145ae5d3fa345b4700897bc350c30ba05c73bb..a4a7be3080002cb2c1577eeb2cb1cfb40ec4b68c 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 0fbf87b163385296ee932644d54a6875cfd7bdc3..b1f937eda29c87e885a68fc0f03a2df7189dae9a 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 0a1498ae899aea4e114e855989010bd3b2d6da51..c991b149bdf2bfe804337fccc1fca357213ff713 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 925b12ea0990bde4d9df1500854717877d9f8b0f..554064e9030755bde60293701de36cef12088e50 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 01a0f0838e5b3d012a1c7aa1e94e4a70011464ae..469fd968d517aa7136b32b5b118f6976250d5409 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 0a313e82fb7440054ebd604cbfdcbb0d15b0d66c..d83b80478b091781086bd94ad087d3d606995260 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 2b2e7a110724b12aa0f8c07a576e4474a2ca8603..4891828454f5fdca8c72f5146633e2e5a362c204 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 901cc205015e81a4149a4f56e87e056fe372951f..148d25fc636fbe2c7d91596d4c312272e6460015 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 4089951acb4719420cda1d86af0655172b0c0b96..ff5e33298914ca3abf864e7cc9273ea96ccda6c6 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 ee65dda584cfbd51ec7a9fa4539badfac69d1dad..906d59b0a7aa4912275c0947beeecab7c27af1aa 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 c261f59b0b4cf014c537af76b0d20b09d5a0a0d8..3cb7f457e5d08fda5cbeaa0b1cad45a0680a7e2c 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 eb12de1da42d2c5f6d47b7aedfbdf650f1174bcc..63511de3a5592c9cdbccd8ca4345bedf602c7f7c 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 92aa4fd19d99359de6db2343014c233961417137..d23ae571c03f83d948b57c635ddab5a126a18a3c 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 fe5c4217322ed5813364feb642adc75b5829dd4a..c595260ec1f96df7ed6adf005b6a8aee6f4a8968 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 06bd6180bfc3ad27ad6a39e00de518454f53bf4f..b2a3bcf8266e8f4303e83aceac04f1c85bc39691 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 8a577f367250bd7f320a922d99cb238f7257741f..e6abe181b96755b0062b405abb3e1bd23a6129b7 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 79f2be45d13965ec0945109b044989a7b728243c..ab87419dc9a080fbbe35c02f80cf21e74a123b84 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 ad5a1122d765ad238143314cbae59e593c7b09bc..bedf5b8d976aa46a043a6a6b38112dfd1d3abdd1 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 42920f9c1a112e8c4781d527efee8b8409b79f3b..8ad5cc3e83e3483d6042a7cc3ba320d89ba0ba0a 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 fb47239da72feed53f336ba6d8d579324f6e5f81..6c8a41f20e516fdd773a061c4f7689eb44a59967 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 cc2abbb2d0f47635f513eda0322ae2d37c2f655b..cd6c3951482635a8df9fef80ecae12ab904d635c 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 90dd0431b0dce95ca71df8cc82098b092c0f0979..4de258420f398035add256d074dd490b98a9cfe1 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 8256139891ff143dcaed8203a8c5918d9c75d05b..d972cf941b76f86472a9191e1a2d9789d92e69a6 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 81b6bde1c5a3c0ffc65bab66d6a2cebe63c3a787..986bd4df0e972f3522a9c4abf786227d1abe6007 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 02c85ca2e1df804f2dda56830aad3b85d2605c4d..056ae64e0f557c912aede0c5f73850c60dfde940 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 c06e7a553472cae61164ffc47f9d789c3cf10686..07b07522d5bf99b643cdb6d557c24b339bd11528 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 d496e50fec40ced80eaf194cb2f2cdd5898d8dd0..d23979bc0fd52aebce992a9caa34e897d9fc877b 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 75b1c7efae7e3ef7c8e6cc6751d77bdc23662ccd..aad194f61a331f3c092f660668049da7f617c06d 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 efaf053eba85371a5d59ed1c69f06b2af3436471..0acb5560229c349ba66fa2327e838a9d4409a8d0 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 eb37c40ea83a606d6fbcc85cfeb21c6a6dd4bd75..609a5a4a7e292ef66c134c84aa86a188a201c98d 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 d110a7fdfbd800949aeac4e41a9a93fac121d2c6..d57ec2f4d0a9a85f94024e3bee816df68f24012f 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 e4ec0c591216c50a2d5d1fdf16c4cf36ecb53e15..4c4d7f8dbd7236cf6d33afa2eee8748e9d78e357 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 7f6bf8772af7e6c5ae961ce34d7ce7f041039c05..5326e0d61597725aab8da89f930383f6d9400a16 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 b45ad312c58732c480e6c5b96fb8a4b722e6f688..e34d96a825e3a60259a48cbd6dd92a3f79499881 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 f9196c3b1a7bd1677351c467ba5bc23666783db3..78869a9a1cc24700786549c23af8993f2b293d3a 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 b7b32208ced7768ff43253947916312515080917..ea00486a5e5314b5e5255a7c3aa9d4a9af306960 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 bc5d3ac6661191e3eeb68ef2c2d0723688d337fd..e2dbedd581e8966fb97c762532cdc3657101aa93 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 fafcd32e6907a2a70fed302ef656c09f7112fe34..489556eecbd1189a7a61638deec0f33d3aff59ad 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 4ef7b4f5474e581e12983c2e827d13229ceb2683..58aff8485df9c9843f1bb78a21b4e120f9dff8c5 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 e3a3bad1d84fee7e3c014119dff38a3228cf3f4b..56be87d13edb1cefb46356f2fda7c2eaf63ba4e4 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 1b4c1600f8d8c4c0f53ed5f70bd974d219777b83..2fc4d6abbd0a8a22a580542b93fb838a565b13b3 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 0ff5a6c53aa0e79fca0f58d90493273f7e1b123c..89463190923a6d2f152b7bd261232571b086b2ef 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 2594cbff3947e12f8d37c966e22fd99a22c5a1d1..f00289abd30f6f51d015f6f3cf932d77eb868ffc 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 ae2186892c85f9728e1cfdee07861412281ae0f4..54dfeb5d56672ca0c34b37d0c41f40074cf38eb9 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 aac2cda60e09a0c4fe08a9f5e57cd7ec42f48208..102916f1e4659108f5ca329ac5958c73a112ceef 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 3a8ee2272add9d3f062d6239070e49680044316d..983cc8c2008190db5e686f65a69f2a47bd2fd5cc 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 79141f862728d92e73cf09b9a062453f49cc8afa..965480eb4fe67312c24c0647d2e101bc900b7539 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 ee8d6038ce82be8f0204a1c2bcffc22deba765b3..82ff5733e4dc9c5fdb113bea5d34d8d40d9c0be2 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 46cd6acb4d40cebf28c80f110a5e419949f4bfa2..699671fa6e0ba06e47f7a2c91a5b7f8e74ebdca2 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 98f8e7eeacc28a1dabc753bc6ed7e643c25f31c6..34b80b7d40b825d3d728779b056315f9b6d59fda 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 f0d68e0fea01dc91f31a3cc7c81473978ebeba83..7abf918b77e9fec5af2f7334e277c2dc82684565 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 c8f50835fed2fcd69f76cdfb98fe6749411b2541..4f46bf71e7524e485356950ea9e0f6373fc6235e 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 1a15a441e027550e9503a662592c8015544992c7..a30f2e3ec17852a8f865b2ddb8320f6c9b3f4987 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 2817fe09931925492aa4b1cb32b2551028391cac..a6ba147692c19f916fb4647d4229eea499c961a6 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 94680fcf726dbf275e9653b045fd95eb7d6d9120..070d284ce96e49602ed0e5c72a34be2bad280410 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 7974afca297ce2282a276ed51063b5d28e3e738e..9664e011dae2f1bd9f521d5cd9469ac991c6c188 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 c3a2629e0ded67443455dcb3508fb3842845e473..92e2687009ead4420a088fe3827e174d39a32252 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 d7bba919a77ea487b37129a79f410a55886d40c4..a8b69d77571b5562ac1912d17322f321421afb8f 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 ec71a69657867edcbc7ffb79a2eda78d36f73bf3..1c3382fefdd21ebbea16abc2e33c4928d6f7b929 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 1067619f0ba07a5a2b12ebc0838e941d8d3d745b..004edab23954d5c46c054c26e13af91a522d27a8 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 8a5546e6d547e248bfea5a82e9aa70fec8f33f3c..bb7b8198d0c4f34790a3b06d276eeafa66b6071d 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 e993140edd880e3f62be0eed4d6851f5496375ab..9264d814cd7a9db1f5a5d0901fc62e81fa921aa0 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 8f5c13f4c93614abbcc37315b8c7a3fbb987d38b..295e25dd6381f69da0eaf59c8e9da1854434ddd8 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
@@ -142,6 +145,19 @@ ENTRY(v6_coherent_user_range)
 #endif
        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)
  *
index bda0ec31a4e2c9d2f06e856396a65d09082ad9d0..e1bd9759617f16cce4d8b59c738e340afa22b2e2 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 6bda76a431991287cc86e6995b3769bfde2ebf43..a9e22e31eaa1135ca9997840266f3144dd587735 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 b30925fcbcdcb05b705afa79da75f8ecbd2eceaf..b9590a7085ca27aef49fcfb1b057205615c3fb54 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 bc0099d5ae85c022d12a051062915fa1bae6aefb..d0d17b6a370304749d4f0f04c63662716e1c65e2 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 ae0e25f5a70eb57987c131f5fbfd4fe795df3302..10e06801afb38e9d0a60cdb8b8cd94d43bc9e139 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 b27942909b239e1c7d8dac35ad10cf5fe89d3353..7f294f307c835ed45d82c434e51954ba272481fc 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 73cae57fa707db6ce286e3945420c88601dd8a67..30f82fb5918c9e2a8b3cce49849ff4fd7d97c2dc 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 877c492f8e108e2ec275415677f051d5e5101fc5..52c40d15567242177b40c5c60943cf63c18e3ee1 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 02243eeccf50d79b9175e085fa77069a3f349862..ea67be0223ace255de0d96af02009fc5274085b0 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 194737d60a22691c263daf1cba31b0f7ae189e0d..70f75d2e3ead086f30ac8de43ede15225ec0bc02 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 23ebcf6eab9f63241e3743170c168e2e38ec0ea2..eeeed01ee44a82a74235e927f155cce7b32e7830 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 fe581383d3e264d544a3bf02d142eb8194d81e77..f7d2ec5ee9a1282be6f6089625b97906fbe9df0d 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 fd3154ae69b172e0c4f6b2b803cf9896d4c9b6c6..b53125f412931c6e535df1e111cc293ae067a6b0 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 11e73d9e8928458adc5656add696d835cf330d7a..f129efb3075ead421bc204dd9bef3a4aa39ecb2e 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 d91b9be334ff2ff1b80078f95c1d805c0d278224..3ae52ccc793c5d7d47e8913738691902f6c882b2 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 6271d8556a40f32d5ef8d360bc6bbf8b74265559..fa6461423bd06baea45768ae23090315ecb94990 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 4b6012707307f99c3fdd0995544f8ac4741c8052..94584f167a8222b1a013bf68d036afe913615daf 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 57f7122a09191756ef9ef61577752f67702e170c..dc3fac3dd0eac8c40787ea8e3006e6a59ce19e80 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 88ac9768f1c1295a7a462dc3b27f2733fbe06fbe..e664b912d7bba72088b405837d35cf9358b1ec24 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 925f64711c37c7d2f37bc67bc31fc87264a81290..75d1f26e5b177055f352bfd2dc428eca39ee09ed 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 11117a7ba911e735f911b6ba5dea75d8bf3d2f66..df47322492d55b0dfa24f1f4912bd19968264c2a 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 5447e60f3936550c5bf13a08d40b6a6d0ebafb06..4af9dd948793000632caa6182636f9c582cb982a 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";
@@ -111,6 +112,15 @@ static struct cpu_table cpu_ids[] __initdata = {
                .init           = s3c2442_init,
                .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,
index 196b19123653a244bc9da318a25c8b6fc5977d01..f046f8c51084c6628bb437319c67f1d8f79dfba6 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 95df059b5a1db2b7430ee52972b83034e6b3f6de..5467470badfd32ca481074bdfb3910813b9f88ec 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 efeb025affc74f6e449aba2c728adfaf1b3cfc3e..c776120b99e68257fb9c38cbc146e1f8d5ed7d66 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 b6deeef8f6637d62c5e50387164a4db0ae1578d0..82ab4aad1bbe03ae664e176a93f5840a9467e990 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 a8777a755dfa52746e4b3a7ba4199ea5b1493d54..ff46e7fa957ac2c99f47d850865df8fa88b4d179 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 9745852261e03a7c149bbc46b83001607a2a9d7e..6ffa21eb1b917296d5db50ac4322fd75940ebe5b 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 44d0bfa1f4095b7e531b653d43a9a7f6d6a27cb2..9c96a130f3a858b02b33a3d66f1347623a2ba1ea 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 9a01d445eca8ed505570495e2f7d5b2fd46f021a..ae6a60f101203632f514325b1cf25e8c10ac1ed7 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 88f36d599fe895c858924b6b85581bb4d147719a..d27c6274247df5e74612c18d25ba8647adfe386d 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 aef0594e7865556a89af0d82e3dd754022c82e10..10064f902d201849f5f1c09b0e494b2230aee6d6 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 c281c6328276188665a6f32563c09ad1c99c536c..ed4f8c6db0cdd12778ca41d561fa0760a7564dbe 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 425ece64fd5e8449284b5dedbd17a933775b9af4..abdb2af529027877ade494101030808cab81ac00 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 fccbb595464a5f6037b744875a70e7578b53802b..5248c133bc686ac226d27b802fb3fdb736fd394d 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 daffa71576d41149da64014fce99a4bbc542d88c..a2ff3fb3568dcac95e486990e95c83ba36b4a66d 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 4d4439583396c5c263f88f577a0b6e14b22779c6..eb7c1441d8f9ebf846111f66f91c6ac03f38a490 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 655e49540e41d902b6396d5a2dbbb4ae594b2778..6f4548a1355539191e077770f090b548c3eb17ee 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 3e69106a4d37a893ce3a90bc941da5d15a6def5e..9558416d578b58f939e1969c268fe58da6c19331 100644 (file)
@@ -1,6 +1 @@
-#ifndef _BLACKFIN_BYTEORDER_H
-#define _BLACKFIN_BYTEORDER_H
-
 #include <linux/byteorder/little_endian.h>
-
-#endif                         /* _BLACKFIN_BYTEORDER_H */
index 477050ad5c53cb4665625739d3305b173cd80bbe..8542bc31f63cae7445482a4a46b41d797f06acfd 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 7e55549e180fb03547a0b3ad7903d2eb08444a88..af03a36c7a4e6e7ba04f7c875a70fa36b003e0a8 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 35f841bce57dd032e217d866837402570b426302..8778e0f03730fe9a5db7d2d1997e49be7f01b566 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 793581fc955610f574f604ac7f214fadda47f06c..a23415be0de1ae96950eaee94b9423ce792c9671 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 033bba92d61cc212d3faf88ecbf02513975c1024..f80dad5ff2577feeea61d031bf4c7776f6081623 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 f8a664f022b1ad1022bf7c9aa842e369124e4808..5dffaf582a22e9b6b1d3f9d9f55a09ec3a5ef867 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 d18d16837a6d6086667d6b31f03b196b6ffb41c7..fda96261ed6239997bc69d94b7bd6f3ef4be42b2 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 05b14a631d0c63a7fcb0d6b0d5e56a54f6244a42..f315c83a015d5b77827655345d264b3362a1c82b 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 fadfa82f93b2d11c3ffa3cbfa9324a10c4b94261..b191dc662bd802076587e30a31cbca61beef7a7c 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 6341eebff3dcff0f1db35fdb9bd9634dde76a75c..25906468622fc76147c22fb19ee98edc8e15f340 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 ed6b1f3cccce769cf62b38ae70cbac7c7c77e1bd..7a23d824ac961693d5935ccd757fa359f2cb8438 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 96e8208f929a77bd8091c147c145dc12728a3f27..925e66cb2d49273581ec44c09b9ffe339dab19b4 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 53a762b6fcd2a586a3840e0d322f8063ae9b042c..68a910db8864f95cb32d39238681bd0dd5f6db3e 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 c823e8ebbfa1973855103ab291e190cadc874f2b..8e0764c81eaf18df6d2e0ee0167596b2fdea5e25 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 55b808fced7132185f91c04810aeb113369d83ac..a6886f6e48194027f529a0380feb618eb1f2abcd 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 9c4037127857faba2310b27a98895f183584d675..8727b2b382f11207ae224b519a7a6da83aa109f7 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 32c4d495d847b14a53ef86dafbb478d906fff211..73fe53e7fd2417f6fdd18f01b32c10c02ce81a9f 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 733a178d782d0dd8e77e2c619f7b67d3271d2500..c1314c56dd1898d467baac3b9b3ed70fa1f8c926 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 fe139619351f0f243a36bf0b5c3ff590a62d19e4..5b44d05ca53e8a6f89b0e5d9c0e80cb095527309 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 0b78b873df5103fca28d39673703a4aac45e3e04..c078dd78d998b54a5e39889bfa545dc58b964030 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 37053eca200eaf7f1741dcd66caa0d5760c5db1b..d1f5029189a7dc194fd1a06bbe96bc52a1e3fd24 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 42a15f5ce0d08d9fefd8a47371e0e6c0402dc1e3..e7c0623f90915b8929dd3a89923daaea9e38f099 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 7d9e2d3bbede79980b38724e1d887c814137a20d..7fbe42307b9a4ce176be29458fba04b2769a20d6 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 79dbefaa5bef1701484a2753e871cc7a8c72d2ae..c87e68647a2b85048c7b915ed8216cc604d1f827 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 5a822bb790f72135862dcc0b7a97296954d73bd9..f7d6d47a048d227cf03c4862e24d599a186ffaab 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 dbfd686360e6bf65dd0aa0f5a7dc2f178b84f377..26f6b70b11e2d21dd9b19c3f8177b07476914ed7 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 040410bb07e1e5ac82c31095eebff76e31bc018d..4a3be376ad5b906cf7c7371dda02ec37be7cdccd 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 e3128df139d68a261419b0f997a9a167d31a6a92..9c1cfffddd9b2c832fedb0ebdffc6207c0e9fac8 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 5cc641c5083465ac468cb96b773954b945c02a3e..f726e3a80ad0795c4b34b7537e61e99f9db62860 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 afbaafa793f1ac86f4f46e13111ca468c34c420e..3ae8b569edfc416414e1608a5b47e20eeda7efcc 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 29dcf75c611258cb3d6b4d21e868cca97ba4f43d..944a07c6cfd6084500347ef3b440786d2d546bd9 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 cbaff24b4b25040dda2b82fb9d84397d299adaf9..d06a89b89d200f8cde528772433fdbf1c813a2f5 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 a6f95695731d99ebda1cb14e5823f362f53b5d26..d49bb261d9b7c89a2e6e714b62c8b085a06decec 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 783c8f7f8f8c90840f54667208eaae30952267a4..821c699c22387c2a607170a128cb2a962866360a 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 a0556671357b8d9aee8568d57abecd957352dd1a..072d8966c5c3cc4fe94082df0e00ee41cff7ffd6 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 88eb5c07cc24e14c8eaf345fb6dbc31bdc0ff290..edd8ef3a37886b1f045b0dabf38e69f906ed2159 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 80c9d64eb26ceb1dc0d427256dc78da5cbaa59b3..41bc1875c4d7fd367bbbea5432b9332a2821557f 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 a36ad8dac0681914dd067af2a6c1609d39e475c5..aea880274de7223f99c5049425c8c5a1b64b603a 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 e3f086dc7268eca47b1d7c4c72d57fa13a2d0f40..27290c955a7ae61dd6d0eb69bf842615667c9b0d 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 ae4dae1e370b150a3df989bd2fd403a6e8e5ba24..1f5381fbb4a7483897ac7006c8ead510268a959c 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 02cfd09b5a99d680728e04c5927177701e81ced4..f8e1984ffc7e3c30f996c0beaa319eb81d2a1d9d 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 ce00b03c27751a090dc312f8d23d3e1ca67d8517..ce4081a4d8155118f035f29e1540c7e5a0ae217b 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 eca4565cea376b76374d5da9b51567c785ae9aa5..3e81306394e20fdb4630d08a9f25b575a5f64b9b 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 118deeeae7c05ad1f042ffa4bf75eb2cd1112ec0..6a0fe94b84a62a5aaa7ee22ec810812c3b8f170d 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 d6ff4b59fcb195e03925a773373c2fdfd9e9035f..b0c7f0ee4b03e54d3d24004d9df75e1345c4ce8a 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 b1e3c4c7b38222f5d54acab3227f7544f17a35fd..be75762c06100a3b2e19255a855c29dabd99c120 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 d2b6f11ec231011672b3e6f68bebbee60d884cc7..2e27665c4e91956c1bb7cc7525c0815c4c1ab485 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 321f4d96e4ae481ff248eb1e6b36b64233c1bc32..d7f0ccb418c347e5d9bb7e15f2c0a131d9c1d5b7 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 d442113de515158f69ec6b4c7b0a3a31fc579fd0..89de6507ca2bbd38adcae0503fafff08b8fae61f 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 85e8f16cf8c2243f28c2384ad468fa0ffcff7cf1..dde19b1d25f51020cf359aeda42bfede292fd25e 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 2bbfdd950afc49c4623d876125b0a71dd7de4903..afb3a86263806ec830efde8d057767355e0f235e 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 89a12ee916d8555d12ef443708af395023815e5f..a74ae08af1a71a3b9f82dfe12056e7036244a861 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 312b596b9731f477ac1c2238ef7ad92478c626dd..609ad3c841891c0bb59cb9784edf113da932ed39 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 3cdc454cde23462c9f71914d03f19f7195da85e4..9fe0da612c09dbdb89bcc860b4b5bac4d78fe0bc 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 2f469a1f80fb255834901ab2637860fbda340987..c03b8532aad398cef7bcfcee584a9765c0bf9dc2 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 02b1529dad579811d5a85bd114d406e25c7f5645..779be02a910a8d9e730586eae8ec3b5488242079 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 f05d1b99b0ef4a7f2c3c29671f7b0b22a38fe3c2..bd32c09b9349b789068015afa3999a9abd720f89 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 384868dedac3771c2de63a42829129706e88f39b..1f170216d2f9b35f475db4a7fa37d9c2064a9fe3 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 fc4681c0170e5d43211ab183967b2c6c87af3cec..22705eeff34f5b64c4f510cc4a781a18d6afc0f8 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 36193eed9a1f03c91692e6bf24285e422bc02c32..f7b9cdce823977a58e944999f6cbb35b1d0e0bbd 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 8e1e9e9e9632680dc5c2e4b3a1dc9da8a54f28ae..69e0e530d70ff2940c468c5bf34e62ddd0cac76b 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 5d8ad503f82ab52ef69d29f4d980e2eb9ffac8b1..fd9a2f31e686f63ceabe2354b401df5c919bb1f6 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 d9ea46c6e41a581087ca26f4ecc07c25eadc4c76..5b88861d6183fbb40653d85a5dfbf11c52145508 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 64d78300dd08ac967dce85cf6f2ca229459fba46..0bdaa517a5017097ffd7e37fa07d354fb4c1e808 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 2f62a9f4058acbf9eea9bc75142f8990967d0c0e..e74e74d7733ff254ecb5cba001eeb28765be2c94 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 931c78b5ea1fc086ca43d1c03c62cc646e45bcf9..84ed8375113c27b2a576f3010ad98d0c9c54626c 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 3f8769b7db54bc775a916d6829e515654b178706..f27dc2292e1b5aae716cdb477cf44297c99f52b6 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 0d2d9e0968c834e314f53ad53ded7f889172bd74..0565917f23ba7a699709db2f9b7518fce24cc0cb 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 d188b24305364e4e348a592a2075734a8204a7e2..a88daddbf074b2185d54e279bfadd897a5b07549 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 c26c34de9f3cb096580d3d48ef9de3a728d9f975..118c5b9dedacf9fdbb9ed719dffa4c430a4af2f9 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 4b5fd36187d936ad308a1ab9db84eca03ceb9560..db9f9c91f11f926730ffc42df62a4daa4b840645 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 67fc7a56c865211cef10d339f0dc4fecac696336..a6dfa6b71e63c89fa45f2cd260db215cd61d525e 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 f5b286189647ff0f3fcd68ab1abe0d7e79fdc52c..430ae39456e8e1b5cbe9c2c5c6396ff921699722 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 30f4828277ad8782ab8a909c7d98e5f6770bdfb4..0982b5d5af100ab70f3aee3efbd780eb234175b2 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 369535b61ed1a3fc9bf844aab7d53fe2242ae0c8..c202a44d141696e2873edc1c9aa670396c91118b 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 8b8c7107a162aac193953aacea1b51bf92a85264..557e9fef406ac05529cc5fac410dd908db6db386 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 dbc3bbf846be2f4cf7197644fa287c5e9f8ed070..9d90c18fab23d1544e73659b96bb3cbd977139f6 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 3da60fb13ce46d8a45b5194e152985608c0cbaeb..afcef129d4e843fb3c81b27253356f55c76bbc50 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 f9715764383ed145d23b2a0caa1bbdd00fdfba58..359cfb1815ca77c00c4adcebbe1101a7e76da227 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 adb54aa7d7c81a19eeeeb25f094179224a073a78..bd3b53da295ef6745bbaf365a239617e1bc9b4d9 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 56464cb8edf3105e9a105a9e823eb22b3fead290..6b7325d634afe28659aef236303558be7a1f2967 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 ffd90fbbc8f967bf1a09a89e8a71b1c19580901f..10e12539000ebad641207ee49daf7e9ad5b8cad3 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 a8c279e9b1923eed6560e00789fbfc3645bea775..ab69d8768afcfe560042223fee64be89debbf591 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 a0d3419329ca5a6ab1a795c981652ef0cd1f58a0..b5b351e82e10758da00dc714f800f17a729ab009 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 cd605e7d8518c43ce400cb3ab9be75e4b3c26244..c62969dc1bbb4aefea5d146e30887ac5f6cbe1eb 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 2ac59c70dd94276bc7c769146bf763f6f4b3ba4e..f89c5a49c47b665ab349a1f39bf493148e7b2a9c 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 9ccd39a135ee7b6f91adac55d0e51e3e1d76a104..724f07f14f8d0e1ebd0ef7bd8e3451c18d5311d4 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 e57bf6fbdf3f4040bee13652a35c984b8cc45d85..53f1741047e50f6a06fd92aa25055f3b305cf61e 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 5da428134d32b9f75cad800f42c8bf332ad9f908..542e40f8775f73d48dda644175776a80084f0fc2 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 219fa2877c62a9f0ca096d51091838157bd57a66..ce5b9f1a8267eed3c6656f5d027935353713e688 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 e654a18a0754c861f10a9fc049227060a8854cfe..c31bf22aab190adcb35e187ec258b3833e4a6943 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 33f8653145b7e8bc5c68c36dcd231a9c49dfe064..80c240acac600a37691f73b3484c1a4c0962f620 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 8159136a29ea2e355ee183d189607d232d14aac2..c30d99b109694bcee489a51acc808288a38f7b2b 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 ca1dd3973b3958424a6148db94217a1622eed291..8b0c7d4052af1a9483ad2c9fe0f9ff01193dce6a 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 abde120ee230c5ae406c692548f72d86ee4afbcc..953a38a1d1d190cabf1e2750f390d8b856e8d01b 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 4685b7aa00806a7722083e0a117184082ddf5cef..250f4d4b94368c6158917d701dabf12026f9eb0d 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 e383cd3eca5d9c428e605b144290b4477b57bba3..99ee8c5de38b3e5ec4ab3916c810454e980a1e1f 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 58fd96d747665fd8a2f3c8568de1af547c970213..97e904315ec6491bafb121ef79749e8d04b67645 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 4f2b76ee76265fc040dc2a51f8792f3933190ba9..168eba7c64c8f02fa57fbf456f6c3bcdc54cc713 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 67b799351e3e845ba9da8ff0100d9f5e3d2010e3..051824a6ed00b583005dc954fdd72d8c46d106e9 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 03e4a9941f019a3abdcbb5aefcaa7e9e1b878fa7..01975c0171168a656a558c423da183534e2549a7 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 698e88ca51049039d7d5f0544b5442e95cfd4ed6..78b43605a0b55ebf7a3b628c47fe85cf06ef67ef 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 78da1a07ee73e03f67b23830cfa9c9c6be06a4d1..856b330ecf0b3fcd08cacfd563b00389ce24b909 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 dbade93395eb2b996e1467702504436a6c97c958..970d310021e73639e7861e75b91aeeaccac549d4 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 83421d3931482e2d3da1c4ed333107a76e566f77..6cfb246aebecc35a6307f913ff3b19f934587e3f 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 820c13c4daaab28a4c36ce43fc44a2274b2d97c8..493020d0a65ae39495289390246c84b6d5a16ad8 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 dfe492dfe54eaa6df09388780f22fcd2aa469a0e..e1d99911025d73e555f85cda632ad43ab20734cd 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 14df43d4677ac1dd78d244e2c6770aa5dbaaeaa6..6b364eda4947f5ee7637e4e23b01b5701ac010aa 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 bafb370cfb3c4c810fcb294889c015d2e451866d..929b90650bd430c9ce0949cf09a6aad86f533d0d 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 ee3d4733369c15fc9b04d48297ee8eec7a4bccbc..1d970df7aee94cabd8dc46503c077a8a1b67e6c0 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 a96ca90154dd24324a5270c5b82825ccf7b512e3..9b505bb0cb2dbcaf6182fcbf5f389b94f3cb27bd 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 56ee5a7c2007938f104a23aaca922412f7d077b2..b5adca23a788081498ac838acba6d2469854b886 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 dfc93843517d2e4f9fb8999dc0f6d305bac021c1..7eb18774d7279a02428548f7e7156a7502172d25 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 6e982abf4ede738584647b8d8a9c2d0f7bc21688..794cf06eb5bae608e95ee1b56af9d30699293e5d 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 1bec8d1c2a73cfb00604f974c175345da77b1e1c..e06f4112c6950500e8aa025ed319ec7a39690975 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 9757683c3948fd46b1b6e96b4b2df453192ee0c9..bbab2d76499ca0d58b15041f4a474422d4bf813f 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 3ff0f093313de1d0188182ca7a3ea853a25cc843..14e52ec7afa5093d643807361aaf33e3711268f3 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 a0fc77fd331518f48039f76dde51370581883bba..e352910f7f994fc11da036e712f53ba2396ee959 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 3151fd5501ca384284de936c0530ed506f657008..bb05bef34ec08e2bbe56754d119ed5b85a6643b3 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 08a3f01c98865f15e43bf97bc97bd6d2bc55ffd5..f1996b13a3daf1844b598a6b45cb8b7c3c1e8c10 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 68b4c804364c043b2e81273a6315f3b4091f70c7..cad23b15d83c5ba233db0ef3c275a894732a2055 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 2849b09abe995387cf279e1c30a4dd4095e804b9..f09665f74ba03053d79b53901a9b7249ad4142f3 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 231877578243484ce446bbe308086d4594f2fa71..7bc7577d6c4f3b0b2c6562fc6c41d564572c6684 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 3832aab11e9a743ff33d01eb2463ff8d451108da..ff68c889708785059fe1fded470556349f4369ef 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 ebd6cebc1fbc40bd500b6df924b05fd81b1b53f7..c1d55b878b4503424623909a13406eb43cf87125 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 ea9cb0fef8bcd677a881d3dc4ba329870979857e..e7d6034f268fef5f876b3fb720735e046abe5e16 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 663c2bbdfd91558ba7f846fe8044bd65ba4da670..1079af8c7aef190b050570b956531797457015f0 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 00377eb59b75aab122b610196eeec685bcaeee0f..dc3119e9f6634ac55d58957008afca5c3a4e7da7 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 fca8db70811975926e3796e7f54698707b982a1d..d6579449ee463b182254f5c77d6d219588b18859 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 1fe76d8e040322564fedc62a9f333ae581a7d38d..7014dde10dd6b2c122fd5bcfb5caf322fcadb026 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 0a8cdcdf0b495a7b66386b4c091b6de22a503088..cb139a254810431e02788baafe91b20c6e85a479 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 5cd7576fef764bd4065197ace4fc35190658c7e8..82abefc1ef6cfa49e85374256c36e462003e557f 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 f040f364afa323330f80e2027aeea567fe965e27..570a125df025b5916004dc7131362300a5ae2f89 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 68b55d03fedf58f0e87b76b6d85d7912fd9e78ec..f821700716ee44f891e2d5c64a55eb6b04ca853f 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 06b6eebf0d499242ae1a175aedce1d0c3a024c56..104bff85290d0d9fbbc3382451e30b6555b9509c 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 8ea660d8151f889733d89e5e2eff5619eac535c8..aa6579a64a2f0dccae0a81f66a5886680934e773 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 72b1652be4dabe6abd500ba11569e411ebc14600..d4518b6f4adfb53b27f0d019114e329d550a3663 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 f8c8acd73e3099d3cccf52e8ed3fefd9605121a2..44ca215bf1649b24e343e6caf67387fa0b9e3a66 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 6c2b47fe4fe4254339a5cb0ec64bd488c8a87778..43f43a095a996744082b35f0c24152ac0adcb0cd 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 8208d67e2c9766cf3c496b41dd09bab7d99f2016..b580884848d4175aabf31afe9f0008afcd858d67 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 7443b26c80c5df17eaf7e4c20cd45a3ca3acb790..7fc3b860d4ae9846bc07a5601a4091026ad16e9e 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 fd518e383b79ea8b3aa3657c39c154fec757c02a..d4689dcc198e6b5073b3daef3cd0f1f3f1f6c022 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 f19b63378b1299ec086b0358bbb3261cc7c9e113..644be5e5ab6f4008568c69ba35dbf595fb53cc69 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 729fd7c263360be6bd10a3dc80333cc64e223095..82f70efd66e7106a541bc8dcfaccf42d247c230e 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 7a443c37fb9fd8d6297a280813bfbb1cdc84d677..4a14a46a9a68dc589e138e82280dd809f6b78c56 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 cf4427cd3f7208a7cf2da947b40fa8f54f5b4ea9..e3e05f8f7af92e84417685cdc52c589fd22543c9 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 6965b4088c44a5d09bec394dadc286320be60303..9e1f3defb6bcbd6b61e04938e7fe47f0f619cf35 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 499e897a4f4f17fc0186cb5a7fb6c541bc99651b..f4bd6df5d96899c3fc1889ac2a984347085a418d 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 bbc3c8386d48527096218588a3f8f8db0c46dadf..feb2392c43ea0ad68e3aa31fd2c40299d4caf0ea 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 7f4633223e6d49d7aaad50dc91a6c87874c30029..02b328eb0e073d0200b27387081f18bb8c3d5027 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 e45c17077aff4b5ff84baa35a321665c7e573ff2..2af19d69a7a7d8c3f6409900ef0e443c1afa456d 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 db1e346cd1aacc24bc1a3f989a56357e1e666e90..c31498be0bbb48a9a244e70bd503342daac33a4b 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 2f59ce0b0cb5400319b64b61176aeb96f239bf7b..075dae1af164627a77cff02d3f77f798ade8ec15 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 f51994b7a2b9c06ce4179b57ac01ad7b39f34471..8f714cf8135bd23f74a405edc32307caadc513c2 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 87acb7dd2df37a1cc1bf3e909acefa2379e195c3..c85f4d770535e5c838a8e94fea1452a9db3c9d1c 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 8219dc3d65bd8d88a22e80b49c343fb9ea726953..ea11aa81340de555b209bff8db92fcc09b041418 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 399f81da7b933f5a189a3aef59e4f4ece80f7d5c..0da9272527013c3a3faa2d435cb610f3f0f5b784 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 10b35b838bac659db57f841a0043101994523960..9ba290466b5695775ec00ac26bfb69029b778dc1 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 9db6b40743e0ff052ffc2d6b124058332180b6da..c46baa5e6d9b22e047165f67c1e016b5da665775 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 61353f7bcb9e006c8c25f2a4504b125ed8a1d92e..57163b65a4f5d230463d8699e22d4a3253d37d75 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 d23fc0edf2b956cca2e15f63cb7e832f55c0dee0..5c8c4ed517bb77fc02c5268299008d2b727b0449 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 f194a848ae8e75c18f191aba79528d1623a76837..17fab4474669e7ee75bea250d772117432123fbf 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 e95d54f9af6c008075cb9529b47e066ac376cc4d..635c91c526a38fe324bfce4b67e98bdbb6d69adb 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 9ee8834c8f1ad5aea3ab88b908eec58064c54370..eab006d260c5daf513c6d8e9def488a08da350d9 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 5f8b5f845be60d3a43323c1593949c086faf9f8c..91825c9bd226e1914acf714d7f6983a8c14a85f0 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 b8fc949a991ff17fa0fcab605e2baa96e2bf9cfd..9363c3990421eedf5dbd2d2810fc697b74656464 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 a3227f9003fffd8a11cd230d6c4f1e4fafe2bbca..cebb14feb1ba9c1e1f51d08180e823452ef24be3 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 3d6c83e31b1e46b085b17da6ddfc743d06d9b8ac..8cb5d5cf0c94d9d73f66a9353ffc9b215e507ff3 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 d77a31e45a30f8bc9272b511f8fd737a3bdcad22..104bff85290d0d9fbbc3382451e30b6555b9509c 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 b2a71d5d4e5fc22ef3975435e87c8a78c5a39794..0defa9457e7f91edd607bba27b153df21581d380 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 87285e75e903107e04d1eab8e168c6c742d0b218..da9760329e49aca39542cedcc35146f8b3f6f91f 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 51c48087e03be767247452224a180de11f15eda7..f6500622b35d0eb85eb5e788cb7696deb4911889 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 f2ac3b0ebf2467bda9532e1ee3085308f183dfd8..14af5c2088d44192f70b383e6ea9eb3ae2ec18e6 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 d6837fbf94ea4b22d755071b25a58f41a4193a47..5dc022589214a0d846374fec643a53e7febe1061 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 9c8abb307908d002e5b2fdd750e23a62e9e6e0af..0cf5bf8dab840bdb554df11773c77d388da5f09c 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 999f239fe1a6376373efe75f5424398d48308ee1..5c148142f041e9be76ad5f0786f20166149b09b3 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 5ecee1690957476ad01610c6435253da3146cb60..278e8942eef23e4df7e6dbf90d8bc6c0980556a0 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 1de67515dc9d3ef7f4fc8b89e9fe290d4d9dfa43..401ebd79d0aae74f3a5b70fcc21183fe406e9174 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 1c58914a87406e50f60f14918d35363058b78528..5f6c34dfd08e8faf8e1c181731280f795d5c058e 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 30f4f723f7ccf8b5b2f01fd06e5dfd281ab3877a..295c78a465c2476eb91a05f7446da7c2ea5391e7 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 fdc87fe2c17468830da8868a5906f930caacc289..a4b7fcbc556b5fe817be7f1dbfe7cd604555d128 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 c8db264e3e4d83779f17faa2e543470ae9d5ad2b..6121cf8b5872a63f110d7c457313c100fb1080ab 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 70d17e550e05292895e7d87956c458f866f13151..1fa793ced347f26d9dfa1b5ffab6e818997fc866 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 e565aae11d724e79518cbe45233129f1da227ae4..ccdcd6da2e9fc09f00b7e1f19bb2b26bbfbdccce 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 c66f3801274f543a9e004b7a756f847061b131c4..1a5286bbb3fac68a4fc095fd494d0231a0a5608e 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 d9239bc05dd4a945b1a0ea6048cfff2ecdc510f7..039a6d9d38f3c0c6a5fb50149a88e8362942521a 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 cd31f72bdd820e70ad22732d89ca17a9e45e62f1..7bead5ce0f3b8712b453bb5252821da86ca4d485 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 9c7ca62a45eb09621f2495021553ab9c097a7ddc..8821efe57fbc7be2a5aded6b7e9cde9d6cda7c60 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 1fb4ec77cc2596d4d9c7e7cf6cf1d07e9a35a865..49338ae299ab759413ba7468533de4ad7fae106d 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 2d1b5fa3cca04dece182ba61115674b3d868cb4f..dd44aa75fe72727ae5e97668550b80c304359239 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 318667b2f036a021d364ffe1c97225449202cb20..13302b67857a50ee4dd424480e64a5689381d75d 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 07aefb9ed79beaa20faf688287c6b4719bfec4d4..42f4a9469549ca317ae18aae4f82e529145c5fba 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 431a69278991af8bd08337fd7c8bea2c18ad0061..2207799575ff3d558cc153b7bcfcbba8070b4495 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 93376e90dfc5f81e79b0fed860500c852d999b4b..42342151513426a33f8f27c370fbe24672d8f193 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 9cd74384136fa92d212d68ea124af5ee78603dde..df84180410c45e2d0d47799050ca49a9e0159ed8 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 ead360b69dea8a0588680a34cbc932a232de0d7a..34c84c7fb256a7d28bc7b03ef4cb861710dab979 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 6e636c418cb0364848b2d18380f060c96dca4a0a..a2e9d9849eba22ac2b119c604ca124188de05e0b 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 b1316541b8d694bc2d27fcdb41e89983547e2427..d3bc6d1df547ef61b9e0c92ee32916c03c6e1e52 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 c2c785bdc5fc11b3b4410d2a006ae02196501e01..dd414ae4ba4cc317b1e89684fde4676269a00466 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 661f0d877bd13cdf9938ab49fc1fabcf589e7ca1..5a9dbabe0a68d6191a2466e06557baa63fe582e6 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 85d4bade911df1d8d988977577731ff3a9bc5aa1..82cd593f73911acb219bf2ea51e668f962855662 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 096734541644dd9c862cfa587bd939134c1ee80c..6fc6e39ab61bea0f46836902f26e62b2912d0d3a 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 e022e896cb1839717d4ea92f6e5dca3e7b3c0b73..8590c8c78336269b132df9c5b203f8921bd01a19 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 3a2051709787d0c24c8c5b33292a8b6b30014290..850e39d193e3f159bd3064a1bb55954b471c7606 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 f194625f68216375bdf720f743826d31e28d7581..106db05684aeaebcaa67afc497e4ddb75a9066fc 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 ce372ba0f04644ff4c8e7b79060973265608e8be..89ad6a886362951bdfb47acea7eb79a2f34880bb 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 9dd0fa3ac4de39610697177c035282fd636528f6..48dd3a4bc4a5582041065635f2ccbda0178df882 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 9439bc6bd01fe66f5e527f09a2fd96f802570feb..0261a5e751b35189d79f5684ff227f6552145ff3 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 6577ecfcf11ebc5476270aaf11ac6f72bec9fe0c..dfc8d5b7798612b7741cb33fc94fdc08ebbe053e 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 caed96bb957e26db1ecbbe86d54a9e968cec0f07..9e2d8cfba546c58e252742f36e8dc11a27365739 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 6f77dbe952f5e0a759b87acf9d22ecc48dc185eb..8ba7252455e13d8960a2acaf3b4839e3641256d3 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 42b0037afe611805ef11785e40678c3e23ffd1bd..c938c3c7355d86e52aa87a65d4b4226014dcc925 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 9968362a2ee4acc3bdae280e7c947e28defc3307..9f9a367e6a24e945c9dbb4498a1b06d78c4ea13b 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 fd5e8878b8c419f73f99b84d89a5db7b96748173..e33e158bc16dee500692284b508e9f5dde8650c7 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 8be31358ef8817c43f061ebc72456a80bfb3cd27..67d6bdcd3fa88d04463477cb422e9ebe435e14ab 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 9d9858c2be68bacadf7a5f78ca228c9175639a6d..81ecdb71c6afe4635f1bf6bdd010c5af8418299f 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 5fc0f05026e093a7f4cb74fee1b41f6fb206e2c0..a31e509553fbe8d7a408e901498a62351173df9e 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 7882f79e1ade66440cd1c80e8cfc0f251c141b15..a651a8cf805f34779105dddf6dfb81ce7bfbc220 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 6698389c556451c51306b9dba7ed2f029af73416..7b208db267bfcc238cb69fc3fecd583c188e7b1c 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 2e5ad6347dea74738fd56b3cb04cf8032a9feb3c..3a7b46bbe84969f2897f90594376ab901ee936e5 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 f9e65ebe81b2146c25e98d4bdf86416dbb12140c..390c7f4ae7b331c3b20689b044fe9b914f1f657a 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 9d2f2334472088876cc113376095c10c4dd0721d..b4424172ad9e7fc4a7a2519f6a227fecb7ffdae9 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 f72a6af20c4fc21b05625b14b10661cbcf4eacb0..8e6050369c060b6d83e960492975e98ec0ca2be4 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 8c10701c251f4f4ffd4962a2172b323146904465..510f57641495b4bfe900679d935665b0fb227335 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 5998d8632a734f7d299629dba090c2d0712e21bb..9dbafcdcf4791e3ba7eb8522cf1b6de911c05b0a 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 4ebbd78db3a4e8cff1a3c265a79afd62f387c1c8..a60a24f5035d3bb0ccc30a59bd073f611c9a5f85 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 d9666fe6c3d6e4847db784ae6d3f2ab1bb14af01..ea540318a228c0b8fc5dfc35da0c695eeea64d02 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 85c658083279715a2d9c3654e6a7e4c7d7af03f1..01506504e6d05cb464234febd43dabddf66e420e 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 1e7cac23e25fcd90d26c657019f08a6ee9182b93..94a0375cbdcf6afd5833e38389fe75fbcb0bc089 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 9c79dfea2a53b42e94286b0bf52a0b947c29452d..cab0a0031eee9b0ed13fc682c0186d13c578d622 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 82d417ef4b5bc2933a75f5863ba1c68d36c14dc4..8085ff1cce004828ff83a5bc2a68aec0afa59636 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 6ffda78aaf9d57383dcaa1747f7c888d3ea0ab5f..660ea1bec54ca28041e6eaa69ba3a23f4d99f290 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 883e3241b17eeee7f66e755fe7d4e88c9bbbbca0..c6496249e2bc253434d7399f980aff7c5cba3d74 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 0e3d4ff9d8b677ff22ac28dbc9725579b5f13c69..8837be4edb4a47ebb90501129d2aa69fc725486e 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 349ee3f5466a8dd089902e335e765e1492563509..d98585f3237d5114f9d054e386c64898a13ce08a 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 bc0062884fde3388337a30a0c0bf4b833e04430a..fb0b1599cfb74758b0c7eeed051225bb082e0db3 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 b88ce7fda548c7e76303f842ad485fd173c7118c..bb9c98f9cb5b5845bf2caf87589902375a01289d 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 beb1a608824c1f7c47225a493158477503b9ce76..84cdc5a1c139bddc5f81c7e2ac17a8af112ed45d 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 eb63ab353e5a1efdd5a124eade0fb1b355de4490..f068c11ea98f5ca6c53568b4e7cf2dfc3a363a1f 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 6b0a2b6fed6a9326ab8f4d28955cda0bada96b6a..0974c0ecc594817ee9d8067aeba0eee7e3379dbf 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 30bb930e1111de62dac9af626b6c4b24dda0920d..239ecdc9516d042e69fc5b1773cfa2fb29fcad4a 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 b61d136d9bc29b09aa5d9e2e5e85740fe917328b..474e46f1ab4a0a19527ecb2b2a32b05d520a1400 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 d2877a7bfe2e2db079d396d413a423aa8469d9a0..496ac7a99488cdc5721a2bedf378e2e5d6a9c60e 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 6db08599ebbc551a372782a90dedf730ae2ca143..776dd40397e2f9e447bb036166b548dd77b03ff0 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 f426dc78d959261647aa9a5c47b6c57af4e71df7..ee09d261f2e6c0be4071e1de30aee0339d6b9706 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 7de76dd352fe4e6350ee0a8bf6d366fe05c66f35..c0fca2c1c858372493675695f9a5341200c139ae 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 25831c47c579bcf3f3059c5bd914dc22e17f6c98..308e6595110e4e4f6aa03047f12333dd83663dad 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 4c7e747909583b5de652d5b3b73507a3ed6a644c..55ac3c4e11d2e66ee8e707c1f25ff71c08acd8c2 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 1b7598e6f6e815fd2129146a9925cedac2495573..8a88f1f0a3e2d7faab1fd065491340f076ccd82d 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 29dd8489ffec5efb617a070df0e712c90ba3095a..ecdc19a299b2333c335790a19eeaeb95ebadf853 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 594ee0e657fe0da77cbd20740c202b044e0d7ded..9a8876f715d81d73214c97079d2a601460fe6234 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 f56faa5c9cd91a06e2c24e153c3fd54fa72a183e..56043ade394197ebb011fcfcd94a50df9d181179 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 b1703c67a4f195f54203e8cbeed93c3441b8d9a8..f3236d0b522ddceaa39a9a468b7cc4f02d27b5d1 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 0f41ba82a3b533d1ff6a3815f59916c6d3e5f77e..942397984c66ca685bd93e1d559585ecbabf71f5 100644 (file)
@@ -17,7 +17,6 @@
 #include <asm/mcfsim.h>
 #include <asm/mcfuart.h>
 #include <asm/mcfdma.h>
-#include <asm/mcfuart.h>
 
 /***************************************************************************/
 
index b1aef72f3bafb23dcb5e3285be12029de801542b..9d80d2c4286668f2715d64a5026026e5f98cfae7 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 55dfefe386427ea875bbf96b39dae967095ff514..6d3460a39cacf1383a16f2e66146c60aeecf6509 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 3b471c0da24a0bd6232acbf98d5b7b6b0135217b..dd7d591f70eae6df0af6504428f2afbba503140d 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 acc1f05d1e2c04665f2224d91bb9d61bb9929e48..e3ecb36dd554ebc3504e08ac369a29359e8c304f 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 6b0288ebccd6674c21c9ed0bee8a095903507412..2b86c03aa84187cb5857974fba2cb949e349ce93 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 4201c743cc9fb33e17a52ae057940345d79e2681..c592d475b3d890a50061f8f3b265c4516457d749 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 705a7a9170f32bc5aec7cc30865d1ace7eb1edf7..03bd56a2fb6e5f02a265111ecbc84bf161d13f41 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 c88c821b4c36c00398b66b8a53fcc1d75c07531f..d670928afcfd50251ab39453ff90fce8cacc8cb6 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 cc32c69a74ad5b5dad3247ac4f05bbabdff105dc..45b61c9b82b9a8672d658df5fd2d9be842ccc578 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 e2278c04459d184625f58a9f939a205c08913d81..835f3f0319ca77b7b8be96e4babac9db16283c1f 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 c146d1ededede3e4a0eeeb37e268dc3472b753f5..00064b6608096f1cd8722cf832cae7b353e39eec 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 78e155d21be61cdc8c59c4cf84395d6f54183805..05a35cf5963d4bc075b703381ff7d7cf61bbede8 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 6dc43f0483e80b8fa77f23694daa7ed7da51e9ef..70378bb5e3f93d63b8dd3e631307742fa2491694 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 5f3d89c4a988fa36c2917e5370fe01ad92153afa..b0519461ad9bf5754f72b67231e6bf01495b7e4f 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 b18a0ca926fa3d5ad326a662e11f8b090ffb2fa9..d0056598fbfcac2e36438dda2940b7cd0df7194b 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 384f1842bfb1a4c0743979f55ec40b07b4172abb..6f2acf09328dbe00a80215cc84acc6e6739bfe50 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 32d51a31dc4803667a690a328d76190eb08adf81..c198efdf583e88dd6d23c5342f7a7cc170e5178e 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 efeddc8db8b1ee15883aec8e23fa95c7e905217b..0b89b83e20551cd05d072fd26a8b56c834c62efa 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 36fd969d64d6fc83a1b37daf5a22fe3b46c504b1..c0cf76a2ca890a8ace9f0e4caec0377eef7bd8d7 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 a8f57341f12364eca41411cf8041bbcbfa176bea..9b9436a4d816bfe7f26a1eb8a7e7cb677507c388 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 de71694614de85e25cc2c64319517ca73e5b5219..21cbbc7064481d992cb999c1849276e84bc0028b 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 feea00148b5d5fd813956c0d39b73cb3b157fab0..91595fa89034eb20991ef0723c09d55d6f6d6f8e 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 f6837422fe65e201bb760a30e692b81f71a1cfcf..09a59bcc1b078c4a0323e16f21c4524e55d25a4a 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 ce5b6e270e3f06eb4257d89277e779631d617b2b..9947e57c91ded01216ff49274df87dd96cb19129 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 d9743536a6217c09e413fec50ff00647e842fadc..6083db586500ba14e22f94acab819f40e13a158f 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 e600cedda9762dac44ea7975f8bdab18d4ad2ba0..50511aac04e91de24f7565f515ab63f99476d1df 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 8ce51757434051d6daa0af76a5a8dd5680304096..15278dbd7e79efa624b7309e1f2cabd5eb61794c 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 01cc1630b66cc4cf7f8f7a0159245fd72e5bf893..845da2107ed144379b2e9bc6761a169c30ae9f23 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 7fd170d007e7587d4839abcfd1f48370285c5c34..7bd32d04c2cc7c0df7867d8e7f6a81385f38ebca 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 e02f79b1eb516f3213914fe2bc5fb3dec909b5c9..bfea327c636c1e635089f19846f14303d7d5911b 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 6996da4d74a276ed1d61cf07459fb7ac82dfd7db..00a4da277cbbef1b94b6d0f767973fb19d3c676c 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 92351e00ae0e2ff3f98f8d7432aebf88d659966f..f5d265eb6eae7f5708e53912d06ff63b4f7cd42a 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 2652362ce0477d9449dfbd6fa4a0f7e48a2f0ef0..b469ad05d520c3629348368a3037d07a0ef7a631 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 ac5903d1b20e3490bd7e3f0cc02336184c5f7777..da78eeaea6e81a5d6fc7516ed4dcb04195d143a2 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 0037f21baf0d788028ed828c4ac14a3245191615..218ee6bda9353822e010b5ba8d521b96a05991b9 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 f709657e4dcd104e3fccd3518658d4478122e484..7a51866068a4796631cfd4132dc07d7918dc105f 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 531ce7b1612479305c05602def67bd7e100f7992..ea695d9605e99e1bda75ca3573722a9a3819973f 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 f7d8d5d0ddbf0337978cacacf5232b38bf4a87a4..ed5c441615e471cf4b4c1888bcce3eec9c84e6fa 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 d2072cd385922db78c5b1278622ad4d4243a4949..b181f2f0ea8e71709f331c8ee32a7f6792999106 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 6242bc68add720f86d66698fe544af7f08a23c1b..b77fefaff9da2c5ab49f12da5ee069b754b5db5d 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 9bbf9775e0bdade7b45a1cf227506cadb7e33b22..14dde4ca932e287a9ef312f910c68fd87f3efd6d 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 4d181df44a407bc487d8362ec12640cd2655b72f..24630fd8ef604729c1d36d8f84788f033489b4c0 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 6ddb507a87ef68faaf7e54b56e9698c874aafd22..1821d12a6410b7b01ef2ec63e2ebdfca793f721e 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 03092ab2a296fcb89472f89ce45c44275bf922d7..60477529362eb004945808cef384ee30ed3573f6 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 f368c735cbd33b4389aed0f1f666af4fca01fceb..b32b4a3e513772b94b7376218ceeaa699631bed8 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 1c555e6c6a9f8efdf20203b77a629c22e369af80..d9ae1dbabda700f2cf20b642476a62efb5199b26 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 770f0f4677cd5a8c542f670396872afc1cba4d69..3175477d36f6a57690bcbb5535458d29550758bc 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 15aa1902a788b4d83fa74833d9ca73a60ff879f7..8d1f4f36304900fa5bb33d23a31a4cc4deaefe94 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 df9e526312a24ce4772cb3a332dcab66c3927a50..469d9b0cee6dd16f80d402d5cce6ae73d8ca245e 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 3e0a9b35ba5cde0019c6b6efa419f1a91613732d..4c3fca18a1711b4c60241b2dbd95a1902a2afaf4 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 b9743190609a0aab3d3effffc8d5ad4d746871bf..2fbfa1a8c3a9a96a4a2bc159a9eb8c986bc4297e 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 f080f114a1bf6d343baba163b88958f9ee406cf3..7aca7d5375e5cb4917eb23c705c18868cadb2f2f 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 18b192784877d9f8f9da3bc46174d9d07acce5bb..8836c6203df0994fcdd1084fba3c681ed7b483c7 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 deed1d5d4982b1ecf5bd6f0ad0e66dda7583b917..575cd14734759314f3da89e87705ea14a224fbf8 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 6d0e59ffba2ed17826a13d475961c7c10fe82c4a..d6802d6d1f827a21b79cd0d8c4fb54b29cf7ae4d 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 62df6a598e0a6a33bfe45dc2817280aa068ce07d..f3b60e671207bea19676fd1c0cca9a4a38180ccb 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 c860810722c0a1450a47a3268e9e520e97712efc..e10184c1b3e14cebd667166503fc67297087b257 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 f388dc68f60544cf941dfd66267b2a6f7167db1f..524d9352f17e56a4120008d601d219590fad6a23 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 de3fe3a18229a23e99cea0ec2ec6a7cc7a9e6669..6fec4d4a1a1831f72650cabbdc94c89d4eaec2bb 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 ce93133d511243104080f57a2fb6be59e415bd86..0d68184a76cb54006aeb5142c54315564eabd7aa 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 302f68dc889cb0e3c5ddc04a1a42ad19e5e58998..aead40b16dd8f4d01206fba9a1a7b5328a321de1 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 ac775a76bff71508a939a08fc983d9d4b8e272f5..7ecc1039cfedfcb130c83da82fd64ed325b68364 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 699cf8ef211816576c5ee10d29c7bc67257580fc..fcd3c707bf126005c3fdb75325a65540890f9923 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 8c4712b74dc13b626f449e699ee31aca15701315..3a44f7f704fad67792fa0cc6325060adb6db933c 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 330f536a9324798afda4580d152c09eb3b04c141..2e7610cb33d5be4afa18daae6a5f9187078a2bf4 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 61ee0eec4e699b93f3555770c18bc2b221c8f0de..212074653df7fc5a109da9222137a13226cc7bff 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 927db3668b6ffd6bec55e8a1b90d099f5cd7a1dc..c4f49e45129dee568e4d75c99e26934fac16e523 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 8eb3c63c407a43e5aaac3e96654ce391cd8764a5..e8467e4aa8d16b054aabac097bc19210ae4a409c 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 59fc1a43ec3ef094ae514694e549ab6b518aa05a..f5f96021caa0deedec2257af361dc95ba0307ea5 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 775be2791bc27e1313e73bf49d1e4d1ee8984dcd..fda4baa059b5002a99f64fdb832cf134b20756ee 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 d5aca31fddbb5a59e8d8100750167c12fb13f38c..13b6e3e59b994762a7efb47483c4b144ca0c5feb 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 cee8080aa2454871cae0f54e39f3c5afab2a2773..dd3860846f156402ea47bc618f6225414d31e3ba 100644 (file)
                        compatible = "fsl,mpc5200b-i2c","fsl,mpc5200-i2c","fsl-i2c";
                        reg = <0x3d40 0x40>;
                        interrupts = <2 16 0>;
-                       fsl5200-clocking;
                };
 
                sram@8000 {
index 4c36186ef946ebd831a468005ae843f18e871f1b..8e9be6bfe23e46a40dd78072054536986a1b1785 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 de30b3f9eb264b60582a9836c873dd2a555c2d5d..82ff2b13bc37905deebbda9816616a2d92a0ee61 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 d13cb11ce623509fbb39baf780ede87958a2a532..e45a63be3a8618f73b0ed0921e81cf4d755dd2ae 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 e297d8b418755e67c80597a2dcd4cfe3e96a2a24..0c3902bc5b6a148542316fe4d12f2b46d38743e1 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 7be8ca0386766aa6b31a5f0a1ae7fa6eec4c291b..6ca4fc144a33a6b4344c1ee02e70d6bdbf04a7d8 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 c2b8dbfab79e6dc1e4fa5f4b365a06d6f103776f..c353dac33416a705ef4872b00a9448a1a2792cd2 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 30bfdc04c6dfacd88a9c6e325e873d75a633bdf5..8a4ec30b21aeb3b6d55ee7eb5cb455399fae4ca4 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 030042678392dd7b37e0493a97c3ba4a4bbbfbc5..85d857a5d46e4f3a1409cb94f820028eccb0ddbb 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 c9590b58b7b0ce6d3d6a3136f588ffe9e0d2031d..1db07f6cf133cd1779c4d85903a1d43379632f82 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 3838b77b8116d1938f6e39be9cf2b177a713a810..0396ce7bffc688eb2845a2cacfcf50467149fb96 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 29b0f34488f5aa2ad3afa758ecbfb440ae6e9392..f5c07fd72239def09c0c7bd21c1e494ef0702eb0 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 07b6b266ea95aa92a4cd4b0aa817441cefaf5536..4f77a1bdc8f9534d1306900e96b94351083bc890 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 afb1a3d1ef0a01232d04a0550830cbccd8fbaffa..f9168c1a2fa577732fcacae70f5aa17009e97306 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 8585c7c128612a040cf6040a54555a043c050c44..75c835c2ae6699247a038f40660d9120e840e308 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 aaa4416660e9dbc8dc67b110e6300694d881c308..523d5fe18c0edd8259593f046de55f4ec0123257 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 3a179827528d1b8ad53f998fec23d4fd788c77f1..20778a405d7adf7906479778302dce73972f5b78 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 0b9c9135922e3980e1a547fb6a5778c5c9e8caba..03c862b6a9c4a85799f59bcaa444b5db9d106149 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 900e0eea0099ddaed2a7868a86b4e7d76ad62bb4..9763267e38b46cbcdb2d6c9bfffd83d61b1eeb08 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 fe8f71dd0b3f1bd711ca4a480cdcdc2943007c9f..641c74bb8e27eca7deb4a8e06c053b80ce4e0b12 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 bb8209e34931c740fe176df01f94d76047ca3650..e8dfdbd9327aec5c2fe3fc77903d4a1b9155e694 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 ba949a2c93ac457afed39f2f390f9b72cff57dca..ccf56ac92de552fd0f5d7867430f6d510977064f 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 bbcbae183e92fce861fd800bdfa3647dae8ff31e..87f1663584b054182b3f7719fe96088e637fb78c 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 1168c5f440ab669a361878c2f3b11287d5685a0b..c930ac38e59f0274cf488d28c441aafe4b6c0c65 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 797ea95aae2e66858f9a8dbb1ac47d8e1de6b02a..04f638d82fb3cd3ff5387bfe62f395144e4f7c82 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 94e2df3cae074d2fe5ca514f21960d57b9b3c9a3..137dc22afa428322eecf5629896ac793befb172f 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 904ef1360dd7bca3ee4cbffead2e4dfefcce57f2..0546bcd49cd0363c317424e25359c7e08176b832 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 f56429362a121f0e92fe78044d7f0174bb4d4323..27735a7ac12b6709d1dd04e51a7871e1bce33232 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 bc44dc4b5c67f4dfe1efb0247b60b4b7493a3945..95ce355816966b36ccca9b3b4fbb4a956c60214d 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 c31e5b534f0aab0304a9d8dee70b5730dd8e5f81..d45be5b5ad497baadb007821e479d7898879acab 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 aca5741ddc6777663dcc55c9a840d963b83128f7..a86c34b3bb843b716459bad934054be9292adabc 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 cc7161ff166665ea120614c846f8ecd8082a6069..ce014928d4605b9cf4489fe4e1d4e7a3a61b256f 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 c5a87a72057b42b700fe1a514795185e12b31f80..7f45a51fe793eadd7816c7a8cd41715aa33239a1 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 21226b74c9b20e05aa7cb143c1f40a43fc902d15..414ca9849f239f365b136cf05742144a7c6ddc0a 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 5a707da3f5c2b037aec5654133c90dd82dba4e30..0a14d8cd314f7395b2315bd82b20620537c2db7b 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 c6f0a71b405ee97bce3f7753147cfe4adc1f3fda..bdbe96c8a7e4574c7304e12688e3c3e68ad71a9c 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 704dd396257b4c168b4082d5888c517ca7c378b4..77df726180ba8253d4d4ff896aa7556d1fbe07ef 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 24b1244aadb9b632a5d605dababe7bff86f89893..f23961ada7fb2ce8c99e3b240627d8e1016e1ba2 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 a356c958e2609d4d91ebf5b42bca2c79307bfaba..8a096b83f51f634623217fc3b5da8f61520a81e7 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 74d0bbb7d955a53d863f97b6577c2ddf35d018fb..e885442c1dfe99622217a06444ed680c18b23303 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 539263fc9ab9e2f7c5a124a101d0018a4f3e3ace..95dcf183a28df8565afe8892a8968c8c4bd2c23c 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 d69bec0b03f58e830cc1eecbe3476173be22d39d..cfb874e66c9a1f7f9bed1e9c5c330c3aed4be455 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 b537cb0e9b55f607652f217f802ac7c2d8358d0b..eee999853a7cbaa196c2d3b740591e457847ea92 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 682fb69dba21388842051635dda6d21b8f52850f..cbd9901dc0f8fb0502be32fa89f8631496587793 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 57bdcb1e3cdf0391928565dc26118e5272b3a21b..f5fe34dd821b548cfad6552d04faf6aba5ffa812 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 ee57a42e6e930a9a6be4a985ab6d938bfd97eac8..4890ac6d7faa6da171b096e2e870cc291ffe4c93 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 ab2e3ed28abc89256f7b305ee7ac63dfacfd34e4..639380a0c45c6278db26a03ea7b39eeec8fc48f2 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 802c8ab247f30cc25bda2e67569991a2919f0ad1..0729f36c2fe3498b0a659939ab17ccae28d9e10a 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 a8738676b26c51baee9059c6391f0504133c7590..653c6a1787404480f532d7f033223540e2fcc616 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 9ed13a1ed376a667c908cec821518887031454fc..061479ff029fbea84ce9895558b1b724d332a340 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 c932caa5e8504e3e026708f2efe16f44ad0ce316..93e52039321b1f6bcb2a89c335c3c9b4ef1c1104 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 fe927d0bc20b73b6bf1a8a0c5355de6f440404e1..0c26cc1898ec68a96e4b176be0eeff29bff57882 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 45a3e9a7ae21db6f5705eac145fe62790e4c5b0f..adfb32aa6d59a9b31ae5ac84d9134d360e5fadf5 100644 (file)
@@ -246,6 +246,13 @@ int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp)
                goto out_up;
        }
 
+       /*
+        * 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.
@@ -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 bc15ef93e6568b9094ee5620128a8cad95883a60..a68ac10213b26475483e5568f78297cdf431a7ad 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 ec5eee7c25d83e4dcc2245f80382b13938c6a263..06cce8285ba01883ee2e4f97a126ff6b50ea11d5 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 97c1eca83cc24274e796c491f60d5851252de150..752b362bf651d7e1bdf84a3f54601ddf863e8b12 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 3f15aaf54855c8b66522e6d28a5cbce5547ed638..58da3f461214874a4b31629ea9bcfc7fcc425793 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 d2ffbadb51a79e6ff803a3a55abc32be3c59df61..07deaeee14c833e20557d5a57f4799c9de261944 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 c60bfb309ce60c3a92bebcf5817b6de60d96ae4a..2757c5616a0767eb124dcf1b017a9eab96d984c0 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 b940424f8ccc0ee7915cc7c79fcc0b7d9983f406..88cdeb9f72d90b682f8334c1543a287d26db3696 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 fc51a918b31ad00f402c51191af201e057ba9f2a..66e40aabc60072957204c9928997a368d75dddd7 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 0a37c8bfc959e0a8a3e34ea7d8d4d60c7738b204..99ffc5f1c0dd3900f3aa8a24337dd1a65b8e90ce 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 ebe99227d4e6674704b96e4c03c7e699401b6194..a4b7402d6176245b0f0387bf983d0db0d6f9dafa 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 5f9881e16e2f90769cd09d4b12aee006ea096914..3b1ceb46fa543dbcaaa3033e0e5d63507cac81eb 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 25cdf7358000ac7c5ea0d669c33876af2bd34177..528013188196faae625b7202cb45b56e85b81592 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 4af3a771c058d76733016c0d148c1af5d32a0b76..c37617e6322031d892d33ed3b4266fdc62e4f9ca 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 af64d030a5c7027a09be844ca28014a8ee728e49..a5c0df785bfec6bb7c3355a667560dff0b011c21 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 a1316872be6fc67e7148476151ca1f22ba280450..cb8cf5572e7977f701b777c7ddf86fc04b6547fb 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 0151933e52538b807b2fcdce47ed4290b62ce29d..bb407ef0b91e66bc15af0ca5ea000a8b25be088f 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 03b3616c80a5e164502b0d4d4a77e35831348de3..2d07084e4882b2a35404c927e3f02a1392145284 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 68d9223b145eadf7ae77f5b3f332fd0b859ade0f..3eb84931d2aa73faac8c00614c7060899a51b6bd 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 a3dcc6d5d25332d9ec52046cd7c68c735abf334b..2c48e267256e131f6981f7f42d54fbde4247881b 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 4ff507239286cc83db38a151f354fb4a363c6275..b8fa6524760af3be77c391b1a92ffbd0ba4362ca 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 7cb933ba49579d7c97391119cb18d1e6cbfe08d5..eac7da772fc259c3c870152b3c1155492d76e477 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 548f6607fd0fbd074c8ee23759cc6710015618a8..cbce639b108a6144351f39b85212eb00a48f433a 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 f9d44f8e0df648465395cd8fa49cd2b54b4c4eb4..99b4fb553bf1a7cdbf99a56cd8bd9e0e007f8007 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 8dbe26b17c4486362b628a068c95ac8334740bfb..444cce3ae921c3ca2f15394c1e626cd5d15d8557 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 6729703547a1de1d9324ca45cc9cc72d53dcb244..3db37425210dc79c682c1af1c5ca2ddc9fc20e40 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 442d8d47a41e40baa75f18476667929d0aff9f98..160db1003cfb121dde1b41b1463de400805495eb 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 69bb1652eccde2d512bd36772329ed33657ca1b3..7a2ee3a6b8e726f61b47534fbc469f0fdbd9b766 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 64dc1ad5980192174f934cbf99570d176d62e4e2..7f7b52f9bebabc603e022d3112c2187cd278ba92 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 b2453bbef4cd8158cbff83aa59c83b1d1d51eb28..519e2d16cd0628298a7890060cea611f70a9df9f 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 2cadee2037ac5aa225a9f8c405f001f10c05e05d..2601935eb589a73e8e20514e09ed4ec33ff5bbfb 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 35c37b7f717a6a693d0d5eb499975a8f370740f3..a2dc7f9ecc514b02c22ed8018cb419fd030fb210 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 c3250614e3ae291ce2d97208b87fc822377e911e..a86eaa9d75a5a6e4d776820dbde9b6e5542de0e9 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 b1a714a92b14fe4fcb8d029d6100456b3cc46d5b..aade311021124ece9c161278a2b145df8c39782a 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 ac45aab741a508f4dfd63d49e6fd7095969b09ac..05ef5380a687e4773ffa88de981c6a895c104c1c 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 4f63ed8df55191517f819cacd3ec54f886a19941..162007643cdcb94faac5ceec465c095a2520be51 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 ea43057d47633164b0100367a01f4c9f3ff67e12..cbf4801deaafc9c9bbb3cb11a3383c5e209a240d 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 0ff92fa22064f6a335233acfa39a72a6bfb88a4d..f3cb790fa2ae0771a4ac7b2b0ba7c73b14338111 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 3ea6e8cde8c5beba98f7460d199d8a9f128057c0..1d361477d7d639ebe871a8b36243cd42d689b54d 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 adf5f273868aaf1f461a47a97f2be4b3a217518d..cb3c72c45aab441786c6ad5274cfb9aa056f735c 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 2d6a1b10c81da93a67d426fe1f1f4937e3eebc5a..fa5936e1c3b9e8d632c024d5dd6ea0ce8863eba1 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 a70a5e1904d9d556e43fcd893b83752856d0cd3e..1886d37d411b2e129c9b711ca381d7856daead4f 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 f97cb8b6ee5fec51b5f20d572357442e340115be..f9024bccff163f06fcca11054865b885086dc8c0 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 14a102e877d66e51a1e28a4f5a64ce23b509050a..cf8a97f3451856665b11fdb6172b67953d6ee513 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 19930081d3d8e93c42c7c0cf3d8be783ede5c304..4ebc8a34738f7d43a6020c8a05e604d8cad7d8e5 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 454cdb43e351a93fbb6ea50db791f726a8fb2733..039270b9b73bf91f76b079f2bf756b97c8cd27e1 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 8da93745c08790f8e8fa431b010f3ba08fd49a9b..72ace9515a07a44525778899e1ea04b32b3accbc 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 527519b8a9f9997241eb5897f316cdbe855bb341..2649840d888ffeac6fe8ec6b77f73a599ed73ee1 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 a012ee8ef803302642a5eac1daa791fe8f7c617a..d2d24c9ee64d926de80a249330e938095623ca85 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 0f6ec455a2b13a58151861b2e8d307776d866742..03c0683636b6fbf859a8795262f249631e6157f9 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 585edebe12cffa97d0b6c7381b66f6b38b81bc80..49c552c060e9b65c1ddb70e710becfbd246d3791 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 74619c4f9fda82652b37cfd3edbd6a52f6845fa7..581b0568fe1941e9cf18c730138b9dbf0ff8c815 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 3be000435fadd763c806460d54a6c0893a1245fa..d83892226f73c799c7d11e32254ea1cd7ff429ec 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 b608a64c5814de6ca6b78ae050a301704fdadc0e..f1363b72364f3e2a53609e77e52379f7f3998b3a 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 8aebcc41041d7cbc15a0b3c1023cdccf7010e407..efb38994859c6c961c68a0cf301106098e0b86cc 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 dd0f5b32489dfec730849202b474d453b773dbb5..9357473c8da06b7d37f76fa22ea610942cbc90e7 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 25a92842dd994f688239186211b0d76b8d5772cb..d823c245f63bf0fc26bd2ac9425b913903f928bb 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 04eb6c958b9dce975a7b6082a31f66a487e21f97..d1414af9855961ff52a1a952908995eacfb57b69 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 7da00b799cdab3806c97a42e4e854754c57fe01b..060fff8f5c5bdf257fd9f4c94827db6d01149107 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 f5f5886a6b539c43e7564ccbf09edd8d48bd5483..326c25477d3de17c85440973cd85c98f86148636 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 183c3457d2f4bf6af422a9f7e7e6f0ffac587a04..721a77ca811536eb2129e02449701948fe9aa9c3 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 889f665fe93d78322093505882e636feac5029ac..7c785634af2b495682565db7ecf86c2452d5edb5 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 f04e72527604f2e231e81705552cc5ce72a88bc1..3c1b12d461d151303d6e2787c5aa9fddc078c1ad 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 f7cdb3b457aadc7f0f8951323dc507827211be75..cd97ce18c29d10e27e6c9f0421f1492137a313e6 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 85419bb7d4ab5c0e72f479c834a61d582f887d19..d17d482a04f4c84edd4e87229372b52621e5d1c8 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 41fd965c80c6d41caefd801ee16948d23214d905..b9c830c12b4ac1de45d137a736be6de7fbd19fb4 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 ad5bd988fb7958834cc731266f2c9b7a02d21958..cdcfb122f25650ca407b9bdf9b138d46b883284b 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 1736c5a725aafe21959f4903d721788d1cc0354c..9c3bd4a2050e802a62ff13dfc52e855e641a802b 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 74656d1d4e30f8fa560391253bb6b541b74e2b08..04bbd52785688c4152c449459d943a0482c68830 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 64b838eac18cc3e22994559e4c15bea9afe32d78..b2a71dca5642c4fe513083783bd2b86e52532f41 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 98a827ee9ed7fc48d27b84dd16e43740cd77757f..a7f1b64f86e0476321c82dc44d3fe7dd20758927 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 27349f92a6d79078bca5bce37cfcf23f490ab84a..a1a3cdda06e18e989827197e48b4fddbe7ef43dd 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 dcb00d2785127df39f3814ec3478c64658733582..be2573448ed9de5965ac19fccc3749ba0efa7160 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 503c1f2e8835a585bf45e3bc4abbdddd2de5d0e0..1740c85e24bbe81a34977ab4fcd6fffde6c02492 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 699f7eeb896a15481e08130355c988c6e365190f..cd022121cab611629ec9b04de51677e44bef3567 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 596d54c660a5e63f819b46a06561b2b0ce3fcd90..3af2dff58b213262d403a8f9c1c55f84920b1d8d 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 31e6f6cfe53ef8ea0ecad83b8d28940fce256ca3..d430e4c3019300d02cdd0854d74e444b74e2a7b2 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 92929fb3f9fa929acda8f0579570d2dea4ea942a..3c68fe2d46cfad42b22c2011c6de4cced838bd7f 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 82ad523b490187c4d2f9cea90228293f868c8496..144e7f60b5e2c50f14edde7e3732761fbc22d8d9 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 1ae5ceba7eb2f0f4426f5c1a9c5b8c073375f511..23c217692ea9ac958295a1c1a64190a45bf07f92 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 eca41ae9f453cda6dc61112ab925ce66cdb7fef3..818b92ad82cf14bc9aae8cf3b8a93fa9e3e1f87e 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 d2fec9c12d224e60ce5e8755383e4387ea642ca7..72558f8ff3f5a999a3f7192dd3117fe667d72098 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 944cc9c04b3cea96be481838bf2fd890ed1edc5a..c17404add91febfd66d12570057a12695e972d9b 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 f3812014bd0b3e4d04ecd5c0645eb0dad9baa0e9..ed53b42caba119bb7b488efdf79170b44ba922e4 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 be451ee44249be80cdc4829df1f8a6ccc1f5d2f5..9b9695322f567875169c4d934e4100cb266e5d52 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 3e549b8ec8c9da4ebf3c02db2289196abc0a5b1b..85f5db95c60f03718f292080587f7faa337ef570 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 3439616d69f188787a6b06f60cc901f37b69735c..23a4d80fb39e80a496bcd847e5de6d0886255fc3 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 19085ff0484a27df21142c14a3fcc5384b4497a6..19f7df30937f23c8ea774547a13adcb8d70af7be 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 81f34311659a21cc172d3ce3dde996643941e5eb..71da5111120c09a6b52c26bf509cb4c14269aab2 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 b0de8574fdc84e40e1bdf87dea4eb1af98769bb4..99cb5cf1f447fa8759d73f06bf64fe4b20eec580 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 e0695bca702777d7455e9d4266590be47977443e..66d4aa8799b7517de258e3e334a69372154580a9 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 2e5cfeb59333ecc088576324f1d6e0e88faf3bed..6b0f52c20964e484c95a2e6c120dc77e2b821b88 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 9c4b679908f41cf034cdddc79a9bff8bcb1f4e85..069a61017c02c9ee4307a43ba97786f86a1ec196 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 1975b619c86d4e7f4212116c7fd3dd11b2a090eb..a847046c6e536fa9d4f168971b0905300495fde3 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 5a0861da324d76f975e2cb281f1fcc4e88f98606..517e4332cb37481dcad965e8f9986f029b42e64a 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 d9aa733db1647b51c1eea32de4840dc21cd9659d..0a55da70845e739426dd56a6c2ff704e43a70c0b 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 b88db6d1dc65f70626d15b141497dd9bcff40b07..6b5cc4fba59f0a52e9b20689ed029cbb65b6209a 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 6d73dde4786d3ca05aff5c431de9e060f4ba9131..943f2abac9b44fa6cab26fc763c1939702e7a6e8 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 b459a9034aace5270b4e2d7f73387ca4bac4eb05..79182dcb91b797760579482176cb652c495263a8 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 0ed42d8870c7cdde61dfa686475a4b45edd469e4..93d2c7971df626d6fb2db453b700c2b16a95a199 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 98b9690b0159abdfb7e1a999553fe916dfa5a4c1..b6ed60b57b0dd095686479862064ae42d4fc8a2c 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 9335b87c51747a6f480017e5bf94d92c97b173cc..0c9c6a9a002cb397867269e7bc44f56d4bd9f9bd 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 31122214e0ec68c92b7da6020789fcb61daed48e..1af808171d4682be716b0e7613980ed0c3fe8dc8 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 f6e54bf8dd96e5d5767547bad753a22da03a52e0..64e3c581b7a987cf4fef32f0ee78ff16e247c554 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 7032f25da9b5d1e5d919c9b702c20efceb395cbb..575593a8b4e66b2f6132f6541178c1d68498bbcc 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 acd1162712b18920ff4a0c2a00d6b7e44c4fc3bd..a06f5d6375a88edd4324881f43131fbd38b7bec3 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 01964b6e6f6bfae474a8cea47d8e4e1424288567..b0882cddfd4cae52856cabeb487ecc51c8cc81a3 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 0ddaf43d68c68dd89e2b36409487bf57b5f54686..d7f0f1b1ae3e3d18b404c29dbe8ccb332b9f9a02 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 a04488f0de882f2f38b30ade8a8c6defd1b7edcb..bba2ae5df1c2270664c7b9c0c19f94ca4eefb63b 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 be8e2628f82cd7805fe1c42220eab28ffa835a62..823e630963627f75e807a3af793457c8cbf84d6f 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 fc9c5d6d7d80a45ddcda3cc777af2a16be925bd0..1432dc9d0ab819d899ac3a506606a6778b146f30 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 aa4b3f6ae7719c029354844a49c7981d932ae2cd..ae4454d4e9555aa5ce29d25708202e742759567d 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 7990de925d2e296cd79d9d7abf4622713662bc09..6fe7ded40c6a346027bf091019ea6dc65edbdf5e 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 f49814d6fd2eaf8de34566542fb40e15be8788fa..3bbed8322ecf0cb72bf57d23e0c143cd22aeca49 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 45657cacec43ff21f5c10bda21f813d980f724a1..88984b803d6dab2c2137c8203ad1669f8719ceff 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 17f9ff9067a2b3dd6e185719e4086b3aa196a17f..6f5093b7c8c597ad63078d98763a222adf0d0a09 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 86a40582999ce0f80364e2bb5e0995970b6f906e..1eb4e020eb5ce3be2ab78cf2f3760f40a41f3b20 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 973bf2ad4e0d3ae19eed9d91d53bef730a43d50a..63c143e54a5783656d9f0208acd3c9c4166ec4e2 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 ed2ebd3c287d24917f6d48dd963a3b27d0a19305..f367885a76460cea4097372a035408560206c7d5 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 ed156a13aa40bfe40bc51d2d61ec899ec0059b1d..4fa954b07ac4ada384d27ffba6b293c22651febd 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 e0dc4071e088209aab36d51a69bf658062503fd7..8aa2443182d517ddec760d594f8781029a3e9fe5 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 38556f6cc22d5439dc9dded2a763043c3ba1ae17..a770498a74ece95daa7f2eade9434e0e7518e095 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 fb5be2d95d52c57a8ac8aab4f0375579a8852de6..6399e5090df4d59175063ae1b158f7b77e8a41e3 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 edda9ea7c626afeb6ba08b7700dfc8c46f531016..bd112c8c7bcde9b3efdbceadc6fc89d65f6c9ea0 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 43f19389647a99b4efb7e78ce556e94153189197..51042f0ba7e163e6b3dbbd7c0c2fbd2a498a33aa 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 08a6f50ae791952508ba62fa896a99032788af38..6aad99ec4e0f12626038c0d93c0a025b4d7d4b4d 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 60ab75104da93b4aae627ee292cf2aff2a231686..1c129211302d34e15c6fce2a4475fce8b15a32d5 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 73a0765344b63a4cde03de5cfbb1381a7b410a5d..fe2cb2f5db17281cd98eeb55a53867445cba0a00 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 9d589e3144de8f0541ba1cd2399e3c49c18f30e5..dde5134713e23f88fe185e2f4216cd9ad62ebfac 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 9e4e569dc00ddf80b51c541e8fbe48182de2cc42..d400cbd280f2fbb858102f0defb111a583979f3a 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 aac0985a572b86811bae33317d7d4176e924d317..31e7c91c2d9d25679a63b2b792bfbbd534e6166a 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 962968f05b9421dd0182677a874be7795cce0990..915157fcff984bc48b3885158f24971525d5c045 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 ab2f3349c5c4cc9dc13e3021307a3ede3ddf9a92..402838f4083e31091fe2480490c8a3ac0e42efa6 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 ec58d8c387ff2303f67db428622f68b7eff76057..d3400b20444f4f726b7de49e6ff88a5aa78cc938 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 e066c4fdf81be774e4be3317b8aa2e26a3f65d61..62f282e67638ccaa7863e2836b68645e90e77ae6 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 01f2654d5a2ee514eebea3a32bce224a08c3b120..f121357e5af093ee270e9332ce6267df807ea724 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 74339559f0b9a3be4a768c5ef1f65d4cc8b3ca58..780506326a73672298a02ed532b8f8936313428e 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 2fb49e89b3241184eb1e236e2412f1663810b3d4..47fab7c3307302d3d0b553b61e8276a7e5be0824 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 e0d0f8b2696b7360e39fcec6cfe25a874fe1a027..bc4ab3e54550fb25252424e17891b99126422707 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 33a2b531802ecd3fcf839bb2d5edae5406daa437..9610861d1f5f5b091a26a214050351785f1c47ba 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 fd3dced9777610c25b2d4f106eaca349a6a5de34..8c262aaf7c26e2edd5d414e06498871762773120 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 53e504f41b2043fa89b4b9a83637fe31251d38ab..db6dcfa35ba0dc44e183f33c5ded7b3a4f0e6051 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 8f2284be68e192201a069886ff3d0a1209553955..80ea6bcfffdc4136c07a79483d4ad65d11556302 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 45d58002b06c0087ad5ece5a2bbb14a844f574c0..47c2d276345665bb6e1c46ff2386d002e87853bc 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 3108991c5c8b60f312742ca4eaeb37e4c812ad4c..66fa4e10d76bd47e1192a4593a488e8491e09b68 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 0d328b59568d46f33c7b6e44c676c6709dea2371..a035ae39a3594bad321536817c5943695c3be433 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 6b36ee56e6fe972db14dd1f4785e5cf173468acf..ed86d3bf249a1e001a076e27985216cf94714d0e 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 abf4a2529f8011c6d4dbd87dc4412c8925dca41c..60697909ebdb00c9e0a4546764fe7e283e4fe800 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 ad41f19b8e3fa22d008a4c1e3c1ce9ec79fa025e..12fdd3987a36c2b09ab65b9d598f276e51fbf5b7 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 76cb6b345e7b4a732e99f1c86b8dfc175a64cb52..0af80577dc7bbfd9d80f276765e5afb7d218c067 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 02127e59fe8e68f8f3518453028d47b84988e598..55c9c59b3f713c0f29b211f89806f321fcffc879 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 7a473bbe8abd77bfab7784e2b707ca627a8cb798..bc5dc232a0fbf046b15a28ce069d232aa11fb2b2 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 4e551e63b6dc5fffd25c80b53b61e66a646772bf..d4560d9d5a83519f0fa886109f7eee750fa71be5 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 8ea07e2715dcad85ec1faa03e4921066ce6fb514..c6f359a85207e24552baac189270cb3702173b51 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 d3675b76b3a7d0792033abfb460f802b78136efb..29f1f7a612d92671976b356b48efd10594f09d6f 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 0c21c370c9dd001c2da04e1c914c5248708f219e..713ed7d372475dc325ac7cfca8cc5e22181af29b 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 d335086f4a265c98cec4300ce2dc5e16d3137e35..77a9579d716777c70b5dd399a1f40f44cab87e74 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 b08b6d8e2dc7c20cb101c7c611c3cd99a483a97b..f99d10655ed45cd3132f50a80144166e10aad1f5 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 */
 
@@ -1214,28 +1209,6 @@ static void i5400_enable_error_reporting(struct mem_ctl_info *mci)
                        fbd_error_mask);
 }
 
-/*
- * 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.
@@ -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 157f6504f25ea14bee970b909f2f04856ffe5395..cf27402af97b9cb0f22ec2677ea1fe811581b929 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 50f0176de61590e82b5ac2c0420139b8fe3bf1ea..98dbbda3ad4140d89867e46b1c62d477a37c7179 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 420a96e7f2dbb1a31d299f70daa07f22e8b95db3..051d1ebbd2876b68db9df2209161b13da7e8d7bb 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 d53fbbfefa3ee2893ece684f2a5cb25eddf77b04..dfb15c06c88ff8482de2b03164679633748848b7 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 afad14792141116898c6291288616b23e9308a36..49384a7c54920399e2d629d3e87b6986b3a964eb 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 8e7b0ebece0ca1581ed3322a19e70d8a49b39c74..5cae0b3eee9be491c1a9b23a1a1ba0b156ff19bd 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 3c0d2b3aed76c0ee92320074c4395541d9712cec..cea665d86dd387e3515b0ed1a1fb310d1ac15075 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 819ddcbfcce5b6ceb51433f65e0b9acd15f0018a..9c924614c418c3a92aca03011c580bcea8390f3d 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 45d507ebd3ff0bf192f1290d859b509779a356c6..92aeb918e0c02481fa7909972add10e59b1a0f27 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 b93814c0d3e247dcfb804ae9973c3cd7220b2dc3..7f436ec075f6221df8ee6beafebae603054be003 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 b24b2d145b75dc4450fdd24095eca0b519a9fa47..c5df2234418d5e48b251930b84ce5506302d2f3a 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 40727d4c2919d6cbb4fa719b7a7a3fe906b7917a..abfc27b0c2eaea77bf8f64eee6ec8f2f3908cefb 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 4dfeec7cdd42c9a0e0c8b1832cc6c29ae4efa6e2..c3ceffa46ea0e2dfdfc600e7440f1750376eb1f9 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 5567a40816f374282eadc9c28792765fc9850582..01840d9bc38fa8b58401841caf795301beb8b795 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 93ff6c03733e6359b69e720dc48f3193272ce04f..3c14240cc0028d32cada1af63a069e78776ea306 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 8aa4b7f30daa58bea5280bc9569041e4dc25c157..ef61fe9507e2e86a67ffc2dea1503ac409dbc855 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 e85d7e9eed7df192580a15608f49e301b813bf68..2b0fe54cd92c7394763add4cf95409b443c05199 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 fa304e136010b0cef680590adbfc606b1776dcfa..663ab6de0b582602d0b62cc8e088cbf6f99c7fae 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 98ae3d73577ee473ed927065b2c0d6e540c33b36..808bbe412ba8d7db796782c906595686ecb5bb32 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 c64eab493fb081f0f721575b722a920e8913b44b..9ca917931afbc27db9e0b1ac6de6488f4d625b18 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 6a015929deee77ab89779d7e27ee0489e58e59da..14fa9701aeb39a351c0467d618c9d837a373d6c8 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 e6cce24de8020a2830a5d675e5ffc2d99e1b2dc8..161094c07d9443957b8f193386e28db258244620 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 c4b257ec920e29e5760ac4819c54cfd0f8c25185..df29a630c466454d0ee78a87f3577d824f18b6b3 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 cf7fea5ff2e59653d15b526f0422d2c3aac540ff..eb740fc3549f82c5530c5450f4862ca8cf764fa3 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 1ebea8cc8c935e3f322b44dced5b630a06daea6c..e08c4a8974ca2130245ea4c34f5273e9e3d882d0 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 d4fa3eb1074f1d41a151cee005e651b5d41adc6d..4c73114f0de98362f86aa45e7914bac072f50063 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 49a2fdc57d27e72d3a98ebe69b6b4272e4a1ae78..5c7fe52de30e2688132f6cb5e188f9b6df101cc8 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 a48a7db1e2aa81dda2a169fad8f8e1246892fff0..fc78d31a0b4afe727d0e8bc987ba803e10fede02 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 0bf13fccdaf2cee28e5f38228e1a1794595d20cc..a555b7b19b48aefd3da033a2717b414fdbbccf97 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 2e4e60edbff4e3a08fb80b727b617a18164af5e9..609719490ec28c26b064df9d43eb642954fbb442 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 d988eece0187253787397d3265bf07f0a6fe1e89..dec501081608364ce09c45c615ec12aeadc6f14b 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 acae33e2ad51cd26c9bb2152c4b261b279c0aff7..93108bb31d1d950637f52e9ab7e87be2b9c7ae77 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 d28970db6a2d1538eeed0c998e78952c77c0b494..17e42195c632eab62ddef0db40aaf713c9fc067f 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 4a9028a85c9b225ce4cda0ccf8e82a77fa03fa26..9b64d47f1f82ff4116f0c8b25872730843f92c0a 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 950b346e343ff5a66dd8ae438e588782409e4bf9..5ab35b81c86bfdeedf71ec6ff2b03e114bcfb4ec 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 c8a4e7b5663dfcfe38d07730b104fa18d4e57a4d..c3532c7a6f3f04f74d26d6ef97ece8fea7da053e 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 96e37a6e7ce4d7e28c85a3e42a0445d57f7120ef..34a9b9119518273c97cb1df5e1b966709a838c7b 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 152eef13197a1721602841511467652756e09a62..f5c32a766b10d772b01d12b19660c11a4ce208e2 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 ec835d56d30ab97b7b7b00e2a002d4daa396aeaf..df988142e6b0f8fc01d981859fc07dd71d2f27d2 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 5d8141b13765c9234f6c1011fc5dcc6526ac4225..3655d91993a6bd8d1d46034b6262e93553a8ef81 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 621646752cd2520e6275a8b6ebcd7d79a8b3b174..a65ab1a0dad20c06338c521bff3eac5505981f81 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 1ba704eedefb9f39f3647227288d0b042bfd83ae..b38c4c8e2c611f9d8f6d9276bc69d8f199e056c0 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 1841145a7c4f873a6445ea7a6780046a76d8e9f1..8e0a8759e428e85a62289b6616352c22d2376e57 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 2b997a15fb1f5bb8b46746ba0dc1d856a368ae52..36410f85d7059a73830137d26a3287f51535febd 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 b1547f700d739eeb9787b2e55a09b826e6af3d57..6ceb958fd194cda46f729a0ce64d80cc189fe6f9 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 570a58729daffd0aeff3178c252f4d2feb24110c..e61226817ccf1812a00fe442532d7e567db3e203 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 73af463b7a59f734c245a52076f4c007c0b0b869..1f056dadc5c2243339c0562801669bf28a903b1b 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 a3fbdad938c71bc75d98dec1ac8282b7ddb2361a..a769c296f6a615463746145ecba7239f92fb04da 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 4a4fe1cb131c0cbcabc8ef362ec31f761debb64d..10dfa78762da22cbac4bd95ba366ae6644417e18 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 7a0098ddf9776ff00e456e1b5897a177b9b5c6e0..025e3225346cc6a6902392fddcade5c1cce99134 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 e53b5ca7a253803e04563448c998187205e66f27..41a34c23e6d8514b39d9f427ce59880a405cce04 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 e0b97d161397bafd3889b32e35d5c1b01e5f6295..595ac638039d87a1ee2e423d2304ccdbc833a112 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 541744d00d3e549b0d6665eb0d9c727522f867bc..b17007178a36e57bb59c82e8f3378fe9f5741d29 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 be34d32906bdd381bb5399e296007a04296f6fd1..7d05c4bb201e088513a771800f971d049504c721 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 b05f602c051e0009c3fa8e1e707ee362449c986b..c40afc57fc8f7abd2e60da9ad5e559097e346c18 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 ba05275e5104f7d30771254b82e3f35a48017bfa..cdd136942bcaa9e1435b1d2efc5444bf6f3317fc 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 6857560144bd782a4c8a7d41af2041b5171b7a5a..700e93adeb3308a37fbd1e35ae948d1391f980c8 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 fe4fa29c9219b9884e2e55065728920240a55e14..5a3ee00c0e7d2b65baafde7fefdb62a9fe935262 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 2c2cb1ec94c5f1a22ea47a6607c8408a4fe588c7..27d62574284fa14faefbaa754f53bdc0244bcbfc 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 2a7a85a6dc360e9615725fc7be5c25b0f845799c..da1b1f9488afc335c60b1833ee3fb7d89d3b832d 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 6679854c85b075b82d0a5eea82dbaaf36051853b..be475e844c2a73b146314bf3209f487c02110f59 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 ffeb2a10e1a76c59f090e6d8082a7a089a96f502..a3749cb0f181ec623a4d628ea615c66a154a6c5e 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 ecd739534f6a4a76c674fd5323daa8a30fcaf2a7..82b16808a274c1e0045692fcfc32dcfdb641ec31 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 303c02694c3ca0b8b07c49786b25c0c1701fe9b4..ebe38b680ee38494520c5cf162e50a027ab21799 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 4afba3ec2a612ceb242a86a080fd48c474d7a62c..e3654d683e157bd6accbc486cd864ad8cb12f919 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 d325e86e3103dc1059c754e51e7ee269c5cc1c8f..f627001108b8dc5855f591207e766f01f230225a 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 6396c3ad3252cb22173ff7f632e264151715299d..837322b10a4c45875462f603ab1e59ee279b124e 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 680e5975217fe59dce8febedc3389e1766704e27..ca0c46f6580a4985ea62935e64e3068e74f7facc 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 28d09a5d84500b588ffe862a6cfc0221bb5a3a1e..017c09540c2f70b416af3a39eaf122a5a49287f1 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 afca22beaadfc3c279ed53693d31e0a98c48779c..3b88eba04c9c81fd33acd3f2b21196ac8a243a54 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 0bc3d78ce7b1b8695d3eb25c2aefd216c0277265..8aa56ac07e2920d371a5af41eca7f09c8b752380 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 d287ba79821d0f93b70b598f9ff3be24bd7eb3b5..949064a05675cbb766cded13fc2bba78a680ad49 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 5be1bd4fc7edb8401b94cee52b10cbf5b178c614..bd07803e91838355b77f0d6f133cfbfe12a8e985 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 55d093a36ae48a29a09877176b1448e279555d00..0f89909abce98f1e68d36289cb47642126bf4e2e 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 4346a24568fb74746a74a12b2b1f534f23f1731f..bb96d3c4b0f4e06d3b8eeb6b8c685cddc4418eba 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 6895523779d0d5ebb9d5eeb4f58e9d5ca42a1c0c..ed7175549ebd18e0005f08b5877ff88a442a981b 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 6e86534719414ff5e5e6c859dd4fd3cbf995cfa5..1cecf98829ac93293e608238a316ce7f9ef0662f 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 04e88b600558caceaa0cedaf073b4ffeb7145ba5..013d1380e77c7bae05ab5b776c9cd0c331b06dd5 100644 (file)
@@ -31,6 +31,7 @@
  * SOFTWARE.
  */
 
+#include <linux/sched.h>
 #include <linux/spinlock.h>
 #include <linux/idr.h>
 #include <linux/pci.h>
index b2a9d4c155d14fbe44006156ed76a8ea21d54592..a805402dd4aecf9d2bb60fc909baec8abce7704d 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 6c21b4b5ec718b63f7ecef9d57093806cb1d9629..c0a03ac03ee7351618d9a3d72a0af29a7e58c21b 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 3a5a89b609c4e99bc761e28193b24bd01600250c..cb2d3ef2ae12426a2ee3da2937118de3145c0c61 100644 (file)
@@ -32,6 +32,7 @@
  */
 
 #include <linux/err.h>
+#include <linux/sched.h>
 #include <linux/vmalloc.h>
 
 #include "ipath_verbs.h"
index 2296832f94da868e3c2f884bfbcd2d9e94cc4fed..1f95bbaf7602289c79854a2919f966cce35e618a 100644 (file)
@@ -31,6 +31,7 @@
  * SOFTWARE.
  */
 
+#include <linux/sched.h>
 #include <linux/spinlock.h>
 
 #include "ipath_verbs.h"
index 6076cb61bf6a62d43648cb8a126889913a47c505..7420715256a987246816f36dd4308f7cc5bfef9e 100644 (file)
@@ -31,6 +31,7 @@
  * SOFTWARE.
  */
 
+#include <linux/sched.h>
 #include <rdma/ib_smi.h>
 
 #include "ipath_verbs.h"
index 855911e7396d8d246a8169cee757a2a499fba205..82878e3486279afc08df648a4c821c3cb3d199dd 100644 (file)
@@ -33,6 +33,7 @@
 
 #include <linux/mm.h>
 #include <linux/device.h>
+#include <linux/sched.h>
 
 #include "ipath_kernel.h"
 
index 7bff4b9baa0a83ada20f29abceea8d90333f0026..be78f6643c066b3d0436f5708263a95aa7da07bb 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 d73e3223287930c344784cea458e7eacf2b820ad..6923e1d986da49b95e9c8e39a3a8955f2a2ffac9 100644 (file)
@@ -32,6 +32,7 @@
  */
 
 #include <linux/rculist.h>
+#include <linux/sched.h>
 
 #include "ipath_verbs.h"
 
index 0ba6ec87629616e946a64aedad68d86a3b6d4010..add9188663ffef816830ee9b4c130205c439fc28 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 c6f88ebb40c766e21c17104cdbbe12563ed075a7..cc763c96fadadf0565048a2a897d0f6202d81f09 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 2388cf578a62d4f84b807efd8b3a143077f2f20a..79e3edcced1a7bd9875a6cea0abccabb73536f96 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 4709e15af6070522dcf03516acb058bd024b07d7..4452eabbee6d66f14482271c35943a3125721aa6 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;
@@ -851,29 +890,6 @@ static unsigned int atkbd_hp_forced_release_keys[] = {
        0x94, -1U
 };
 
-/*
- * 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
  */
@@ -881,14 +897,6 @@ static unsigned int atkbd_samsung_forced_release_keys[] = {
        0x82, 0x83, 0x84, 0x86, 0x88, 0x89, 0xb3, 0xf7, 0xf9, -1U
 };
 
-/*
- * 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
  */
@@ -910,6 +918,30 @@ static unsigned int atkdb_soltech_ta12_forced_release_keys[] = {
        0xa0, 0xae, 0xb0, -1U
 };
 
+/*
+ * 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 a88aff3816a0440558ce34ee799fbbc003d0731d..77d130914259ae68419d3781452bf57e494d5d27 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 e9d639ec283d2facb198234c96ff94c1579ab432..5f72440b50c809be4798b6dc11d718c523a6544c 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 472b56639cdb2d1b08ab1a4ae078fd5c5016fc9f..a99a04b03ee49f3161d3f97ff6cecc8141b50ec9 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 02f4f8f1db6f3af8a440167518a02a2ebd61e31a..a9bb2544b2def1a8a1c3a93791ccc07c429fdcd5 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 216a559f55ea5c706731afc7f7f4abc1219891ed..ea821b54696991929e835ec1e308d7ba2f987fcf 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 c806fbf1e1741ae68a542bc402e8236776c01f7c..3b9f588fc74746e5bfb5179418e414d1e8a8921e 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 c4f42311fdec9834a08ba2a331aa1c259bd77b1e..b064419b90a235fbe3ad58be8c25ab437252c6e0 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 11fd038a078f2121367e0b80f16dcc54fcd94ea1..a932179c4c9efa7fa589caf56b7d83dd111e0df1 100644 (file)
@@ -934,6 +934,15 @@ static struct dmi_system_id dmi_ids[] __initdata = {
                },
                .driver_data = keymap_wistron_md2900
        },
+       {
+               .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",
index de745d7511624ab8a488eb17066db9252e6d1190..ab5dc5f5fd8322e902257f48720bb13b8169a841 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 b66ff1ac7dea651ebbfc263dc83774168f5f9ae5..f4a61252bcc9410a867360b747c54675b5222926 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 c4b3fbd1a80f667f20f56eb90f6b736ccce00ad2..aa533ceffe34d62556e92a196a4daacddaecf82f 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 a39bc4eb902b642cbbb897550519c7bfc53ddcc1..a537925f76511ee0d1b5cb50e5f3d18d39f62a8d 100644 (file)
@@ -326,6 +326,17 @@ static struct dmi_system_id __initdata i8042_dmi_nomux_table[] = {
                        DMI_MATCH(DMI_PRODUCT_NAME, "VGN-FS115B"),
                },
        },
+       {
+               /*
+                * 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 = {
@@ -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 bc56e52b945f68c8e0fa604a7d88659dfa77fc23..1df02d25aca5e4843cc6b02988f93dc0c05f2803 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 769ba65a585a562a2f298df5f3e62403e316c721..f3876acc3e8394e4810fcf16a67773fe96cdc0e1 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 b03009bb74684a2edaf15f6d4f31f7a9904b31bb..27fdaaffbb40dae15963ddc5e788d9b33c149518 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 b9694b6445d00267142a14c04fe175405bcfd10f..6d345112bcb758c1ef5dda8c538659328af48759 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 f06332c9e21ba069bb177ff915897db2b9492e52..c21e6d3a88444e3db67da6829e8e95d96e28ce09 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 2d8352419c0db445c57f03d80336cf9e1458faf5..65bf91e16a42725c7aeb5754fdb5954553fd73af 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 650120261abfbac9816386927fed562bf6ab37d4..3e6d17f42a98309bcdcd11b0296d2ea606cc8e20 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 57d26360f64e38f13a09591a1fec08da76bfa115..dc506ab99cac03c1d9ca42a8053a5a0d5ff1cf2b 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 234cc5d53312ab90b339edd1c96a005fd10a7942..44a58e6f8f6585f5fd7a5db45eed7d2473f705b5 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 781c4041f7b0d1a856b2be280126d89e0adf55e2..5ed1d99eb9f3125b830b5a83cee806e4cbb9814d 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 e4141bf8b2f3a705436115491bab35a18e198062..33dcd8d72b7cb72ced39b702a0e486400c4fcd52 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 2d91049571a4ce20470acb86d7120bee326b911c..cc768caa38f54b86f48ec92310ed93e3b1fcf998 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 9b22f9cf2f33b2bd4895bf15f5d3cb16e73918df..654489d836cd18b7d3559a45a608e11018b4a1f9 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 f33ac27de643f4631817e6165c034fa38f1c006d..6a8e1384e7bd09b6441ef6a27eaed5c497f31061 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 bed38fcc432b62b8a88335a697dfa93295110a2e..9f3ef7b4248c35d918321376d956d2a0da629a12 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 d30ce5b978c2ae3546ede8dedaa7e6339dc6c070..85a8fd8dd0b7c64f69688b926e9a30a0ecbff5cf 100644 (file)
@@ -10,6 +10,7 @@
  *
  */
  
+#include <linux/sched.h>
 #include "hisax.h"
 #include "isdnl1.h"
 #include "isac.h"
index 5c46a7130e064520def2c4f1160826bcf81c1147..8d22f50760eb2e52d6919c843b2729e7b670f190 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 d110a77940a49a6885eda2a985ea6c2524519818..10914731b304986d740f53bc72f0dc98f38fe35c 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 8f9f4912de3243e4b118c09c4a346a006dc73981..90b35e1a4b7e6e85c9d8ea4374184d3c6c02f40c 100644 (file)
@@ -11,6 +11,7 @@
  *
  */
 
+#include <linux/cred.h>
 #include <linux/module.h>
 #include <linux/poll.h>
 #include <linux/proc_fs.h>
index 8991d2c8ee4a9d74b02e15c9f44246c06593eb63..8bcae28c4409ea0edbf40a65db309214463ec81c 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 74032d0881efab82d80b93193a2ebfc372e9bd58..7511f08effa5300fed35f561695f154567b83618 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 8c66bcb953a1e97051b1fc23e7f7e43eb78f957b..123c1d6c43b45f82a3713c62e7d8f3357a64e947 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 e075e8d2fce044a445720e39f97c61b71870d5f7..30f0f45e3139293a68007236f1c12bb80156f56e 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 dd0acd06750b2fd614e242e83e6df125cbfb7338..5a0774880d560640e669734ea689a1874ce4dd94 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 18648180db02ed94beaa32f9aec8fbe12e90b1ad..daaf866316478dd262f344124f02c9891530dc7b 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 b40fb9b6c862c3bdecd5b21ebbd5ef20e1fd7434..6f308a4757ee60dd6aa8acd4881745efc4eb4521 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 1dc4185bd781f3137b86e3f29e53c2dd3de5e745..e355e7f6a5366971475750ea1cfcc1c6540931e1 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 6986b0059d23279fd83e67da452b225bdf946708..60e2b322db110b96d52f66e4f502610b29d822fe 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 556acff3952fe450e73e4673f46bcac84b453a47..7dbe652efb5aabe8b42bbae0847ab9d062197495 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 812c71872ba093643ba9a5e603fff2d22e4177fb..8a223a48802c0c867f79818045399937e650bf5e 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 652bd33109e3333b97bd307514a24f7553241078..7ac2c1450d1004c4de300df3aab50fead2cfe5e0 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 d5b2e08750d59d6574884c66424916d3d3d6f6ff..0c746420c00810f9c2e57ad346f3bd2589250821 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 57f1bf7f3b7a1d4ffd18f51563a2d5c52b0693ad..3a3ba46e6d4b68fc9f70b87b7ad322a8ca2c9846 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 23e76fe0d35958d604657a559a5954095854bf23..724efc63904dd5459b5e675a5ead3f5aba0394f6 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 26ba42a79129bdb953fa5b98628a744689a6594c..10eb1fce975e9bde28f3331f5b9800ca8d1130ca 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 d1b9bd5fd4f6cad04f4037ece137f43904f50de6..a053423785c92e74256e4ad8e2aadc658538aee0 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 51c4c5c4d87add417a297714f7873df95979001d..c2cb7b87b440dce777d92bb6c215d1c82efddbe1 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 94829804ab7fd2f68c839e0f481444bfaeb3be7a..81abefc172d92d6d8cdb677695d3679de05391d1 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 2390e0e83daf7c939344f8062a9d4a6ef737c476..dd708359b4519daba42fc7d74fa30879374cc953 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 699dfeee494459afdd1ba2ff3b7a7e90c063b12f..2654d5c854be244ba1a19509b21d001b5cda15e0 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 f9bf9cba357fd1202b6bef088a7e26b49fed6ab2..d1e276a14fab2d22eecfd3b8c6d94bc51bd0e2ac 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 58ffdf4f51619caa05253d5d42abb520ae5c8e20..2874cbef529db7e947805310c0a2aaa115483419 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 8c9ae0a3a272de8e724a583476979b80717d3fbf..0241a7c5c34a65ae53f28698936d06ae41df8c43 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 4b1bc05a462cefcc59020baa1cdaf6dbb8a1cbe7..01e1eefcf1eb8549b5d7d1725d1dae607bc26084 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 f1ccf98c0a6f071d287a066a2902c4783b3675fd..8e93c6f25c83ae4cab47bc715712b56ff5aa059a 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 53cdd67cebe14e6407d352d7de27c7f109f4d66e..032ebae0134a7190a1c1c3e4e50054eaafee8523 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 bc2ec2182c0079c67367b90f667c9490eaf31029..34f3f36f819befac8ef345e24a3c85abe3e814c9 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 e424cf6d8e9ed4b69c998b31b5160558a553136b..a1c47ee95c0eef065e591cfeadde949eafb8e414 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 fea9085fe52c67e089f38fbded9ae0fb1f83b389..60c3988f3cf3c4cecf0d9cc544b86521f9be3411 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 d3015dfb9134a5402cf44d49bc456a9961229887..ac056ea6b66ed6c432e47683e0a9fe78ac0e464e 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 1ad27c6abccad303a8a9a0501398762db08aeb25..a92a3a742b439fdf2e6277929ccdd5ed3fff2dcf 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 276d3fb68094a53d6815979688b89cd412e8b489..e2031739aa29fda4a188d4ac35101bc9f7439ee0 100644 (file)
@@ -22,6 +22,7 @@
  *
  */
 
+#include <linux/sched.h>
 #include "ibmasm.h"
 #include "lowlevel.h"
 
index 68a0a5b9479519c140456cafcbca5471c106b5a1..572d41ffc186a37fbd4d90dbea14554570681ecf 100644 (file)
@@ -22,6 +22,7 @@
  *
  */
 
+#include <linux/sched.h>
 #include "ibmasm.h"
 #include "lowlevel.h"
 
index bec9e2c44bef2655d2ed98eb6b6f70d8a143383c..2de487ac788c24e5e9c689a23ba1924c7e2aa80f 100644 (file)
@@ -20,6 +20,7 @@
  *
  */
 
+#include <linux/sched.h>
 #include "ibmasm.h"
 #include "dot_command.h"
 
index 90a95ce8dc344953365cc1ec3d5eafc58e02a490..04c27266f567548306e29df293deda919866d4e6 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 e1035c8958086b92ee9e563028c573d161cd104d..f85dcd5365082ab27cc77adefcb84f1364892f80 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 e556d42cc45a755597e435e54e21235113611505..63924e0c7ea9a6c3fab8c2b38857be8832149612 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 4487cc0979112ea71e412f2c722ad45282cd3328..0aecaaebef3d48c40141666f267f8da3fb473a65 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 5e0b1529964d638c4462c16986eb20d48a956a88..b00d6731905826864abf43a762910899087a3887 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 379c316f329eb0d054718a12ed1c9111845d68db..4c19269de91a4ad8afb3383ea7f27d10e02325a5 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 c2baf3353f84d718135a72fdff1d8aa23c2efdfe..0a11721f146e0857947af8fddbdcd49b8f318d7c 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 e1f7d0a78b9d58e28a2b6c1fdad43423cddd3956..14cec04c34f90c8adec61770e6607faa5f8540ab 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 e7161adc419dadd45f14be17b7750ce9ed0ed532..90af61a2c3e4d1a1a5341d85bbfe246d4bbe3ec9 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 bab31695dacef14b9ec579b4b76af0562ac7b665..ff179ad7ca55965ed4a710c1910721e47f6c36e6 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 712776089b4600349c7e6cdd6148e63d819b53fa..e19ca4bb75102448879208df00d90aece5b8503b 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 d866b8cf65d19b184574dbb3ba3463899e31ba4a..246323d7f16171cf475c76d07dcc4160248224e7 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 5f0b05c2d71fbe64f4699394f88b621c214bf2df..d82a9a994753c2a8061bd5102be797767bcaf2b6 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 fdf5937233fc9e91c2a9d6c8e3ac32f2e37dfea4..ce6f1ac25df83e6ea3b26298f707cad6a9e488a3 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 79d35d122c08c8caa066cb54d8f5f91b11de141d..28a0eda926809a573cbd9829e9310162d3cc9054 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 8b4c2cb9ad624faff6d8fa13cbff44dbd7143655..49953787e41c5a20b233170caa1e01617f4a36d5 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 11445df3dbc03aa6bdced9515cf4cca22917acce..cda5bf2fc50acf5b07406eff6ff488c532f67dbf 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 2f9b50156e0c4febe663341bb853f9a4e9a83636..1f941f027718afd95dde07c70f26db49ab55ccde 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 6c7f795d12de5c35230ce8ed76a4888b2c431794..a4d83409f20555eb60c73e9d10ada9edd2a777b3 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 69c5b15e22daca1239e5d10bc6f00b767ae3ce4c..40fb5eefc72e63b884d6f69a2897ef9b0038f1cd 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 ff449de6f3c00ab0eb394640cc56b07ce7e968dc..8762a27a2a185dd37d47db0263fcc019f471b1da 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 3373560405ba3a2acafa4997a604b951bc5adb48..9dd076a626a5b329b1ff368f3682daabe516acd9 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 46c87ec7960c83c03d10772a4793629c3cd8904d..3bf1b04f2cab77068c6cb08c206aa0174fbae6d9 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 65a2d0ba64e226919cb1be572c8d3de578f266b0..f72c56dec33c668f3056dcb74184ca0be49f14c4 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 9686c1fa28f13b07a105e29f5607cb9b8ae68969..7a3bdac84abe9b89705f373da12761b957064285 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 80817c2edfb377ee5b8d7b2a5631d385048cc19e..fb1c924d79b4370d859d7e2e337519d21fa0a923 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 679965c2bb8600f42ba0c44fb99c68ea84472600..3c29a20b751e831fd4d338ec316535cc7e43c093 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 b53b40ba88a806b545a2981d54e49f7ed44de6dc..d1e0563a67dffdb8ad988659bf90b221b2635cc6 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 c0f185beb8bc1a7cdd1dd04393f5635470b7473c..1190167a8b3dc59db03c500a1b500716d856ab58 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 981936c1fb46759846cad4b379471fe61ee1a99e..189dfa2d6c76b80ad4702bfb281a541ed500b783 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 fd44d9f907696aff5ee2fdb6558d79feaf0b27e7..aaea41ef794dc1ee1fe23d124a4192b058e146e5 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 99df2abf82a956d52d0e80658f0e655cb8cfe89d..51ddb04ab19588adcb16e460f7beecd1261b8e69 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 */
 
@@ -567,13 +596,40 @@ 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;
 }
 
 /**
@@ -751,6 +808,326 @@ static s32 e1000_phy_force_speed_duplex_ich8lan(struct e1000_hw *hw)
        return 0;
 }
 
+/**
+ *  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;
 }
 
@@ -1053,6 +1376,38 @@ static s32 e1000_check_polarity_ife_ich8lan(struct e1000_hw *hw)
        return ret_val;
 }
 
+/**
+ *  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
@@ -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 994401fd0664fbc188980ea188e33bdf95fdb0ec..03175b3a2c9e25c28923439db0699ea312bca376 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,40 +533,110 @@ 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,26 +2795,52 @@ 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 d4d9a3eda69556f5b8ab5f11d39d8adeb9b036a4..f5b96cadeb2544994c4aadeeb45f30113c082116 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 b7311bc00258569e210949fcf2c17ceaaa62b46b..f7d9ac8324cb986a58e80947657bc216aad39088 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 b2a5ec8f372147b4c2dfb1624b12458b6d68d68b..dd4ba01fd92de390103ab8232d0e661d3dd98078 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 29234380e6c68b02369d9c30c8e87826fa2b088e..16a1d58419d985788de253cd85018124d7b5b253 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 c40113f58963f9f765268141db1d78f367125a8c..66dace6d324f307ae3474616c04ea2fdc373c811 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 31e6d62b785d81beb13ea7b4f76792975a385127..ee0f3c6d3f888e636c6da076a83d5b3ac4187d72 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 0a1c2bb27d4d841dc889b908cf5c911039b1d526..e1da4666f20426ecf4e5e9848fae64975d2bf463 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 2bc2d2b20644ba924f0031c512b9a8468cc46fa0..ec2f5034457f7b58099906633928456f91fabf05 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 93b481b0e3c7faf7bec15bae910d090478be4efa..24ff9f43a62b4e6378da3f231b280e75258bfce9 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 a2d69c1cd07e311113a11d74ded63d883f584430..96eba4280c5caaaa36ce7b5b1a738e06200769c4 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 d167090248e2f31d6ba7211e447e3bd68dc43da6..6ac4648669728421b934d32646ffbb6261283876 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 1e5289ffef6fdda0ce8fd75f92f77f057d860689..5bf31f1509c93acca119f3e87175f97505bd4d31 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 1d5064a09acaf3de8ede90ac65bae51991774778..f7519a594945e831bee7fcc60fcbec24a3c9ca83 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 7bcaf7c66243af20bc87c88d6fe0251492142d6e..e344c84c0ef9828efdfcf3b6b7ccf31895763758 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 aa4488e871b24d0497d3fcb92bf1954e01eab29d..ed60fd664273e4a089c3e39c2c4c7a91d1022803 100644 (file)
@@ -71,6 +71,7 @@
 
 /*****************************************************************************/
 
+#include <linux/capability.h>
 #include <linux/module.h>
 #include <linux/ioport.h>
 #include <linux/string.h>
index 88c59359602029440c00c947cb77f3351e23ef54..1686f6dcbbce849525968a57152009faa24e2b63 100644 (file)
@@ -61,6 +61,7 @@
 
 /*****************************************************************************/
 
+#include <linux/capability.h>
 #include <linux/module.h>
 #include <linux/ioport.h>
 #include <linux/string.h>
index 0013c409782cfc60e6fdd54e362347b097e27f41..91c5790c9581ded3ad1cdc790b99eb77913accc5 100644 (file)
@@ -42,6 +42,7 @@
 
 /*****************************************************************************/
 
+#include <linux/capability.h>
 #include <linux/module.h>
 #include <linux/types.h>
 #include <linux/net.h>
index a9a1a99f02dde3f841c2f0951c765e26c3c577c3..dd866513806274be18d79419e0d367fa07a26c8d 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 89c82c5e63e4e576476eefe65936bce754bd08ff..3fae875597914b4fafd64550b5e8ab16cb2648f8 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 0afc2cf5c52b94ba52d3bf9c2669b90f1a40d7c1..d34adf99fc6a45c87d5294f05b675251131b52dd 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 801f088c134f81370bcca650c30e2a33c2dd6b05..030913f8bd26ef40876170abad2fb93e7215e16e 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 d004c359244c9b03e2e5e753f5300abc15be8bc1..b243ed3b0c3620de498982636240573138f0217b 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 ee17a097d1ca91929f4ab405d6a9b81a02a14498..c68265bd0d1a41d1f39dbbc68473b04e1d4076a2 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 38bf7cf2256d04f7c15dd655be706e3c3b779c94..c412e80261737b6cc34b3ce986879f139cd0dd54 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 fcf287b749db5a9e8885941cdd9d6bacfeb7b49a..99e1ec02a011108d7066f6e27fa4a49a3645c2ca 100644 (file)
 #include <linux/module.h>
 #include <linux/delay.h>
 #include <linux/init.h>
+#include <linux/sched.h>
 
 #include <net/irda/irda.h>
 
index 2ec58dcdb82bf6fba6013599c7695eb76d0804bc..34b04924c8a1f6412f7231306833c3ceebafbe63 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 fa314cb005a4dcf15ce8884c0da5e9987f1e2604..856c18c207f33c9a7a4db9fad6dacc0cd6d47d07 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 28fbb9d281f915c505c980b246bf1571de7fe3fd..cbb143ca1eb88386d03209cb6b92d5b2936450d4 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 7c93e923bf2e1fd2346969eb9625b4867d6407a9..ef4bdd58e0162e96c1bfad79980d2fd3dc3a73bb 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 b02a981c87a8e7f7d332f5dfd122d59396181bb9..34a6cfd17930c2d1ff4c2d27eb51ae6a4a6edf18 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 127243461a5161c09f33e5bdbf80f8cc1286712f..9aee0cc922c952191512be96d22433f0ec59b1fd 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 2378358643576daa21a034202a87f0ee3f2ebbb7..a23f739d222f03f553bc9717189995cbb96c7461 100644 (file)
@@ -170,6 +170,36 @@ static void ks8851_wrreg16(struct ks8851_net *ks, unsigned reg, unsigned val)
                ks_err(ks, "spi_sync() failed\n");
 }
 
+/**
+ * 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 85abe147afbfb6473304b0d3c0c5143b1d1c09fa..f52c312cc356c6deb2af0f2c9934d8a2a46cdd32 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 3dd481e77f92f1f5cff4af9cfd9d9975439520af..291a505fd4fcaac388d86597fc0ff8540bd9feea 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 6930c87f362e573c69399a8b35c1c8d1daa67dc1..f3624517cb0e2a68ab6beaf3468bcf474d130de4 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 7a7177421d7cc6fe46131d712c5671b64a228c7f..1c46da63212586647c7d3696a117f9de1821541f 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 32314000dfcdeb4f7a924a377d08a823054108e3..3185a98b0917ead8c51d4b3fea2f13da3abe6f66 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 91c2bc61c8eb6746a0a26ad854965688a34ad151..e40b914d6faf7def7bedbb9f309195afc2a61e59 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 b5aa974827e53bc5b69b209797b332028eec6a42..0b4a56a8c8d5fc2d9d9d1f8619e88e2031577a55 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 f9364d0678f27d19cc4ab1e5a0519034e627e2db..d6c7ac68f6ea8a8010fe6ca542c9fbbd05d8d738 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 c594e1946476f097386894c5aa484fef744e0ee6..57fd483dbb1f91f4b3e6440d9d30d2255ede4d57 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 064a4fe1dd90efcee86a805ed6e94e1037385c2b..28a86224879db42187fae1adffcca056236b79b0 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 ee8ad3e180dd308b3b20e6b32d3a686b6b3eba6f..b58965a2b3ae256eba2642a7b98d1dbff4bfa9b9 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 474876c879cba3579f8745e5927c1a1042af8334..94c9ad2746bc68cede7ea8ae5f4a42b5114d3095 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 6d28b18e7e28e6cd511cf7df86f9ac1986e04bc7..c1b3f09f452c5450bcc42c1983099293055077bd 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 250e10f2c35bb083519efe6f76ce778c6ad11420..8659d341e7696fcfe8df1b55318db5957181d013 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 7cbf6f9b51deddb790372a652e169ca0ccf0ef77..2559991eea6a59e23a88837a897cf8e8dad7cc0a 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 30d5585beeee4771e45a0b316d93629169f25bcc..c2383adcd5275b4974f645c16c7032e80b5c06fc 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 68f9bd280f86b028843b02911f9fd3a63ad861f7..52073946bce35cec6da556f032f1ae4c8b2cc746 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 3d0efea32111bd15ce5f66a0eaec7ce20ae56408..cea7531f4f407d7a2a1542750142d2fa95f17fb1 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 6685bd97da91f211452743dd7cfd9c5ae77996a3..bcf13c96f73ff5d22137975b345acb27128a2fd1 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 50c6a3cfe439d9702f72291acfd938c85c75f114..fa49356784883049d4487f95bf0b0fa1db8b3cd7 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 ee366c5a8fa333b191eb2c6a6e251f950031ac24..c9c70ab0cce0c738989a1a6b32e6831af40ba2d7 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 01f9432c31ef9f2c02ec3df3dce4159c2fda1bb4..98bff5ada09ada5d5023ff2e741e72d0b5f56c2a 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 f49d0800c1d103c70bdb37f59cba9f00047b5285..528b912a4b0dbac26ecd88a77498a4be91743376 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 97949d0a699b0c99bda67ba110bd70b605e4d6d0..c072f7f36acfd7d5cb02b727557ea0fe4ee1e562 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 38a508b4aad92a0835be81a17e4b9a714a7ecb09..b27156eaf26741757ccf1d10112cb61ebddba3ad 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 01f6811f13249af0aabf7114f32d1f413fdee775..8f5414348e8629569a6fa12ff08f710d425abe6a 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 2ab5c39f33cabfa4c40a3e2a5fe71e67d7b5778c..6a10d7ba58778245ca14ad4ba7b18c20aa7be79e 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 e17c535a577efeb9d1b6447243423590246263f0..fe3cebb984deb028b8a2e6ac1b1a2e2ac25717a5 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 305ec3d783dba30dd396b2fcfb6df9ce12913384..7019a0d1a82bd48dd9e15f2e5b213be928423f9e 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 f09bc5dfe8b2c7d652f8d3848ee204d5c2630fba..ba5d3fe753b694d58b93bedf2fc050f001995fef 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 524691cd98969885bfc1f849f01be0ccc7a6e950..bab7940158e65d208ca734f22d12e432620f69bb 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 525bbc5b9c9d7aeacefbb632f1940d2830258b47..75fa32e34fd00df30c9f8c009fc53449b44f0288 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 d6d345229fe941cdc95d52dc5a3f7fcbfb1ad4e8..5921f5bdd764e57d72184142134cfdd588e40d9c 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 72470f77f5561368757002eb46548660edc499f7..a2b30a10064f131e996657fb5f03dd600c528be8 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 6fdaba8674b9104af6dcbda8d2132d68b9abc51b..ed4a508ef26220d19a7bb4620be5c84eb43e9ca3 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 f968c834ff63581bf73cdceec371352a5e44fa29..5d02f0200737a45770de3f7f7d49a681f8e0a85d 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 d032bba9bc4cde252ef23518428f96eaa33df113..f56dec6119c3fcadb97740dd1d2d0cad33fef487 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 8d009760277cede76fead3a54edf2c7669a7acbc..05630f2f6930419fd501dfb3b40d5ed6781a1251 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 9693b0fd323dbb82c252ba53720ab971445af126..0bd898c947594fbdef1affaccbd86734f80aacc8 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 66360a2a14c2f174ac4fe4018fcd1d005f078287..e2c33c06190bb1fa0975b634b765de70d22ad71f 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 2573c18b6aa531830b8a92645bb6438393503520..cd8cb95c5bd78920c648b2b47831bd9e086bb701 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 81c8aec9df929b5f97df8b6978c505e0d86719f2..07d00b4cf48a8e80e65fadcd451901c90462c865 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 3e90eb816181b508ee2c4e151206a72eb4eafbe7..beda387f2fc79536c3907bd37bca533dd12b7d23 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 cf5fd17ad7075b7f1753ff1c4d84f028ea03338b..f1bff98acd1fc8e1765b88d7d7195a740933b3dc 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 83da596e2052a84df3920cb2d681579e0caa9205..58c66819f39b161f6b7d4bde9e3fd400ea4e42b6 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 a52f29c72c33eeed101ea834607072267e60af95..f1340faaf022a248274ab502cdc7076e89087172 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 4f6ab1322189805660e99b0e5b3bc3acf2fba9d8..b07e4d3a6b4dda728ec598ae2689d180887556fe 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 7116a1aa20ce0b2a7046e8ed58e509a24926798e..abf896a7390e5172f9fdf00339102d96f7d1e17c 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 16a271787b85bcb5fa87edfbd06ae7f8c0955622..1895d63aad0a8a8e65c3599918ab6bd159bef88e 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 fa1549a03c71f328cc005f26a7c199e19394ba65..660716214d4915efa7ab356f4a9d74760a1415ee 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 8701034569fa520dc09caf90756badc913913714..de4e804bedf05541c3b9c943bfec268836b24222 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 fbe3d4f62ce2bbdfb6e67826f97fcf6c06889f43..1e8dba4880047352f445807b80b24865b90c9b35 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 9592e4c5a5f5596ee8c4e041307f2d137067dc15..32b66d53cdac4579100af72cf8a92b784545b37b 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 9b907a36bb8c90608170d1505428c34f898e6164..86f35827f0085a19d01d94624c4f2aee3603df3f 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 9c1397996e0a57753e97f372bce2ad1296abcbb9..9b9044400218e4e59a085272001037993ccda90a 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 7a3218c5ba7dd69085afbddd65d38d6d40a08b08..ffdce6f3c90922179e4d21df0acab33f9e9ded0e 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 ac9f600995e406ab4804b0b775eda826bfbc8dae..f4e9695ec18611a2c33439184fa501fc9dc9a8c7 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 1d9223b3d4c47e53ca928d6fb8c2dd8273e1ded6..4b60148a5e61c9cc9b2f0eea64fe128d72d1ac55 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 11319ec2d64a75d0788a3e6ea97357973b766da5..aaf227203a98f94dd93854bf936e95ec0c6841d1 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 6fa14a4e4b53e95c7f870049cf770ec79ac146b6..4dfb40a84c96ed9d54d83ef8b091bafabc28b215 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 3f2bda881a4f1a40e68b00fc24045c583ae2c0a2..9419cebca8a582f8d9dab12bc442a67409ddebea 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 240cff1e6979a4e77cb54c11ccc074dadf3ff028..a741d37fd96f247d50191b4412aac633adf243da 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 8d58e6ed4e7d7208a2fc2e28a7d94829122006bc..9b0f2c0646e08ae4c1657d9c6b4f2968e5195cea 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 bf45391172f3a3a6b739826e8e7816176ba29d0d..f42ade6c2d3e72a80aa53d6eaef140a25a7a5b8a 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 a0e9f6aed7daf8568ff27b0d484d17fc9df5da03..be5b809ec97a257543719a7c56255c7890493df2 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 a16bd4147eac7898fa222b318c78e3525dad6396..cbb0585083a9cbfbbf838889c4b74dea67f684c3 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 e70c5b0af364d35b796a6bad2447aaedfd82e4d5..f059b49dc6910d318729836bf3358f3a4ed15e3a 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 a22a0501c1901a1fa996f538e5f996fcceee378b..6f703a0418473272546f6a02aacae3821a6a248c 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 eb08f4411000cdd8f430de8b0342f97dd8627521..6e6f516ba404e25e85a59df55aa131c16825e332 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 cdc07c477457b557a82288dd676eaeca6a4eee71..eaafae091f5bd48bfc3eec8d323e2a210864c54a 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 2c5c88fc38f5456e665310b2d7feffb5b011ae3d..4afaf773aeac1c501c00e79183d363d3791f08fa 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 484d5c1a7312053121ac09ac75d39b435492701a..2dc928755454b3e9906395bca20403359c06f7d1 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 3d2b93a61e620f6916c0dd43b9cce4ca7d2974a0..e14c9952a9356961a46ef48471420b1a7b39d5f8 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 6b68db7b1b812d387b0d08b4c2e31b65ab1bfc40..80b9e45d9b9c43c460227961e0573358557b205b 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 532c8d6cd8daffedbd3816e4bc51592c9c92ce44..a6856daf14cb68072795517a20760ab0ae8bf9f3 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 8e1bb53c0aa3ffe1fa14291c88a697670f89836c..493626bcd3ec53102f7d5d00c15cc5a7045588dd 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 c18907544701c6a81a31857145a29b6bc05b9129..fb9bcfa6d9471e057bac4a2d7e98237c451c03e0 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 c390dbd877e4a59000571e2064e7eba4611bddbd..d00a80334095beb2a5fd372697b01f1c7a4c3410 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 a56a2b0ac99a64473582e792c310a74e1fa9d41c..f3c55658225bb97951a5ab9055030b84f9ed6389 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 23b52fa2605ff93256e52565adf839bcd4069944..84158b6d35d818ae80701e74cc1c5411f909085a 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 d668e47563245dff549e2f89d6a43ab168e83a3b..222eb2cf1b30706b3f73c50f1aa91fe1fda39822 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 40dbcbc16593b163e36cd7f3031cbb64187d904e..771a301003c9ff79b23bb855636c9990f8cc774e 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 685098148e10e137a2cf14d47d491fc7a4973975..0a324dcd264cccf65821b41ee1dee4802aa6ab18 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 c42d3faa2660208c556cc66adabff7071b206782..23f684337fdd0f9db16b9a89a8c88a1dd1b6930d 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 cb8be8d7abc15a26ec48d8d8fb19719633d09c9d..5b3672c4d0cc0a961a8c35f45c7843fe46864528 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 92bc8c5f1ca216e337f4897a9b1cdbd44ec3a289..3fac4efa5ac896dd06d9e3d1cbc216072fde0ecf 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 4c018f7a0a8d0ccc5adb690ca7d8ce6758f972c5..8c3766a6e8e7f9c7c948e7aab5a0af6c779ba33a 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 4c97c6ad6f5dea80cfee1869551e1ea32d50818d..bc08464d83232578cc8b57fdb1a681370eb2e016 100644 (file)
@@ -19,6 +19,7 @@
  *
  */
 
+#include <linux/capability.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/if_arp.h>
index e26d7b3ceab51cee23198ab5fc5c7fa60406ed59..2505be56ae39fd8c48c2f3ea562ec64453141841 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 f7c677e2094d168e53fe5ea890bdec5a6459b4b2..69d2f882fd065e18af75ac62ca88fec3e776ab39 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 88cd58eb3b9f4b42bfc58d55cf8a9026d429a256..1c88c2ea59aa4e605fc738f8adde1e2d01ea26cb 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 a084077a1c6115942a27caa9c9cf8b261fbf4115..9fe770f7d7bb497146ae88a708beaf254185de18 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 7b3ee8c2eaef91bac4c9d959f69785d197c1ff35..68bc9bb1dbf9fdcdf57857a2f260afdca93f8086 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 b8f5ee33445e15d877c662ad315e6598af01b794..14e7bb210075d1405300f71759e467bcde64e7d9 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 a0384b6f09b64163636d18e36c296457826508ed..b42347333750afcdf67d9347e8c9c4e88c28cad4 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 bacaa536fd515aef951f8f0e8b4d1e4625d839ab..4b22ba568b19919a1cb81c0164ba248bd90bd17d 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 2b7ae366ceb151f1c197fd116b251d55fdeb3b74..5df60a6b67766adb402a30fee44d7b7782bc5e08 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 14bbaa17e2ca8ec8729eda3702c6883865558406..22b02c6df8542138a27fcad4511eb008f0afbb0c 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 53836001d511e3af1b3e77dc76d64785f8713bf8..9c6a9fd2681229911dd206882df207aeccb5b3d9 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 855dd7ca47f3be2c6f8e79da514035ea5a3ad77c..b1e97e6825009295088d62b183f8136616bbe917 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 6edecff0b41953a99b86c6edeb664325d7f14d90..4e4c295a049f7bfba524f24efe8379530e3dc906 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 2ce8f9ccc66e33f27052c1a9e09c89de7d27eea7..40c3cc5d1caf1f1c74eb0a64cb3096aa700c4ca2 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 6df5c984a79118ae96969369dd75d77781ba0dca..f635e476d6322d5032082e5697c208c18f3174b7 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 6099facecd79191d6b1f06d060dc33fca42bec66..245d2cdb47651d4d095edd847417b5251565fc69 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 706f82d8111fe621f8ad163f43cc417a1a743fba..c54526b206b5da957d78170a6e430ce5c3b9f95b 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 4a110b7b2673911885741209b3891c5eab891fab..6c4a4fc836309e0af50b0a252de0a964a8291612 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 934d4bee39a09b040d670fd35b656977ec5ac168..698d75cda084c36a4e15cdae7c6c1809bb9d417b 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 79615e6d540ba69a01573d3999340e46d001f9b5..1f4098f1354db464cccf1b8ab0f7345c62516ee8 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 9f300d3cb12539377f30105e0cdb697106b46524..f5b7079f13d36e90d606215af99965a3b2f1fe52 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 b906abe26ad08d49b972053b2ec24e2374415eb7..a4aacb830b80772d0f59a99a8bf029b4be6001f8 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 d1d89c4491ad185df3de5da8f56656c2eecad9d0..7dfbee1dcd769acbc9a3ec6308b3cbb72813ceb1 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 a0655839c8d33ea7a755c940724e62a5f5e2626a..c6524f99ccc390b14f10c1e21d6f7ddd80cdb6a8 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 c69f2c4fe5204dd19fb6c6034278042d785f7a36..403559ba49dd74954a2ea50516c6e82d4b973a61 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 32c44040c1e8bd00734f51e3fd96aa5fcc10bb38..30cf71d2ee235ce57cbef4d32600f63dd7b8f324 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 1c39d3438f20c3a8cd8a6a7ca386e0c862e2cc5c..70a33468bcd0b6851f2320578963b74a4df9ea96 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 9ca22c7aafb29f5959bbcb3ddb2ed0296408b6c4..7039f3cf5b77e5650a99d090d5eabd239ff70ad8 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 163cf98e23863d2671a2448615fafa31f9fb6760..ef7e9e58782b2328c66ab14d4b563656ee3a84a2 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 ff9a3bb3c88d5c26e4f619c23f444352817167d2..78d5aab542f7fdfc8fcf29361cb4b053b9b2bdec 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 582413fcb62f5c4e4f0b1882e042771d5cf0a639..6918849d511ec3f447bd5f536e75a91dc61e83ec 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 abe0e44c6e9efb05bf16344fcf292700cfe316c0..8be4cc447a176a9d1bea0f33b355791dd460b6b1 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 749e2102b2be7519b8f0835979d7b0e9320356de..d379e74a05d0f7d55d22470a7c10f979bf969838 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 f35aee5c21491ebc763bdff1e5a41a6fdba147dd..bcd4ba8be7db4781699d7d862d81d2372160e368 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 4cdb31a362ca010e9d6c39aa7d332f683ed0f10a..a0c816238aa9bd0966c78a67262141fa25c2ab02 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 8a11de9552cd06427e222f8eaba23409f3b49476..62227cd5241053e14171c7ad2ab4daf2089a5db2 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 dad0449475b698fdeae045db1b06b1393a70a21d..aaccc8ecfa8f1bebc953d5e06fdde31094dc96fd 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 ab352175558885861ab3426dd8a3e921ec67bab6..417b97cd3f9495cee6ba74116dcfaa0bb836d9f2 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 d6a022f55e92a81e3d241737a90d948a308ab19f..62ddf5202b79a17d1980ed2af5e8f68a748cfcd0 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 daaec185ed36e656e3d77a96e250f35da3884e3f..b44462a6c6d3d3cc0a7ccf6c14fa3f1e9e5d7bad 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 178724f2a4c303a53b188fc9bc61f8e0ffee201d..b9d2a007e93b651842a90c92af6bc773c817e456 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 64f57ef2763c394e1f6e62584da3b002e3d7d24a..0c0705b91c28535d5bacd669fd405e4776c9d0dc 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 6565f027791eb5fe8bb91616ac6218a170c91c54..7eab9ab9f40650902c1405a98551e43362c9c21b 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 40002830d48a83030cf3158201f43e3d0bc14885..8ab51608da55ddf193c97ffd49343fe8dce186cc 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 f780bdd3a04ea6093f4b3a6a41ba61425c1da164..2490b741e16a25e28f4e30755ef002baede385b1 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 ed39a2caaf4757e0837a6ac9e054234c77034e2d..246c6482842c2c42947f8a261c5402bc87e4cf36 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 e728ce447f6ee107e5482886cb0c8f41115cb363..b9613d7df9ef85531656a8a8cc2af0f12d0cf84e 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 c20d4790258e247c9638f61a928bf4f578c163c8..5677b40e4ac019ba1e8034db6ba526aaeb92f02e 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 102000d1af6f9d8912e325f9796d4caf3028d1a8..3012355f8304e875953a732d2ab4b4e6dde1681f 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 1be6bf7e8ce698dc15c1fdb7f07e0d81f6d5d2e4..2889e5f2dfd3f95ff0558f476bb6e68620f05191 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 0c90f8e71605882266cb644f1dd3fe9825e14ffd..e08339428ecf38eb0e3341289a282c732d2f99c8 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 8305c874e86f7e5b2e4ed0f5711ec139b144d51a..ef681dfed0cca4325699368530e6460a74d8d960 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 73d366ba31e593755d2854d4591888b9e949bba9..f73e2180f333c1e2cfd125ffe1bf1de900bd2c82 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 36935bc0818f262f74db6fd655ed1994a7bca73e..b3f28deb450572d07228f1adfbd94802abaa6893 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 722f22de875351d564595ff019322a3550982687..df23bcead23dbc45e8dfa5b4b0833e8ee3fac7e3 100644 (file)
@@ -360,6 +360,17 @@ out:
        zfcp_port_put(port);
 }
 
+/**
+ * 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
index f09c863dc6bd1f85dba0eebcc2500ed58b93f4cc..4e41baa0c141a7caa8bdfb79df41d531e70d3a78 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 079a8cf518a3864e72a5d8d57031cbd4c2ba224f..d31000886ca8fcf357dc53786ed248161161a647 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 82bb3b2d207a08a3d94330114d40ae12d28bf4f7..e11cca4c784cbfd5b359a40db6938e69458dfab1 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 61a94af3cee731443e31ccdbbeab16b34de9fc66..3ad61db5e3fa52cf1003ab1217f6c66e383da4dc 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 d7576f28c6e9b55f40420daba80b0c3999aa3667..5edde1a8c04df5f991b252d99602d2687175cd73 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 41e1b0e7e2ef30403909c226c21f6365afa73c1c..5c8d7630c13e4c0a403aeacc4cf1533ef40579c0 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 9a7ba71f1af4c0786d79115aa9ccc4cf9d60c479..cafb888c237625c55aa4e35d848b8f5d23eaf194 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 c399f485aa7d1228c415c703c85ceddafcbdc0cf..2631bddd255e8530cadcf9d39813ccf5a4cdf1f8 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 11c89311427e3900fa0d5b0f270418c259f83c9a..268189d31d9c0c94148ce871bcaf0ee0ec8c3e27 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 b6af63ca980b4f1cb6be6acb2ca6762fe3f67548..496764349c4143ce5ac50c8bfd3fb1854144986c 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 c596ab5f05c358b3a95ded2d34e248e941412d49..a0e7e711ff9d0ca8f81d1a0018a5c9e6ede1e5fb 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 a0289f2197524f66ec97e81cd8ce20385a1cce09..0b871c0ae5683697b82647e99450b5fde20b5ff2 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 2b1b834a098ba42d733e1b817f4414d407fc9e81..edc49ca49cea8aae4579d34ff12044b8b94e5034 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 8dc73c489a179efb833116589a35e937d0768ec2..f1a4246f890c044a9cb548366cd7a79865a42f4a 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 61d089703806f92c385af77fc88b34c630bd552c..c88f59f0ce307c5ab12e57081c9e32443a50f63a 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 4a86855c23b3e129d1cbae4a01cf096e8b47233c..70c4c2467dd870dea94f5e96d7b776410b00c059 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 7bb2ece8b2e4215996b28cd704c051a537f8c713..f9f6c0839276f5ada31cc0c1c0f26e7ccbfc7d16 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 2f27cf6d6c654277840ad9fa3698fdabac0c4cbb..ab47c4679640be3042ce1fa239355cad438ef221 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 f1115f0f0eb2da5a9b9a0d404ec67124b4fbe259..563e56d2e945ee1fdcedd390e26043e97446320d 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 8c5d81870c0328e6f2ae1fa51df95f30fba6e86f..c294128bdeb4088321e27c8f2c919f279a32f330 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 2ff4e936bd390d254d66266ca668f72636ee3272..007e950f7bfaae1264294c88e3fa6ebf574b0be5 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
@@ -111,6 +115,77 @@ typedef struct _MPI2_TOOLBOX_MEM_MOVE_REQUEST
   Mpi2ToolboxMemMoveRequest_t, MPI2_POINTER pMpi2ToolboxMemMoveRequest_t;
 
 
+/****************************************************************************
+*  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 d95d2f274cb323bfcb8d5de1df32637e640cb826..670241efa4b555041e5b4fcb88cfe27929709d50 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) {
@@ -1190,19 +1227,6 @@ mpt2sas_base_map_resources(struct MPT2SAS_ADAPTER *ioc)
        return r;
 }
 
-/**
- * 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
@@ -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
  *
@@ -1271,6 +1295,39 @@ mpt2sas_base_get_smid(struct MPT2SAS_ADAPTER *ioc, u8 cb_idx)
        struct request_tracker *request;
        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);
@@ -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 2faab1e690e9850cc6c775cb6f26662a527c531f..0cf6bc236e4d03a61d7136b0e1cff51fcfa44159 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 ab8c560865d8ac8fde992cc05c25d734e66c3855..594a389c6526f265d9cc8b58d530702a3f1ba312 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 c2a51018910fe38bae5de12d17111e8c795b0468..57d7246339067992792a5b24b81d3cdb0a2e0692 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 4da11435533f39a4da67cb13da749322c9a386c6..211f296dd191c1c6696c5682505175a847263f2c 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 ad325096e84248e85fce230315381784ca762737..5308a25cb307083d7408fd3794f9d171c8757290 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 774b34525bba09a0024a8c10aa60243b02b5f02b..86ab32d7ab15805f410470588d23ee0e17c1fd3f 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
@@ -2353,6 +2316,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
@@ -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 742324a0a11eecda3ac5f1530b81bf0a1492a147..eb98188c7f3feb3c9373996276eec77fff8a6227 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 f8cb9defb961fe75ec5ac64c1c802f31d6e7c638..1849da1f030d60ccd28743d044b972a62063b8f1 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 8646a19f999ded0475a253a57542b8ec00a8c46f..c790d45876c47591d04f8906b79aaa134cbccb2d 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 4302f06e4ec9b026472a651059df38451bb8688c..f7c70e2a8224b442b827f255728a784ceaf0b0c5 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 42b799abba57da6bda0dc35b6fcf133d9092da8b..e07b3617f019397188cd24674fdcfabe09e49eb5 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 b6e03074cb8f9bff620f47b8838e0345d16f1c2c..dd098cad337bf19c1295943f263567ad857bf1c4 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 fb9af207d61dea365d3c3128809ada1da7258258..c4103bef41b59cc8988be725fa74822bba9e5d5d 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 877204daf549644338fb2b55494944af7127a8ea..1b0060b791e8dc6fe0b1dd4ace0a1e3f3ea96c7e 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 c44783801402083b7dbd610df35f8990eb090ef9..0547a7f44d4277768f6c4fc4b407fedd72df39d0 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 fde54537d715cf185f1d6edef655cee1136c2beb..5c7eb63a19d13732514e0bd3f50ade6ab380c4d5 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 b98885de6876c76c7b1b52f95b4a06a6fd7d100c..a67fed10598acfc3dd00234d3f3222470d18a9f9 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 8dd96dcd716ce66089c13204166170446193c75a..9093c7261f330085bf4ba843b18b8e53ad4270cd 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 8474b5bad3fe0076b8042818eb3020a0ea409023..e374804d26fbdb11cf17987b35c1db73386568ee 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 82f14a9482d0791fdd852a397eb2641e2f09e192..88da977457102e78729781f89a5a8f82f5e2f80a 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;
 
@@ -359,62 +350,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
index 747a5e5c1276f62feb3f12f4c2ade154797e6d0b..040f751809ea97c4e09af568aa327e178e9f4218 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 eb61f7a70e1d45f37da30e0ec773379f3c29017d..d6f340f48a3bcecebbf57aef61d5b0e8cd67d3b5 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 b33d04250bbc3badeeb3f00644f137402af07bf1..12d58a7ed6bc7dbbaa3a76250c9ab84497f52159 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 e7108e75653da8a75326d420133b1e471a68c655..42e8550cd2b6cff6e6d5888394aaad909581e1b1 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 3551c5cb70940cb9c4733ce645ce81ba1d9f2e3f..9d948bccafafa50bd13534ff330b6535cde29996 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 d7bcd074d383dc8bb728bd59164d430fb2cf820a..7ce9e9f567a3ded5a3f1b336db531b0538981e94 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 1689bda1d13b0b486096c584ec8d73da4464b965..dcc72444e8e7015e904c70d726a83873dbeff21e 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 a3bb49031a7f9b08373d7fee681f742bdb263c2c..7c7914f5fa02cb239fd27b109ed039045e6b2a0c 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 958a3ffc8987b19bf0baa49253fcba8b4cc672d1..ff5bbb9c43c9961485b94f8cb86e5fd349789823 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 9a4dd5992f65d6e1a60f1c0f8a490ae1bfca5d85..d21b3469f6d7a5d1a85904d14315d3c64639c295 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 104f2f8897ecc390fb0c9c8015e33436f06198fc..8cbf1aebea2ec7e440662569fbbac7258cea88a4 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 247194992374b233bc80e9e5cd5f6ca269f27e28..eb675635ae60c532e800ae6a57c1c9c667b052b8 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 94c5d27d24d7a58b7ea4de184234c47e7e1970dc..cda26bb493b3d3185177e8d3041f4ebf106e0f79 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 af723cb9d08f86d4116a2ed1eb2df2cee249803f..d63c889ce5574a6017cb627389eaf26b81fe47ee 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 f54bb9b3ee37d7e475c6e603ec0123ade364df04..aaad76e0a76a351f6b26a508982dbbfa9787c7a9 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 12d12b43a6f1349381797c0837cc4eac0db761cf..80c0df8656f317d5517d49bd2df494a95fb10f13 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 4d10bc31d4618ce10e738d9db610bd8429855c72..09e6e3bdfb3e6d9b9d0021ca3faf9f8d99d59091 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 14bf29bf5781e6f575f0c284955987e6e463761d..0d2c2eb23b2328c40594bace90dc114db28c72ee 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 2cda7ad1d32f35e328916267ef8e05f84a2208f8..80e192d2e77e8a5f8f82fa6fb3fd108d7e4e3946 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 6b118c15b49e3d147d99491f2b7c86d62aa011a2..bbf75eb6d7f218dbaf91066a2b542c8f95765323 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 6a7797604c97f2cb89067f84c2b57b0737e58f44..ec31a39706648a212083d1215e9e51bf2ea75519 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 b06e81c526e8e5c1ebd3d99d1918ba5701cc8e56..0700a8bddd1e415d721a2815fc30521824bc7875 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 57aecfa883c7faab899ff938303892014249d97f..a3053b8da1c64c67cb6876488884c039ee3dfca4 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 e3ffb067ead18b8916e34ec179dd162966e9f814..753ee05123425211c3c22d17ab15c9432ded7a2a 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 b7322963cf78bdbd5ee078c7edb05a791183f8ad..9aef87fc81dcd3560cda172fef89471b87b14bec 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 52b2eca9e73d37dec67cea2fbcbe92ab8f8556c3..d544698f2414e2b5685fdd5ac7df950548582589 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 19d87553d9061988799126879412f946cb89a3d1..24c8b8ed5b4c4c04e8b9c860f13c7c1dcd5ddb49 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}, {
@@ -952,6 +953,25 @@ static const struct ni_board_struct ni_boards[] = {
         .caldac = {caldac_none},
         .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",
index f63bdc35cffd973fa6a2982cd279e578ab48ee60..344b82353e08ba96013c50cfc93b822d949d8aaa 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 b89e1ec267c5d3dab0a578d760641d822fe4683b..07c21e686f270b69a92baa5689ce52a230347e5a 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 a2196798394240ae793a8d6799a4438d80d6c7d3..82aa86e718b2c819ff6e81e33282eda355ea8e08 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 6294d3814e72c8ef7c406881b8dbb931f47df712..2c3d65a622a7897caea27f11a34d3ce42202b78f 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 8f2e91fa0a8648991909c790a1dfbe5c9af9f7cd..10e21db57ac3d87143ad6dbb2f3a8ed16e8dcd15 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 a839d8fe6cecb4777f13aac053a88f8d3074bf43..fa973d86b624810eaf06a799c64f54453696deae 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 1610b845198f79f2c71cbd6f666613cdebddd29d..d384c0ddf06916275a666ea8b8fa8bf054b2c258 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 4d390b2377422d431b325920d77f7122343b2c77..dbfbde937a6683316a6d8f5812556fc04a27edc4 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 8fe543bd99104cf9b177a1ce78410fe2ac3951d2..3a4793a0fd050996d83c2de8e07d5e1183dfd4c4 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 9504604c72bd0706983fd2ff279adb564700453e..ce064e8ea644dd1acb3c2dd6a948e450266ba82f 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 582318f10222160a9a9615368c4cff1fcf87b8cf..894eecfc63ca5bd3e8e84fb2b5bf11dc4680df05 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 beb99a547f09bfbc9c896d8995b9bddfed5a0728..4586650d65c38b30aec09d1314d798b3ff77f9c8 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 1fa18f2558148b0d5e0f685b1289b41c5377bb1e..768f44894d087ec2fd3bc2c9b7db93f727a06ce0 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 d549d08fd49591ef16c2a3926be3696203f922f5..f6cc2625e34195c4c6220514e44381d9b3338f5a 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 9111dcba37a128eaf9ebe18a4b1b13302d3efd92..8ccfff723eecd6e7863b8d801f68b01f4ed8129b 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 dd7d3fde96996102d719984e5cae486acdc4a8b8..4ce399b6d237546961b826734ca8c77003915eb4 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 0d111ddfabb22c15408b14b891c094022fe85225..2eb8e3d43c4d6a503ca58cf9de70f44c357ee4a7 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 7f44e5e724637d1293d50fb59f68c9fcbf503630..efe38e25c5ed5c657078c7f96c4fd4507550be14 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 fb1735533b74c1d84091f6f35a36b4c31b9a7734..857ff450b6c9dbd8798980bd5364a76ba0e60ce1 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 9d589c240ed00eab97d3e0a07dc0e426940513dc..019cc4474ce80cfe536a63c7054ab096278c0703 100644 (file)
@@ -25,6 +25,7 @@
  *************************************************************************
 */
 
+#include <linux/sched.h>
 #include "../rt_config.h"
 
 INT    Show_SSID_Proc(
index b396a9b570e2f165ed1bb966af75932fe6a4622e..ed27b8545a1b3d507251f4387a4ac17284dd2160 100644 (file)
@@ -25,6 +25,7 @@
  *************************************************************************
  */
 
+#include <linux/sched.h>
 #include "rt_config.h"
 
 ULONG  RTDebugLevel = RT_DEBUG_ERROR;
index 76841f6dea939d609a250a2ecafc6a8947c9116a..aea5c8221810c5dc22b25cb59a2860fcb30247b3 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 255e8eaa48362447964c0295405768f0cddd98a7..2b3f745d72b7cfb4dcf2f12e50d8c5955c5afc13 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 5be0714666cbb86610eb2a9e2d83d415801c1041..3e51e98b474c95ae6f6ceda764ac9bd5ea1a594a 100644 (file)
@@ -34,6 +34,7 @@
     ---------    ----------    ----------------------------------------------
  */
 
+#include <linux/sched.h>
 #include "../rt_config.h"
 
 
index d2241ecdf583e0d6754e0e75b044b56da345312e..9b94aa6eb904043d71591a3507049fabd06fab3b 100644 (file)
@@ -25,6 +25,7 @@
  *************************************************************************
  */
 
+#include <linux/sched.h>
 #include "rt_config.h"
 
 ULONG  RTDebugLevel = RT_DEBUG_ERROR;
index 236e42725447a49c395264a884737af921f22bb0..203c79b8180f3fc1c930348a5e3cb4c954150ba7 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 013c3e19ae25a4486e6bab3e8bed44afa30922c8..4c5d63fd583364dfccbcc4c5b72ab8a46f898819 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 6fbe4890cb669fa88303c082cab5b65123d1ca1a..18392fce487deb22dab8054c3ae248c282237c2a 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 59b2ab48cdcf697ef1b99a9f08c061c9b89367a8..334e4c7ec61bda83a9a80792a5f95f4e6db5dade 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 8d8bdd0a130ea80bd2890b3a63b8f4b157bdcc78..a08b97a09512a92c4544d1cfe22983945b1e7464 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 3100aa58c940a7ee6c3bbad313df5e87a2b7d624..37e4fde4507382917a5aa4c4ecb13a4c43941f6e 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 1a8ea8a40c3c9bb6e92b895bce1b1e32c39f8a7b..b1c54932da3e5931cf602d9bd7cb8f0108ef4df3 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 16256a31f993f75dbb66c87ed4a257b3bca3e696..12c2a18e1fa2a832803aa1fdc11f661b837bc5ed 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 2fc04df872cabacd64bde7995a05dfbcfe9ce7e6..eae7c4579a681d8ab4b0f2fb9a4ec98e013c6197 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 223483126b0e774975472a6352754b81c2162a34..4e34a1f4c66b5a3159339724e3253c57722216a5 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 d4fa65489655c3792abbc69ad68404e201c01ca6..b0802a7aeb5f01b40839e54bffdefaf7c494ecbd 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 770f41280f21d5412a93761b2ea8522b88fce4f9..b8c95f942069c22be8f5cbd94c876950111cd899 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 d76a54d59d2ffce04a8d2f1978e83e058a56f573..521e7b989934eae69614cfa1a74ba32ec4dcd52f 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 68dc8fa094ccea523f3b40aca0bbc48261b50862..c3383bb8b760dda21229cedbca5daffe2988a1b0 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 c64ae03f68a085ab9712d40b921282f58292ddc0..fd8e11252f1b254ca5e5a8b01182839d3ee024bd 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 10775902433540e063de4e5370555e078232a9a1..6146c6435ddeebbf4ac63ee70f9f39fcc49ce52b 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 87f8a1192762bde6cbe32531c7a5e6ca717145d4..f890a16096c0c628f04b8cdfa098626b0d8473c3 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 3d2a84c458299910f3ec9b1773ce0d84351fc1a2..e139eaeaa174f6158ee82aecd302bbddb8ab5d6f 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 8960fa9ee7aa9423ef870d86c63cf768322b8d94..00fe0803c21c3e0f31243866dea1c4d7c4483f9a 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 7f96bcaf1c601a8fa99d54ce10ed9d1aa0566c11..05186110c0294ce3218074a57216ed923754da3d 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 940460c39f36683c2d5f93ce65ddb7aa828eae68..132671d96d0d90b1262b2c18964b90e3aabb0e9a 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 8950724f168ee7092fa11618f47c9ad02f68eb64..067082a7d759f2149029b1735c0f55a779fe861f 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 9959b658c8cfa29ac9b9394e597b455bb6033971..f44294b0d8dcfb99300c761b44df6a06f57c653b 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 a9d7070472021908aaa17d2e32828db50857ab3d..e941367dd28f8ab907350e83cedc7e1b1ac40a94 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 864f0ba6a344ada55735e0f06d02f6033edb1cdd..2473cf0c6b1d4ba294677c4259941f56151c41e4 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 33351312327fbe900bcb370bebc49c37bc5a4cd3..a18e3c5dd82e48142519f85c1e36d26216052a47 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 f37de283d0ab769e37c506c24e4e433ba2ffb583..167cb2a8ecefc1849545655cddf408dd3f009a7f 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 42a74b8a0bb82e3dcc0ab0becf156e44db9c32a1..fa3d142ba64d966aa4bf454a4f2a55480970bc4f 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 c52a681f376cba495303fe843e9cd0839a15a234..01ee0b9bc9575e7e8902fd67a66bea7ae4234fff 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 03087e7b91905ff84492d9b002533fda6081b82f..9a537aa07968d7b449972ba048a7d99d74f44d99 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 3ea05936851ff72568ff1e655300eee6bd013df9..b25cdea93a1f7101da89b0e85f7183366e7468a6 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 e35d82808bab3be9aa32e1c0b340fd1c80c72458..5c774ab9825272ead015fe3420f00a71dba81616 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 fe60f62a32f38917c71869017cf37ceccd925390..1a253ebf7e50c5bfb409215fa0652a398aa76c73 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 23cf3bde476262d417ded0792a87933cb58efb36..83b5f9cea85ac9f43af8d3b1eb87a259517cc05c 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 749b53742828ad4a4a06767b797c9cc4a9bf4045..e33d36256350b8d0b3a4c23577d9f59a92ed1ef3 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 c632437c7649db90d22219e0ad421caafb8e5db2..562eba108816cb689bda3eee2b9b2125150c77fe 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 a9e05bac66463c919cc0943d9df25b0b6d142c3d..0db3fb2dc03ae500f545b8356485c6b460c12859 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 99911e727e0b7950e4a11dec17bb17f08151e5e4..932f9993848175e476244fd23fa90303cc6b7d61 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 29092b8e59ceb7347a2f217282d7918eaf98cfe2..4fb120357c5569cc7ab1bc5a90e83f1851910f54 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 803adcb5ac1d3e358f481963b1c1d20e6d23e260..b84abd8ee8a585f4e4ff884077be4f0f3a6ce7f0 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 f2f66ebc73626a28265fe1f0dd0a6887fb10038b..fcec87ea709e6d682f4c045d79c19c2c4a1fbcda 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 381d648a36b8122e974b0f4c5e0001611d8f0e49..6aa5f22e52749e2325997f27e34d5e2ba366e511 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 fbfd3fd9ce1f876f4949b15b1de016e7877d1348..cc1d71b57d3cae33435d2f204fb60b12dd6aa41d 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 2cbfab3716e59c3764cf333d5bdb933add1e69a9..b10ac840941137a8516da829a9832b0ace64a665 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 4a208fe85bc9b10c7af4a27a48af8257e5224195..698252a4dc5d9b59878a26b64a9a5caf00c8efef 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 e0a8b715f2f24bcf6046e1cff52dc9cca1a304ff..a591ebec0f89c0af5d0ece8c3e9685fbe3d80d4f 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 ab3dd991586b86a961e63c26594e7f3403f3b9aa..68e80be6b9e1888dbc82b7c8cc6584a9f7abddb7 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 33c9e9cf9eb2a1f92cb1b299c419d4218cc90747..7dd0e3eadbe64ce3fab049ed2af23e1ba7e424f4 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 4f883b1773d0541f2b2a536c2908c68a149affe1..9c60d6d4908a411019f61e7ce73e2a27877a9912 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 20432d3455295e5fcac7df0b3958dfd0c6679ad3..5ac900e5a50edbb3a44418271fa900272f882ad8 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 deba08c7a0151da060ffc66f01a02325da1cbe6b..bbe005cefcfbee6fc27d139541146c7174999468 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 24fcc64b837d443d01c660ddccf93288fb407d43..d6231c38813e41d7b3072312907fcb33067de2d4 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 257c16cc6b2abb68793da0ea2c882c3fea664f1f..1296a097f5c354285efdad53d7e10388cbaa6a7b 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 f7373371b137fd996a100ffbdfc74375a847afe4..3a7873806f465aaf02a41213df7c2d41e5f866f1 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 ad4998bbf16f0855609d5ebdef763323413a3615..cd009cb280a50b29d80a50610f8303a4badbd9af 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 1085a577c5c1c9b209fee089c1c36ac156ac5bc1..80f59b6350cbdcee5a9864ef51990c51e2309ad4 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 f66e39883218c6052b3da7420cb6200818733787..cd44c68954df55e65dff18ae6f89c007d698b938 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 0f4a70ce382372170291b36188ac93b6ee635ea8..c644e26394b47360e1a1d52c684d59d16f16d609 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 1128e01525b117001841dfd3462871bbbdc7e299..9ec1a49e23622a6787d93ec3280f62ce14aac93e 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 8c075b2416bb6237402326dcd92d9d00dc454b7c..5019325ba25dda93486a08757c68cba44cf0b4a0 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 cb7e95f9fcbf584151a8f6a13bc3bd1ac0a08ad3..b282c0f2d8e565101bd17a7f0f37e220b9b17e6d 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 aa6b2ae951ae9a15f1b28b7de4438ce8d551aaaf..bd3fa7ff15b12166bf0cf2ad86f3214144f914c0 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 1aa5d20a5d998d8d4511cae37d24620128f10474..ad1f9232292d264506b16cb5b5bd8a625dc2e88d 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 62424eec33ec1ebc7fda3cc909afcbe611a502cc..1093d2eb046ad06a02e4082fe0c1656fc953f332 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 e20dc525d17763642f65a07835a4a2ca462f1a4a..589f6b4404f0b1550718c66353ec4c807c0a46ac 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 079ae0f7bec1b0b640eb6fa3d04a01f50c2f2cca..d4f034ebaa8a44080af462b8876ecbc632c62cee 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 b2f149fedcc50ce2a705c51c8f1148ec2346c8ed..4516c36436e6187e053d74c5766ea020036a2218 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 1d9a6f54658ecf1383094edf3f98020d7247bccf..01950c62dc8dd4ca58e1e4e0700f5e9b51771dc7 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 42e1005e2916ca19be87b0f1ad806907f849a105..d065894ce38fbf952a46d2da87da67b34374289a 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 f2de5a1acd6def8375dcffa11df4887fd9a04b28..5c5a1ad1d397417f39747c60d3c603357fbd47ec 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 d5e59556f9e2d3a056432535129021a7d42d25ef..70dadf9d2334c9a26c88bd10dc43ac1d20251b52 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 125e605b8c6827e60c707a37939598b4468d482e..0d0c8c8b9b56dc95660f256624c3afe754939870 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 200c22f55130ba890d37a73a0e565460e8240315..9dd5880428803d78a3ad349d43aae049dd4f4344 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 4a1f1ebff7bf232ab60f507331b60aa71b3903a3..28d9cf7cf72f9fd1ee8aeea96085da394d48702e 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 f536005807269728f3285f7bbf6f176cd790e5c2..fbd2ecde93e409ea9287d068d3f2322297c910cc 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 1e8f02f440e6f5ee6db426f0e0d9863731b686b0..d3c824dc23588b668096cd368efec6755cbbb9af 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 5ea80b19785bf5472bfb0cf1518ba739241f624a..f4ca0c7eb51cb12899132cb755679d9b362a6b18 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 3f8c4f6bc43fbe8a48e23e7c2f4e5407ea50a036..7a8adc06eb34b964ffe5479a464a08a698a33a32 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 873cd31baa47c6c77022918665a5f343d93f8425..15cce53bf61e7832e92fd8fbc72f08f220a8084a 100644 (file)
 #include "v9fs_vfs.h"
 #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 5947628aefef142f99edb0bcc67f9bc625d125aa..18f74ec4dce922da7ff4d6f88638e7aa4077ae8a 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 d4bf8caad8d0827e627fb995b1db4e189d2142e3..2126078a38ede8fd89180b3051c835142785933f 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 9cf4b926f8e47a509f0994ad0e696d79205335bb..8bed0557d88c17ac9600a179f8127d855e509bab 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 69b355ae7f49139d928ec398807b9f0bc908c307..36160424427124947179e7270bfb77e03dbc1686 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 282ca085c2fbff854bcf4a396d0773db129c5085..c0861e781cdbdfde4b7c42ec1b90032f2059e69a 100644 (file)
@@ -63,6 +63,51 @@ struct btrfs_worker_thread {
        int idle;
 };
 
+/*
+ * 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 fc089b95ec14f24c9a971b44f3718c2029f241ef..5077746cf85e049e87bcd8ded49b592ecc271605 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 a54d354cefcb71894a89975fae23ff94a9b939ad..f6783a42f010965e344fddc68c2689a7d4a9fc14 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 dd8ced9814c4a5d0bc35e9bd8ef12cd8745382b9..444b3e9b92a4b88391fd610a76346530436baa01 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 af0435f79fa605e96f0461efd496599c576eb7e2..02b6afbd745020fb51bf43d88c93025459687e12 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 359a754c782cd8338f0a1bf0d456306e3240c32c..e238a0cdac677c06b1774018bf549b03399da4c8 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 de1793ba004aa472afc8c983521cea7380ef4720..96577e8bf9fdb62819ab2dbd5f9da91200624596 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 4794ec891fed31a3998098cb1999818627aacb12..36de250a7b2bce5ef6f36d35ded4f1f88a2dfc58 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 f19e1259a971d52d62a9979ba311d3f136289e05..06550affbd27ea9181bd08db8d1ea18d9e8f42c0 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 112e5aa85892c35dbaf921ba16bba119d4c2c49e..dae12dc7e1595e5e4a78e6f9b03fe566b7dcc24e 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 9a780c8d0ac83df7bc2444d90830e3214649e8a4..cdbb054102b9f860ee4d119dfff39e891ac29438 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 897fba835f897a0d02f1d4677447fdcf70d115d7..5799bc46a30993a1cb477fb3a4dd9db23dcad6da 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 361ad323faaceb4ed3313bd1e2904ea29ea7d2f3..cfcc93c93a7b4db99b87ef3b91b30cc8d2f7e36b 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 9de9b22364190de829c4479cc74b81578f41b18a..752a5463bf53aee147068c2a0a9f678e12250f38 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 0b8f36d4400a70919d055cac8b467b7a0f9c24d7..bca82a4ca8e6d8f78bad1bd21b511a433aaed48e 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 663c67404918dd30fb1c5cf0943b07b2455018bd..d4e3e7a6938cddebb56e05ae4131b7055f08be05 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 7827841b55cbd5399606cd02820055f2ff6eded2..741666a7676a80a6553f5b22a37a41dd31971d3e 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 d09c7609e16b3281a0b7658083888c277fb1ccf8..0776eacb50830f14c405bd44d8d8817dc9554295 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 b0fc93f95fd0c7f18ac60471c60d767221df37af..b6dd5967c48a2785074f75db2dacd6a7370a9ec2 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 43003e0bef18606947a67315472519602e6a912f..b09098079916ee082887b18bd43c82bc28e6805c 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 240cef14fe58b84b95e9c89934e5c322bd896ca6..70736eb4b51652e9ad64078180ffc8c154265df4 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 8aadb99b7634b76b20abe2314cf050d9b571472b..1cd6d9d3e29a53dd102524b3b065b39642672dbc 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 101fe4c7b1ee6db074eecdd56adf459736c271c3..c6ac85d6c701f5b7d82e069c9a3f82a67a51d0b3 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 72743d3605091d886247cd21310d656f4ea91421..7a520a862f49fc300967177d3e7ca911b295bd49 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 984ca0cb38c38be74fb091d19e8d811fcc1d95ca..00d153f2f26134523ead16e60106800eed8eb861 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 312211ee05af39618274736a49096cb88ff067de..d4ca92aab51411de0bab1bf8824e9aa8974b8d17 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 f313314f996fcaeb4457c04d64fd8eae25338423..87e129030ab1564a69061b82b9608c59cced9f1a 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 9b9d6395bad36127b04a67b8048d149e2bc89d3a..052f214ea6f0c39657d4cfb84e3eb96f7a391818 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 175d08eacc868226d581d46a2101169bd103f096..bed78ac8f6d1f5e530a93c0afac22e1cfdf2178a 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 63976c0ccc2539d72155d11613fbaa9322358afb..99ea196f071f04d81c82fbc42bdcb000b9f0694d 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 32062c33c859496198395db435117c7c33105d3d..7cb298525eefd1a5ebcac1870ce08679447a3f2e 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 6c3210099d518406b8453296312d759396fbae41..e1d415e97849a882052914509abaf59804d47b43 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 2636c26d56fa1c7d214d1981c86d9c41a118b946..fa3408f201126790eb66ac42db7eff3b12f345e4 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 ed7c269e25143175a21156a4c5ce784e3efea4c1..ff37454fa783f42196b733a9723dba7567c37f72 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 e27c6cef18f291abb642141e762055bcaf85f4f6..0156c01c212c26ee9cf358a2ec21ed31853f33af 100644 (file)
@@ -126,12 +126,6 @@ nfs4_schedule_state_renewal(struct nfs_client *clp)
        spin_unlock(&clp->cl_lock);
 }
 
-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)
 {
index 83ad47cbdd8ad5f584849495989229be9ac47bc4..20b4e30e6c828e5e0aed77ea01c445a52caab0ee 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 29786d3b93266e1d78da4e3d05e94f5fa360961a..90be551b80c19fa2733349cbecfdfe231f2a5573 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 5941958f1e47325e9497cef3101065f3efd73f46..84c25382f8e3b35b13f6509463aef70308bb3164 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 683df89dbae5a3366ac459e660776bcccc69bc47..6eff66a070d5e39c23a8c2af4f51f6b62ba91881 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 828a889be90954962cc30ae0b229af4525dad768..7e54e52964dd7e7b0a7de23ca682b33b9f8f8e62 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 c8a07c65482b079d50483beabcf8e2cfb5291369..3165d85aada2d5ee14a7e46dee6f0c8d07ee8686 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 3816d5750dd55eb6f8b2c710b6a017a4694b450c..b8bf53b4c10897802c83db2c1ce1320aad16236e 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 f38fee0311a7a82b3ee19ece135c3e17b38e1cdd..7b685e10cbad8cc9b052cec48737fbf7bf6f7afb 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 52c4151148383c2e9cd89f891e322241e110d3c1..ae17d026aaa3f496fc0bf9d8522f52d027d8dadb 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 56013371f9f3cdcd8c89a4455233522a415291aa..a44a7897fd4d20988aa933a89fab2d9c1600d53a 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 c7bff4f603ff1557f7663fa22b9fb7ae8ed8a2e8..a65239cfd97ebc9aecc3914e9f228673b46da9bb 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 2281c2cbfe2b4ddeefc5d4417de1e40dd7df4dfb..5033ce0d254b90dcd0ca19162c6cbe9df254c87d 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 b3208adf8e71e0be84b46c318209b4c997b61b10..71e2b4d50a0ab5104087237c350c20057dc3e38f 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 0050fc40e8c9f373a3f7c61855870ad7d4a1952c..5fad489ce5bcde2ab514e3108f112cd5de005f17 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 561a9c050cef687ebc48649af895f163572c2476..f5ea4680f15fdca8a009f66a979bd6d3805244f6 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 381854461b282fe928c93cf61efb41edb1ad1acf..c2e30eea74dc2cd6344dd6710806465b029db422 100644 (file)
@@ -185,6 +185,24 @@ xfs_destroy_ioend(
        mempool_free(ioend, xfs_ioend_pool);
 }
 
+/*
+ * 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
@@ -192,13 +210,13 @@ xfs_destroy_ioend(
  * 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 629370974e57e6010eee6fc44e7d5d7127514c1a..eff61e2732af27c8aad199ebab5c66d83c5b904f 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 da0159d99f82795cd28277138a1f3d5e06916b03..cd42ef78f6b54e705ad604e3ccfc4eb1a3df3743 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 49e4a6aea73c3c85f7d388d56d4371867c930178..072050f8d34634d59e4d200dfe14218bcf0e75ad 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 9e41f91aa269f392ae4eb00490b785e21d74049d..3d4a0c84d634f947f36eb3bad04128cbc603f17d 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 bdd41c8c342ff7b052de193a998076d00b62667b..18a4b8e11df2d4241bcfafd59297c30e961241ad 100644 (file)
@@ -976,6 +976,28 @@ xfs_fs_inode_init_once(
        mrlock_init(&ip->i_iolock, MRLOCK_BARRIER, "xfsio", ip->i_ino);
 }
 
+/*
+ * 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
@@ -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 320be6aea4924ed6fdcf4ac1e581c0c616d04c83..961df0a22c7837e9a969a8ab73331c594d5a6116 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 4e4276b956e8c5f925490dec8e4dfb320ed071a2..5d1a3b98a6e68875a47dc283483a9be376cdce42 100644 (file)
@@ -876,7 +876,6 @@ xfs_dqrele_inode(
                ip->i_gdquot = NULL;
        }
        xfs_iput(ip, XFS_ILOCK_EXCL);
-       IRELE(ip);
 
        return 0;
 }
index 7465f9ee125fcc2b80194043e9c141799a05ffde..ab89a7e94a0fd4b861114f656b99e5fcf0355a14 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 fa913e4594421adefc392e80c254d492b8a9ec91..41ad537c49e983a8ec052bfe38c68814f9a0d796 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 ab64f3efb43b3a375bf690b7ade11726db94bdc2..0785797db82886eea0833f3fc3561204e4e50c4e 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 c1dc7ef5a1d853ea935fd954ad0cf4863e701cd4..b92a4fa2a0a12eda161c2ff897bd820f5cbde1e8 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 0b38b9a869ece2136bf798a5329d2a38b8bf98ea..41555de1d1dbd4e6befcd64840712de5beff8235 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 47d5b663c37e44a2b3528413edba37ec43eba880..9794b876d6ff65e34336e390a9becca46fa8e330 100644 (file)
@@ -231,6 +231,15 @@ xfs_inode_item_format(
        vecp++;
        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
@@ -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 b68f9107e26cce1e3eb7f4b08f272d493a9d8b06..62efab2f38392e845bf82fc8ba48825f3c016727 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 a434f287962d18588e0711110b8b758818b9ceee..b572f7e840e0b82a372225581d87c85c104dfec6 100644 (file)
@@ -2475,12 +2475,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
index 23bb4dad4962cee55b3d39f9ce14edda6043cb9c..62f59080e5cc215edb843f928763d9898055071f 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 ef47dfd8e5e962cc43ea9ba2e98ff33a9291abed..b29e20168b5f76d33fe572d42333070069647a1f 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 4aa5740ce59f1c0808cc32595a32997aa20df049..58c892a2cbfac410cfee2613acfec0dd66b750c6 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 3f6e545609be892f79374033d79a851372d1e2fd..e6f3b120f51a5e4f9d51bf694b8ecba0b8d7503c 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 cff4a101f2669a0450d4ab5679402351141b63b0..1feed71551c9676b6863cf1bc96ef4c2cd86ea60 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 6299a259ed19ff371fecba9f62bd8daa2bff5c79..4fb357312b3bf4b4484879fa5ede0942e39fb15f 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 25119041e034c9f51bdbbbfe4d3ad146ac9ad9c4..221cecd86bd3bf031e583ac37139be43355fbfec 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 44717eb47639211ec9196875fe20212c72d603c5..79a2340d83cda45c88138841fe4b2a8a3892bcad 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 aca31bf7d8ed36ae03a07673fa95645bbe635d20..2ea3e49218129a6a4a4f314858ba0e0cbaa49691 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 45a937be6d38c1079ea0b92adb8b595d760af1f8..90a4ed0ea0e5201c21cd475dc52a330f97b0a67b 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 cd3d2abaf30a806f508d0d98950f97739ba26562..0b4f97d24d7f510b243bdd8cd461daa2786eaa19 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 8ec17997d94fa0aafeaab5cc95824194c9e913f3..1e5a26d7923216e2de6883fff7c4faf6f5507036 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 7beaa21b3880051c341d55358b5312cdfb10c65a..297df45ffd0ad27e8219aaf3715a00d030f5bf54 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 2d02dfd7076c4697673433b0cc6c6999722b192c..508824ee35e6e4bea836d0a42d40a83dc42a570b 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 400adbb45414f74f71e989b9910cfd3dfc3208ca..ff8bde520d03b078c5e343dd9437f005fe915fa2 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 b78cf8194957644b05908807839b0ed570802310..7ca72b74eec7e4142866f44debf96f594c70037f 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 d3cd23f3003962de7d50219b1967a87e37f9d364..f4e3184fa0540724d7777d0f140fc189cd806941 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 76319bf03e373b89719d00feb0cbfcd3bbeaf293..87698640c091e1d91379ea01050242ec884645da 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 81bb42358595728f2c10b02077c4edb7cdf3a219..eaf36364b7d44ef778c1b8f346cc09481c6ae53f 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 6547c3cdbc4c17cddda61d0f92fe83352de2f77c..82a9124f7d758ae74ea04812da2cb51732dde893 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 94958c109761287798f187e1c2bb96abf0b5693e..812a5f3c2abe90da914e7c998b7b7d8e509b0e38 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 da1fda8623e089fbd8d1a67d40f317216e071a6f..b0f0f3851cd4c704c8b14e57b74d209a6b5ecc47 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 3a9d36d1e92ac815cc56718e199a47701f9fa965..9e7012689a8407b65d21b57f8ea97760a40bb888 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 931150566ade8d720f156665b2a5400bbc499f0d..a3baeb2c216156831606a11c5bd8636d80b8b76c 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 6fe0363724e90a6271c06bdb955d80928a765fcd..3ebd0b7bcb08430e80d56dfa717785e186c90495 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 37682770e9d2cb90c22d7032cf49293b502a1584..9642c6bcb399439f5b36bb45f3df5a66f7d17ca1 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 df7b23ac66e6dac7610efe67fa95888f0f4e3ae2..bcdd6606f46876c16a9dd64ab41639b77c12740e 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 3b461dffe244a120f012294ebf46ba718526e04c..3273a0c5043b96321bf6dda00bc44d4d4c254003 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     */
@@ -100,21 +100,6 @@ struct cmsghdr {
                             ((mhdr)->msg_controllen - \
                              ((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
  *
@@ -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 489019ef1694fdb883993ef3eafda49ef7ae4cb0..b8508868d5ad428ab0c220ee2b39296e92eceb89 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 fc0bf3edeb6705814af2b1ba8428fc0a39e78e0b..57e63579bfdd7f193511675fc9ed26141b586638 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 c134dd1fe6b6c45970175d445836f009ea7d9608..09077f6ed12850cd43a44e26926a3f7b13fcacc7 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 c17eb64d721387a44df43c611ddfbc9e8f510daa..ce911ebf91e82c54c65cc2f46d428ed4c1bcab6a 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 ea7226a45acbbf46a36684a8596e1734e5f52331..095e10d148b40d32780621dec6f259a5c90c22e1 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 09d730085060afc91d3a01d60c9698a274e57555..1418f048cb34741919b788160a4657eba462b2fe 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 15cb666581d7cbdb42cd7d39f4d309ac59399fb0..fd294c56d5717d56bc0df1412d621cc059673e1e 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 b5f51980601445b79a13493cb8521a1c97692bb3..fe885174cc1f061ef8d0b706a362d27574ca616f 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 1f41734bbb777b0147926ed0964a79d84fa6d026..085e42298ce5b1b9f353f457951e7fc49a5ef949 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 48121c3c434b6781661167debbf7b4a7540945fd..c4d5de896f0c1b0fa1cd2d0b2e98dadf4a4d8b8f 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 7ef0c7b94f31f02781c873733161b36066b18ff7..cf24c20de9e48e43a4712722196aad8555207d8c 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 e26812274b757f0355293a15f33a776dd78348d0..fb00b329f0d3dd91d3998871f4dc080d9b4f2065 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 b63b80fac567a2e103c996d8c021b10ef6e150e8..f93ad90a601b62015466d8800379c89a79eed564 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 ef91fe924ba42ddf5a0748836726098ec2a95f9a..4d22fabc7719de9b6b620ebfeba29332a2b31e2e 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 466859b285e1d6d4de4c16a004d3607ea75bc91a..c75b960c8ac8e0e954c400f43c4c163cc360caea 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 1621935aad5bc5b3e69299c136c685dd42dbff92..9f96394f694e42dead181978ce59fdb6443df8fb 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 d696a692d94a677af807292b8aef92c80785ea50..e0f6feb8588c0e062161431b31681542bb58450b 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 887e57e3e223fb9ced92b5ebfa8bc91f6856bb76..a72edd4eceece2438469bd902e1c81e5fb2e4baa 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 084478e14d243bb4bea2fc8aeec0d26290544de8..34c46ab5c31b8aba91e3859d913e539e326d63b2 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 3878d1dc7f596f8c7c4fb8d3fb547448a9b2dba1..a5e885a111dff359c0e8931c1a8281d8542fa134 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 b62a097b3ecb05b010f49fae1211e113ab3e5023..6e728b176904664abb12f132fa63aaced2a4aa00 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 c7bac39d6c61b7da35e5ee1e9a8c9e33a2033807..f51586406d622a03728152cd4f5c272433b748f5 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 7449819a4805b14dd3c68d7300cc54ce5d4b8044..5988debfc505c84c8c5f7abeb0b5fb1e2d88f1fc 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 ca83b73fba195ac643a594f9cae3abf4347c2f42..0249f4be9b5cf8fefe9885b6093911746d7a9cdd 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 5859f598c951bde881a9e7ce1c29d19fd66b3463..f7864ac2ecc1ad54c0af6b06b6f9d2da4a93f1ac 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 266c6af6ef1b089a1c64ee96428bd153db39217c..166b8c49257c589750f0b67479011ba7bac97038 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 b911adceb2c488523d0c2809049878dfde1eed27..fb65e822fc41ae698c282aeadc6933b411aa8a78 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 6d7020490f94fdc3563f81c0582935492f724a34..3e1c36e7998fdbeffa17142bade5c358c61a2857 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 a81cf80554dbf4da46c53cada05fc747f7c8eeff..17c71bb565c6ed287901aaef1c201a3c70f79aef 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 3815ac1d58b2660c5e7eba0d9f201e6201d1b967..9af56723c09605a07742180983e465500cef2d9d 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 50d022e5a5606dd64d985afbff9d33621f06ab96..ec815a960b5d526a29992dfd59e30ae21e35d9f3 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 bcdef26e3332f7e197b7fd8740f697010a257bb4..96b45d0b4ba50853030c295f5b0dbcf9bf33cc88 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 9da58eabdcb246dd3b156d7799ca49bf2799a304..d656c276508de6a9bbeb62407b59e477ff7ff61e 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 0f86feb6db0c227c2f4e7b1c47c8b4d2c0e92156..7f29643c898549a5e523d07479d581edc4e870f5 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 04b3a83d686f63e430723e2a3e26a1fc3d3e0601..04a9e90d248f8e981357344dfe24623660bb2627 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 17d8bb1acf9c411ccb6f1ae6aaee28be8df5f23b..25596e450ac723d7a9409cb304784224f5fe3990 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 b101cdc4df3f644d1ffb170861bc9c971a9adb72..890f6b11b1d3afe3cde18f816e5a77fb09cf99cd 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 37ac454830829cc84f7fe3d816f0c9e69e684373..400183346ad22b0e216d21a429295e2cb28b123b 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 233768f21f9735845c32c6ee9e3b27974a73e3b8..697c0a0229d47026c07434910d7dc231e2d1bb97 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 52b06f6e158c5e695f5a53f61eb11298b2bed04a..0536125b0497ab0d5f66bac3dc81ecec26fbd0ea 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. */
@@ -841,18 +840,64 @@ 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 8e8287a983c2b3714336c2b8eacfc4595323c9df..1823c6e20609405e4bb0ecbc235dc7709546b7a3 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 1cee04f627eb2631aab0083e5eebe02e6be394be..ef2a58c2b9d5f977665329a07ef2ceda61677b3b 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;
 }
 
 /*
@@ -392,6 +398,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.
  */
@@ -418,6 +444,22 @@ static void __cpuinit rcu_preempt_init_percpu_data(int cpu)
        rcu_init_percpu_data(cpu, &rcu_preempt_state, 1);
 }
 
+/*
+ * 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,
@@ -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)
 {
 }
 
@@ -539,6 +584,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.
  */
@@ -555,6 +610,16 @@ static int rcu_preempt_needs_cpu(int cpu)
        return 0;
 }
 
+/*
+ * 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 179e6ad80dc03a44a853641175a547c6153f360e..4b31c779e62e6bff126c270c1e8dae3578fd6932 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 1535f3884b88ebd7c33bff7c0e5970a96980a29d..a455dca884a6231ddf34e28bc9f0bb1e47ddb34d 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);
 
@@ -2514,23 +2515,18 @@ 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 4e777b47eedac1f5f779c002091e2dc8b696abe1..c32c3e643daa0cbaaf399276a132535fbe51a8e6 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 255475d163e0cdb62602306a28134d67005e87c0..ce17760d9c516720af8dcf1522b47da937ba0023 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 b38423ca711ad5ef191db6b74205c6cc945cc463..b6e7aaea46043a024a5fb2c622974a2199efda94 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 e0f59a21c06110b0dad7c0a5d031b40c9d3c660a..89aed5933ed4f23b4edef0e8ef6026dfe777dae7 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 fb0f46fa1ecd0fc09b656e2759ff990372faacb3..c3a4e2907eaaf3ec25941d0cc69b04ac35b8dc40 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 46592feab5a6b0cf47e5cc147f43e1669efcf712..9c451a1930b6a7db58be0f78323f487e2ddd4562 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 81b1645c85490175beeea335fcebecb12fd4783a..a91da69f153ad0c859997356d53db6548006db7c 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 d4ff01970547ac7da986d1f90ddefc8c870b30ae..3ffa502fb2433352cb986a6e6821cf203c63652d 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 45068269ebb1746673f23c20b146ca9104a0b325..b20d3ec75de9c6f505e5a591d7d746013b88d6db 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 7a7a9fd249a9c7c158d136dfc998efc9e908f35c..4a194f08f88cc8d7143d5fbd1d43c0efc2013292 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 dd44b8768867f4e312d8792a98f5b38c015c605a..8d5c171cc9987d924f9fcfd3328fcb966288b9a0 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 23245785927f8dfb6810313db3fcc19f3aa0d8e6..98a6cc5c64edec869176962836de406097266cab 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 23b63859130e3e4084911ec07842c65c456331a9..69543a905cd5f1c92086cb47576a21028db11a37 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 f572f44c6e1ede0c13a42223c11520d74efa1f41..b6c12c6a1bcde267a7e25d6b1b8df41c559f1500 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 9fbce6c9d2e14610762039f0e484ca1509790c6d..527e17eae57516a1f36932d13e1799d1244ef03f 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 addfe2df93b13d8982235054d986c1d059fc0894..12328147132c0e6e560ff2e3de39c2fda2a4f116 100644 (file)
@@ -639,6 +639,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
@@ -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 891155817bc6e05aa52abc88e2fe7f93a9c41baa..234ceb10861f304ba858ec9a0baa9f6b297a43a6 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 2755a3bd16a1ca527b5bd01ccd2c9cabde05a77e..eae56fddfa3bd6517653e9387de92c4e56875044 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 f97af55bdd969bfe0303903be7f561fd15a79a58..7e65af70635e4c6db2be536f7e387dedb1daf1d2 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 edd300aca17309cfb6c2e1ef9cef2fcf36de1d74..fd3386242cf06a9f588a363362ecc94b646ddc41 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 3d3accb1f8001dc58ade1436df6295415eda00c6..1065b715ef644e74836d4adf3c877c17d654b542 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 4ea4510e2996cb5dab18852cb1f5e285f7fbd81e..8bf765c4f58d03922adf1f7a100679fe05c65d7d 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 f7edac356f465275031110db70c1e57aafbc5cda..bef1af4f77e36186503c9fe2f91530954a456f3f 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 729d4b15b645aa49c6eca2f003ebbd66f371796c..dacc64183874c739e6a501c780d28ee220c4ac2b 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;
@@ -774,6 +759,24 @@ int __memory_failure(unsigned long pfn, int trapno, int ref)
                return PageBuddy(compound_head(p)) ? 0 : -EBUSY;
        }
 
+       /*
+        * 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
@@ -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 7e91b5f9f690e4ae9d7c3e58bc1530c995311089..6ab19dd4a1990f3f463c1db3eee4f19ce4f5a3de 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 7dd9d9f806948e23a7f0be04dac209bfc1c584f5..4545d59442431e33d7d64e2f98c8f9d1a403780b 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 5189b5aed8c073a388ca5f2dafcc9c3240f7c938..9876fa0c3ad30e75d842f965ac4417e66be6f07a 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 a3b14090b1fb8f296ce9ce2fcec2bd2bbccd8d22..2c5d79236ead88fe692eb97eb0f4ec6b0388753a 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 bf720550b44d85adc294f7fd0b8ede38f73a8902..cdcedf661616464890be93be22d9a8dc39ddd822 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 4a048abad0436d2bd883fd25395b1e44c0b6b99f..d90797160c2a7fff7be950b04ac9817292208ee0 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 a1bc6b9af9a23634f4185e85775d94a6500bbb0e..9c590eef79122dc0597dac27912f60e6b7dc6a72 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 69511e663234482228909f373e247d21082e6ada..0f551a4a44cddc7a042d47bbcd85c7126569ee69 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 64e438898832371277e8baeb89fd5ebb1f72a14a..777af57fd8c8c80971d7abaf4edb974e360288c9 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 5bf5f227dbe0d83eaf28cc400a665594c6452a22..8af95b2dddd62eb4baa6205c776681bf09b91a64 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 b2e07f0dd29844f046fef7acad2e6e1824d33d8b..ea1e3daabefeddb1dc6f46ddf5538b33cc3c0317 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 7f939ce2980195f2aa219429014235c8fe8bcf78..2bc6f6a8de682bec6ae7c43ebcce8d257f9a5632 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 555d9da1869b2fa3daca87eef3f88974a6edb0c8..77e9fb130adb4bd6475c53a481f6e176bf5ec240 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 1c6cf3a1a4f6abc3c605e492c4381d40103d3094..4ade3011bb3c2bd4d270cfb10cdcf5e112402ce9 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 821d30918cfc4f3ebbb2cd79e49dc74e345e61d9..427ded841224e6b7ce79cc91158efec24ab54b4a 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 b69455217ed6270fae1b3d6c4b011cf53b7a7f95..6eb8d47cbf3a563f7d6479183a1b6339afc839cb 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 e92f1fd28aa5161bc28969ba25b3d9d0bf95418e..5df2f6a0b0f01da83bead89554bb7e7492298646 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 e2f950592566ac93267dbd20bc85473d4a759d48..aa00398be80e6f8114da351f07bd0ba585577f17 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 4351ca2cf0b8554eadd258295d44a93455f3e506..537731b3bcb3e5717769588e2f0768bc02ed8570 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 41ada9904d3125c32b063b3dad025cc4898c2c60..1433338526248bdac71566c94e01c1bcd731f190 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 0c0b6e363a20a9ac2e16b0ba22e816b7327ee6bc..e982b5c1ee17c6788b3a11767336ef59ebb2983a 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 757c9171e7c25b021c21d26a681d5238fa0017c1..ab996f9c0fe0ec0c8210698d874022cd786add7d 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 bb41992520268b08c49f345e2170aeb644c56b7d..5b1050a5d874e35ffd608f8e6d0bbb2f1a5204f4 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 64d0af675823c7fe18d15f53c8d48224105f7c1b..98440ad82558064ce4eb7ee9ad525f9725413739 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 624c3c9b3c2bbe33a37f53b105d041b08ce490ef..4c03598ed9248f29fa721b4a3473fca83b21b18f 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 6ec6a8a4a224236acae5393d997727c7804c07cb..0fa9f70e4b1996f6af891f2984c1344675d62e2d 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 14f54eb5a7fc89e1ab9b3d2c7a83e84a54378dbe..4f7aaf6996a3e674a57724cbc05e6d2c82c977f2 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 3a60f12b34ed053da8cf4261952d6d35ff879f28..cf538ed5ef6aadf849d42cdc4e046f00a0f8f51a 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 eafc010907c2d65c803b2285b8045a598fc00893..3c17540230227069e37bd4795ccbd6c6d0e2172b 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 62116829b817174fc7193289222ee820bbc83c1d..315ead3cb926beb93550b9a89f54b8e7497eb504 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 7b6b631f647fbd704add643b8cac365dc11bcb51..d340110f5c0cecaa877d796d57a4fccac1c36acb 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 cf9a4b531a98f5d73386cb7f8d2c7db3837239cf..cccc2e93234f3033765f5c71e0e13c8861765e8f 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 68cbcb19cbd8a084dc0121997c2701f970c99aa1..7dea882dbb750649b10616f00dcb9bb68697ec64 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 bd765f30dba2027c933dfed8782dce63b938f803..b09948ceec4ae1c031754c08c59d425de3e5ab7b 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 5608f6c68413d2169dfc44d3d081a2c9235c938b..7b5131bd6fa17827af6574bb624cf072e5f7b35e 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 0891bfb0699684e0d8971a49b8fa6820b506ec21..48ef1a282b91b8f1cf0bf9c3149c6b66a0467c2a 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 920ec8792f4b4c269fac503581088982b1ce9ce5..f1362f32c17d02c6257f15c9f7705329661304b1 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 e12a786e26b8046769f6b30ba2946c3948f680ff..29b82e98effa6406dd08169d3788041098145d5b 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 8d26e9bf896448167f9f2af8b8a9aa9354d85129..dc5049d58c51fe2c977e55c4b3d29b0e698486ca 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 a59043fbb0ff267e703e1f5779d8ae45730032cc..45667054a5f305308a8bf1faff8b9def3b8b0749 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 c01588f9d453595bb1f36e05c8c418171ff1211b..7170bf4565a8b9570116e5bcc3abc09d3e05e617 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 eec001491e66f6bfba75ca7bf41d22d9563c6788..594f2318c3d82daf25dfac1cc387ac01500f0dc8 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 fd40282966132d9c76719bda986732ce4d511bc5..eaa4118de988929df0a0458e0a67a65f8998e302 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 dd6564321369cf519f2310bc0fdea26c95a89fbc..aeb65b3d2295a7a3c99c279a3e669e583c282e5e 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 7c9ec3dee96e3d17687087d6baf0fd2e594ccfe2..ca6e68dcd8a8573e65dc26377fcf79e3445f3b7a 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 d7ecca0a0c0787d674cc3e28bfab7ed4cc4534a4..f2d116a5cb35775acd9c6e6e5d9e80269142ff06 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 96c0ed115e2a07d6b8ff7afe86632e03fb4174b9..6b0359a500e603510cf30f1a66767dcb3f62b42c 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 6a536949cdc0b0701d3850e9f423101828c6e4f2..7cf6c0fbc7a6d930cf2affe67ab7dd930ec490f8 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 ccc5e83cae5d25cf592237025167d6d1b9d9c7bd..1c246a4f491e9ee5126a8bace259b32a91955421 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 0cf5e8c27a105f399c02e94789227344f5d98934..3fa5751af0ecca4b03002d19a804f969b7011096 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 51ab497115eb7eda412870a895a8e2197adbffca..fc820cd7545309645c018da6a29d170bc67ad0f2 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 45b2be3274db868bbf4db4fc5050f1ea1b448dca..a595f712b5bf3edf09e3f97a6dd10c118e0341a3 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 2a33d8bc886b3abf1a843a7492b21f0b19d622cd..68b321997d4cbe6dbe764f9b20b191135f9aed3f 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 79d2eec54cec84a75bf26a7bdfc628988dbea822..0a6b7a0eca6bf2be42b3e9440a78ad766ec5bb97 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 eddab097435cd9a0473b6f12f98575e45ef1e0f2..ca3c92a0a14f26898c5e07a137a54393e1279fdd 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 93c3ed329204f034c18a1ec08b9d54bb75364abe..9f0b2800a9d7084e198224c178b947779fe63a24 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 4f9c1908593bce72b1572d0a3efb95fd3f22f36f..c67e73ecd5beac46e7212922737479568a95f919 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 7a7778746ea68cf12841cadfd0a84c48ab472588..ffdafb26f5390b414d74ec07a1dde3078fd9a540 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 39677c82747a309281a09d1e049d482f8a6b8696..46be3c5a62b79d533668aeefd50905a6f5dbf383 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 87bbb8bce9bfe3702a3e6b896dce4338bf4f6d2d..bc4114f1ab30b6efe49a9d7fcbc92cc7ff5fc313 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 cdb44b63342e7acfac2229fe0ee75997173a1066..102b76608f35f828a0682399374866de6ae10d24 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 c6ae4052ab43bb5b8a884c23923d59ebf49de8ec..b89ca2c58fdbbe3592f97a27592675417713653c 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 6a12dd9f1181c396f30c1e4c7377e8e0d63402cd..bce3d0fe6fbd8d3f51918098b16c2da45456987e 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 fa4a0a17b7e0e0a12f1637c0c5e9c685a9aadeda..f67cc885c807f0649b508a534d19566dd4de9abe 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 3d93f8c8125246988ade0aa265ddc6b6a9e7289d..47bdd2f99b780dad38d946bbbfde5685d630d7b8 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 2fb28efc5326d88cc94776913743c96a2fc40445..06ec722897be2107db29ea64db6627b090495af0 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 c9ad182e1b4b6a3ddd23b422f2e4f821bde90604..e340792f6cb325eabfca7c2e350aa987a9c35907 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 c08ca660daba19a299173a0b9bcc1f442e11c22a..ff20048504b6484057e4a5464809c52773d7594e 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 bd2338ab2ced8033801bab8700178046db4eab36..0519c60f5be187760abc96ea5590c826a9315af8 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 2dee9839be86035f6b668655dcf84aa12d9e843c..653a362425dfd265b70068361495c0404908df60 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 5735945788bfda39307322bae71519a277f6ab10..6a829eef2a4fc842d08ceeea758571832c00a121 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 5cbbdc80fde3e9d829e91fef099ae21965c54c53..1f35c6fcf5fd7bb1a8553bd6b7677f36a5c3788c 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 3c06c401d0fb86ce6a4b98cb55264af36c807b4c..105a77eeded0e75eec4d618c7ad5844cba0ce442 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 7ff04ad2a97e0511d7b31d49cb7b481c9c0214ed..0a1b2f64bbee38a18947a9fa161eb922dc0f17a0 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 8de6f9dec4a225a495825c86f2dcf03e167403fb..d89f6dc00908284d0e97e5778dfe9444b99683ff 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 1c2ed3090cce2de65ef80be78f9db02644531854..a7910099d6fd5111470b543d9aa2bcfe57fc96c4 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 b5f1953b614438a38dbab19efc4b61d95e8e656c..7e190d522cd5848123b0d98220e6555fd3e70c69 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 a5a050af8e7dbca2e474d3f2907b4bc5f5cebbae..3eeef339c787bdb414a0faba3e31d02a6efa2a02 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 ea9c15c0cdfe0d96fa7c489956e2beb39df77bbe..ce2d5be4f30ef78bab41a803f868a0ee63708616 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 e5f6ece65a1386f51b21f8b537a43fc9833275ea..3db31e7bf1737a438cc93e4648e987ec0073aeb1 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 4405681b31348d5613927488f953d90b016bcd5b..e8a510d935e55d2cdae348e532fbdd47bf22cd4d 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 1ca88896eee452adbc1425005776f66a13fc9611..a1b1d10912dceae2fcab280d41e03f28a60b3a82 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 e9d256e2f47dfad9d570a98d6d98d36cacb95c33..0c5e4f72f2bae827ee0456f7362aff1f0ad20a91 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 f1946d107b108b9e150138281f1617d7866d4aa5..fdd42a824c9870be6c1cfce297dc552093fa45f6 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 c561d1538c039df208f6d7bbdf96d3030c06ef4d..54552a00a1177098e77e0cd76d2ccc9c02858378 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 87c424de79ee39653d3ef7041b878cda97ea459c..8cfb48cbbea01d8fbd5ba6aee541d07c360b7d3d 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 a778fd0f4ae4796617365e105aa660ee6de57907..b3637db025a25cba486b824c45c8291a368d7881 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 559fb06210f58f676f8a342c8382a01a319c847c..226f44a2357de7baf900271a58b12cddffed50c0 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 6e8490716408770b15905437bcebf07a4c89cc70..829da9edba649f9ed7bd01ef6e17a9aaec731ca4 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 f6a8437141c8f464de406e1947d0a3c557716607..55c9659a56e2271b3dcad7056bbde78ee240df3d 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 e79c54034bcde0ea9ff278af1d5a6730948b0939..7495ce3473448cd45ee1dba9e0ae441c83245ca4 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);
 }